diff --git a/public/Images/Images.js b/public/Images/Images.js index 64628882..52b2aa60 100644 --- a/public/Images/Images.js +++ b/public/Images/Images.js @@ -42,6 +42,7 @@ style.setProperty('--image-file-align-self-center', 'url(\"' + new URL(new URL(' style.setProperty('--image-file-align-self-end', 'url(\"' + new URL(new URL('align-self-end.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-align-self-start', 'url(\"' + new URL(new URL('align-self-start.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-align-self-stretch', 'url(\"' + new URL(new URL('align-self-stretch.svg', import.meta.url).href, import.meta.url).toString() + '\")'); +style.setProperty('--image-file-animation', 'url(\"' + new URL(new URL('animation.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-back', 'url(\"' + new URL(new URL('arrow-back.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-down', 'url(\"' + new URL(new URL('arrow-down.svg', import.meta.url).href, import.meta.url).toString() + '\")'); 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() + '\")'); @@ -60,6 +61,7 @@ style.setProperty('--image-file-brackets', 'url(\"' + new URL(new URL('brackets. style.setProperty('--image-file-breakpoint-circle', 'url(\"' + new URL(new URL('breakpoint-circle.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-breakpoint-crossed-filled', 'url(\"' + new URL(new URL('breakpoint-crossed-filled.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-breakpoint-crossed', 'url(\"' + new URL(new URL('breakpoint-crossed.svg', import.meta.url).href, import.meta.url).toString() + '\")'); +style.setProperty('--image-file-brush-2', 'url(\"' + new URL(new URL('brush-2.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-brush-filled', 'url(\"' + new URL(new URL('brush-filled.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-brush', 'url(\"' + new URL(new URL('brush.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-bug', 'url(\"' + new URL(new URL('bug.svg', import.meta.url).href, import.meta.url).toString() + '\")'); diff --git a/public/Images/Images.prebundle.js b/public/Images/Images.prebundle.js index 571bd435..1d8270c3 100644 --- a/public/Images/Images.prebundle.js +++ b/public/Images/Images.prebundle.js @@ -43,6 +43,7 @@ style.setProperty('--image-file-align-self-center', 'url(\"' + new URL('./src/al style.setProperty('--image-file-align-self-end', 'url(\"' + new URL('./src/align-self-end.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-align-self-start', 'url(\"' + new URL('./src/align-self-start.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-align-self-stretch', 'url(\"' + new URL('./src/align-self-stretch.svg', import.meta.url).toString() + '\")'); +style.setProperty('--image-file-animation', 'url(\"' + new URL('./src/animation.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-back', 'url(\"' + new URL('./src/arrow-back.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-down', 'url(\"' + new URL('./src/arrow-down.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-drop-down-dark', 'url(\"' + new URL('./src/arrow-drop-down-dark.svg', import.meta.url).toString() + '\")'); @@ -61,6 +62,7 @@ style.setProperty('--image-file-brackets', 'url(\"' + new URL('./src/brackets.sv style.setProperty('--image-file-breakpoint-circle', 'url(\"' + new URL('./src/breakpoint-circle.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-breakpoint-crossed-filled', 'url(\"' + new URL('./src/breakpoint-crossed-filled.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-breakpoint-crossed', 'url(\"' + new URL('./src/breakpoint-crossed.svg', import.meta.url).toString() + '\")'); +style.setProperty('--image-file-brush-2', 'url(\"' + new URL('./src/brush-2.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-brush-filled', 'url(\"' + new URL('./src/brush-filled.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-brush', 'url(\"' + new URL('./src/brush.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-bug', 'url(\"' + new URL('./src/bug.svg', import.meta.url).toString() + '\")'); diff --git a/public/Images/animation.svg b/public/Images/animation.svg new file mode 100644 index 00000000..35537565 --- /dev/null +++ b/public/Images/animation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/Images/brush-2.svg b/public/Images/brush-2.svg new file mode 100644 index 00000000..31d2f9c5 --- /dev/null +++ b/public/Images/brush-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/Images/src/animation.svg b/public/Images/src/animation.svg new file mode 100644 index 00000000..63924592 --- /dev/null +++ b/public/Images/src/animation.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/Images/src/brush-2.svg b/public/Images/src/brush-2.svg new file mode 100644 index 00000000..e2c6c98b --- /dev/null +++ b/public/Images/src/brush-2.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/core/common/SettingRegistration.d.ts b/public/core/common/SettingRegistration.d.ts index e21b8bc8..57bc0b88 100644 --- a/public/core/common/SettingRegistration.d.ts +++ b/public/core/common/SettingRegistration.d.ts @@ -142,7 +142,7 @@ export interface SettingRegistration { */ export interface LearnMore { tooltip: () => Platform.UIString.LocalizedString; - url: Platform.DevToolsPath.UrlString; + url?: Platform.DevToolsPath.UrlString; } interface LocalizedSettingExtensionOption { value: boolean | string; diff --git a/public/core/common/SettingRegistration.js.map b/public/core/common/SettingRegistration.js.map index 976afe7b..c1a62fcd 100644 --- a/public/core/common/SettingRegistration.js.map +++ b/public/core/common/SettingRegistration.js.map @@ -1 +1 @@ -{"version":3,"file":"SettingRegistration.js","sourceRoot":"","sources":["../../../../../../front_end/core/common/SettingRegistration.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 i18n from '../i18n/i18n.js';\nimport type * as Platform from '../platform/platform.js';\nimport * as Root from '../root/root.js';\n\nimport type {SettingStorageType} from './Settings.js';\n\nconst UIStrings = {\n /**\n *@description Title of the Elements Panel\n */\n elements: 'Elements',\n /**\n *@description Text for DevTools appearance\n */\n appearance: 'Appearance',\n /**\n *@description Name of the Sources panel\n */\n sources: 'Sources',\n /**\n *@description Title of the Network tool\n */\n network: 'Network',\n /**\n *@description Text for the performance of something\n */\n performance: 'Performance',\n /**\n *@description Title of the Console tool\n */\n console: 'Console',\n /**\n *@description A title of the 'Persistence' setting category\n */\n persistence: 'Persistence',\n /**\n *@description Text that refers to the debugger\n */\n debugger: 'Debugger',\n /**\n *@description Text describing global shortcuts and settings that are available throughout the DevTools\n */\n global: 'Global',\n /**\n *@description Title of the Rendering tool\n */\n rendering: 'Rendering',\n /**\n *@description Title of a section on CSS Grid tooling\n */\n grid: 'Grid',\n /**\n *@description Text for the mobile platform, as opposed to desktop\n */\n mobile: 'Mobile',\n /**\n *@description Text for the memory of the page\n */\n memory: 'Memory',\n /**\n *@description Text for the extension of the page\n */\n extension: 'Extension',\n /**\n *@description Text for the adorner of the page\n */\n adorner: 'Adorner',\n /**\n * @description Header for the \"Sync\" section in the settings UI. The \"Sync\"\n * section allows users to configure which DevTools data is synced via Chrome Sync.\n */\n sync: 'Sync',\n};\nconst str_ = i18n.i18n.registerUIStrings('core/common/SettingRegistration.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nlet registeredSettings: Array = [];\nconst settingNameSet = new Set();\n\nexport function registerSettingExtension(registration: SettingRegistration): void {\n const settingName = registration.settingName;\n if (settingNameSet.has(settingName)) {\n throw new Error(`Duplicate setting name '${settingName}'`);\n }\n settingNameSet.add(settingName);\n registeredSettings.push(registration);\n}\n\nexport function getRegisteredSettings(config: Root.Runtime.HostConfig): Array {\n return registeredSettings.filter(\n setting => Root.Runtime.Runtime.isDescriptorEnabled(\n {experiment: setting.experiment, condition: setting.condition}, config));\n}\n\nexport function registerSettingsForTest(settings: Array, forceReset: boolean = false): void {\n if (registeredSettings.length === 0 || forceReset) {\n registeredSettings = settings;\n settingNameSet.clear();\n for (const setting of settings) {\n const settingName = setting.settingName;\n if (settingNameSet.has(settingName)) {\n throw new Error(`Duplicate setting name '${settingName}'`);\n }\n settingNameSet.add(settingName);\n }\n }\n}\n\nexport function resetSettings(): void {\n registeredSettings = [];\n settingNameSet.clear();\n}\n\nexport function maybeRemoveSettingExtension(settingName: string): boolean {\n const settingIndex = registeredSettings.findIndex(setting => setting.settingName === settingName);\n if (settingIndex < 0 || !settingNameSet.delete(settingName)) {\n return false;\n }\n registeredSettings.splice(settingIndex, 1);\n return true;\n}\n\nexport const enum SettingCategory {\n NONE = '', // `NONE` must be a falsy value. Legacy code uses if-checks for the category.\n ELEMENTS = 'ELEMENTS',\n APPEARANCE = 'APPEARANCE',\n SOURCES = 'SOURCES',\n NETWORK = 'NETWORK',\n PERFORMANCE = 'PERFORMANCE',\n CONSOLE = 'CONSOLE',\n PERSISTENCE = 'PERSISTENCE',\n DEBUGGER = 'DEBUGGER',\n GLOBAL = 'GLOBAL',\n RENDERING = 'RENDERING',\n GRID = 'GRID',\n MOBILE = 'MOBILE',\n EMULATION = 'EMULATION',\n MEMORY = 'MEMORY',\n EXTENSIONS = 'EXTENSIONS',\n ADORNER = 'ADORNER',\n SYNC = 'SYNC',\n}\n\nexport function getLocalizedSettingsCategory(category: SettingCategory): Platform.UIString.LocalizedString {\n switch (category) {\n case SettingCategory.ELEMENTS:\n return i18nString(UIStrings.elements);\n case SettingCategory.APPEARANCE:\n return i18nString(UIStrings.appearance);\n case SettingCategory.SOURCES:\n return i18nString(UIStrings.sources);\n case SettingCategory.NETWORK:\n return i18nString(UIStrings.network);\n case SettingCategory.PERFORMANCE:\n return i18nString(UIStrings.performance);\n case SettingCategory.CONSOLE:\n return i18nString(UIStrings.console);\n case SettingCategory.PERSISTENCE:\n return i18nString(UIStrings.persistence);\n case SettingCategory.DEBUGGER:\n return i18nString(UIStrings.debugger);\n case SettingCategory.GLOBAL:\n return i18nString(UIStrings.global);\n case SettingCategory.RENDERING:\n return i18nString(UIStrings.rendering);\n case SettingCategory.GRID:\n return i18nString(UIStrings.grid);\n case SettingCategory.MOBILE:\n return i18nString(UIStrings.mobile);\n case SettingCategory.EMULATION:\n return i18nString(UIStrings.console);\n case SettingCategory.MEMORY:\n return i18nString(UIStrings.memory);\n case SettingCategory.EXTENSIONS:\n return i18nString(UIStrings.extension);\n case SettingCategory.ADORNER:\n return i18nString(UIStrings.adorner);\n case SettingCategory.NONE:\n return i18n.i18n.lockedString('');\n case SettingCategory.SYNC:\n return i18nString(UIStrings.sync);\n }\n}\n\nexport const enum SettingType {\n ARRAY = 'array',\n REGEX = 'regex',\n ENUM = 'enum',\n BOOLEAN = 'boolean',\n}\n\nexport interface RegExpSettingItem {\n /**\n * A regular expression matched against URLs for ignore listing.\n */\n pattern: string;\n /**\n * If true, ignore this rule.\n */\n disabled?: boolean;\n /**\n * When a rule is disabled due to requesting through a script's context menu\n * that it no longer be ignore listed, this field is set to the URL of that\n * script, so that if the user requests through the same context menu to\n * enable ignore listing, the rule can be reenabled.\n */\n disabledForUrl?: Platform.DevToolsPath.UrlString;\n}\n\nexport interface SettingRegistration {\n /**\n * The category with which the setting is displayed in the UI.\n */\n category?: SettingCategory;\n /**\n * Used to sort on screen the settings that belong to the same category.\n */\n order?: number;\n /**\n * The title with which the setting is shown on screen.\n */\n title?: () => Platform.UIString.LocalizedString;\n /**\n * The identifier of the setting.\n */\n settingName: string;\n /**\n * Determines how the possible values of the setting are expressed.\n *\n * - If the setting can only be enabled and disabled use BOOLEAN\n * - If the setting has a list of possible values use ENUM\n * - If each setting value is a set of objects use ARRAY\n * - If the setting value is a regular expression use REGEX\n */\n settingType: SettingType;\n /**\n * The value set by default to the setting.\n */\n defaultValue: unknown;\n /**\n * Words used to find a setting in the Command Menu.\n */\n tags?: Array<() => Platform.UIString.LocalizedString>;\n /**\n * The possible values the setting can have, each with a description composed of a title and an optional text.\n */\n options?: Array;\n /**\n * Whether DevTools must be reloaded for a change in the setting to take effect.\n */\n reloadRequired?: boolean;\n /**\n * Determines if the setting value is stored in the global, local or session storage.\n */\n storageType?: SettingStorageType;\n /**\n * A condition that, when present in the queryParamsObject of Runtime, constraints the value\n * of the setting to be changed only if the user set it.\n */\n userActionCondition?: string;\n /**\n * The name of the experiment a setting is associated with. Enabling and disabling the declared\n * experiment will enable and disable the setting respectively.\n */\n experiment?: Root.Runtime.ExperimentName;\n /**\n * A condition is a function that will make the setting available if it\n * returns true, and not available, otherwise. Make sure that objects you\n * access from inside the condition function are ready at the time when the\n * setting conditions are checked.\n */\n condition?: Root.Runtime.Condition;\n\n /**\n * A function that returns true if the setting should be disabled, along with\n * the reason why.\n */\n disabledCondition?: (config?: Root.Runtime.HostConfig) => DisabledConditionResult;\n\n /**\n * If a setting is deprecated, define this notice to show an appropriate warning according to the `warning` property.\n * If `disabled` is set, the setting will be disabled in the settings UI. In that case, `experiment` optionally can be\n * set to link to an experiment (by experiment name). The information icon in the settings UI can then be clicked to\n * jump to the experiment. If a setting is not disabled, the experiment entry will be ignored.\n */\n deprecationNotice?: {disabled: boolean, warning: () => Platform.UIString.LocalizedString, experiment?: string};\n\n /**\n * Optional information to learn more about the setting. If provided, a `(?)` icon will show next to the setting\n * in the Settings panel with a link to learn more, and the `tooltip` will be presented to the user when hovering\n * the `(?)` icon.\n */\n learnMore?: LearnMore;\n}\n\n/**\n * Metadata to learn more about a setting. The `url` will be used to construct\n * a `(?)` icon link and the `tooltip` will be shown when hovering the icon.\n */\nexport interface LearnMore {\n tooltip: () => Platform.UIString.LocalizedString;\n url: Platform.DevToolsPath.UrlString;\n}\n\ninterface LocalizedSettingExtensionOption {\n value: boolean|string;\n title: () => Platform.UIString.LocalizedString;\n text?: () => Platform.UIString.LocalizedString;\n raw?: false;\n}\ninterface RawSettingExtensionOption {\n value: boolean|string;\n title: () => Platform.UIString.LocalizedString;\n /**\n * Text used to describe the option. Must be localized if 'raw' is false.\n */\n text?: string;\n raw: true;\n}\nexport type SettingExtensionOption = LocalizedSettingExtensionOption|RawSettingExtensionOption;\nexport type DisabledConditionResult = {\n disabled: true,\n reason: string,\n}|{disabled: false};\n"]} \ No newline at end of file +{"version":3,"file":"SettingRegistration.js","sourceRoot":"","sources":["../../../../../../front_end/core/common/SettingRegistration.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 i18n from '../i18n/i18n.js';\nimport type * as Platform from '../platform/platform.js';\nimport * as Root from '../root/root.js';\n\nimport type {SettingStorageType} from './Settings.js';\n\nconst UIStrings = {\n /**\n *@description Title of the Elements Panel\n */\n elements: 'Elements',\n /**\n *@description Text for DevTools appearance\n */\n appearance: 'Appearance',\n /**\n *@description Name of the Sources panel\n */\n sources: 'Sources',\n /**\n *@description Title of the Network tool\n */\n network: 'Network',\n /**\n *@description Text for the performance of something\n */\n performance: 'Performance',\n /**\n *@description Title of the Console tool\n */\n console: 'Console',\n /**\n *@description A title of the 'Persistence' setting category\n */\n persistence: 'Persistence',\n /**\n *@description Text that refers to the debugger\n */\n debugger: 'Debugger',\n /**\n *@description Text describing global shortcuts and settings that are available throughout the DevTools\n */\n global: 'Global',\n /**\n *@description Title of the Rendering tool\n */\n rendering: 'Rendering',\n /**\n *@description Title of a section on CSS Grid tooling\n */\n grid: 'Grid',\n /**\n *@description Text for the mobile platform, as opposed to desktop\n */\n mobile: 'Mobile',\n /**\n *@description Text for the memory of the page\n */\n memory: 'Memory',\n /**\n *@description Text for the extension of the page\n */\n extension: 'Extension',\n /**\n *@description Text for the adorner of the page\n */\n adorner: 'Adorner',\n /**\n * @description Header for the \"Sync\" section in the settings UI. The \"Sync\"\n * section allows users to configure which DevTools data is synced via Chrome Sync.\n */\n sync: 'Sync',\n};\nconst str_ = i18n.i18n.registerUIStrings('core/common/SettingRegistration.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nlet registeredSettings: Array = [];\nconst settingNameSet = new Set();\n\nexport function registerSettingExtension(registration: SettingRegistration): void {\n const settingName = registration.settingName;\n if (settingNameSet.has(settingName)) {\n throw new Error(`Duplicate setting name '${settingName}'`);\n }\n settingNameSet.add(settingName);\n registeredSettings.push(registration);\n}\n\nexport function getRegisteredSettings(config: Root.Runtime.HostConfig): Array {\n return registeredSettings.filter(\n setting => Root.Runtime.Runtime.isDescriptorEnabled(\n {experiment: setting.experiment, condition: setting.condition}, config));\n}\n\nexport function registerSettingsForTest(settings: Array, forceReset: boolean = false): void {\n if (registeredSettings.length === 0 || forceReset) {\n registeredSettings = settings;\n settingNameSet.clear();\n for (const setting of settings) {\n const settingName = setting.settingName;\n if (settingNameSet.has(settingName)) {\n throw new Error(`Duplicate setting name '${settingName}'`);\n }\n settingNameSet.add(settingName);\n }\n }\n}\n\nexport function resetSettings(): void {\n registeredSettings = [];\n settingNameSet.clear();\n}\n\nexport function maybeRemoveSettingExtension(settingName: string): boolean {\n const settingIndex = registeredSettings.findIndex(setting => setting.settingName === settingName);\n if (settingIndex < 0 || !settingNameSet.delete(settingName)) {\n return false;\n }\n registeredSettings.splice(settingIndex, 1);\n return true;\n}\n\nexport const enum SettingCategory {\n NONE = '', // `NONE` must be a falsy value. Legacy code uses if-checks for the category.\n ELEMENTS = 'ELEMENTS',\n APPEARANCE = 'APPEARANCE',\n SOURCES = 'SOURCES',\n NETWORK = 'NETWORK',\n PERFORMANCE = 'PERFORMANCE',\n CONSOLE = 'CONSOLE',\n PERSISTENCE = 'PERSISTENCE',\n DEBUGGER = 'DEBUGGER',\n GLOBAL = 'GLOBAL',\n RENDERING = 'RENDERING',\n GRID = 'GRID',\n MOBILE = 'MOBILE',\n EMULATION = 'EMULATION',\n MEMORY = 'MEMORY',\n EXTENSIONS = 'EXTENSIONS',\n ADORNER = 'ADORNER',\n SYNC = 'SYNC',\n}\n\nexport function getLocalizedSettingsCategory(category: SettingCategory): Platform.UIString.LocalizedString {\n switch (category) {\n case SettingCategory.ELEMENTS:\n return i18nString(UIStrings.elements);\n case SettingCategory.APPEARANCE:\n return i18nString(UIStrings.appearance);\n case SettingCategory.SOURCES:\n return i18nString(UIStrings.sources);\n case SettingCategory.NETWORK:\n return i18nString(UIStrings.network);\n case SettingCategory.PERFORMANCE:\n return i18nString(UIStrings.performance);\n case SettingCategory.CONSOLE:\n return i18nString(UIStrings.console);\n case SettingCategory.PERSISTENCE:\n return i18nString(UIStrings.persistence);\n case SettingCategory.DEBUGGER:\n return i18nString(UIStrings.debugger);\n case SettingCategory.GLOBAL:\n return i18nString(UIStrings.global);\n case SettingCategory.RENDERING:\n return i18nString(UIStrings.rendering);\n case SettingCategory.GRID:\n return i18nString(UIStrings.grid);\n case SettingCategory.MOBILE:\n return i18nString(UIStrings.mobile);\n case SettingCategory.EMULATION:\n return i18nString(UIStrings.console);\n case SettingCategory.MEMORY:\n return i18nString(UIStrings.memory);\n case SettingCategory.EXTENSIONS:\n return i18nString(UIStrings.extension);\n case SettingCategory.ADORNER:\n return i18nString(UIStrings.adorner);\n case SettingCategory.NONE:\n return i18n.i18n.lockedString('');\n case SettingCategory.SYNC:\n return i18nString(UIStrings.sync);\n }\n}\n\nexport const enum SettingType {\n ARRAY = 'array',\n REGEX = 'regex',\n ENUM = 'enum',\n BOOLEAN = 'boolean',\n}\n\nexport interface RegExpSettingItem {\n /**\n * A regular expression matched against URLs for ignore listing.\n */\n pattern: string;\n /**\n * If true, ignore this rule.\n */\n disabled?: boolean;\n /**\n * When a rule is disabled due to requesting through a script's context menu\n * that it no longer be ignore listed, this field is set to the URL of that\n * script, so that if the user requests through the same context menu to\n * enable ignore listing, the rule can be reenabled.\n */\n disabledForUrl?: Platform.DevToolsPath.UrlString;\n}\n\nexport interface SettingRegistration {\n /**\n * The category with which the setting is displayed in the UI.\n */\n category?: SettingCategory;\n /**\n * Used to sort on screen the settings that belong to the same category.\n */\n order?: number;\n /**\n * The title with which the setting is shown on screen.\n */\n title?: () => Platform.UIString.LocalizedString;\n /**\n * The identifier of the setting.\n */\n settingName: string;\n /**\n * Determines how the possible values of the setting are expressed.\n *\n * - If the setting can only be enabled and disabled use BOOLEAN\n * - If the setting has a list of possible values use ENUM\n * - If each setting value is a set of objects use ARRAY\n * - If the setting value is a regular expression use REGEX\n */\n settingType: SettingType;\n /**\n * The value set by default to the setting.\n */\n defaultValue: unknown;\n /**\n * Words used to find a setting in the Command Menu.\n */\n tags?: Array<() => Platform.UIString.LocalizedString>;\n /**\n * The possible values the setting can have, each with a description composed of a title and an optional text.\n */\n options?: Array;\n /**\n * Whether DevTools must be reloaded for a change in the setting to take effect.\n */\n reloadRequired?: boolean;\n /**\n * Determines if the setting value is stored in the global, local or session storage.\n */\n storageType?: SettingStorageType;\n /**\n * A condition that, when present in the queryParamsObject of Runtime, constraints the value\n * of the setting to be changed only if the user set it.\n */\n userActionCondition?: string;\n /**\n * The name of the experiment a setting is associated with. Enabling and disabling the declared\n * experiment will enable and disable the setting respectively.\n */\n experiment?: Root.Runtime.ExperimentName;\n /**\n * A condition is a function that will make the setting available if it\n * returns true, and not available, otherwise. Make sure that objects you\n * access from inside the condition function are ready at the time when the\n * setting conditions are checked.\n */\n condition?: Root.Runtime.Condition;\n\n /**\n * A function that returns true if the setting should be disabled, along with\n * the reason why.\n */\n disabledCondition?: (config?: Root.Runtime.HostConfig) => DisabledConditionResult;\n\n /**\n * If a setting is deprecated, define this notice to show an appropriate warning according to the `warning` property.\n * If `disabled` is set, the setting will be disabled in the settings UI. In that case, `experiment` optionally can be\n * set to link to an experiment (by experiment name). The information icon in the settings UI can then be clicked to\n * jump to the experiment. If a setting is not disabled, the experiment entry will be ignored.\n */\n deprecationNotice?: {disabled: boolean, warning: () => Platform.UIString.LocalizedString, experiment?: string};\n\n /**\n * Optional information to learn more about the setting. If provided, a `(?)` icon will show next to the setting\n * in the Settings panel with a link to learn more, and the `tooltip` will be presented to the user when hovering\n * the `(?)` icon.\n */\n learnMore?: LearnMore;\n}\n\n/**\n * Metadata to learn more about a setting. The `url` will be used to construct\n * a `(?)` icon link and the `tooltip` will be shown when hovering the icon.\n */\nexport interface LearnMore {\n tooltip: () => Platform.UIString.LocalizedString;\n url?: Platform.DevToolsPath.UrlString;\n}\n\ninterface LocalizedSettingExtensionOption {\n value: boolean|string;\n title: () => Platform.UIString.LocalizedString;\n text?: () => Platform.UIString.LocalizedString;\n raw?: false;\n}\ninterface RawSettingExtensionOption {\n value: boolean|string;\n title: () => Platform.UIString.LocalizedString;\n /**\n * Text used to describe the option. Must be localized if 'raw' is false.\n */\n text?: string;\n raw: true;\n}\nexport type SettingExtensionOption = LocalizedSettingExtensionOption|RawSettingExtensionOption;\nexport type DisabledConditionResult = {\n disabled: true,\n reason: string,\n}|{disabled: false};\n"]} \ No newline at end of file diff --git a/public/core/host/AidaClient.d.ts b/public/core/host/AidaClient.d.ts index 6799dda2..968c9742 100644 --- a/public/core/host/AidaClient.d.ts +++ b/public/core/host/AidaClient.d.ts @@ -6,6 +6,7 @@ export declare enum Entity { SYSTEM = 2 } export declare const enum Rating { + SENTIMENT_UNSPECIFIED = "SENTIMENT_UNSPECIFIED", POSITIVE = "POSITIVE", NEGATIVE = "NEGATIVE" } diff --git a/public/core/host/AidaClient.js.map b/public/core/host/AidaClient.js.map index 95fcb3a1..d8829b0d 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';\nimport type * as Root from '../root/root.js';\n\nimport {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';\nimport type {AidaClientResult, 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 // Chrome DrJones Network Agent.\n CHROME_DRJONES_NETWORK_AGENT = 7,\n // Chrome DrJones Performance Agent.\n CHROME_DRJONES_PERFORMANCE_AGENT = 8,\n // Chrome DrJones File Agent.\n CHROME_DRJONES_FILE_AGENT = 9,\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_INTERNET = 'no-internet',\n // This is the state (mostly enterprise) users are in, when they are automatically logged out from\n // Chrome after a certain time period. For making AIDA requests, they need to log in again.\n SYNC_IS_PAUSED = 'sync-is-paused',\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 = -1;\n let modelId = '';\n if (config.devToolsConsoleInsights?.enabled) {\n temperature = config.devToolsConsoleInsights.temperature ?? -1;\n modelId = config.devToolsConsoleInsights.modelId || '';\n }\n const disallowLogging = config.aidaAvailability?.disallowLogging ?? true;\n\n if (temperature >= 0) {\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.isSyncPaused) {\n return AidaAccessPreconditions.SYNC_IS_PAUSED;\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\nlet hostConfigTrackerInstance: HostConfigTracker|undefined;\n\nexport class HostConfigTracker extends Common.ObjectWrapper.ObjectWrapper {\n #pollTimer?: number;\n #aidaAvailability?: AidaAccessPreconditions;\n\n private constructor() {\n super();\n }\n\n static instance(): HostConfigTracker {\n if (!hostConfigTrackerInstance) {\n hostConfigTrackerInstance = new HostConfigTracker();\n }\n return hostConfigTrackerInstance;\n }\n\n override addEventListener(eventType: Events, listener: Common.EventTarget.EventListener):\n Common.EventTarget.EventDescriptor {\n const isFirst = !this.hasEventListeners(eventType);\n const eventDescriptor = super.addEventListener(eventType, listener);\n if (isFirst) {\n window.clearTimeout(this.#pollTimer);\n void this.pollAidaAvailability();\n }\n return eventDescriptor;\n }\n\n override removeEventListener(eventType: Events, listener: Common.EventTarget.EventListener):\n void {\n super.removeEventListener(eventType, listener);\n if (!this.hasEventListeners(eventType)) {\n window.clearTimeout(this.#pollTimer);\n }\n }\n\n private async pollAidaAvailability(): Promise {\n this.#pollTimer = window.setTimeout(() => this.pollAidaAvailability(), 2000);\n const currentAidaAvailability = await AidaClient.checkAccessPreconditions();\n if (currentAidaAvailability !== this.#aidaAvailability) {\n this.#aidaAvailability = currentAidaAvailability;\n const config = await new Promise(\n resolve => InspectorFrontendHostInstance.getHostConfig(config => resolve(config)));\n Common.Settings.Settings.instance().setHostConfig(config);\n this.dispatchEventToListeners(Events.AIDA_AVAILABILITY_CHANGED);\n }\n }\n}\n\nexport const enum Events {\n AIDA_AVAILABILITY_CHANGED = 'aidaAvailabilityChanged',\n}\n\nexport type EventTypes = {\n [Events.AIDA_AVAILABILITY_CHANGED]: void,\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';\nimport type * as Root from '../root/root.js';\n\nimport {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';\nimport type {AidaClientResult, 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 SENTIMENT_UNSPECIFIED = 'SENTIMENT_UNSPECIFIED',\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 // Chrome DrJones Network Agent.\n CHROME_DRJONES_NETWORK_AGENT = 7,\n // Chrome DrJones Performance Agent.\n CHROME_DRJONES_PERFORMANCE_AGENT = 8,\n // Chrome DrJones File Agent.\n CHROME_DRJONES_FILE_AGENT = 9,\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_INTERNET = 'no-internet',\n // This is the state (mostly enterprise) users are in, when they are automatically logged out from\n // Chrome after a certain time period. For making AIDA requests, they need to log in again.\n SYNC_IS_PAUSED = 'sync-is-paused',\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 = -1;\n let modelId = '';\n if (config.devToolsConsoleInsights?.enabled) {\n temperature = config.devToolsConsoleInsights.temperature ?? -1;\n modelId = config.devToolsConsoleInsights.modelId || '';\n }\n const disallowLogging = config.aidaAvailability?.disallowLogging ?? true;\n\n if (temperature >= 0) {\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.isSyncPaused) {\n return AidaAccessPreconditions.SYNC_IS_PAUSED;\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\nlet hostConfigTrackerInstance: HostConfigTracker|undefined;\n\nexport class HostConfigTracker extends Common.ObjectWrapper.ObjectWrapper {\n #pollTimer?: number;\n #aidaAvailability?: AidaAccessPreconditions;\n\n private constructor() {\n super();\n }\n\n static instance(): HostConfigTracker {\n if (!hostConfigTrackerInstance) {\n hostConfigTrackerInstance = new HostConfigTracker();\n }\n return hostConfigTrackerInstance;\n }\n\n override addEventListener(eventType: Events, listener: Common.EventTarget.EventListener):\n Common.EventTarget.EventDescriptor {\n const isFirst = !this.hasEventListeners(eventType);\n const eventDescriptor = super.addEventListener(eventType, listener);\n if (isFirst) {\n window.clearTimeout(this.#pollTimer);\n void this.pollAidaAvailability();\n }\n return eventDescriptor;\n }\n\n override removeEventListener(eventType: Events, listener: Common.EventTarget.EventListener):\n void {\n super.removeEventListener(eventType, listener);\n if (!this.hasEventListeners(eventType)) {\n window.clearTimeout(this.#pollTimer);\n }\n }\n\n private async pollAidaAvailability(): Promise {\n this.#pollTimer = window.setTimeout(() => this.pollAidaAvailability(), 2000);\n const currentAidaAvailability = await AidaClient.checkAccessPreconditions();\n if (currentAidaAvailability !== this.#aidaAvailability) {\n this.#aidaAvailability = currentAidaAvailability;\n const config = await new Promise(\n resolve => InspectorFrontendHostInstance.getHostConfig(config => resolve(config)));\n Common.Settings.Settings.instance().setHostConfig(config);\n this.dispatchEventToListeners(Events.AIDA_AVAILABILITY_CHANGED);\n }\n }\n}\n\nexport const enum Events {\n AIDA_AVAILABILITY_CHANGED = 'aidaAvailabilityChanged',\n}\n\nexport type EventTypes = {\n [Events.AIDA_AVAILABILITY_CHANGED]: void,\n};\n"]} \ No newline at end of file diff --git a/public/core/host/InspectorFrontendHost.js b/public/core/host/InspectorFrontendHost.js index f0a696b5..fc6f4da4 100644 --- a/public/core/host/InspectorFrontendHost.js +++ b/public/core/host/InspectorFrontendHost.js @@ -334,6 +334,10 @@ export class InspectorFrontendHostStub { devToolsPrivacyUI: { enabled: false, }, + devToolsEnableOriginBoundCookies: { + portBindingEnabled: false, + schemeBindingEnabled: false, + }, isOffTheRecord: false, }; if ('hostConfigForTesting' in globalThis) { diff --git a/public/core/host/InspectorFrontendHost.js.map b/public/core/host/InspectorFrontendHost.js.map index 53ae45b7..5e6c8b3d 100644 --- a/public/core/host/InspectorFrontendHost.js.map +++ b/public/core/host/InspectorFrontendHost.js.map @@ -1 +1 @@ -{"version":3,"file":"InspectorFrontendHost.js","sourceRoot":"","sources":["../../../../../../front_end/core/host/InspectorFrontendHost.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\n// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport * as Common from '../common/common.js';\nimport * as i18n from '../i18n/i18n.js';\nimport * as Platform from '../platform/platform.js';\nimport * as Root from '../root/root.js';\n\nimport {\n type AidaClientResult,\n type CanShowSurveyResult,\n type ChangeEvent,\n type ClickEvent,\n type ContextMenuDescriptor,\n type DoAidaConversationResult,\n type DragEvent,\n type EnumeratedHistogram,\n EventDescriptors,\n Events,\n type EventTypes,\n type ExtensionDescriptor,\n type HoverEvent,\n type ImpressionEvent,\n type InspectorFrontendHostAPI,\n type KeyDownEvent,\n type LoadNetworkResourceResult,\n type ResizeEvent,\n type ShowSurveyResult,\n type SyncInformation,\n} from './InspectorFrontendHostAPI.js';\nimport {streamWrite as resourceLoaderStreamWrite} from './ResourceLoader.js';\n\ninterface DecompressionStream extends GenericTransformStream {\n readonly format: string;\n}\ndeclare const DecompressionStream: {\n prototype: DecompressionStream,\n new (format: string): DecompressionStream,\n};\n\nconst UIStrings = {\n /**\n *@description Document title in Inspector Frontend Host of the DevTools window\n *@example {example.com} PH1\n */\n devtoolsS: 'DevTools - {PH1}',\n};\nconst str_ = i18n.i18n.registerUIStrings('core/host/InspectorFrontendHost.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst MAX_RECORDED_HISTOGRAMS_SIZE = 100;\nconst OVERRIDES_FILE_SYSTEM_PATH = '/overrides' as Platform.DevToolsPath.RawPathString;\n\n/**\n * The InspectorFrontendHostStub is a stub interface used the frontend is loaded like a webpage. Examples:\n * - devtools://devtools/bundled/devtools_app.html\n * - https://chrome-devtools-frontend.appspot.com/serve_rev/@030cc140435b0152645522b9864b75cac6c0a854/worker_app.html\n * - http://localhost:9222/devtools/inspector.html?ws=localhost:9222/devtools/page/xTARGET_IDx\n *\n * When the frontend runs within the native embedder, then the InspectorFrontendHostAPI methods are provided\n * by devtools_compatibility.js. Those leverage `DevToolsAPI.sendMessageToEmbedder()` which match up with\n * the embedder API defined here: https://source.chromium.org/search?q=f:devtools%20f:dispatcher%20f:cc%20symbol:CreateForDevToolsFrontend&sq=&ss=chromium%2Fchromium%2Fsrc\n * The native implementations live in devtools_ui_bindings.cc: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/devtools/devtools_ui_bindings.cc\n */\nexport class InspectorFrontendHostStub implements InspectorFrontendHostAPI {\n readonly #urlsBeingSaved: Map;\n events!: Common.EventTarget.EventTarget;\n #fileSystem: FileSystem|null = null;\n\n recordedCountHistograms:\n {histogramName: string, sample: number, min: number, exclusiveMax: number, bucketSize: number}[] = [];\n recordedEnumeratedHistograms: {actionName: EnumeratedHistogram, actionCode: number}[] = [];\n recordedPerformanceHistograms: {histogramName: string, duration: number}[] = [];\n\n constructor() {\n this.#urlsBeingSaved = new Map();\n\n // Guard against errors should this file ever be imported at the top level\n // within a worker - in which case this constructor is run. If there's no\n // document, we can early exit.\n if (typeof document === 'undefined') {\n return;\n }\n\n function stopEventPropagation(this: InspectorFrontendHostAPI, event: KeyboardEvent): void {\n // Let browser handle Ctrl+/Ctrl- shortcuts in hosted mode.\n const zoomModifier = this.platform() === 'mac' ? event.metaKey : event.ctrlKey;\n if (zoomModifier && (event.key === '+' || event.key === '-')) {\n event.stopPropagation();\n }\n }\n\n document.addEventListener('keydown', event => {\n stopEventPropagation.call(this, (event as KeyboardEvent));\n }, true);\n }\n\n platform(): string {\n const userAgent = navigator.userAgent;\n if (userAgent.includes('Windows NT')) {\n return 'windows';\n }\n if (userAgent.includes('Mac OS X')) {\n return 'mac';\n }\n return 'linux';\n }\n\n loadCompleted(): void {\n }\n\n bringToFront(): void {\n }\n\n closeWindow(): void {\n }\n\n setIsDocked(isDocked: boolean, callback: () => void): void {\n window.setTimeout(callback, 0);\n }\n\n showSurvey(trigger: string, callback: (arg0: ShowSurveyResult) => void): void {\n window.setTimeout(() => callback({surveyShown: false}), 0);\n }\n\n canShowSurvey(trigger: string, callback: (arg0: CanShowSurveyResult) => void): void {\n window.setTimeout(() => callback({canShowSurvey: false}), 0);\n }\n\n /**\n * Requests inspected page to be placed atop of the inspector frontend with specified bounds.\n */\n setInspectedPageBounds(bounds: {\n x: number,\n y: number,\n width: number,\n height: number,\n }): void {\n }\n\n inspectElementCompleted(): void {\n }\n\n setInjectedScriptForOrigin(origin: string, script: string): void {\n }\n\n inspectedURLChanged(url: Platform.DevToolsPath.UrlString): void {\n document.title = i18nString(UIStrings.devtoolsS, {PH1: url.replace(/^https?:\\/\\//, '')});\n }\n\n copyText(text: string|null|undefined): void {\n if (text === undefined || text === null) {\n return;\n }\n void navigator.clipboard.writeText(text);\n }\n\n openInNewTab(url: Platform.DevToolsPath.UrlString): void {\n window.open(url, '_blank');\n }\n\n openSearchResultsInNewTab(query: string): void {\n Common.Console.Console.instance().error(\n 'Search is not enabled in hosted mode. Please inspect using chrome://inspect');\n }\n\n showItemInFolder(fileSystemPath: Platform.DevToolsPath.RawPathString): void {\n Common.Console.Console.instance().error(\n 'Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect');\n }\n\n save(\n url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string, forceSaveAs: boolean,\n isBase64: boolean): void {\n let buffer = this.#urlsBeingSaved.get(url);\n if (!buffer) {\n buffer = [];\n this.#urlsBeingSaved.set(url, buffer);\n }\n buffer.push(content);\n this.events.dispatchEventToListeners(Events.SavedURL, {url, fileSystemPath: url});\n }\n\n append(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string): void {\n const buffer = this.#urlsBeingSaved.get(url);\n if (buffer) {\n buffer.push(content);\n this.events.dispatchEventToListeners(Events.AppendedToURL, url);\n }\n }\n\n close(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString): void {\n const buffer = this.#urlsBeingSaved.get(url) || [];\n this.#urlsBeingSaved.delete(url);\n let fileName = '';\n\n if (url) {\n try {\n const trimmed = Platform.StringUtilities.trimURL(url);\n fileName = Platform.StringUtilities.removeURLFragment(trimmed);\n } catch (error) {\n // If url is not a valid URL, it is probably a filename.\n fileName = url;\n }\n }\n\n const link = document.createElement('a');\n link.download = fileName;\n const blob = new Blob([buffer.join('')], {type: 'text/plain'});\n const blobUrl = URL.createObjectURL(blob);\n link.href = blobUrl;\n link.click();\n URL.revokeObjectURL(blobUrl);\n }\n\n sendMessageToBackend(message: string): void {\n }\n\n recordCountHistogram(histogramName: string, sample: number, min: number, exclusiveMax: number, bucketSize: number):\n void {\n if (this.recordedCountHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {\n this.recordedCountHistograms.shift();\n }\n this.recordedCountHistograms.push({histogramName, sample, min, exclusiveMax, bucketSize});\n }\n\n recordEnumeratedHistogram(actionName: EnumeratedHistogram, actionCode: number, bucketSize: number): void {\n if (this.recordedEnumeratedHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {\n this.recordedEnumeratedHistograms.shift();\n }\n this.recordedEnumeratedHistograms.push({actionName, actionCode});\n }\n\n recordPerformanceHistogram(histogramName: string, duration: number): void {\n if (this.recordedPerformanceHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {\n this.recordedPerformanceHistograms.shift();\n }\n this.recordedPerformanceHistograms.push({histogramName, duration});\n }\n\n recordUserMetricsAction(umaName: string): void {\n }\n\n requestFileSystems(): void {\n this.events.dispatchEventToListeners(Events.FileSystemsLoaded, []);\n }\n\n addFileSystem(type?: string): void {\n const onFileSystem = (fs: FileSystem): void => {\n this.#fileSystem = fs;\n const fileSystem = {\n fileSystemName: 'sandboxedRequestedFileSystem',\n fileSystemPath: OVERRIDES_FILE_SYSTEM_PATH,\n rootURL: 'filesystem:devtools://devtools/isolated/',\n type: 'overrides',\n };\n this.events.dispatchEventToListeners(Events.FileSystemAdded, {fileSystem});\n };\n window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024, onFileSystem);\n }\n\n removeFileSystem(fileSystemPath: Platform.DevToolsPath.RawPathString): void {\n const removalCallback = (entries: Entry[]): void => {\n entries.forEach(entry => {\n if (entry.isDirectory) {\n (entry as DirectoryEntry).removeRecursively(() => {});\n } else if (entry.isFile) {\n entry.remove(() => {});\n }\n });\n };\n\n if (this.#fileSystem) {\n this.#fileSystem.root.createReader().readEntries(removalCallback);\n }\n\n this.#fileSystem = null;\n this.events.dispatchEventToListeners(Events.FileSystemRemoved, OVERRIDES_FILE_SYSTEM_PATH);\n }\n\n isolatedFileSystem(fileSystemId: string, registeredName: string): FileSystem|null {\n return this.#fileSystem;\n }\n\n loadNetworkResource(\n url: string, headers: string, streamId: number, callback: (arg0: LoadNetworkResourceResult) => void): void {\n // Read the first 3 bytes looking for the gzip signature in the file header\n function isGzip(ab: ArrayBuffer): boolean {\n const buf = new Uint8Array(ab);\n if (!buf || buf.length < 3) {\n return false;\n }\n\n // https://www.rfc-editor.org/rfc/rfc1952#page-6\n return buf[0] === 0x1F && buf[1] === 0x8B && buf[2] === 0x08;\n }\n fetch(url)\n .then(async result => {\n const resultArrayBuf = await result.arrayBuffer();\n let decoded: ReadableStream|ArrayBuffer = resultArrayBuf;\n if (isGzip(resultArrayBuf)) {\n const ds = new DecompressionStream('gzip');\n const writer = ds.writable.getWriter();\n void writer.write(resultArrayBuf);\n void writer.close();\n decoded = ds.readable;\n }\n const text = await new Response(decoded).text();\n return text;\n })\n .then(function(text) {\n resourceLoaderStreamWrite(streamId, text);\n callback({\n statusCode: 200,\n headers: undefined,\n messageOverride: undefined,\n netError: undefined,\n netErrorName: undefined,\n urlValid: undefined,\n });\n })\n .catch(function() {\n callback({\n statusCode: 404,\n headers: undefined,\n messageOverride: undefined,\n netError: undefined,\n netErrorName: undefined,\n urlValid: undefined,\n });\n });\n }\n\n registerPreference(name: string, options: {synced?: boolean}): void {\n }\n\n getPreferences(callback: (arg0: {\n [x: string]: string,\n }) => void): void {\n const prefs: {\n [x: string]: string,\n } = {};\n for (const name in window.localStorage) {\n prefs[name] = window.localStorage[name];\n }\n callback(prefs);\n }\n\n getPreference(name: string, callback: (arg0: string) => void): void {\n callback(window.localStorage[name]);\n }\n\n setPreference(name: string, value: string): void {\n window.localStorage[name] = value;\n }\n\n removePreference(name: string): void {\n delete window.localStorage[name];\n }\n\n clearPreferences(): void {\n window.localStorage.clear();\n }\n\n getSyncInformation(callback: (arg0: SyncInformation) => void): void {\n if ('getSyncInformationForTesting' in globalThis) {\n // @ts-ignore for testing\n return callback(globalThis.getSyncInformationForTesting());\n }\n callback({\n isSyncActive: false,\n arePreferencesSynced: false,\n });\n }\n\n getHostConfig(callback: (arg0: Root.Runtime.HostConfig) => void): void {\n const result: Root.Runtime.HostConfig = {\n aidaAvailability: {\n enabled: true,\n blockedByAge: false,\n blockedByEnterprisePolicy: false,\n blockedByGeo: false,\n disallowLogging: true,\n },\n devToolsConsoleInsights: {\n modelId: '',\n temperature: -1,\n enabled: false,\n },\n devToolsFreestyler: {\n modelId: '',\n temperature: -1,\n enabled: false,\n },\n devToolsVeLogging: {\n enabled: true,\n testing: false,\n },\n devToolsPrivacyUI: {\n enabled: false,\n },\n isOffTheRecord: false,\n };\n if ('hostConfigForTesting' in globalThis) {\n const {hostConfigForTesting} = (globalThis as unknown as {hostConfigForTesting: Root.Runtime.HostConfig});\n for (const key of Object.keys(hostConfigForTesting)) {\n const mergeEntry = (key: K): void => {\n if (typeof result[key] === 'object' && typeof hostConfigForTesting[key] === 'object') {\n // If the config is an object, merge the settings, but preferring\n // the hostConfigForTesting values over the result values.\n result[key] = {...result[key], ...hostConfigForTesting[key]};\n } else {\n // Override with the testing config if the value is present + not null/undefined.\n result[key] = hostConfigForTesting[key] ?? result[key];\n }\n };\n mergeEntry(key as keyof Root.Runtime.HostConfig);\n }\n }\n callback(result);\n }\n\n upgradeDraggedFileSystemPermissions(fileSystem: FileSystem): void {\n }\n\n indexPath(requestId: number, fileSystemPath: Platform.DevToolsPath.RawPathString, excludedFolders: string): void {\n }\n\n stopIndexing(requestId: number): void {\n }\n\n searchInPath(requestId: number, fileSystemPath: Platform.DevToolsPath.RawPathString, query: string): void {\n }\n\n zoomFactor(): number {\n return 1;\n }\n\n zoomIn(): void {\n }\n\n zoomOut(): void {\n }\n\n resetZoom(): void {\n }\n\n setWhitelistedShortcuts(shortcuts: string): void {\n }\n\n setEyeDropperActive(active: boolean): void {\n }\n\n showCertificateViewer(certChain: string[]): void {\n }\n\n reattach(callback: () => void): void {\n }\n\n readyForTest(): void {\n }\n\n connectionReady(): void {\n }\n\n setOpenNewWindowForPopups(value: boolean): void {\n }\n\n setDevicesDiscoveryConfig(config: Adb.Config): void {\n }\n\n setDevicesUpdatesEnabled(enabled: boolean): void {\n }\n\n performActionOnRemotePage(pageId: string, action: string): void {\n }\n\n openRemotePage(browserId: string, url: string): void {\n }\n\n openNodeFrontend(): void {\n }\n\n showContextMenuAtPoint(x: number, y: number, items: ContextMenuDescriptor[], document: Document): void {\n throw 'Soft context menu should be used';\n }\n\n isHostedMode(): boolean {\n return true;\n }\n\n setAddExtensionCallback(callback: (arg0: ExtensionDescriptor) => void): void {\n // Extensions are not supported in hosted mode.\n }\n\n async initialTargetId(): Promise {\n return null;\n }\n\n doAidaConversation(request: string, streamId: number, callback: (result: DoAidaConversationResult) => void): void {\n callback({\n error: 'Not implemented',\n });\n }\n\n registerAidaClientEvent(request: string, callback: (result: AidaClientResult) => void): void {\n callback({\n error: 'Not implemented',\n });\n }\n\n recordImpression(event: ImpressionEvent): void {\n }\n recordResize(event: ResizeEvent): void {\n }\n recordClick(event: ClickEvent): void {\n }\n recordHover(event: HoverEvent): void {\n }\n recordDrag(event: DragEvent): void {\n }\n recordChange(event: ChangeEvent): void {\n }\n recordKeyDown(event: KeyDownEvent): void {\n }\n}\n\n// @ts-ignore Global injected by devtools-compatibility.js\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport let InspectorFrontendHostInstance: InspectorFrontendHostStub = globalThis.InspectorFrontendHost;\n\nclass InspectorFrontendAPIImpl {\n constructor() {\n for (const descriptor of EventDescriptors) {\n // @ts-ignore Dispatcher magic\n this[descriptor[1]] = this.dispatch.bind(this, descriptor[0], descriptor[2], descriptor[3]);\n }\n }\n\n private dispatch(name: symbol, signature: string[], runOnceLoaded: boolean, ...params: string[]): void {\n // Single argument methods get dispatched with the param.\n if (signature.length < 2) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n InspectorFrontendHostInstance.events.dispatchEventToListeners(name, params[0]);\n } catch (error) {\n console.error(error + ' ' + error.stack);\n }\n return;\n }\n const data: {\n [x: string]: string,\n } = {};\n for (let i = 0; i < signature.length; ++i) {\n data[signature[i]] = params[i];\n }\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n InspectorFrontendHostInstance.events.dispatchEventToListeners(name, data);\n } catch (error) {\n console.error(error + ' ' + error.stack);\n }\n }\n\n streamWrite(id: number, chunk: string): void {\n resourceLoaderStreamWrite(id, chunk);\n }\n}\n\n(function(): void {\n\nfunction initializeInspectorFrontendHost(): void {\n let proto;\n if (!InspectorFrontendHostInstance) {\n // Instantiate stub for web-hosted mode if necessary.\n // @ts-ignore Global injected by devtools-compatibility.js\n globalThis.InspectorFrontendHost = InspectorFrontendHostInstance = new InspectorFrontendHostStub();\n } else {\n // Otherwise add stubs for missing methods that are declared in the interface.\n proto = InspectorFrontendHostStub.prototype;\n for (const name of Object.getOwnPropertyNames(proto)) {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n // @ts-expect-error\n const stub = proto[name];\n // @ts-ignore Global injected by devtools-compatibility.js\n if (typeof stub !== 'function' || InspectorFrontendHostInstance[name]) {\n continue;\n }\n\n console.error(`Incompatible embedder: method Host.InspectorFrontendHost.${name} is missing. Using stub instead.`);\n // @ts-ignore Global injected by devtools-compatibility.js\n InspectorFrontendHostInstance[name] = stub;\n }\n }\n\n // Attach the events object.\n InspectorFrontendHostInstance.events = new Common.ObjectWrapper.ObjectWrapper();\n}\n\n// FIXME: This file is included into both apps, since the devtools_app needs the InspectorFrontendHostAPI only,\n// so the host instance should not be initialized there.\ninitializeInspectorFrontendHost();\n// @ts-ignore Global injected by devtools-compatibility.js\nglobalThis.InspectorFrontendAPI = new InspectorFrontendAPIImpl();\n})();\n\nexport function isUnderTest(prefs?: {\n [x: string]: string,\n}): boolean {\n // Integration tests rely on test queryParam.\n if (Root.Runtime.Runtime.queryParam('test')) {\n return true;\n }\n // Browser tests rely on prefs.\n if (prefs) {\n return prefs['isUnderTest'] === 'true';\n }\n return Common.Settings.Settings.hasInstance() &&\n Common.Settings.Settings.instance().createSetting('isUnderTest', false).get();\n}\n"]} \ No newline at end of file +{"version":3,"file":"InspectorFrontendHost.js","sourceRoot":"","sources":["../../../../../../front_end/core/host/InspectorFrontendHost.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\n// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport * as Common from '../common/common.js';\nimport * as i18n from '../i18n/i18n.js';\nimport * as Platform from '../platform/platform.js';\nimport * as Root from '../root/root.js';\n\nimport {\n type AidaClientResult,\n type CanShowSurveyResult,\n type ChangeEvent,\n type ClickEvent,\n type ContextMenuDescriptor,\n type DoAidaConversationResult,\n type DragEvent,\n type EnumeratedHistogram,\n EventDescriptors,\n Events,\n type EventTypes,\n type ExtensionDescriptor,\n type HoverEvent,\n type ImpressionEvent,\n type InspectorFrontendHostAPI,\n type KeyDownEvent,\n type LoadNetworkResourceResult,\n type ResizeEvent,\n type ShowSurveyResult,\n type SyncInformation,\n} from './InspectorFrontendHostAPI.js';\nimport {streamWrite as resourceLoaderStreamWrite} from './ResourceLoader.js';\n\ninterface DecompressionStream extends GenericTransformStream {\n readonly format: string;\n}\ndeclare const DecompressionStream: {\n prototype: DecompressionStream,\n new (format: string): DecompressionStream,\n};\n\nconst UIStrings = {\n /**\n *@description Document title in Inspector Frontend Host of the DevTools window\n *@example {example.com} PH1\n */\n devtoolsS: 'DevTools - {PH1}',\n};\nconst str_ = i18n.i18n.registerUIStrings('core/host/InspectorFrontendHost.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst MAX_RECORDED_HISTOGRAMS_SIZE = 100;\nconst OVERRIDES_FILE_SYSTEM_PATH = '/overrides' as Platform.DevToolsPath.RawPathString;\n\n/**\n * The InspectorFrontendHostStub is a stub interface used the frontend is loaded like a webpage. Examples:\n * - devtools://devtools/bundled/devtools_app.html\n * - https://chrome-devtools-frontend.appspot.com/serve_rev/@030cc140435b0152645522b9864b75cac6c0a854/worker_app.html\n * - http://localhost:9222/devtools/inspector.html?ws=localhost:9222/devtools/page/xTARGET_IDx\n *\n * When the frontend runs within the native embedder, then the InspectorFrontendHostAPI methods are provided\n * by devtools_compatibility.js. Those leverage `DevToolsAPI.sendMessageToEmbedder()` which match up with\n * the embedder API defined here: https://source.chromium.org/search?q=f:devtools%20f:dispatcher%20f:cc%20symbol:CreateForDevToolsFrontend&sq=&ss=chromium%2Fchromium%2Fsrc\n * The native implementations live in devtools_ui_bindings.cc: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/devtools/devtools_ui_bindings.cc\n */\nexport class InspectorFrontendHostStub implements InspectorFrontendHostAPI {\n readonly #urlsBeingSaved: Map;\n events!: Common.EventTarget.EventTarget;\n #fileSystem: FileSystem|null = null;\n\n recordedCountHistograms:\n {histogramName: string, sample: number, min: number, exclusiveMax: number, bucketSize: number}[] = [];\n recordedEnumeratedHistograms: {actionName: EnumeratedHistogram, actionCode: number}[] = [];\n recordedPerformanceHistograms: {histogramName: string, duration: number}[] = [];\n\n constructor() {\n this.#urlsBeingSaved = new Map();\n\n // Guard against errors should this file ever be imported at the top level\n // within a worker - in which case this constructor is run. If there's no\n // document, we can early exit.\n if (typeof document === 'undefined') {\n return;\n }\n\n function stopEventPropagation(this: InspectorFrontendHostAPI, event: KeyboardEvent): void {\n // Let browser handle Ctrl+/Ctrl- shortcuts in hosted mode.\n const zoomModifier = this.platform() === 'mac' ? event.metaKey : event.ctrlKey;\n if (zoomModifier && (event.key === '+' || event.key === '-')) {\n event.stopPropagation();\n }\n }\n\n document.addEventListener('keydown', event => {\n stopEventPropagation.call(this, (event as KeyboardEvent));\n }, true);\n }\n\n platform(): string {\n const userAgent = navigator.userAgent;\n if (userAgent.includes('Windows NT')) {\n return 'windows';\n }\n if (userAgent.includes('Mac OS X')) {\n return 'mac';\n }\n return 'linux';\n }\n\n loadCompleted(): void {\n }\n\n bringToFront(): void {\n }\n\n closeWindow(): void {\n }\n\n setIsDocked(isDocked: boolean, callback: () => void): void {\n window.setTimeout(callback, 0);\n }\n\n showSurvey(trigger: string, callback: (arg0: ShowSurveyResult) => void): void {\n window.setTimeout(() => callback({surveyShown: false}), 0);\n }\n\n canShowSurvey(trigger: string, callback: (arg0: CanShowSurveyResult) => void): void {\n window.setTimeout(() => callback({canShowSurvey: false}), 0);\n }\n\n /**\n * Requests inspected page to be placed atop of the inspector frontend with specified bounds.\n */\n setInspectedPageBounds(bounds: {\n x: number,\n y: number,\n width: number,\n height: number,\n }): void {\n }\n\n inspectElementCompleted(): void {\n }\n\n setInjectedScriptForOrigin(origin: string, script: string): void {\n }\n\n inspectedURLChanged(url: Platform.DevToolsPath.UrlString): void {\n document.title = i18nString(UIStrings.devtoolsS, {PH1: url.replace(/^https?:\\/\\//, '')});\n }\n\n copyText(text: string|null|undefined): void {\n if (text === undefined || text === null) {\n return;\n }\n void navigator.clipboard.writeText(text);\n }\n\n openInNewTab(url: Platform.DevToolsPath.UrlString): void {\n window.open(url, '_blank');\n }\n\n openSearchResultsInNewTab(query: string): void {\n Common.Console.Console.instance().error(\n 'Search is not enabled in hosted mode. Please inspect using chrome://inspect');\n }\n\n showItemInFolder(fileSystemPath: Platform.DevToolsPath.RawPathString): void {\n Common.Console.Console.instance().error(\n 'Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect');\n }\n\n save(\n url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string, forceSaveAs: boolean,\n isBase64: boolean): void {\n let buffer = this.#urlsBeingSaved.get(url);\n if (!buffer) {\n buffer = [];\n this.#urlsBeingSaved.set(url, buffer);\n }\n buffer.push(content);\n this.events.dispatchEventToListeners(Events.SavedURL, {url, fileSystemPath: url});\n }\n\n append(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string): void {\n const buffer = this.#urlsBeingSaved.get(url);\n if (buffer) {\n buffer.push(content);\n this.events.dispatchEventToListeners(Events.AppendedToURL, url);\n }\n }\n\n close(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString): void {\n const buffer = this.#urlsBeingSaved.get(url) || [];\n this.#urlsBeingSaved.delete(url);\n let fileName = '';\n\n if (url) {\n try {\n const trimmed = Platform.StringUtilities.trimURL(url);\n fileName = Platform.StringUtilities.removeURLFragment(trimmed);\n } catch (error) {\n // If url is not a valid URL, it is probably a filename.\n fileName = url;\n }\n }\n\n const link = document.createElement('a');\n link.download = fileName;\n const blob = new Blob([buffer.join('')], {type: 'text/plain'});\n const blobUrl = URL.createObjectURL(blob);\n link.href = blobUrl;\n link.click();\n URL.revokeObjectURL(blobUrl);\n }\n\n sendMessageToBackend(message: string): void {\n }\n\n recordCountHistogram(histogramName: string, sample: number, min: number, exclusiveMax: number, bucketSize: number):\n void {\n if (this.recordedCountHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {\n this.recordedCountHistograms.shift();\n }\n this.recordedCountHistograms.push({histogramName, sample, min, exclusiveMax, bucketSize});\n }\n\n recordEnumeratedHistogram(actionName: EnumeratedHistogram, actionCode: number, bucketSize: number): void {\n if (this.recordedEnumeratedHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {\n this.recordedEnumeratedHistograms.shift();\n }\n this.recordedEnumeratedHistograms.push({actionName, actionCode});\n }\n\n recordPerformanceHistogram(histogramName: string, duration: number): void {\n if (this.recordedPerformanceHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {\n this.recordedPerformanceHistograms.shift();\n }\n this.recordedPerformanceHistograms.push({histogramName, duration});\n }\n\n recordUserMetricsAction(umaName: string): void {\n }\n\n requestFileSystems(): void {\n this.events.dispatchEventToListeners(Events.FileSystemsLoaded, []);\n }\n\n addFileSystem(type?: string): void {\n const onFileSystem = (fs: FileSystem): void => {\n this.#fileSystem = fs;\n const fileSystem = {\n fileSystemName: 'sandboxedRequestedFileSystem',\n fileSystemPath: OVERRIDES_FILE_SYSTEM_PATH,\n rootURL: 'filesystem:devtools://devtools/isolated/',\n type: 'overrides',\n };\n this.events.dispatchEventToListeners(Events.FileSystemAdded, {fileSystem});\n };\n window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024, onFileSystem);\n }\n\n removeFileSystem(fileSystemPath: Platform.DevToolsPath.RawPathString): void {\n const removalCallback = (entries: Entry[]): void => {\n entries.forEach(entry => {\n if (entry.isDirectory) {\n (entry as DirectoryEntry).removeRecursively(() => {});\n } else if (entry.isFile) {\n entry.remove(() => {});\n }\n });\n };\n\n if (this.#fileSystem) {\n this.#fileSystem.root.createReader().readEntries(removalCallback);\n }\n\n this.#fileSystem = null;\n this.events.dispatchEventToListeners(Events.FileSystemRemoved, OVERRIDES_FILE_SYSTEM_PATH);\n }\n\n isolatedFileSystem(fileSystemId: string, registeredName: string): FileSystem|null {\n return this.#fileSystem;\n }\n\n loadNetworkResource(\n url: string, headers: string, streamId: number, callback: (arg0: LoadNetworkResourceResult) => void): void {\n // Read the first 3 bytes looking for the gzip signature in the file header\n function isGzip(ab: ArrayBuffer): boolean {\n const buf = new Uint8Array(ab);\n if (!buf || buf.length < 3) {\n return false;\n }\n\n // https://www.rfc-editor.org/rfc/rfc1952#page-6\n return buf[0] === 0x1F && buf[1] === 0x8B && buf[2] === 0x08;\n }\n fetch(url)\n .then(async result => {\n const resultArrayBuf = await result.arrayBuffer();\n let decoded: ReadableStream|ArrayBuffer = resultArrayBuf;\n if (isGzip(resultArrayBuf)) {\n const ds = new DecompressionStream('gzip');\n const writer = ds.writable.getWriter();\n void writer.write(resultArrayBuf);\n void writer.close();\n decoded = ds.readable;\n }\n const text = await new Response(decoded).text();\n return text;\n })\n .then(function(text) {\n resourceLoaderStreamWrite(streamId, text);\n callback({\n statusCode: 200,\n headers: undefined,\n messageOverride: undefined,\n netError: undefined,\n netErrorName: undefined,\n urlValid: undefined,\n });\n })\n .catch(function() {\n callback({\n statusCode: 404,\n headers: undefined,\n messageOverride: undefined,\n netError: undefined,\n netErrorName: undefined,\n urlValid: undefined,\n });\n });\n }\n\n registerPreference(name: string, options: {synced?: boolean}): void {\n }\n\n getPreferences(callback: (arg0: {\n [x: string]: string,\n }) => void): void {\n const prefs: {\n [x: string]: string,\n } = {};\n for (const name in window.localStorage) {\n prefs[name] = window.localStorage[name];\n }\n callback(prefs);\n }\n\n getPreference(name: string, callback: (arg0: string) => void): void {\n callback(window.localStorage[name]);\n }\n\n setPreference(name: string, value: string): void {\n window.localStorage[name] = value;\n }\n\n removePreference(name: string): void {\n delete window.localStorage[name];\n }\n\n clearPreferences(): void {\n window.localStorage.clear();\n }\n\n getSyncInformation(callback: (arg0: SyncInformation) => void): void {\n if ('getSyncInformationForTesting' in globalThis) {\n // @ts-ignore for testing\n return callback(globalThis.getSyncInformationForTesting());\n }\n callback({\n isSyncActive: false,\n arePreferencesSynced: false,\n });\n }\n\n getHostConfig(callback: (arg0: Root.Runtime.HostConfig) => void): void {\n const result: Root.Runtime.HostConfig = {\n aidaAvailability: {\n enabled: true,\n blockedByAge: false,\n blockedByEnterprisePolicy: false,\n blockedByGeo: false,\n disallowLogging: true,\n },\n devToolsConsoleInsights: {\n modelId: '',\n temperature: -1,\n enabled: false,\n },\n devToolsFreestyler: {\n modelId: '',\n temperature: -1,\n enabled: false,\n },\n devToolsVeLogging: {\n enabled: true,\n testing: false,\n },\n devToolsPrivacyUI: {\n enabled: false,\n },\n devToolsEnableOriginBoundCookies: {\n portBindingEnabled: false,\n schemeBindingEnabled: false,\n },\n isOffTheRecord: false,\n };\n if ('hostConfigForTesting' in globalThis) {\n const {hostConfigForTesting} = (globalThis as unknown as {hostConfigForTesting: Root.Runtime.HostConfig});\n for (const key of Object.keys(hostConfigForTesting)) {\n const mergeEntry = (key: K): void => {\n if (typeof result[key] === 'object' && typeof hostConfigForTesting[key] === 'object') {\n // If the config is an object, merge the settings, but preferring\n // the hostConfigForTesting values over the result values.\n result[key] = {...result[key], ...hostConfigForTesting[key]};\n } else {\n // Override with the testing config if the value is present + not null/undefined.\n result[key] = hostConfigForTesting[key] ?? result[key];\n }\n };\n mergeEntry(key as keyof Root.Runtime.HostConfig);\n }\n }\n callback(result);\n }\n\n upgradeDraggedFileSystemPermissions(fileSystem: FileSystem): void {\n }\n\n indexPath(requestId: number, fileSystemPath: Platform.DevToolsPath.RawPathString, excludedFolders: string): void {\n }\n\n stopIndexing(requestId: number): void {\n }\n\n searchInPath(requestId: number, fileSystemPath: Platform.DevToolsPath.RawPathString, query: string): void {\n }\n\n zoomFactor(): number {\n return 1;\n }\n\n zoomIn(): void {\n }\n\n zoomOut(): void {\n }\n\n resetZoom(): void {\n }\n\n setWhitelistedShortcuts(shortcuts: string): void {\n }\n\n setEyeDropperActive(active: boolean): void {\n }\n\n showCertificateViewer(certChain: string[]): void {\n }\n\n reattach(callback: () => void): void {\n }\n\n readyForTest(): void {\n }\n\n connectionReady(): void {\n }\n\n setOpenNewWindowForPopups(value: boolean): void {\n }\n\n setDevicesDiscoveryConfig(config: Adb.Config): void {\n }\n\n setDevicesUpdatesEnabled(enabled: boolean): void {\n }\n\n performActionOnRemotePage(pageId: string, action: string): void {\n }\n\n openRemotePage(browserId: string, url: string): void {\n }\n\n openNodeFrontend(): void {\n }\n\n showContextMenuAtPoint(x: number, y: number, items: ContextMenuDescriptor[], document: Document): void {\n throw 'Soft context menu should be used';\n }\n\n isHostedMode(): boolean {\n return true;\n }\n\n setAddExtensionCallback(callback: (arg0: ExtensionDescriptor) => void): void {\n // Extensions are not supported in hosted mode.\n }\n\n async initialTargetId(): Promise {\n return null;\n }\n\n doAidaConversation(request: string, streamId: number, callback: (result: DoAidaConversationResult) => void): void {\n callback({\n error: 'Not implemented',\n });\n }\n\n registerAidaClientEvent(request: string, callback: (result: AidaClientResult) => void): void {\n callback({\n error: 'Not implemented',\n });\n }\n\n recordImpression(event: ImpressionEvent): void {\n }\n recordResize(event: ResizeEvent): void {\n }\n recordClick(event: ClickEvent): void {\n }\n recordHover(event: HoverEvent): void {\n }\n recordDrag(event: DragEvent): void {\n }\n recordChange(event: ChangeEvent): void {\n }\n recordKeyDown(event: KeyDownEvent): void {\n }\n}\n\n// @ts-ignore Global injected by devtools-compatibility.js\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport let InspectorFrontendHostInstance: InspectorFrontendHostStub = globalThis.InspectorFrontendHost;\n\nclass InspectorFrontendAPIImpl {\n constructor() {\n for (const descriptor of EventDescriptors) {\n // @ts-ignore Dispatcher magic\n this[descriptor[1]] = this.dispatch.bind(this, descriptor[0], descriptor[2], descriptor[3]);\n }\n }\n\n private dispatch(name: symbol, signature: string[], runOnceLoaded: boolean, ...params: string[]): void {\n // Single argument methods get dispatched with the param.\n if (signature.length < 2) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n InspectorFrontendHostInstance.events.dispatchEventToListeners(name, params[0]);\n } catch (error) {\n console.error(error + ' ' + error.stack);\n }\n return;\n }\n const data: {\n [x: string]: string,\n } = {};\n for (let i = 0; i < signature.length; ++i) {\n data[signature[i]] = params[i];\n }\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n InspectorFrontendHostInstance.events.dispatchEventToListeners(name, data);\n } catch (error) {\n console.error(error + ' ' + error.stack);\n }\n }\n\n streamWrite(id: number, chunk: string): void {\n resourceLoaderStreamWrite(id, chunk);\n }\n}\n\n(function(): void {\n\nfunction initializeInspectorFrontendHost(): void {\n let proto;\n if (!InspectorFrontendHostInstance) {\n // Instantiate stub for web-hosted mode if necessary.\n // @ts-ignore Global injected by devtools-compatibility.js\n globalThis.InspectorFrontendHost = InspectorFrontendHostInstance = new InspectorFrontendHostStub();\n } else {\n // Otherwise add stubs for missing methods that are declared in the interface.\n proto = InspectorFrontendHostStub.prototype;\n for (const name of Object.getOwnPropertyNames(proto)) {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n // @ts-expect-error\n const stub = proto[name];\n // @ts-ignore Global injected by devtools-compatibility.js\n if (typeof stub !== 'function' || InspectorFrontendHostInstance[name]) {\n continue;\n }\n\n console.error(`Incompatible embedder: method Host.InspectorFrontendHost.${name} is missing. Using stub instead.`);\n // @ts-ignore Global injected by devtools-compatibility.js\n InspectorFrontendHostInstance[name] = stub;\n }\n }\n\n // Attach the events object.\n InspectorFrontendHostInstance.events = new Common.ObjectWrapper.ObjectWrapper();\n}\n\n// FIXME: This file is included into both apps, since the devtools_app needs the InspectorFrontendHostAPI only,\n// so the host instance should not be initialized there.\ninitializeInspectorFrontendHost();\n// @ts-ignore Global injected by devtools-compatibility.js\nglobalThis.InspectorFrontendAPI = new InspectorFrontendAPIImpl();\n})();\n\nexport function isUnderTest(prefs?: {\n [x: string]: string,\n}): boolean {\n // Integration tests rely on test queryParam.\n if (Root.Runtime.Runtime.queryParam('test')) {\n return true;\n }\n // Browser tests rely on prefs.\n if (prefs) {\n return prefs['isUnderTest'] === 'true';\n }\n return Common.Settings.Settings.hasInstance() &&\n Common.Settings.Settings.instance().createSetting('isUnderTest', false).get();\n}\n"]} \ No newline at end of file diff --git a/public/core/i18n/ByteUtilities.d.ts b/public/core/i18n/ByteUtilities.d.ts new file mode 100644 index 00000000..922a4e3b --- /dev/null +++ b/public/core/i18n/ByteUtilities.d.ts @@ -0,0 +1 @@ +export declare const bytesToString: (bytes: number) => string; diff --git a/public/core/i18n/ByteUtilities.js b/public/core/i18n/ByteUtilities.js new file mode 100644 index 00000000..0b123862 --- /dev/null +++ b/public/core/i18n/ByteUtilities.js @@ -0,0 +1,57 @@ +// 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 { defineFormatter } from './NumberFormatter.js'; +const narrowBytes = defineFormatter({ + style: 'unit', + unit: 'byte', + unitDisplay: 'narrow', + minimumFractionDigits: 0, + maximumFractionDigits: 0, +}); +const narrowKilobytesDecimal = defineFormatter({ + style: 'unit', + unit: 'kilobyte', + unitDisplay: 'narrow', + minimumFractionDigits: 1, + maximumFractionDigits: 1, +}); +const narrowKilobytesInteger = defineFormatter({ + style: 'unit', + unit: 'kilobyte', + unitDisplay: 'narrow', + minimumFractionDigits: 0, + maximumFractionDigits: 0, +}); +const narrowMegabytesDecimal = defineFormatter({ + style: 'unit', + unit: 'megabyte', + unitDisplay: 'narrow', + minimumFractionDigits: 1, + maximumFractionDigits: 1, +}); +const narrowMegabytesInteger = defineFormatter({ + style: 'unit', + unit: 'megabyte', + unitDisplay: 'narrow', + minimumFractionDigits: 0, + maximumFractionDigits: 0, +}); +export const bytesToString = (bytes) => { + if (bytes < 1000) { + return narrowBytes.format(bytes); + } + const kilobytes = bytes / 1000; + if (kilobytes < 100) { + return narrowKilobytesDecimal.format(kilobytes); + } + if (kilobytes < 1000) { + return narrowKilobytesInteger.format(kilobytes); + } + const megabytes = kilobytes / 1000; + if (megabytes < 100) { + return narrowMegabytesDecimal.format(megabytes); + } + return narrowMegabytesInteger.format(megabytes); +}; +//# sourceMappingURL=ByteUtilities.js.map \ No newline at end of file diff --git a/public/core/i18n/ByteUtilities.js.map b/public/core/i18n/ByteUtilities.js.map new file mode 100644 index 00000000..3c88d513 --- /dev/null +++ b/public/core/i18n/ByteUtilities.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ByteUtilities.js","sourceRoot":"","sources":["../../../../../../front_end/core/i18n/ByteUtilities.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,GAAG,eAAe,CAAC;IAClC,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,QAAQ;IACrB,qBAAqB,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,eAAe,CAAC;IAC7C,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,QAAQ;IACrB,qBAAqB,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,eAAe,CAAC;IAC7C,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,QAAQ;IACrB,qBAAqB,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,eAAe,CAAC;IAC7C,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,QAAQ;IACrB,qBAAqB,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,eAAe,CAAC;IAC7C,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,QAAQ;IACrB,qBAAqB,EAAE,CAAC;IACxB,qBAAqB,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAa,EAAU,EAAE;IACrD,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;QACjB,OAAO,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,GAAG,IAAI,CAAC;IAC/B,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;QACpB,OAAO,sBAAsB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,SAAS,GAAG,IAAI,EAAE,CAAC;QACrB,OAAO,sBAAsB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IACnC,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;QACpB,OAAO,sBAAsB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,sBAAsB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAClD,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 {defineFormatter} from './NumberFormatter.js';\n\nconst narrowBytes = defineFormatter({\n style: 'unit',\n unit: 'byte',\n unitDisplay: 'narrow',\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n});\n\nconst narrowKilobytesDecimal = defineFormatter({\n style: 'unit',\n unit: 'kilobyte',\n unitDisplay: 'narrow',\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n});\n\nconst narrowKilobytesInteger = defineFormatter({\n style: 'unit',\n unit: 'kilobyte',\n unitDisplay: 'narrow',\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n});\n\nconst narrowMegabytesDecimal = defineFormatter({\n style: 'unit',\n unit: 'megabyte',\n unitDisplay: 'narrow',\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n});\n\nconst narrowMegabytesInteger = defineFormatter({\n style: 'unit',\n unit: 'megabyte',\n unitDisplay: 'narrow',\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n});\n\nexport const bytesToString = (bytes: number): string => {\n if (bytes < 1000) {\n return narrowBytes.format(bytes);\n }\n\n const kilobytes = bytes / 1000;\n if (kilobytes < 100) {\n return narrowKilobytesDecimal.format(kilobytes);\n }\n if (kilobytes < 1000) {\n return narrowKilobytesInteger.format(kilobytes);\n }\n\n const megabytes = kilobytes / 1000;\n if (megabytes < 100) {\n return narrowMegabytesDecimal.format(megabytes);\n }\n return narrowMegabytesInteger.format(megabytes);\n};\n"]} \ No newline at end of file diff --git a/public/core/i18n/ByteUtilities.test.d.ts b/public/core/i18n/ByteUtilities.test.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/public/core/i18n/ByteUtilities.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/public/core/i18n/ByteUtilities.test.js b/public/core/i18n/ByteUtilities.test.js new file mode 100644 index 00000000..57f88a1e --- /dev/null +++ b/public/core/i18n/ByteUtilities.test.js @@ -0,0 +1,28 @@ +// 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 { describeWithLocale } from '../../testing/EnvironmentHelpers.js'; +import * as i18n from './i18n.js'; +describeWithLocale('ByteUtilities', () => { + describe('bytesToString', () => { + it('formats for < 1000 bytes', () => { + assert.deepEqual(i18n.ByteUtilities.bytesToString(50), '50\xA0B'); + }); + it('formats for < 100 kilobytes', () => { + assert.deepEqual(i18n.ByteUtilities.bytesToString(5 * 1000), '5.0\xA0kB'); + }); + it('formats for < 1000 kilobytes', () => { + assert.deepEqual(i18n.ByteUtilities.bytesToString(500 * 1000), '500\xA0kB'); + }); + it('formats for < 100 megabytes', () => { + const oneAndAHalfMegabytes = 1500 * 1000; + assert.deepEqual(i18n.ByteUtilities.bytesToString(oneAndAHalfMegabytes), '1.5\xA0MB'); + }); + it('formats for > 100 megabytes', () => { + const oneMegabyte = 1000 * 1000; + const twoHundredAndTenMegabytes = oneMegabyte * 210; + assert.deepEqual(i18n.ByteUtilities.bytesToString(twoHundredAndTenMegabytes), '210\xA0MB'); + }); + }); +}); +//# sourceMappingURL=ByteUtilities.test.js.map \ No newline at end of file diff --git a/public/core/i18n/ByteUtilities.test.js.map b/public/core/i18n/ByteUtilities.test.js.map new file mode 100644 index 00000000..e9f25711 --- /dev/null +++ b/public/core/i18n/ByteUtilities.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ByteUtilities.test.js","sourceRoot":"","sources":["../../../../../../front_end/core/i18n/ByteUtilities.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,kBAAkB,EAAC,MAAM,qCAAqC,CAAC;AAEvE,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,kBAAkB,CAAC,eAAe,EAAE,GAAG,EAAE;IACvC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAAC;YACzC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,WAAW,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;YAChC,MAAM,yBAAyB,GAAG,WAAW,GAAG,GAAG,CAAC;YACpD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,yBAAyB,CAAC,EAAE,WAAW,CAAC,CAAC;QAC7F,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 {describeWithLocale} from '../../testing/EnvironmentHelpers.js';\n\nimport * as i18n from './i18n.js';\n\ndescribeWithLocale('ByteUtilities', () => {\n describe('bytesToString', () => {\n it('formats for < 1000 bytes', () => {\n assert.deepEqual(i18n.ByteUtilities.bytesToString(50), '50\\xA0B');\n });\n\n it('formats for < 100 kilobytes', () => {\n assert.deepEqual(i18n.ByteUtilities.bytesToString(5 * 1000), '5.0\\xA0kB');\n });\n\n it('formats for < 1000 kilobytes', () => {\n assert.deepEqual(i18n.ByteUtilities.bytesToString(500 * 1000), '500\\xA0kB');\n });\n\n it('formats for < 100 megabytes', () => {\n const oneAndAHalfMegabytes = 1500 * 1000;\n assert.deepEqual(i18n.ByteUtilities.bytesToString(oneAndAHalfMegabytes), '1.5\\xA0MB');\n });\n\n it('formats for > 100 megabytes', () => {\n const oneMegabyte = 1000 * 1000;\n const twoHundredAndTenMegabytes = oneMegabyte * 210;\n assert.deepEqual(i18n.ByteUtilities.bytesToString(twoHundredAndTenMegabytes), '210\\xA0MB');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/core/i18n/NumberFormatter.d.ts b/public/core/i18n/NumberFormatter.d.ts new file mode 100644 index 00000000..30f7a913 --- /dev/null +++ b/public/core/i18n/NumberFormatter.d.ts @@ -0,0 +1,11 @@ +export interface NumberFormatter { + format(value: number): string; + formatToParts(value: number): Intl.NumberFormatPart[]; +} +/** + * Creates an instance of NumberFormatter. + * + * Safe to call in top-level of a module, since the creation of Intl.NumberFormat is deferred + * until first usage. + */ +export declare function defineFormatter(options: Intl.NumberFormatOptions): NumberFormatter; diff --git a/public/core/i18n/NumberFormatter.js b/public/core/i18n/NumberFormatter.js new file mode 100644 index 00000000..8627a2c3 --- /dev/null +++ b/public/core/i18n/NumberFormatter.js @@ -0,0 +1,62 @@ +// 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 { DevToolsLocale } from './DevToolsLocale.js'; +/** + * Creates an instance of NumberFormatter. + * + * Safe to call in top-level of a module, since the creation of Intl.NumberFormat is deferred + * until first usage. + */ +export function defineFormatter(options) { + let intlNumberFormat; + return { + format(value) { + if (!intlNumberFormat) { + intlNumberFormat = new Intl.NumberFormat(DevToolsLocale.instance().locale, options); + } + return formatAndEnsureSpace(intlNumberFormat, value); + }, + formatToParts(value) { + if (!intlNumberFormat) { + intlNumberFormat = new Intl.NumberFormat(DevToolsLocale.instance().locale, options); + } + return intlNumberFormat.formatToParts(value); + }, + }; +} +/** + * When using 'narrow' unitDisplay, many locales exclude the space between the literal and the unit. + * We don't like that, so when there is no space literal we inject an nbsp manually. + */ +function formatAndEnsureSpace(formatter, value) { + const parts = formatter.formatToParts(value); + let hasSpace = false; + for (const part of parts) { + if (part.type === 'literal') { + if (part.value === ' ') { + hasSpace = true; + part.value = '\xA0'; + } + else if (part.value === '\xA0') { + hasSpace = true; + } + } + } + if (hasSpace) { + return parts.map(part => part.value).join(''); + } + const unitIndex = parts.findIndex(part => part.type === 'unit'); + // Unexpected for there to be no unit, but just in case, handle that. + if (unitIndex === -1) { + return parts.map(part => part.value).join(''); + } + // For locales where the unit comes first (sw), the space has to come after the unit. + if (unitIndex === 0) { + return parts[0].value + '\xA0' + parts.slice(1).map(part => part.value).join(''); + } + // Otherwise, it comes before. + return parts.slice(0, unitIndex).map(part => part.value).join('') + '\xA0' + + parts.slice(unitIndex).map(part => part.value).join(''); +} +//# sourceMappingURL=NumberFormatter.js.map \ No newline at end of file diff --git a/public/core/i18n/NumberFormatter.js.map b/public/core/i18n/NumberFormatter.js.map new file mode 100644 index 00000000..97450032 --- /dev/null +++ b/public/core/i18n/NumberFormatter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"NumberFormatter.js","sourceRoot":"","sources":["../../../../../../front_end/core/i18n/NumberFormatter.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAOnD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAiC;IAC/D,IAAI,gBAAmC,CAAC;IAExC,OAAO;QACL,MAAM,CAAC,KAAK;YACV,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,gBAAgB,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACtF,CAAC;YACD,OAAO,oBAAoB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;QACD,aAAa,CAAC,KAAK;YACjB,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,gBAAgB,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACtF,CAAC;YACD,OAAO,gBAAgB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,SAA4B,EAAE,KAAa;IACvE,MAAM,KAAK,GAAG,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAE7C,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;gBACvB,QAAQ,GAAG,IAAI,CAAC;gBAChB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC;YACtB,CAAC;iBAAM,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;gBACjC,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAEhE,qEAAqE;IACrE,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,qFAAqF;IACrF,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,8BAA8B;IAC9B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,MAAM;QACtE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC9D,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 {DevToolsLocale} from './DevToolsLocale.js';\n\nexport interface NumberFormatter {\n format(value: number): string;\n formatToParts(value: number): Intl.NumberFormatPart[];\n}\n\n/**\n * Creates an instance of NumberFormatter.\n *\n * Safe to call in top-level of a module, since the creation of Intl.NumberFormat is deferred\n * until first usage.\n */\nexport function defineFormatter(options: Intl.NumberFormatOptions): NumberFormatter {\n let intlNumberFormat: Intl.NumberFormat;\n\n return {\n format(value) {\n if (!intlNumberFormat) {\n intlNumberFormat = new Intl.NumberFormat(DevToolsLocale.instance().locale, options);\n }\n return formatAndEnsureSpace(intlNumberFormat, value);\n },\n formatToParts(value) {\n if (!intlNumberFormat) {\n intlNumberFormat = new Intl.NumberFormat(DevToolsLocale.instance().locale, options);\n }\n return intlNumberFormat.formatToParts(value);\n },\n };\n}\n\n/**\n * When using 'narrow' unitDisplay, many locales exclude the space between the literal and the unit.\n * We don't like that, so when there is no space literal we inject an nbsp manually.\n */\nfunction formatAndEnsureSpace(formatter: Intl.NumberFormat, value: number): string {\n const parts = formatter.formatToParts(value);\n\n let hasSpace = false;\n for (const part of parts) {\n if (part.type === 'literal') {\n if (part.value === ' ') {\n hasSpace = true;\n part.value = '\\xA0';\n } else if (part.value === '\\xA0') {\n hasSpace = true;\n }\n }\n }\n\n if (hasSpace) {\n return parts.map(part => part.value).join('');\n }\n\n const unitIndex = parts.findIndex(part => part.type === 'unit');\n\n // Unexpected for there to be no unit, but just in case, handle that.\n if (unitIndex === -1) {\n return parts.map(part => part.value).join('');\n }\n\n // For locales where the unit comes first (sw), the space has to come after the unit.\n if (unitIndex === 0) {\n return parts[0].value + '\\xA0' + parts.slice(1).map(part => part.value).join('');\n }\n\n // Otherwise, it comes before.\n return parts.slice(0, unitIndex).map(part => part.value).join('') + '\\xA0' +\n parts.slice(unitIndex).map(part => part.value).join('');\n}\n"]} \ No newline at end of file diff --git a/public/core/i18n/i18n-tsconfig.json b/public/core/i18n/i18n-tsconfig.json index 52a6616e..80298827 100644 --- a/public/core/i18n/i18n-tsconfig.json +++ b/public/core/i18n/i18n-tsconfig.json @@ -29,7 +29,9 @@ "useUnknownInCatchVariables": false }, "files": [ + "../../../../../../front_end/core/i18n/ByteUtilities.ts", "../../../../../../front_end/core/i18n/DevToolsLocale.ts", + "../../../../../../front_end/core/i18n/NumberFormatter.ts", "../../../../../../front_end/core/i18n/i18nImpl.ts", "../../../../../../front_end/core/i18n/i18nTypes.ts", "../../../../../../front_end/core/i18n/time-utilities.ts", diff --git a/public/core/i18n/i18n.d.ts b/public/core/i18n/i18n.d.ts index 2c7a6bad..ba074f24 100644 --- a/public/core/i18n/i18n.d.ts +++ b/public/core/i18n/i18n.d.ts @@ -1,4 +1,6 @@ +import * as ByteUtilities from './ByteUtilities.js'; import * as DevToolsLocale from './DevToolsLocale.js'; import * as i18n from './i18nImpl.js'; +import * as NumberFormatter from './NumberFormatter.js'; import * as TimeUtilities from './time-utilities.js'; -export { DevToolsLocale, i18n, TimeUtilities, }; +export { ByteUtilities, DevToolsLocale, i18n, NumberFormatter, TimeUtilities, }; diff --git a/public/core/i18n/i18n.js b/public/core/i18n/i18n.js index fdb08330..8839e63a 100644 --- a/public/core/i18n/i18n.js +++ b/public/core/i18n/i18n.js @@ -1,8 +1,10 @@ // 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 ByteUtilities from './ByteUtilities.js'; import * as DevToolsLocale from './DevToolsLocale.js'; import * as i18n from './i18nImpl.js'; +import * as NumberFormatter from './NumberFormatter.js'; import * as TimeUtilities from './time-utilities.js'; -export { DevToolsLocale, i18n, TimeUtilities, }; +export { ByteUtilities, DevToolsLocale, i18n, NumberFormatter, TimeUtilities, }; //# sourceMappingURL=i18n.js.map \ No newline at end of file diff --git a/public/core/i18n/i18n.js.map b/public/core/i18n/i18n.js.map index 2a2e5046..13861a02 100644 --- a/public/core/i18n/i18n.js.map +++ b/public/core/i18n/i18n.js.map @@ -1 +1 @@ -{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../../../../../front_end/core/i18n/i18n.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,aAAa,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,cAAc,EACd,IAAI,EACJ,aAAa,GACd,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 DevToolsLocale from './DevToolsLocale.js';\nimport * as i18n from './i18nImpl.js';\nimport * as TimeUtilities from './time-utilities.js';\n\nexport {\n DevToolsLocale,\n i18n,\n TimeUtilities,\n};\n"]} \ No newline at end of file +{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../../../../../front_end/core/i18n/i18n.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,aAAa,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,aAAa,EACb,cAAc,EACd,IAAI,EACJ,eAAe,EACf,aAAa,GACd,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 ByteUtilities from './ByteUtilities.js';\nimport * as DevToolsLocale from './DevToolsLocale.js';\nimport * as i18n from './i18nImpl.js';\nimport * as NumberFormatter from './NumberFormatter.js';\nimport * as TimeUtilities from './time-utilities.js';\n\nexport {\n ByteUtilities,\n DevToolsLocale,\n i18n,\n NumberFormatter,\n TimeUtilities,\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 f81b105e..af1ead76 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 | animationsPanel":{"message":"Animations panel"},"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 | fmsExpanded":{"message":"{PH1} milliseconds"},"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/RehydratingConnection.ts | noSourceText":{"message":"No source text available"},"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 | 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 | 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 | 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 | 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 | autoTheme":{"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 | 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 | dontMatchChromeColorSchemeCommand":{"message":"Don't match Chrome color scheme"},"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 | matchChromeColorSchemeCommand":{"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 | switchToBrowserPreferredTheme":{"message":"Switch to browser's preferred 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 | addAllAnonymousScriptsToIgnoreList":{"message":"Add all anonymous scripts to ignore list"},"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 | extensionLocalStorage":{"message":"Local"},"panels/application/ApplicationPanelSidebar.ts | extensionManagedStorage":{"message":"Managed"},"panels/application/ApplicationPanelSidebar.ts | extensionSessionStorage":{"message":"Session"},"panels/application/ApplicationPanelSidebar.ts | extensionStorage":{"message":"Extension storage"},"panels/application/ApplicationPanelSidebar.ts | extensionSyncStorage":{"message":"Sync"},"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 | clickToOpenInElementsPanel":{"message":"Click to open in Elements panel"},"panels/application/components/FrameDetailsView.ts | clickToOpenInNetworkPanel":{"message":"Click to open in Network panel"},"panels/application/components/FrameDetailsView.ts | clickToOpenInNetworkPanelMight":{"message":"Click to open in Network panel (might require page reload)"},"panels/application/components/FrameDetailsView.ts | clickToOpenInSourcesPanel":{"message":"Click to open 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/ExtensionStorageItemsView.ts | extensionStorage":{"message":"Extension Storage"},"panels/application/ExtensionStorageItemsView.ts | extensionStorageItemDeleted":{"message":"The storage item was deleted."},"panels/application/ExtensionStorageItemsView.ts | extensionStorageItems":{"message":"Extension Storage Items"},"panels/application/ExtensionStorageItemsView.ts | extensionStorageItemsCleared":{"message":"Extension Storage Items cleared"},"panels/application/ExtensionStorageItemsView.ts | key":{"message":"Key"},"panels/application/ExtensionStorageItemsView.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 | clickToOpenInElementsPanel":{"message":"Click to open 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 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 +{"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.NavigationStartUnreliable,\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 });\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 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 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 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 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 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 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 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 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 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 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/NetworkRequestsHandler.d.ts b/public/models/trace/handlers/NetworkRequestsHandler.d.ts index 71cfd422..5bb358ee 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.d.ts +++ b/public/models/trace/handlers/NetworkRequestsHandler.d.ts @@ -1,5 +1,5 @@ import * as Types from '../types/types.js'; -import { type HandlerName } from './types.js'; +import type { HandlerName } from './types.js'; export interface WebSocketTraceDataForFrame { frame: string; webSocketIdentifier: number; @@ -25,7 +25,6 @@ interface NetworkRequestData { webSocket: WebSocketTraceData[]; } export declare function reset(): void; -export declare function initialize(): void; export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): NetworkRequestData; diff --git a/public/models/trace/handlers/NetworkRequestsHandler.js b/public/models/trace/handlers/NetworkRequestsHandler.js index 94814203..8bbd2010 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.js +++ b/public/models/trace/handlers/NetworkRequestsHandler.js @@ -42,7 +42,6 @@ function firstPositiveValueInList(entries) { // a -1 here because it would affect the calculation of stats below. return 0; } -let handlerState = 1 /* HandlerState.UNINITIALIZED */; export function reset() { requestsById.clear(); requestsByOrigin.clear(); @@ -51,15 +50,8 @@ export function reset() { networkRequestEventByInitiatorUrl.clear(); eventToInitiatorMap.clear(); webSocketData.clear(); - handlerState = 1 /* HandlerState.UNINITIALIZED */; -} -export function initialize() { - handlerState = 2 /* HandlerState.INITIALIZED */; } export function handleEvent(event) { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Network Request handler is not initialized'); - } if (Types.Events.isResourceChangePriority(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'changePriority', event); return; @@ -113,9 +105,6 @@ export function handleEvent(event) { } } export async function finalize() { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Network Request handler is not initialized'); - } const { rendererProcessesByFrame } = metaHandlerData(); for (const [requestId, request] of requestMap.entries()) { // If we have an incomplete set of events here, we choose to drop the network @@ -189,6 +178,8 @@ export async function finalize() { if (request.changePriority) { finalPriority = request.changePriority.args.data.priority; } + // Network timings are complicated. + // https://raw.githubusercontent.com/GoogleChrome/lighthouse/main/docs/Network-Timings.svg is generally correct, but.. less so for navigations/redirects/etc. // Start time // ======================= // The time where the request started, which is either the first willSendRequest @@ -398,12 +389,8 @@ export async function finalize() { } } finalizeWebSocketData(); - handlerState = 3 /* HandlerState.FINALIZED */; } export function data() { - if (handlerState !== 3 /* HandlerState.FINALIZED */) { - throw new Error('Network Request handler is not finalized'); - } return { byId: requestsById, byOrigin: requestsByOrigin, diff --git a/public/models/trace/handlers/NetworkRequestsHandler.js.map b/public/models/trace/handlers/NetworkRequestsHandler.js.map index 1476bfb6..bcb1be43 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 {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 ?? Protocol.Network.ResourceType.Other,\n statusCode: request.receiveResponse.args.data.statusCode,\n responseHeaders: request.receiveResponse.args.data.headers || [],\n fetchPriorityHint: finalSendRequest.args.data.fetchPriorityHint ?? 'auto',\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 +{"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} 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\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\nexport function handleEvent(event: Types.Events.Event): void {\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 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 // Network timings are complicated.\n // https://raw.githubusercontent.com/GoogleChrome/lighthouse/main/docs/Network-Timings.svg is generally correct, but.. less so for navigations/redirects/etc.\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 ?? Protocol.Network.ResourceType.Other,\n statusCode: request.receiveResponse.args.data.statusCode,\n responseHeaders: request.receiveResponse.args.data.headers || [],\n fetchPriorityHint: finalSendRequest.args.data.fetchPriorityHint ?? 'auto',\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\nexport function data(): NetworkRequestData {\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 9f35927e..9dd12d41 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.test.js +++ b/public/models/trace/handlers/NetworkRequestsHandler.test.js @@ -4,28 +4,9 @@ import { TraceLoader } from '../../../testing/TraceLoader.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(() => { - 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 Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); - } - catch (e) { - thrown = e; - } - assert.strictEqual(thrown?.message, 'Network Request handler is not initialized'); - }); - }); describe('network requests calculations', () => { beforeEach(() => { 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'); @@ -157,8 +138,6 @@ describe('NetworkRequestsHandler', function () { describe('parses the change priority request', () => { beforeEach(() => { 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'); @@ -182,8 +161,6 @@ describe('NetworkRequestsHandler', function () { describe('redirects', () => { beforeEach(() => { 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'); @@ -245,8 +222,6 @@ describe('NetworkRequestsHandler', function () { describe('initiators', () => { beforeEach(() => { 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'); diff --git a/public/models/trace/handlers/NetworkRequestsHandler.test.js.map b/public/models/trace/handlers/NetworkRequestsHandler.test.js.map index 75d3f2c1..00cfe43f 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 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 +{"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('network requests calculations', () => {\n beforeEach(() => {\n Trace.Handlers.ModelHandlers.Meta.reset();\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 });\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 });\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 });\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 32f0f844..abd1be3b 100644 --- a/public/models/trace/handlers/PageFramesHandler.d.ts +++ b/public/models/trace/handlers/PageFramesHandler.d.ts @@ -1,6 +1,7 @@ import * as Types from '../types/types.js'; export declare function reset(): void; export declare function handleEvent(event: Types.Events.Event): void; +export declare function finalize(): Promise; export interface PageFrameData { frames: Map; } diff --git a/public/models/trace/handlers/PageFramesHandler.js b/public/models/trace/handlers/PageFramesHandler.js index 0839b0f3..67a5d1fb 100644 --- a/public/models/trace/handlers/PageFramesHandler.js +++ b/public/models/trace/handlers/PageFramesHandler.js @@ -33,6 +33,8 @@ export function handleEvent(event) { }); } } +export async function finalize() { +} export function data() { return { frames, diff --git a/public/models/trace/handlers/PageFramesHandler.js.map b/public/models/trace/handlers/PageFramesHandler.js.map index 14109b9b..407eb717 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,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 +{"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;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;AAC9B,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 async function finalize(): Promise {\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/RendererHandler.d.ts b/public/models/trace/handlers/RendererHandler.d.ts index 338b7d71..ac8706d9 100644 --- a/public/models/trace/handlers/RendererHandler.d.ts +++ b/public/models/trace/handlers/RendererHandler.d.ts @@ -1,10 +1,9 @@ import * as Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; import { type FrameProcessData } from './MetaHandler.js'; -import { type HandlerName } 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.Events.Event): void; export declare function finalize(): Promise; export declare function data(): RendererHandlerData; diff --git a/public/models/trace/handlers/RendererHandler.js b/public/models/trace/handlers/RendererHandler.js index 7afe049b..e4fceee2 100644 --- a/public/models/trace/handlers/RendererHandler.js +++ b/public/models/trace/handlers/RendererHandler.js @@ -26,7 +26,6 @@ const compositorTileWorkers = Array(); const entryToNode = new Map(); let allTraceEntries = []; const completeEventStack = []; -let handlerState = 1 /* HandlerState.UNINITIALIZED */; let config = Types.Configuration.defaults(); const makeRendererProcess = () => ({ url: null, @@ -53,18 +52,8 @@ export function reset() { allTraceEntries.length = 0; completeEventStack.length = 0; compositorTileWorkers.length = 0; - handlerState = 1 /* HandlerState.UNINITIALIZED */; -} -export function initialize() { - if (handlerState !== 1 /* HandlerState.UNINITIALIZED */) { - throw new Error('Renderer Handler was not reset'); - } - handlerState = 2 /* HandlerState.INITIALIZED */; } export function handleEvent(event) { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Renderer Handler is not initialized'); - } if (Types.Events.isThreadName(event) && event.args.name?.startsWith('CompositorTileWorker')) { compositorTileWorkers.push({ pid: event.pid, @@ -90,21 +79,14 @@ export function handleEvent(event) { } } export async function finalize() { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Renderer Handler is not initialized'); - } const { mainFrameId, rendererProcessesByFrame, threadsInProcess } = metaHandlerData(); assignMeta(processes, mainFrameId, rendererProcessesByFrame, threadsInProcess); sanitizeProcesses(processes); buildHierarchy(processes); sanitizeThreads(processes); Helpers.Trace.sortTraceEventsInPlace(allTraceEntries); - handlerState = 3 /* HandlerState.FINALIZED */; } export function data() { - if (handlerState !== 3 /* HandlerState.FINALIZED */) { - throw new Error('Renderer Handler is not finalized'); - } return { processes: new Map(processes), compositorTileWorkers: new Map(gatherCompositorThreads()), diff --git a/public/models/trace/handlers/RendererHandler.js.map b/public/models/trace/handlers/RendererHandler.js.map index cfadca62..8d219f54 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":"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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 +{"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} 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 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}\n\nexport function handleEvent(event: Types.Events.Event): void {\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 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}\n\nexport function data(): RendererHandlerData {\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 811ace20..7f8a5a06 100644 --- a/public/models/trace/handlers/RendererHandler.test.js +++ b/public/models/trace/handlers/RendererHandler.test.js @@ -588,7 +588,6 @@ describeWithEnvironment('RendererHandler', function () { }, ], ]); - 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]; @@ -699,9 +698,6 @@ describeWithEnvironment('RendererHandler', function () { 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) { Trace.Handlers.ModelHandlers.Meta.handleEvent(event); Trace.Handlers.ModelHandlers.Renderer.handleEvent(event); diff --git a/public/models/trace/handlers/RendererHandler.test.js.map b/public/models/trace/handlers/RendererHandler.test.js.map index 75901cdf..01e90356 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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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 Utils from '../../../panels/timeline/utils/utils.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(Utils.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(Utils.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, 'missing-url.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(Utils.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 +{"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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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 Utils from '../../../panels/timeline/utils/utils.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(Utils.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(Utils.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 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\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, 'missing-url.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(Utils.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 c887a89c..3a42ab3f 100644 --- a/public/models/trace/handlers/SamplesHandler.d.ts +++ b/public/models/trace/handlers/SamplesHandler.d.ts @@ -4,7 +4,6 @@ import * as Types from '../types/types.js'; declare const profilesInProcess: Map>; declare const entryToNode: Map; export declare function reset(): void; -export declare function initialize(): void; export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): SamplesHandlerData; diff --git a/public/models/trace/handlers/SamplesHandler.js b/public/models/trace/handlers/SamplesHandler.js index 00825781..42fa385a 100644 --- a/public/models/trace/handlers/SamplesHandler.js +++ b/public/models/trace/handlers/SamplesHandler.js @@ -18,7 +18,6 @@ const entryToNode = new Map(); // are matched by profile id, which we then finish processing to export // events matched by thread id. const preprocessedData = new Map(); -let handlerState = 1 /* HandlerState.UNINITIALIZED */; function buildProfileCalls() { for (const [processId, profiles] of preprocessedData) { for (const [profileId, preProcessedData] of profiles) { @@ -90,18 +89,8 @@ export function reset() { preprocessedData.clear(); profilesInProcess.clear(); entryToNode.clear(); - handlerState = 1 /* HandlerState.UNINITIALIZED */; -} -export function initialize() { - if (handlerState !== 1 /* HandlerState.UNINITIALIZED */) { - throw new Error('Samples Handler was not reset'); - } - handlerState = 2 /* HandlerState.INITIALIZED */; } export function handleEvent(event) { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Samples Handler is not initialized'); - } /** * A fake trace event created to support CDP.Profiler.Profiles in the * trace engine. @@ -173,16 +162,9 @@ export function handleEvent(event) { } } export async function finalize() { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Samples Handler is not initialized'); - } buildProfileCalls(); - handlerState = 3 /* HandlerState.FINALIZED */; } export function data() { - if (handlerState !== 3 /* HandlerState.FINALIZED */) { - throw new Error('Samples Handler is not finalized'); - } return { profilesInProcess, entryToNode, diff --git a/public/models/trace/handlers/SamplesHandler.js.map b/public/models/trace/handlers/SamplesHandler.js.map index eee56114..fd3f6864 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":"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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 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 +{"version":3,"file":"SamplesHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SamplesHandler.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 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\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\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}\n\nexport function handleEvent(event: Types.Events.Event): void {\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 buildProfileCalls();\n}\n\nexport function data(): SamplesHandlerData {\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 c5b5fa2d..b00f06ed 100644 --- a/public/models/trace/handlers/SamplesHandler.test.js +++ b/public/models/trace/handlers/SamplesHandler.test.js @@ -9,8 +9,6 @@ async function handleEventsFromTraceFile(context, name) { const traceEvents = await TraceLoader.rawEvents(context, name); 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) { Trace.Handlers.ModelHandlers.Meta.handleEvent(event); Trace.Handlers.ModelHandlers.Samples.handleEvent(event); @@ -110,7 +108,6 @@ describeWithEnvironment('SamplesHandler', function () { makeProfileChunkEvent([{ id: E, children: [] }], [], [], 0), ]; Trace.Handlers.ModelHandlers.Samples.reset(); - Trace.Handlers.ModelHandlers.Samples.initialize(); for (const event of [mockProfileEvent, ...mockChunks]) { Trace.Handlers.ModelHandlers.Samples.handleEvent(event); } diff --git a/public/models/trace/handlers/SamplesHandler.test.js.map b/public/models/trace/handlers/SamplesHandler.test.js.map index 086eaa80..0d48f7a4 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":"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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 +{"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 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 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.test.js b/public/models/trace/handlers/ScreenshotsHandler.test.js index 2dc0b623..6c75ba61 100644 --- a/public/models/trace/handlers/ScreenshotsHandler.test.js +++ b/public/models/trace/handlers/ScreenshotsHandler.test.js @@ -24,7 +24,6 @@ describe('ScreenshotsHandler', function () { // and later we will pass events to the meta handler, otherwise the // screenshots handler will fail. Trace.Handlers.ModelHandlers.Meta.reset(); - Trace.Handlers.ModelHandlers.Meta.initialize(); Trace.Handlers.ModelHandlers.Screenshots.reset(); }); describe('frames', () => { diff --git a/public/models/trace/handlers/ScreenshotsHandler.test.js.map b/public/models/trace/handlers/ScreenshotsHandler.test.js.map index 96937050..8bf60144 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":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,QAAQ,CAAC,oBAAoB,EAAE;IAC7B,MAAM,SAAS,GAAG;QAChB,GAAG,iBAAiB;QACpB,IAAI,EAAE,YAAY;QAClB,oEAAoE;QACpE,0EAA0E;QAC1E,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QACvC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QACrC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QACtC,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,MAAM;QACX,EAAE,oDAA0C;KAC7C,CAAC;IAEF,IAAI,UAA+C,CAAC;IAEpD,UAAU,CAAC,KAAK;QACd,oEAAoE;QACpE,mEAAmE;QACnE,mEAAmE;QACnE,iCAAiC;QACjC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC1C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QAE/C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,EAAE,CAAC,yBAAyB,EAAE,KAAK;YACjC,MAAM,kBAAkB,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAE9E,UAAU,GAAG;gBACX,GAAG,kBAAkB;gBACrB,EAAC,GAAG,SAAS,EAAE,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,EAAC;gBACxD,EAAC,GAAG,SAAS,EAAE,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,EAAC;aACzD,CAAC;YACF,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAEnF,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;gBAC/B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACrD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC9D,CAAC;YAED,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;YAE1D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC;YACjE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,SAAS,gBAAgB,CACrB,oBAA8D,EAC9D,wBAAyD;YAC3D,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE;gBAC9C,MAAM,SAAS,GAAG,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAkC,CAAC;gBAClF,MAAM,YAAY,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;gBACzD,OAAO,YAAY,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,8DAA8D;QAC9D,EAAE,CAAC,IAAI,CAAC,wEAAwE,EAAE,KAAK;YACrF,qEAAqE;YACrE,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;YAC9E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACrD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC9D,CAAC;YACD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;YAE1D,MAAM,oBAAoB,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC;YACjF,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAChF,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC;YAEjF,KAAK,MAAM,MAAM,IAAI,wBAAwB,EAAE,CAAC;gBAC9C,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAE,6DAA6D;YACzG,CAAC;YAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,oBAAoB,EAAE,wBAAwB,CAAC,CAAC;YACvF,qFAAqF;YACrF,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE;gBACpC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAG,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,KAAK;gBAC9F,CAAC,KAAK,EAAG,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAG,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM;aACjG,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK;YAC3C,iGAAiG;YACjG,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YACpE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACrD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC9D,CAAC;YACD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;YAE1D,MAAM,oBAAoB,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC;YACjF,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAChF,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC;YAEjF,KAAK,MAAM,MAAM,IAAI,wBAAwB,EAAE,CAAC;gBAC9C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAE,mEAAmE;YAC5G,CAAC;YAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,oBAAoB,EAAE,wBAAwB,CAAC,CAAC;YACvF,sBAAsB;YACtB,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE;gBACpC,CAAC;gBACD,CAAC;gBACD,CAAC;gBACD,CAAC;gBACD,CAAC;aACF,CAAC,CAAC;QACL,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 {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().all;\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 // Skip while we resolve the getPresentationTimestamp mystery.\n it.skip('[crbug.com/41363012] 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().all;\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().all;\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 +{"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\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().all;\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 // Skip while we resolve the getPresentationTimestamp mystery.\n it.skip('[crbug.com/41363012] 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().all;\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().all;\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 777c650c..f961f3ff 100644 --- a/public/models/trace/handlers/SelectorStatsHandler.d.ts +++ b/public/models/trace/handlers/SelectorStatsHandler.d.ts @@ -1,6 +1,7 @@ import * as Types from '../types/types.js'; export declare function reset(): void; export declare function handleEvent(event: Types.Events.Event): void; +export declare function finalize(): Promise; export interface SelectorStatsData { dataForUpdateLayoutEvent: 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 +{"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;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;AAC9B,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 async function finalize(): Promise {\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/ServerTimingsHandler.d.ts b/public/models/trace/handlers/ServerTimingsHandler.d.ts index 39ba559e..7cb219d8 100644 --- a/public/models/trace/handlers/ServerTimingsHandler.d.ts +++ b/public/models/trace/handlers/ServerTimingsHandler.d.ts @@ -1,7 +1,6 @@ import * as Types from '../types/types.js'; -import { type HandlerName } 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.Events.Event): void; export declare function finalize(): Promise; export declare function data(): { diff --git a/public/models/trace/handlers/ServerTimingsHandler.js b/public/models/trace/handlers/ServerTimingsHandler.js index 973efb6c..3d405e52 100644 --- a/public/models/trace/handlers/ServerTimingsHandler.js +++ b/public/models/trace/handlers/ServerTimingsHandler.js @@ -6,24 +6,15 @@ import * as Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; import { data as networkData } from './NetworkRequestsHandler.js'; const serverTimings = []; -let handlerState = 1 /* HandlerState.UNINITIALIZED */; export function reset() { serverTimings.length = 0; - handlerState = 1 /* HandlerState.UNINITIALIZED */; -} -export function initialize() { - handlerState = 2 /* HandlerState.INITIALIZED */; } export function handleEvent(_event) { // Implementation not needed because data is sourced from NetworkRequestsHandler } export async function finalize() { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Server Timings handler is not initialized'); - } extractServerTimings(); Helpers.Trace.sortTraceEventsInPlace(serverTimings); - handlerState = 3 /* HandlerState.FINALIZED */; } const RESPONSE_START_METRIC_NAME = 'response-start'; const RESPONSE_END_METRIC_NAME = 'response-end'; @@ -105,9 +96,6 @@ function createSyntheticServerTiming(request, serverStart, serverEnd, timingsInR return convertedServerTimings; } export function data() { - if (handlerState !== 3 /* HandlerState.FINALIZED */) { - throw new Error('Server Timing handler is not finalized'); - } return { serverTimings, }; diff --git a/public/models/trace/handlers/ServerTimingsHandler.js.map b/public/models/trace/handlers/ServerTimingsHandler.js.map index ab8d8db8..6095280b 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,GAAyC,EAAE,CAAC;AAE/D,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,MAA0B;IACpD,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,OAA6C,EAAE,WAAmB,EAAE,SAAiB,EACrF,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,GAAyC,EAAE,CAAC;IACxE,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,uCAA6B;YAC/B,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YAC9B,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC7B,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 {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 +{"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} from './types.js';\n\nconst serverTimings: Types.Events.SyntheticServerTiming[] = [];\n\nexport function reset(): void {\n serverTimings.length = 0;\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 extractServerTimings();\n Helpers.Trace.sortTraceEventsInPlace(serverTimings);\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 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/Threads.test.js b/public/models/trace/handlers/Threads.test.js index 31be32dc..525c07c7 100644 --- a/public/models/trace/handlers/Threads.test.js +++ b/public/models/trace/handlers/Threads.test.js @@ -1,7 +1,6 @@ // 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 TimelineModel from '../../../models/timeline_model/timeline_model.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as Trace from '../trace.js'; @@ -34,7 +33,7 @@ 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, Trace.Types.Events.ThreadID(1)); + const events = Trace.Extras.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(parsedTrace.Renderer.processes.size, 0); diff --git a/public/models/trace/handlers/Threads.test.js.map b/public/models/trace/handlers/Threads.test.js.map index dbc9de35..7ec775eb 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 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 +{"version":3,"file":"Threads.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/Threads.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,wBAAwB,EAAE;IAChD,EAAE,CAAC,uDAAuD,EAAE,KAAK;QAC/D,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAE7E,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;YACvF,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,MAAM,2BAA2B,GAAG;YAClC,EAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,mEAA+C,EAAC;YAC7E,EAAC,IAAI,EAAE,sBAAsB,EAAE,IAAI,uDAAyC,EAAC;YAC7E,EAAC,IAAI,EAAE,YAAY,EAAE,IAAI,uDAAyC,EAAC;YACnE,EAAC,IAAI,EAAE,yBAAyB,EAAE,IAAI,mEAA+C,EAAC;YACtF,EAAC,IAAI,EAAE,OAAO,EAAE,IAAI,uDAAyC,EAAC;YAC9D,EAAC,IAAI,EAAE,4BAA4B,EAAE,IAAI,mEAA+C,EAAC;YACzF,EAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,iEAA8C,EAAC;YACnF,EAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,iEAA8C,EAAC;YACnF,EAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,iEAA8C,EAAC;YACnF,EAAC,IAAI,EAAE,gCAAgC,EAAE,IAAI,iEAA8C,EAAC;YAC5F,EAAC,IAAI,EAAE,4BAA4B,EAAE,IAAI,mEAA+C,EAAC;YACzF,EAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,iEAA8C,EAAC;SACpF,CAAC;QAEF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAC,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK;QACrE,0EAA0E;QAC1E,0EAA0E;QAC1E,0CAA0C;QAC1C,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,sCAAsC,CAAC,CAAC;QAChG,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,0BAA0B,CAAC,6BAA6B,CAClG,SAAS,EACT,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CACjC,CAAC;QACF,MAAM,EAAC,WAAW,EAAC,GACf,MAAM,WAAW,CAAC,gCAAgC,CAAC,MAA+C,CAAC,CAAC;QAExG,iEAAiE;QACjE,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAElE,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEtC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,oEAAgD,CAAC;QACvF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzD,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 {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 = Trace.Extras.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 dc1a392e..2ca919fd 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.d.ts +++ b/public/models/trace/handlers/UserInteractionsHandler.d.ts @@ -1,10 +1,10 @@ import * as Types from '../types/types.js'; import { ScoreClassification } from './PageLoadMetricsHandler.js'; -import { type HandlerName } 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.Events.EventTiming[]; + allEvents: readonly Types.Events.EventTimingBeginOrEnd[]; /** All the BeginCommitCompositorFrame events we found in the trace */ beginCommitCompositorFrameEvents: readonly Types.Events.BeginCommitCompositorFrame[]; /** All the ParseMetaViewport events we found in the trace */ diff --git a/public/models/trace/handlers/UserInteractionsHandler.js b/public/models/trace/handlers/UserInteractionsHandler.js index a8dd7b38..b59ce7bf 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.js +++ b/public/models/trace/handlers/UserInteractionsHandler.js @@ -21,7 +21,6 @@ const interactionEvents = []; const interactionEventsWithNoNesting = []; const eventTimingEndEventsById = new Map(); const eventTimingStartEventsForInteractions = []; -let handlerState = 1 /* HandlerState.UNINITIALIZED */; export function reset() { allEvents.length = 0; beginCommitCompositorFrameEvents.length = 0; @@ -31,12 +30,8 @@ export function reset() { eventTimingEndEventsById.clear(); interactionEventsWithNoNesting.length = 0; longestInteractionEvent = null; - handlerState = 2 /* HandlerState.INITIALIZED */; } export function handleEvent(event) { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Handler is not initialized'); - } if (Types.Events.isBeginCommitCompositorFrame(event)) { beginCommitCompositorFrameEvents.push(event); return; @@ -208,17 +203,15 @@ export async function finalize() { // If we cannot find an end event, bail and drop this event. continue; } - if (!interactionStartEvent.args.data?.type || !interactionStartEvent.args.data?.interactionId) { - // A valid interaction event that we care about has to have a type (e.g. - // pointerdown, keyup). - // - // We also need to ensure it has an interactionId. We already checked - // this in the handleEvent() function, but we do it here also to satisfy - // TypeScript. + const { type, interactionId, timeStamp, processingStart, processingEnd } = interactionStartEvent.args.data; + if (!type || !interactionId || !timeStamp || !processingStart || !processingEnd) { + // A valid interaction event that we care about has to have a type (e.g. pointerdown, keyup). + // We also need to ensure it has an interactionId and various timings. There are edge cases where these aren't included in the trace event. continue; } - // In the future we will add microsecond timestamps to the trace events, - // but until then we can use the millisecond precision values that are in + // In the future we will add microsecond timestamps to the trace events… + // (See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;l=900-901;drc=b503c262e425eae59ced4a80d59d176ed07152c7 ) + // …but until then we can use the millisecond precision values that are in // the trace event. To adjust them to be relative to the event.ts and the // trace timestamps, for both processingStart and processingEnd we subtract // the event timestamp (NOT event.ts, but the timeStamp millisecond value @@ -226,13 +219,13 @@ export async function finalize() { // will give us a processingStart and processingEnd time in microseconds // that is relative to event.ts, and can be used when drawing boxes. // There is some inaccuracy here as we are converting milliseconds to microseconds, but it is good enough until the backend emits more accurate numbers. - const processingStartRelativeToTraceTime = Types.Timing.MicroSeconds(Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.processingStart) - - Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.timeStamp) + - interactionStartEvent.ts); - const processingEndRelativeToTraceTime = Types.Timing.MicroSeconds((Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.processingEnd) - - Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.timeStamp)) + + const processingStartRelativeToTraceTime = Types.Timing.MicroSeconds(Helpers.Timing.millisecondsToMicroseconds(processingStart) - + Helpers.Timing.millisecondsToMicroseconds(timeStamp) + interactionStartEvent.ts); + const processingEndRelativeToTraceTime = Types.Timing.MicroSeconds((Helpers.Timing.millisecondsToMicroseconds(processingEnd) - + Helpers.Timing.millisecondsToMicroseconds(timeStamp)) + interactionStartEvent.ts); - const frameId = interactionStartEvent.args.frame ?? interactionStartEvent.args.data.frame; + // Ultimate frameId fallback only needed for TSC, see comments in the type. + 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.registerSyntheticEvent({ @@ -265,7 +258,6 @@ export async function finalize() { writeSyntheticTimespans(interactionEvent); interactionEvents.push(interactionEvent); } - handlerState = 3 /* HandlerState.FINALIZED */; interactionEventsWithNoNesting.push(...removeNestedInteractions(interactionEvents)); // Pick the longest interactions from the set that were not nested, as we // know those are the set of the largest interactions. diff --git a/public/models/trace/handlers/UserInteractionsHandler.js.map b/public/models/trace/handlers/UserInteractionsHandler.js.map index 60badea1..f97cf565 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 {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 +{"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 type {HandlerName} 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.EventTimingBeginOrEnd[] = [];\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.EventTimingBeginOrEnd[];\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[] = [];\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}\n\nexport function handleEvent(event: Types.Events.Event): void {\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 const {type, interactionId, timeStamp, processingStart, processingEnd} = interactionStartEvent.args.data;\n if (!type || !interactionId || !timeStamp || !processingStart || !processingEnd) {\n // A valid interaction event that we care about has to have a type (e.g. pointerdown, keyup).\n // We also need to ensure it has an interactionId and various timings. There are edge cases where these aren't included in the trace event.\n continue;\n }\n\n // In the future we will add microsecond timestamps to the trace events…\n // (See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;l=900-901;drc=b503c262e425eae59ced4a80d59d176ed07152c7 )\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(processingStart) -\n Helpers.Timing.millisecondsToMicroseconds(timeStamp) + interactionStartEvent.ts,\n );\n\n const processingEndRelativeToTraceTime = Types.Timing.MicroSeconds(\n (Helpers.Timing.millisecondsToMicroseconds(processingEnd) -\n Helpers.Timing.millisecondsToMicroseconds(timeStamp)) +\n interactionStartEvent.ts);\n\n // Ultimate frameId fallback only needed for TSC, see comments in the type.\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 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 2b767424..c4a4c425 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.test.js +++ b/public/models/trace/handlers/UserInteractionsHandler.test.js @@ -6,7 +6,6 @@ import * as Trace from '../trace.js'; async function processTrace(context, path) { const traceEvents = await TraceLoader.rawEvents(context, path); Trace.Handlers.ModelHandlers.Meta.reset(); - Trace.Handlers.ModelHandlers.Meta.initialize(); for (const event of traceEvents) { Trace.Handlers.ModelHandlers.Meta.handleEvent(event); Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event); @@ -16,7 +15,6 @@ async function processTrace(context, path) { } beforeEach(() => { Trace.Handlers.ModelHandlers.Meta.reset(); - Trace.Handlers.ModelHandlers.Meta.initialize(); }); describe('UserInteractionsHandler', function () { function makeFakeInteraction(type, options) { @@ -31,30 +29,13 @@ describe('UserInteractionsHandler', function () { }; return event; } - describe('error handling', () => { - it('throws if not initialized', async () => { - Trace.Handlers.ModelHandlers.Meta.reset(); - Trace.Handlers.ModelHandlers.Meta.initialize(); - // Finalize the handler by calling data and then finalize on it. - Trace.Handlers.ModelHandlers.UserInteractions.data(); - await Trace.Handlers.ModelHandlers.Meta.finalize(); - await Trace.Handlers.ModelHandlers.UserInteractions.finalize(); - assert.throws(() => { - const 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) { Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event); } const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); - const clicks = data.allEvents.filter(event => { - if (!event.args.data) { - return false; - } + const clicks = data.allEvents.filter(Trace.Types.Events.isEventTimingStart).filter(event => { return event.args.data.type === 'click'; }); assert.strictEqual(data.allEvents.length, 58); @@ -152,7 +133,8 @@ describe('UserInteractionsHandler', function () { it('detects correct events for a click and keydown interaction', async () => { await processTrace(this, 'slow-interaction-keydown.json.gz'); 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); + const foundInteractions = data.allEvents.filter(Trace.Types.Events.isEventTimingStart) + .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: // 1.pointerdown, 2. pointerup, 3. click diff --git a/public/models/trace/handlers/UserInteractionsHandler.test.js.map b/public/models/trace/handlers/UserInteractionsHandler.test.js.map index fbc6798d..97ab88a0 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":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,KAAK,UAAU,YAAY,CAAC,OAAuC,EAAE,IAAY;IAC/E,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/D,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC1C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACrD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;IACnD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;AACjE,CAAC;AAED,UAAU,CAAC,GAAG,EAAE;IACd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC1C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE;IAClC,SAAS,mBAAmB,CAAC,IAAY,EAAE,OAM1C;QACC,MAAM,KAAK,GAAG;YACZ,IAAI,EAAE,aAAa;YACnB,IAAI;YACJ,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC;YACtD,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;YACzE,eAAe,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;YAC9E,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;YAC1E,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC;QAEF,OAAO,KAA+D,CAAC;IACzE,CAAC;IAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;YACzC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC1C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAE/C,gEAAgE;YAChE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;YACrD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;YAE/D,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE;gBACjB,MAAM,SAAS,GAAG,EAA8B,CAAC;gBACjD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YACvE,CAAC,EAAE,4BAA4B,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK;QACvC,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,uCAAuC,CAAC,CAAC;QAC/F,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YAC3C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACrB,OAAO,KAAK,CAAC;YACf,CAAC;YAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,YAAY,CAAC,IAAI,EAAE,uCAAuC,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,qCAAqC;QACrC,iDAAiD;QACjD,qDAAqD;QACrD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK;QACzF,MAAM,YAAY,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,oBAAoB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC3E,OAAO,KAAK,CAAC,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;QACxD,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;QACvE,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK;QAChD,MAAM,YAAY,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,oBAAoB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC3E,OAAO,KAAK,CAAC,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;QACxD,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,yEAAyE;QACzE,qDAAqD;QACrD,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC3D,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;QACrE,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,YAAY,CAAC,IAAI,EAAE,kCAAkC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;QAE3C,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC/D,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;QAClE,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,YAAY,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,iEAAiE;QACjE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,YAAY,CAAC,IAAI,EAAE,kCAAkC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,iDAAiD;QACjD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6FAA6F,EAAE,KAAK,IAAI,EAAE;QAC3G,MAAM,YAAY,CAAC,IAAI,EAAE,uCAAuC,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,KAAK,MAAM,cAAc,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACpD,MAAM,CAAC,WAAW,CACd,cAAc,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACzG,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,YAAY,CAAC,IAAI,EAAE,uCAAuC,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE;YACjE,qEAAqE;YACrE,IAAI;YACJ,IAAI;YACJ,IAAI;SACL,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,YAAY,CAAC,IAAI,EAAE,kCAAkC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE;YACjE,yCAAyC;YACzC,IAAI;YACJ,uCAAuC;YACvC,IAAI;YACJ,mCAAmC;YACnC,IAAI;YACJ,gCAAgC;YAChC,IAAI;YACJ,8BAA8B;YAC9B,IAAI;SACL,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,YAAY,CAAC,IAAI,EAAE,kCAAkC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,iBAAiB,GACnB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrG,wCAAwC;QACxC,wBAAwB;QACxB,wCAAwC;QACxC,yBAAyB;QACzB,uBAAuB;QACvB,MAAM,CAAC,SAAS,CACZ,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EACrD,CAAC,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAE/D,MAAM,CAAC,SAAS,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE;YACvE,kFAAkF;YAClF,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,4EAA4E;YAC5E,IAAI;YACJ,IAAI;SACL,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,MAAM,GAAG;YACb;gBACE,GAAG,EAAE,mBAAmB;gBACxB,EAAE,yDAA+C;gBACjD,GAAG,EAAE,OAAO,EAAG,sBAAsB;gBACrC,GAAG,EAAE,CAAC,EAAS,iBAAiB;gBAChC,EAAE,EAAE,MAAM;gBACV,EAAE,EAAE,EAAE;gBACN,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE;oBACJ,IAAI,EAAE;wBACJ,QAAQ,EAAE,EAAE;wBACZ,aAAa,EAAE,IAAI;wBACnB,MAAM,EAAE,CAAC;wBACT,aAAa,EAAE,GAAG;wBAClB,eAAe,EAAE,GAAG;wBACpB,SAAS,EAAE,GAAG;wBACd,IAAI,EAAE,aAAa;qBACpB;iBACF;aACF;YACD,wDAAwD;YACxD;gBACE,GAAG,EAAE,mBAAmB;gBACxB,EAAE,yDAA+C;gBACjD,GAAG,EAAE,OAAO,EAAG,sBAAsB;gBACrC,GAAG,EAAE,CAAC,EAAS,iBAAiB;gBAChC,EAAE,EAAE,MAAM;gBACV,EAAE,EAAE,EAAE;gBACN,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE;oBACJ,IAAI,EAAE;wBACJ,QAAQ,EAAE,EAAE;wBACZ,aAAa,EAAE,CAAC;wBAChB,MAAM,EAAE,CAAC;wBACT,aAAa,EAAE,GAAG;wBAClB,eAAe,EAAE,GAAG;wBACpB,SAAS,EAAE,GAAG;wBACd,IAAI,EAAE,aAAa;qBACpB;iBACF;aACF;YACD,mDAAmD;YACnD;gBACE,GAAG,EAAE,mBAAmB;gBACxB,EAAE,yDAA+C;gBACjD,GAAG,EAAE,OAAO,EAAG,sBAAsB;gBACrC,GAAG,EAAE,CAAC,EAAS,iBAAiB;gBAChC,EAAE,EAAE,MAAM;gBACV,EAAE,EAAE,EAAE;gBACN,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE;oBACJ,IAAI,EAAE;wBACJ,QAAQ,EAAE,CAAC;wBACX,aAAa,EAAE,CAAC;wBAChB,MAAM,EAAE,CAAC;wBACT,aAAa,EAAE,GAAG;wBAClB,eAAe,EAAE,GAAG;wBACpB,SAAS,EAAE,GAAG;wBACd,IAAI,EAAE,aAAa;qBACpB;iBACF;aACF;SAC6C,CAAC;QACjD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC;QAC/E,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC9C,MAAM,EAAC,wBAAwB,EAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC;QAEjF,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;YACpG;;;;;eAKG;YACH,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,wBAAwB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1E,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+FAA+F,EAAE,GAAG,EAAE;YACvG,qEAAqE;YACrE,mEAAmE;YACnE,uEAAuE;YACvE,yEAAyE;YACzE,gEAAgE;YAChE,mEAAmE;YACnE,wEAAwE;YACxE,mCAAmC;YACnC,MAAM,MAAM,GAAG,mBAAmB,CAC9B,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACxG,MAAM,MAAM,GAAG,mBAAmB,CAC9B,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACxG,MAAM,MAAM,GAAG,wBAAwB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD;;;;;;;;;eASG;YACH,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAC3F,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAC/F,MAAM,MAAM,GAAG,wBAAwB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1E,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;YACjF;;;;;eAKG;YACH,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,wBAAwB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1E,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D;;;eAGG;YACH,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,wBAAwB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oFAAoF,EAAE,GAAG,EAAE;YAC5F;;;;;;;;eAQG;YACH,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAChG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAClG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAChG,MAAM,MAAM,GAAG,wBAAwB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1E,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C;;eAEG;YACH,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAChG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAClG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAClG,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;YAClG,MAAM,MAAM,GAAG,wBAAwB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1E,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,YAAY,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;YACxD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;YAElE,MAAM,0BAA0B,GAAG,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;gBACjF,OAAO,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YAChD,CAAC,CAAC,CAAC;YAEH,wEAAwE;YACxE,mEAAmE;YACnE,gEAAgE;YAEhE;;;;;;gBAMI;YACJ,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACnE,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACpE,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;YAElE;;;;;;gBAMI;YACJ,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACnE,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACnE,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YAEpE;;;;;gBAKI;YACJ,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACnE,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACnE,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;QACrG,MAAM,CAAC,WAAW,CACd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,4CAA4C,CAAC,MAAM,CAAC,GAAG,CAAC,qFAChC,CAAC;QAC3E,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;QACtG,MAAM,CAAC,WAAW,CACd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,4CAA4C,CAAC,MAAM,CAAC,GAAG,CAAC,iFAClC,CAAC;QACzE,MAAM,MAAM,GAAG,mBAAmB,CAAC,aAAa,EAAE,EAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,EAAC,CAAC,CAAC;QACxG,MAAM,CAAC,WAAW,CACd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,4CAA4C,CAAC,MAAM,CAAC,GAAG,CAAC,mFACjC,CAAC;IAC5E,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 {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 +{"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 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});\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 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(Trace.Types.Events.isEventTimingStart).filter(event => {\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 = data.allEvents.filter(Trace.Types.Events.isEventTimingStart)\n .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.EventTimingBeginOrEnd[];\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.js b/public/models/trace/handlers/UserTimingsHandler.js index 7ea2fc69..0c8d6cf4 100644 --- a/public/models/trace/handlers/UserTimingsHandler.js +++ b/public/models/trace/handlers/UserTimingsHandler.js @@ -13,14 +13,12 @@ const performanceMeasureEvents = []; const performanceMarkEvents = []; const consoleTimings = []; const timestampEvents = []; -let handlerState = 1 /* HandlerState.UNINITIALIZED */; export function reset() { syntheticEvents.length = 0; performanceMeasureEvents.length = 0; performanceMarkEvents.length = 0; consoleTimings.length = 0; timestampEvents.length = 0; - handlerState = 2 /* HandlerState.INITIALIZED */; } const resourceTimingNames = [ 'workerStart', @@ -108,9 +106,6 @@ function userTimingComparator(a, b, originalArray) { return originalArray.indexOf(b) - originalArray.indexOf(a); } export function handleEvent(event) { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('UserTimings handler is not initialized'); - } if (ignoredNames.includes(event.name)) { return; } @@ -129,18 +124,11 @@ export function handleEvent(event) { } } export async function finalize() { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('UserTimings handler is not initialized'); - } const asyncEvents = [...performanceMeasureEvents, ...consoleTimings]; syntheticEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents); syntheticEvents = syntheticEvents.sort((a, b) => userTimingComparator(a, b, [...syntheticEvents])); - handlerState = 3 /* HandlerState.FINALIZED */; } export function data() { - if (handlerState !== 3 /* HandlerState.FINALIZED */) { - throw new Error('UserTimings handler is not finalized'); - } return { performanceMeasures: syntheticEvents.filter(e => e.cat === 'blink.user_timing'), consoleTimings: syntheticEvents.filter(e => e.cat === 'blink.console'), diff --git a/public/models/trace/handlers/UserTimingsHandler.js.map b/public/models/trace/handlers/UserTimingsHandler.js.map index 35184222..636483e4 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":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAI3C;;;;IAII;AACJ,IAAI,eAAe,GAAkE,EAAE,CAAC;AACxF,MAAM,wBAAwB,GAAsC,EAAE,CAAC;AACvE,MAAM,qBAAqB,GAAmC,EAAE,CAAC;AAEjE,MAAM,cAAc,GAAkE,EAAE,CAAC;AAEzF,MAAM,eAAe,GAA6B,EAAE,CAAC;AAyBrD,IAAI,YAAY,qCAA6B,CAAC;AAE9C,MAAM,UAAU,KAAK;IACnB,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,wBAAwB,CAAC,MAAM,GAAG,CAAC,CAAC;IACpC,qBAAqB,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,mBAAmB,GAAG;IAC1B,aAAa;IACb,eAAe;IACf,aAAa;IACb,YAAY;IACZ,mBAAmB;IACnB,iBAAiB;IACjB,cAAc;IACd,YAAY;IACZ,uBAAuB;IACvB,cAAc;IACd,eAAe;IACf,aAAa;CACd,CAAC;AACF,MAAM,cAAc,GAAG;IACrB,iBAAiB;IACjB,kBAAkB;IAClB,gBAAgB;IAChB,eAAe;IACf,aAAa;IACb,YAAY;IACZ,qBAAqB;IACrB,mBAAmB;IACnB,iBAAiB;IACjB,cAAc;IACd,YAAY;IACZ,uBAAuB;IACvB,cAAc;IACd,eAAe;IACf,aAAa;IACb,YAAY;IACZ,gBAAgB;IAChB,4BAA4B;IAC5B,0BAA0B;IAC1B,aAAa;IACb,gBAAgB;IAChB,cAAc;CACf,CAAC;AACF,mEAAmE;AACnE,oEAAoE;AACpE,oEAAoE;AACpE,gBAAgB;AAChB,MAAM,YAAY,GAAG,CAAC,GAAG,mBAAmB,EAAE,GAAG,cAAc,CAAC,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAS,oBAAoB,CACzB,CAAyB,EAAE,CAAyB,EAAE,aAAuC;IAC/F,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;IACxB,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;IACxB,IAAI,UAAU,GAAG,UAAU,EAAE,CAAC;QAC5B,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IACD,IAAI,UAAU,GAAG,UAAU,EAAE,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IACxC,MAAM,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IACxC,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;QACxB,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IACD,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;QACxB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,wEAAwE;IACxE,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,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,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,GAAG,wBAAwB,EAAE,GAAG,cAAc,CAAC,CAAC;IACrE,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,WAAW,CAAC,CAAC;IAChF,eAAe,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACnG,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO;QACL,mBAAmB,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,mBAAmB,CACpC;QAC1C,cAAc,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,eAAe,CAA8C;QACnH,gFAAgF;QAChF,gBAAgB,EAAE,CAAC,GAAG,qBAAqB,CAAC;QAC5C,eAAe,EAAE,CAAC,GAAG,eAAe,CAAC;KACtC,CAAC;AACJ,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 {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\n/**\n * Similar to the default {@see Helpers.Trace.eventTimeComparator}\n * but with a twist:\n * In case of equal start and end times, always put the second event\n * first.\n *\n * Explanation:\n * User timing entries come as trace events dispatched when\n * performance.measure/mark is called. The trace events buffered in\n * devtools frontend are sorted by the start time. If their start time\n * is the same, then the event for the first call will appear first.\n *\n * When entries are meant to be stacked, the corresponding\n * performance.measure calls usually are done in bottom-up direction:\n * calls for children first and for parent later (because the call\n * is usually done when the measured task is over). This means that\n * when two user timing events have the start and end time, usually the\n * second event is the parent of the first. Hence the switch.\n *\n */\nfunction userTimingComparator(\n a: Helpers.Trace.TimeSpan, b: Helpers.Trace.TimeSpan, originalArray: Helpers.Trace.TimeSpan[]): number {\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 // Prefer the event located in a further position in the original array.\n return originalArray.indexOf(b) - originalArray.indexOf(a);\n}\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 syntheticEvents = syntheticEvents.sort((a, b) => userTimingComparator(a, b, [...syntheticEvents]));\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 +{"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\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}\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}\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\n/**\n * Similar to the default {@see Helpers.Trace.eventTimeComparator}\n * but with a twist:\n * In case of equal start and end times, always put the second event\n * first.\n *\n * Explanation:\n * User timing entries come as trace events dispatched when\n * performance.measure/mark is called. The trace events buffered in\n * devtools frontend are sorted by the start time. If their start time\n * is the same, then the event for the first call will appear first.\n *\n * When entries are meant to be stacked, the corresponding\n * performance.measure calls usually are done in bottom-up direction:\n * calls for children first and for parent later (because the call\n * is usually done when the measured task is over). This means that\n * when two user timing events have the start and end time, usually the\n * second event is the parent of the first. Hence the switch.\n *\n */\nfunction userTimingComparator(\n a: Helpers.Trace.TimeSpan, b: Helpers.Trace.TimeSpan, originalArray: Helpers.Trace.TimeSpan[]): number {\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 // Prefer the event located in a further position in the original array.\n return originalArray.indexOf(b) - originalArray.indexOf(a);\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\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 const asyncEvents = [...performanceMeasureEvents, ...consoleTimings];\n syntheticEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents);\n syntheticEvents = syntheticEvents.sort((a, b) => userTimingComparator(a, b, [...syntheticEvents]));\n}\n\nexport function data(): UserTimingsData {\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/WorkersHandler.d.ts b/public/models/trace/handlers/WorkersHandler.d.ts index 89f032d7..84619425 100644 --- a/public/models/trace/handlers/WorkersHandler.d.ts +++ b/public/models/trace/handlers/WorkersHandler.d.ts @@ -4,7 +4,6 @@ export interface WorkersData { workerIdByThread: Map; workerURLById: Map; } -export declare function initialize(): void; export declare function reset(): void; export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; diff --git a/public/models/trace/handlers/WorkersHandler.js b/public/models/trace/handlers/WorkersHandler.js index 3332fa01..05bec225 100644 --- a/public/models/trace/handlers/WorkersHandler.js +++ b/public/models/trace/handlers/WorkersHandler.js @@ -2,34 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Types from '../types/types.js'; -let handlerState = 1 /* HandlerState.UNINITIALIZED */; const sessionIdEvents = []; const workerIdByThread = new Map(); const workerURLById = new Map(); -export function initialize() { - if (handlerState !== 1 /* HandlerState.UNINITIALIZED */) { - throw new Error('Workers Handler was not reset'); - } - handlerState = 2 /* HandlerState.INITIALIZED */; -} export function reset() { sessionIdEvents.length = 0; workerIdByThread.clear(); workerURLById.clear(); - handlerState = 1 /* HandlerState.UNINITIALIZED */; } export function handleEvent(event) { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Workers Handler is not initialized'); - } if (Types.Events.isTracingSessionIdForWorker(event)) { sessionIdEvents.push(event); } } export async function finalize() { - if (handlerState !== 2 /* HandlerState.INITIALIZED */) { - throw new Error('Handler is not initialized'); - } for (const sessionIdEvent of sessionIdEvents) { if (!sessionIdEvent.args.data) { continue; @@ -37,12 +23,8 @@ export async function finalize() { workerIdByThread.set(sessionIdEvent.args.data.workerThreadId, sessionIdEvent.args.data.workerId); workerURLById.set(sessionIdEvent.args.data.workerId, sessionIdEvent.args.data.url); } - handlerState = 3 /* HandlerState.FINALIZED */; } export function data() { - if (handlerState !== 3 /* HandlerState.FINALIZED */) { - throw new Error('Workers Handler is not finalized'); - } return { workerSessionIdEvents: sessionIdEvents, workerIdByThread, diff --git a/public/models/trace/handlers/WorkersHandler.js.map b/public/models/trace/handlers/WorkersHandler.js.map index 9081b222..01bd7127 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,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 +{"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;AAQ3C,MAAM,eAAe,GAA6C,EAAE,CAAC;AACrE,MAAM,gBAAgB,GAAsD,IAAI,GAAG,EAAE,CAAC;AACtF,MAAM,aAAa,GAAuC,IAAI,GAAG,EAAE,CAAC;AAEpE,MAAM,UAAU,KAAK;IACnB,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACzB,aAAa,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,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,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;AACH,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,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\nexport interface WorkersData {\n workerSessionIdEvents: readonly Types.Events.TracingSessionIdForWorker[];\n workerIdByThread: Map;\n workerURLById: Map;\n}\n\nconst sessionIdEvents: Types.Events.TracingSessionIdForWorker[] = [];\nconst workerIdByThread: Map = new Map();\nconst workerURLById: Map = new Map();\n\nexport function reset(): void {\n sessionIdEvents.length = 0;\n workerIdByThread.clear();\n workerURLById.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isTracingSessionIdForWorker(event)) {\n sessionIdEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise {\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}\n\nexport function data(): WorkersData {\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 5468f875..9913ff95 100644 --- a/public/models/trace/handlers/WorkersHandler.test.js +++ b/public/models/trace/handlers/WorkersHandler.test.js @@ -7,7 +7,6 @@ describe('WorkersHandler', () => { beforeEach(async function () { Trace.Handlers.ModelHandlers.Workers.reset(); const events = await TraceLoader.rawEvents(this, 'two-workers.json.gz'); - Trace.Handlers.ModelHandlers.Workers.initialize(); for (const event of events) { Trace.Handlers.ModelHandlers.Workers.handleEvent(event); } diff --git a/public/models/trace/handlers/WorkersHandler.test.js.map b/public/models/trace/handlers/WorkersHandler.test.js.map index ca9f83e2..a4976c1e 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 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 +{"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 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 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/types.d.ts b/public/models/trace/handlers/types.d.ts index 57c3916c..82b230ae 100644 --- a/public/models/trace/handlers/types.d.ts +++ b/public/models/trace/handlers/types.d.ts @@ -2,9 +2,8 @@ import type * as Types from './../types/types.js'; import type * as ModelHandlers from './ModelHandlers.js'; export interface Handler { reset(): void; - initialize?(freshRecording?: boolean): void; handleEvent(data: {}): void; - finalize?(): Promise; + finalize(): Promise; data(): unknown; deps?(): HandlerName[]; handleUserConfig?(config: Types.Configuration.Configuration): void; @@ -30,9 +29,4 @@ type DeepWriteable = { }; export type ParsedTraceMutable = DeepWriteable; export type Handlers = typeof ModelHandlers; -export declare const enum HandlerState { - UNINITIALIZED = 1, - INITIALIZED = 2, - FINALIZED = 3 -} export {}; diff --git a/public/models/trace/handlers/types.js.map b/public/models/trace/handlers/types.js.map index 8a3e3594..b86e3d77 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 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 +{"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 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"]} \ No newline at end of file diff --git a/public/models/trace/insights/CLSCulprits.d.ts b/public/models/trace/insights/CLSCulprits.d.ts new file mode 100644 index 00000000..a366fe0c --- /dev/null +++ b/public/models/trace/insights/CLSCulprits.d.ts @@ -0,0 +1,57 @@ +import type * as Protocol from '../../../generated/protocol.js'; +import * as Types from '../types/types.js'; +import type { InsightModel, InsightSetContext, RequiredData } from './types.js'; +export type CLSCulpritsInsightModel = InsightModel<{ + animationFailures: readonly NoncompositedAnimationFailure[]; + shifts: Map; + clusters: Types.Events.SyntheticLayoutShiftCluster[]; + worstCluster: Types.Events.SyntheticLayoutShiftCluster | undefined; +}>; +export declare function deps(): ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests']; +export declare const enum AnimationFailureReasons { + ACCELERATED_ANIMATIONS_DISABLED = "ACCELERATED_ANIMATIONS_DISABLED", + EFFECT_SUPPRESSED_BY_DEVTOOLS = "EFFECT_SUPPRESSED_BY_DEVTOOLS", + INVALID_ANIMATION_OR_EFFECT = "INVALID_ANIMATION_OR_EFFECT", + EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS = "EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS", + EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE = "EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE", + TARGET_HAS_INVALID_COMPOSITING_STATE = "TARGET_HAS_INVALID_COMPOSITING_STATE", + TARGET_HAS_INCOMPATIBLE_ANIMATIONS = "TARGET_HAS_INCOMPATIBLE_ANIMATIONS", + TARGET_HAS_CSS_OFFSET = "TARGET_HAS_CSS_OFFSET", + ANIMATION_AFFECTS_NON_CSS_PROPERTIES = "ANIMATION_AFFECTS_NON_CSS_PROPERTIES", + TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET = "TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET", + TRANSFROM_BOX_SIZE_DEPENDENT = "TRANSFROM_BOX_SIZE_DEPENDENT", + FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS = "FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS", + UNSUPPORTED_CSS_PROPERTY = "UNSUPPORTED_CSS_PROPERTY", + MIXED_KEYFRAME_VALUE_TYPES = "MIXED_KEYFRAME_VALUE_TYPES", + TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE = "TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE", + ANIMATION_HAS_NO_VISIBLE_CHANGE = "ANIMATION_HAS_NO_VISIBLE_CHANGE", + AFFECTS_IMPORTANT_PROPERTY = "AFFECTS_IMPORTANT_PROPERTY", + SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY = "SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY" +} +export interface NoncompositedAnimationFailure { + /** + * Animation name. + */ + name?: string; + /** + * Failure reason based on mask number defined in + * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22. + */ + failureReasons: AnimationFailureReasons[]; + /** + * Unsupported properties. + */ + unsupportedProperties?: Types.Events.Animation['args']['data']['unsupportedProperties']; + /** + * Animation event. + */ + animation?: Types.Events.SyntheticAnimationPair; +} +export interface LayoutShiftRootCausesData { + iframeIds: string[]; + fontRequests: Types.Events.SyntheticNetworkRequest[]; + nonCompositedAnimations: NoncompositedAnimationFailure[]; + unsizedImages: Protocol.DOM.BackendNodeId[]; +} +export declare function getNonCompositedFailure(animationEvent: Types.Events.SyntheticAnimationPair): NoncompositedAnimationFailure[]; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): CLSCulpritsInsightModel; diff --git a/public/models/trace/insights/CLSCulprits.js b/public/models/trace/insights/CLSCulprits.js new file mode 100644 index 00000000..f93b9982 --- /dev/null +++ b/public/models/trace/insights/CLSCulprits.js @@ -0,0 +1,350 @@ +// 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 Platform from '../../../core/platform/platform.js'; +import * as Helpers from '../helpers/helpers.js'; +import * as Types from '../types/types.js'; +const UIStrings = { + /** Title of an insight that provides details about why elements shift/move on the page. The causes for these shifts are referred to as culprits ("reasons"). */ + title: 'Layout shift culprits', + /** + * @description Description of a DevTools insight that identifies the reasons that elements shift on the page. + * This is displayed after a user expands the section to see more. No character length limits. + */ + description: 'Layout shifts occur when elements move absent any user interaction. [Investigate the causes of layout shifts](https://web.dev/articles/optimize-cls), such as elements being added, removed, or their fonts changing as the page loads.', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/CLSCulprits.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); +export function deps() { + return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests']; +} +/** + * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define + * which bit corresponds to each failure reason. + * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22 + * @type {{flag: number, failure: AnimationFailureReasons}[]} + */ +const ACTIONABLE_FAILURE_REASONS = [ + { + flag: 1 << 0, + failure: "ACCELERATED_ANIMATIONS_DISABLED" /* AnimationFailureReasons.ACCELERATED_ANIMATIONS_DISABLED */, + }, + { + flag: 1 << 1, + failure: "EFFECT_SUPPRESSED_BY_DEVTOOLS" /* AnimationFailureReasons.EFFECT_SUPPRESSED_BY_DEVTOOLS */, + }, + { + flag: 1 << 2, + failure: "INVALID_ANIMATION_OR_EFFECT" /* AnimationFailureReasons.INVALID_ANIMATION_OR_EFFECT */, + }, + { + flag: 1 << 3, + failure: "EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS" /* AnimationFailureReasons.EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS */, + }, + { + flag: 1 << 4, + failure: "EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE" /* AnimationFailureReasons.EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE */, + }, + { + flag: 1 << 5, + failure: "TARGET_HAS_INVALID_COMPOSITING_STATE" /* AnimationFailureReasons.TARGET_HAS_INVALID_COMPOSITING_STATE */, + }, + { + flag: 1 << 6, + failure: "TARGET_HAS_INCOMPATIBLE_ANIMATIONS" /* AnimationFailureReasons.TARGET_HAS_INCOMPATIBLE_ANIMATIONS */, + }, + { + flag: 1 << 7, + failure: "TARGET_HAS_CSS_OFFSET" /* AnimationFailureReasons.TARGET_HAS_CSS_OFFSET */, + }, + // The failure 1 << 8 is marked as obsolete in Blink + { + flag: 1 << 9, + failure: "ANIMATION_AFFECTS_NON_CSS_PROPERTIES" /* AnimationFailureReasons.ANIMATION_AFFECTS_NON_CSS_PROPERTIES */, + }, + { + flag: 1 << 10, + failure: "TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET" /* AnimationFailureReasons.TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET */, + }, + { + flag: 1 << 11, + failure: "TRANSFROM_BOX_SIZE_DEPENDENT" /* AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT */, + }, + { + flag: 1 << 12, + failure: "FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS" /* AnimationFailureReasons.FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS */, + }, + { + flag: 1 << 13, + failure: "UNSUPPORTED_CSS_PROPERTY" /* AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */, + }, + // The failure 1 << 14 is marked as obsolete in Blink + { + flag: 1 << 15, + failure: "MIXED_KEYFRAME_VALUE_TYPES" /* AnimationFailureReasons.MIXED_KEYFRAME_VALUE_TYPES */, + }, + { + flag: 1 << 16, + failure: "TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE" /* AnimationFailureReasons.TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE */, + }, + { + flag: 1 << 17, + failure: "ANIMATION_HAS_NO_VISIBLE_CHANGE" /* AnimationFailureReasons.ANIMATION_HAS_NO_VISIBLE_CHANGE */, + }, + { + flag: 1 << 18, + failure: "AFFECTS_IMPORTANT_PROPERTY" /* AnimationFailureReasons.AFFECTS_IMPORTANT_PROPERTY */, + }, + { + flag: 1 << 19, + failure: "SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY" /* AnimationFailureReasons.SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY */, + }, +]; +// 500ms window. +// Use this window to consider events and requests that may have caused a layout shift. +const ROOT_CAUSE_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5)); +/** + * Returns if an event happens within the root cause window, before the target event. + * ROOT_CAUSE_WINDOW v target event + * |------------------------|======================= + */ +function isInRootCauseWindow(event, targetEvent) { + const eventEnd = event.dur ? event.ts + event.dur : event.ts; + return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - ROOT_CAUSE_WINDOW; +} +export function getNonCompositedFailure(animationEvent) { + const failures = []; + const beginEvent = animationEvent.args.data.beginEvent; + const instantEvents = animationEvent.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) { + continue; + } + const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => reason.failure); + const failure = { + name: beginEvent.args.data.displayName, + failureReasons, + unsupportedProperties, + animation: animationEvent, + }; + failures.push(failure); + } + return failures; +} +function getNonCompositedFailureRootCauses(animationEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift) { + const allAnimationFailures = []; + for (const animation of animationEvents) { + /** + * 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. + */ + const failures = getNonCompositedFailure(animation); + if (!failures) { + continue; + } + allAnimationFailures.push(...failures); + const nextPrePaint = getNextEvent(prePaintEvents, animation); + // If no following prePaint, this is not a root cause. + if (!nextPrePaint) { + continue; + } + // If the animation event is outside the ROOT_CAUSE_WINDOW, it could not be a root cause. + if (!isInRootCauseWindow(animation, nextPrePaint)) { + continue; + } + const shifts = shiftsByPrePaint.get(nextPrePaint); + // if no layout shift(s), this is not a root cause. + if (!shifts) { + continue; + } + for (const shift of shifts) { + const rootCausesForShift = rootCausesByShift.get(shift); + if (!rootCausesForShift) { + throw new Error('Unaccounted shift'); + } + rootCausesForShift.nonCompositedAnimations.push(...failures); + } + } + return allAnimationFailures; +} +/** + * Given an array of layout shift and PrePaint events, returns a mapping from + * PrePaint events to layout shifts dispatched within it. + */ +function getShiftsByPrePaintEvents(layoutShifts, prePaintEvents) { + // Maps from PrePaint events to LayoutShifts that occured in each one. + const shiftsByPrePaint = new Map(); + // Associate all shifts to their corresponding PrePaint. + for (const prePaintEvent of prePaintEvents) { + const firstShiftIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts); + if (firstShiftIndex === null) { + // No layout shifts registered after this PrePaint start. Continue. + continue; + } + for (let i = firstShiftIndex; i < layoutShifts.length; i++) { + const shift = layoutShifts[i]; + if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) { + const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []); + shiftsInPrePaint.push(shift); + } + if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) { + // Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event. + break; + } + } + } + return shiftsByPrePaint; +} +/** + * Given a source event list, this returns the first event of that list that directly follows the target event. + */ +function getNextEvent(sourceEvents, targetEvent) { + const index = Platform.ArrayUtilities.nearestIndexFromBeginning(sourceEvents, source => source.ts > targetEvent.ts + (targetEvent.dur || 0)); + // No PrePaint event registered after this event + if (index === null) { + return undefined; + } + return sourceEvents[index]; +} +/** + * An Iframe is considered a root cause if the iframe event occurs before a prePaint event + * and within this prePaint event a layout shift(s) occurs. + */ +function getIframeRootCauses(iframeCreatedEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift, domLoadingEvents) { + for (const iframeEvent of iframeCreatedEvents) { + const nextPrePaint = getNextEvent(prePaintEvents, iframeEvent); + // If no following prePaint, this is not a root cause. + if (!nextPrePaint) { + continue; + } + const shifts = shiftsByPrePaint.get(nextPrePaint); + // if no layout shift(s), this is not a root cause. + if (!shifts) { + continue; + } + for (const shift of shifts) { + const rootCausesForShift = rootCausesByShift.get(shift); + if (!rootCausesForShift) { + throw new Error('Unaccounted shift'); + } + // Look for the first dom event that occurs within the bounds of the iframe event. + // This contains the frame id. + const domEvent = domLoadingEvents.find(e => { + const maxIframe = Types.Timing.MicroSeconds(iframeEvent.ts + (iframeEvent.dur ?? 0)); + return e.ts >= iframeEvent.ts && e.ts <= maxIframe; + }); + if (domEvent && domEvent.args.frame) { + rootCausesForShift.iframeIds.push(domEvent.args.frame); + } + } + } + return rootCausesByShift; +} +/** + * An unsized image is considered a root cause if its PaintImage can be correlated to a + * layout shift. We can correlate PaintImages with unsized images by their matching nodeIds. + * X <- layout shift + * |----------------| + * ^ PrePaint event |-----| + * ^ PaintImage + */ +function getUnsizedImageRootCauses(unsizedImageEvents, paintImageEvents, shiftsByPrePaint, rootCausesByShift) { + shiftsByPrePaint.forEach((shifts, prePaint) => { + const paintImage = getNextEvent(paintImageEvents, prePaint); + // The unsized image corresponds to this PaintImage. + const matchingNode = unsizedImageEvents.find(unsizedImage => unsizedImage.args.data.nodeId === paintImage?.args.data.nodeId); + if (!matchingNode) { + return; + } + // The unsized image is a potential root cause of all the shifts of this prePaint. + for (const shift of shifts) { + const rootCausesForShift = rootCausesByShift.get(shift); + if (!rootCausesForShift) { + throw new Error('Unaccounted shift'); + } + rootCausesForShift.unsizedImages.push(matchingNode.args.data.nodeId); + } + }); + return rootCausesByShift; +} +/** + * A font request is considered a root cause if the request occurs before a prePaint event + * and within this prePaint event a layout shift(s) occurs. Additionally, this font request should + * happen within the ROOT_CAUSE_WINDOW of the prePaint event. + */ +function getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift) { + const fontRequests = networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font')); + for (const req of fontRequests) { + const nextPrePaint = getNextEvent(prePaintEvents, req); + if (!nextPrePaint) { + continue; + } + // If the req is outside the ROOT_CAUSE_WINDOW, it could not be a root cause. + if (!isInRootCauseWindow(req, nextPrePaint)) { + continue; + } + // Get the shifts that belong to this prepaint + const shifts = shiftsByPrePaint.get(nextPrePaint); + // if no layout shift(s) in this prePaint, the request is not a root cause. + if (!shifts) { + continue; + } + // Include the root cause to the shifts in this prePaint. + for (const shift of shifts) { + const rootCausesForShift = rootCausesByShift.get(shift); + if (!rootCausesForShift) { + throw new Error('Unaccounted shift'); + } + rootCausesForShift.fontRequests.push(req); + } + } + return rootCausesByShift; +} +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} +export function generateInsight(parsedTrace, context) { + const isWithinContext = (event) => Helpers.Timing.eventIsInBounds(event, context.bounds); + const compositeAnimationEvents = parsedTrace.Animations.animations.filter(isWithinContext); + const iframeEvents = parsedTrace.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinContext); + const networkRequests = parsedTrace.NetworkRequests.byTime.filter(isWithinContext); + const domLoadingEvents = parsedTrace.LayoutShifts.domLoadingEvents.filter(isWithinContext); + const unsizedImageEvents = parsedTrace.LayoutShifts.layoutImageUnsizedEvents.filter(isWithinContext); + const clusterKey = context.navigation ? context.navigationId : Types.Events.NO_NAVIGATION; + const clusters = parsedTrace.LayoutShifts.clustersByNavigationId.get(clusterKey) ?? []; + const clustersByScore = clusters.toSorted((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore); + const worstCluster = clustersByScore.at(0); + const layoutShifts = clusters.flatMap(cluster => cluster.events); + const prePaintEvents = parsedTrace.LayoutShifts.prePaintEvents.filter(isWithinContext); + const paintImageEvents = parsedTrace.LayoutShifts.paintImageEvents.filter(isWithinContext); + // Get root causes. + const rootCausesByShift = new Map(); + const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents); + for (const shift of layoutShifts) { + rootCausesByShift.set(shift, { iframeIds: [], fontRequests: [], nonCompositedAnimations: [], unsizedImages: [] }); + } + // Populate root causes for rootCausesByShift. + getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift, domLoadingEvents); + getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift); + getUnsizedImageRootCauses(unsizedImageEvents, paintImageEvents, shiftsByPrePaint, rootCausesByShift); + const animationFailures = getNonCompositedFailureRootCauses(compositeAnimationEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift); + const relatedEvents = [...layoutShifts]; + if (worstCluster) { + relatedEvents.push(worstCluster); + } + return finalize({ + relatedEvents, + animationFailures, + shifts: rootCausesByShift, + clusters, + worstCluster, + }); +} +//# sourceMappingURL=CLSCulprits.js.map \ No newline at end of file diff --git a/public/models/trace/insights/CLSCulprits.js.map b/public/models/trace/insights/CLSCulprits.js.map new file mode 100644 index 00000000..66251f92 --- /dev/null +++ b/public/models/trace/insights/CLSCulprits.js.map @@ -0,0 +1 @@ +{"version":3,"file":"CLSCulprits.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/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 Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightModel, InsightSetContext, RequiredData} from './types.js';\n\nconst UIStrings = {\n /** Title of an insight that provides details about why elements shift/move on the page. The causes for these shifts are referred to as culprits (\"reasons\"). */\n title: 'Layout shift culprits',\n /**\n * @description Description of a DevTools insight that identifies the reasons that elements shift on the page.\n * This is displayed after a user expands the section to see more. No character length limits.\n */\n description:\n 'Layout shifts occur when elements move absent any user interaction. [Investigate the causes of layout shifts](https://web.dev/articles/optimize-cls), such as elements being added, removed, or their fonts changing as the page loads.',\n};\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/CLSCulprits.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type CLSCulpritsInsightModel = InsightModel<{\n animationFailures: readonly NoncompositedAnimationFailure[],\n shifts: Map,\n clusters: Types.Events.SyntheticLayoutShiftCluster[],\n worstCluster: Types.Events.SyntheticLayoutShiftCluster | undefined,\n}>;\n\nexport function deps(): ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'] {\n return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'];\n}\n\nexport const enum AnimationFailureReasons {\n ACCELERATED_ANIMATIONS_DISABLED = 'ACCELERATED_ANIMATIONS_DISABLED',\n EFFECT_SUPPRESSED_BY_DEVTOOLS = 'EFFECT_SUPPRESSED_BY_DEVTOOLS',\n INVALID_ANIMATION_OR_EFFECT = 'INVALID_ANIMATION_OR_EFFECT',\n EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS = 'EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS',\n EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE = 'EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE',\n TARGET_HAS_INVALID_COMPOSITING_STATE = 'TARGET_HAS_INVALID_COMPOSITING_STATE',\n TARGET_HAS_INCOMPATIBLE_ANIMATIONS = 'TARGET_HAS_INCOMPATIBLE_ANIMATIONS',\n TARGET_HAS_CSS_OFFSET = 'TARGET_HAS_CSS_OFFSET',\n ANIMATION_AFFECTS_NON_CSS_PROPERTIES = 'ANIMATION_AFFECTS_NON_CSS_PROPERTIES',\n TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET =\n 'TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET',\n TRANSFROM_BOX_SIZE_DEPENDENT = 'TRANSFROM_BOX_SIZE_DEPENDENT',\n FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS = 'FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS',\n UNSUPPORTED_CSS_PROPERTY = 'UNSUPPORTED_CSS_PROPERTY',\n MIXED_KEYFRAME_VALUE_TYPES = 'MIXED_KEYFRAME_VALUE_TYPES',\n TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE = 'TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE',\n ANIMATION_HAS_NO_VISIBLE_CHANGE = 'ANIMATION_HAS_NO_VISIBLE_CHANGE',\n AFFECTS_IMPORTANT_PROPERTY = 'AFFECTS_IMPORTANT_PROPERTY',\n SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY = 'SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY',\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 * Animation event.\n */\n animation?: Types.Events.SyntheticAnimationPair;\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 << 0,\n failure: AnimationFailureReasons.ACCELERATED_ANIMATIONS_DISABLED,\n },\n {\n flag: 1 << 1,\n failure: AnimationFailureReasons.EFFECT_SUPPRESSED_BY_DEVTOOLS,\n },\n {\n flag: 1 << 2,\n failure: AnimationFailureReasons.INVALID_ANIMATION_OR_EFFECT,\n },\n {\n flag: 1 << 3,\n failure: AnimationFailureReasons.EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS,\n },\n {\n flag: 1 << 4,\n failure: AnimationFailureReasons.EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE,\n },\n {\n flag: 1 << 5,\n failure: AnimationFailureReasons.TARGET_HAS_INVALID_COMPOSITING_STATE,\n },\n {\n flag: 1 << 6,\n failure: AnimationFailureReasons.TARGET_HAS_INCOMPATIBLE_ANIMATIONS,\n },\n {\n flag: 1 << 7,\n failure: AnimationFailureReasons.TARGET_HAS_CSS_OFFSET,\n },\n // The failure 1 << 8 is marked as obsolete in Blink\n {\n flag: 1 << 9,\n failure: AnimationFailureReasons.ANIMATION_AFFECTS_NON_CSS_PROPERTIES,\n },\n {\n flag: 1 << 10,\n failure: AnimationFailureReasons.TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET,\n },\n {\n flag: 1 << 11,\n failure: AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT,\n },\n {\n flag: 1 << 12,\n failure: AnimationFailureReasons.FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS,\n },\n {\n flag: 1 << 13,\n failure: AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,\n },\n // The failure 1 << 14 is marked as obsolete in Blink\n {\n flag: 1 << 15,\n failure: AnimationFailureReasons.MIXED_KEYFRAME_VALUE_TYPES,\n },\n {\n flag: 1 << 16,\n failure: AnimationFailureReasons.TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE,\n },\n {\n flag: 1 << 17,\n failure: AnimationFailureReasons.ANIMATION_HAS_NO_VISIBLE_CHANGE,\n },\n {\n flag: 1 << 18,\n failure: AnimationFailureReasons.AFFECTS_IMPORTANT_PROPERTY,\n },\n {\n flag: 1 << 19,\n failure: AnimationFailureReasons.SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY,\n },\n];\n\n// 500ms window.\n// Use this window to consider events and requests that may have caused a layout shift.\nconst ROOT_CAUSE_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\nexport interface LayoutShiftRootCausesData {\n iframeIds: string[];\n fontRequests: Types.Events.SyntheticNetworkRequest[];\n nonCompositedAnimations: NoncompositedAnimationFailure[];\n unsizedImages: Protocol.DOM.BackendNodeId[];\n}\n\n/**\n * Returns if an event happens within the root cause window, before the target event.\n * ROOT_CAUSE_WINDOW v target event\n * |------------------------|=======================\n */\nfunction isInRootCauseWindow(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 - ROOT_CAUSE_WINDOW;\n}\n\nexport function getNonCompositedFailure(animationEvent: Types.Events.SyntheticAnimationPair):\n NoncompositedAnimationFailure[] {\n const failures: NoncompositedAnimationFailure[] = [];\n const beginEvent = animationEvent.args.data.beginEvent;\n const instantEvents = animationEvent.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) {\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 animation: animationEvent,\n };\n failures.push(failure);\n }\n return failures;\n}\n\nfunction getNonCompositedFailureRootCauses(\n animationEvents: Types.Events.SyntheticAnimationPair[],\n prePaintEvents: Types.Events.PrePaint[],\n shiftsByPrePaint: Map,\n rootCausesByShift: Map,\n ): NoncompositedAnimationFailure[] {\n const allAnimationFailures: NoncompositedAnimationFailure[] = [];\n for (const animation of animationEvents) {\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 const failures = getNonCompositedFailure(animation);\n if (!failures) {\n continue;\n }\n allAnimationFailures.push(...failures);\n\n const nextPrePaint = getNextEvent(prePaintEvents, animation) as Types.Events.PrePaint | null;\n // If no following prePaint, this is not a root cause.\n if (!nextPrePaint) {\n continue;\n }\n\n // If the animation event is outside the ROOT_CAUSE_WINDOW, it could not be a root cause.\n if (!isInRootCauseWindow(animation, nextPrePaint)) {\n continue;\n }\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\n for (const shift of shifts) {\n const rootCausesForShift = rootCausesByShift.get(shift);\n if (!rootCausesForShift) {\n throw new Error('Unaccounted shift');\n }\n rootCausesForShift.nonCompositedAnimations.push(...failures);\n }\n }\n\n return allAnimationFailures;\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 * Given a source event list, this returns the first event of that list that directly follows the target event.\n */\nfunction getNextEvent(sourceEvents: Types.Events.Event[], targetEvent: Types.Events.Event): Types.Events.Event|\n undefined {\n const index = Platform.ArrayUtilities.nearestIndexFromBeginning(\n sourceEvents, source => source.ts > targetEvent.ts + (targetEvent.dur || 0));\n // No PrePaint event registered after this event\n if (index === null) {\n return undefined;\n }\n\n return sourceEvents[index];\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 = getNextEvent(prePaintEvents, iframeEvent) as Types.Events.PrePaint | null;\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 = rootCausesByShift.get(shift);\n if (!rootCausesForShift) {\n throw new Error('Unaccounted shift');\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 * An unsized image is considered a root cause if its PaintImage can be correlated to a\n * layout shift. We can correlate PaintImages with unsized images by their matching nodeIds.\n * X <- layout shift\n * |----------------|\n * ^ PrePaint event |-----|\n * ^ PaintImage\n */\nfunction getUnsizedImageRootCauses(\n unsizedImageEvents: readonly Types.Events.LayoutImageUnsized[], paintImageEvents: Types.Events.PaintImage[],\n shiftsByPrePaint: Map,\n rootCausesByShift: Map):\n Map {\n shiftsByPrePaint.forEach((shifts, prePaint) => {\n const paintImage = getNextEvent(paintImageEvents, prePaint) as Types.Events.PaintImage | null;\n // The unsized image corresponds to this PaintImage.\n const matchingNode =\n unsizedImageEvents.find(unsizedImage => unsizedImage.args.data.nodeId === paintImage?.args.data.nodeId);\n if (!matchingNode) {\n return;\n }\n // The unsized image is a potential root cause of all the shifts of this prePaint.\n for (const shift of shifts) {\n const rootCausesForShift = rootCausesByShift.get(shift);\n if (!rootCausesForShift) {\n throw new Error('Unaccounted shift');\n }\n rootCausesForShift.unsizedImages.push(matchingNode.args.data.nodeId);\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 ROOT_CAUSE_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 = getNextEvent(prePaintEvents, req) as Types.Events.PrePaint | null;\n if (!nextPrePaint) {\n continue;\n }\n\n // If the req is outside the ROOT_CAUSE_WINDOW, it could not be a root cause.\n if (!isInRootCauseWindow(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 = rootCausesByShift.get(shift);\n if (!rootCausesForShift) {\n throw new Error('Unaccounted shift');\n }\n rootCausesForShift.fontRequests.push(req);\n }\n }\n return rootCausesByShift;\n}\n\nfunction finalize(partialModel: Omit): CLSCulpritsInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): CLSCulpritsInsightModel {\n const isWithinContext = (event: Types.Events.Event): boolean => Helpers.Timing.eventIsInBounds(event, context.bounds);\n\n const compositeAnimationEvents = parsedTrace.Animations.animations.filter(isWithinContext);\n const iframeEvents = parsedTrace.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinContext);\n const networkRequests = parsedTrace.NetworkRequests.byTime.filter(isWithinContext);\n const domLoadingEvents = parsedTrace.LayoutShifts.domLoadingEvents.filter(isWithinContext);\n const unsizedImageEvents = parsedTrace.LayoutShifts.layoutImageUnsizedEvents.filter(isWithinContext);\n\n const clusterKey = context.navigation ? context.navigationId : Types.Events.NO_NAVIGATION;\n const clusters = parsedTrace.LayoutShifts.clustersByNavigationId.get(clusterKey) ?? [];\n const clustersByScore = clusters.toSorted((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore);\n const worstCluster = clustersByScore.at(0);\n const layoutShifts = clusters.flatMap(cluster => cluster.events);\n const prePaintEvents = parsedTrace.LayoutShifts.prePaintEvents.filter(isWithinContext);\n const paintImageEvents = parsedTrace.LayoutShifts.paintImageEvents.filter(isWithinContext);\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: [], nonCompositedAnimations: [], unsizedImages: []});\n }\n\n // Populate root causes for rootCausesByShift.\n getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift, domLoadingEvents);\n getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n getUnsizedImageRootCauses(unsizedImageEvents, paintImageEvents, shiftsByPrePaint, rootCausesByShift);\n const animationFailures =\n getNonCompositedFailureRootCauses(compositeAnimationEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n\n const relatedEvents: Types.Events.Event[] = [...layoutShifts];\n if (worstCluster) {\n relatedEvents.push(worstCluster);\n }\n\n return finalize({\n relatedEvents,\n animationFailures,\n shifts: rootCausesByShift,\n clusters,\n worstCluster,\n });\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/CLSCulprits.test.d.ts b/public/models/trace/insights/CLSCulprits.test.d.ts new file mode 100644 index 00000000..29614938 --- /dev/null +++ b/public/models/trace/insights/CLSCulprits.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/CLSCulprits.test.js b/public/models/trace/insights/CLSCulprits.test.js new file mode 100644 index 00000000..c84c8909 --- /dev/null +++ b/public/models/trace/insights/CLSCulprits.test.js @@ -0,0 +1,216 @@ +// Copyright 2022 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, getInsightOrError } 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 { Models } from './insights.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 }; +} +// Root cause invalidation window. +const INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5)); +describeWithEnvironment('CLSCulprits', 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 firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { animationFailures } = insight; + const simpleAnimation = data.Animations.animations.find(animation => { + return animation.args.data.beginEvent.args.data.displayName === 'simple-animation'; + }); + const top = data.Animations.animations.find(animation => { + return animation.args.data.beginEvent.args.data.displayName === 'top'; + }); + const expected = [ + { + name: 'simple-animation', + failureReasons: ["UNSUPPORTED_CSS_PROPERTY" /* Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */], + unsupportedProperties: ['color'], + animation: simpleAnimation, + }, + { + name: 'top', + failureReasons: [ + "TARGET_HAS_INVALID_COMPOSITING_STATE" /* Models.CLSCulprits.AnimationFailureReasons.TARGET_HAS_INVALID_COMPOSITING_STATE */, + "UNSUPPORTED_CSS_PROPERTY" /* Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */, + ], + unsupportedProperties: ['top'], + animation: top, + }, + ]; + assert.deepStrictEqual(animationFailures, expected); + }); + // Flaky test. + it.skip('[crbug.com/370382177]: gets the correct non composited animations for shift', async function () { + const { data, insights } = await processTrace(this, 'non-composited-animation-shift.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { shifts, animationFailures } = insight; + const simpleAnimation = data.Animations.animations.find(animation => { + return animation.args.data.beginEvent.args.data.displayName === 'simple-animation'; + }); + const top = data.Animations.animations.find(animation => { + return animation.args.data.beginEvent.args.data.displayName === 'top'; + }); + const shiftAnimations = []; + shifts.forEach(entry => { + shiftAnimations.push(...entry.nonCompositedAnimations); + }); + const expectedWithShift = [ + { + name: 'simple-animation', + failureReasons: ["UNSUPPORTED_CSS_PROPERTY" /* Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */], + unsupportedProperties: ['height', 'color', 'top'], + animation: simpleAnimation, + }, + ]; + assert.deepStrictEqual(shiftAnimations, expectedWithShift); + const expectedAll = [ + { + name: 'simple-animation', + failureReasons: ["UNSUPPORTED_CSS_PROPERTY" /* Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */], + unsupportedProperties: ['height', 'color', 'top'], + animation: simpleAnimation, + }, + { + name: 'top', + failureReasons: ["UNSUPPORTED_CSS_PROPERTY" /* Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */], + unsupportedProperties: ['top'], + animation: top, + }, + ]; + // animationFailures should include both root causes failures, and failures without associated shifts. + assert.deepStrictEqual(animationFailures, expectedAll); + }); + it('returns no insights when there are no non-composited animations', async function () { + const { data, insights } = await processTrace(this, 'lcp-images.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { animationFailures } = insight; + assert.isEmpty(animationFailures); + }); + }); + describe('layout shifts', function () { + it('returns correct layout shifts', async function () { + const { data, insights } = await processTrace(this, 'cls-single-frame.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { shifts } = insight; + assert.exists(shifts); + assert.strictEqual(shifts.size, 7); + }); + describe('root causes', 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 firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { shifts } = insight; + assert.exists(shifts); + assert.strictEqual(shifts.size, 3); + const shift1 = Array.from(shifts)[0][0]; + const shiftIframes = shifts.get(shift1)?.iframeIds; + assert.exists(shiftIframes); + assert.strictEqual(shiftIframes.length, 1); + const iframe = shiftIframes[0]; + // Find the event with the matching frame id to make sure we got the right id. + const dlEvent = data.LayoutShifts.domLoadingEvents.find(e => { + return e.args.frame === iframe; + }); + assert.exists(dlEvent); + // Ensure the iframe happens within the invalidation window. + assert.isTrue(dlEvent.ts < shift1.ts && dlEvent.ts >= shift1.ts - INVALIDATION_WINDOW); + // Other shifts should not have iframe root causes. + const shift2 = Array.from(shifts)[1][0]; + assert.isEmpty(shifts.get(shift2)?.iframeIds); + const shift3 = Array.from(shifts)[2][0]; + assert.isEmpty(shifts.get(shift3)?.iframeIds); + }); + 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 firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { shifts } = insight; + assert.exists(shifts); + assert.strictEqual(shifts.size, 3); + const layoutShiftEvents = Array.from(shifts.entries()); + const shift2 = layoutShiftEvents.at(1); + assert.isOk(shift2); + const shiftEvent = shift2[0]; + const shiftFonts = shift2[1].fontRequests; + assert.exists(shiftFonts); + assert.strictEqual(shiftFonts.length, 1); + const fontRequest = shiftFonts[0]; + const fontRequestEndTime = fontRequest.ts + fontRequest.dur; + // Ensure the font loads within the invalidation window. + assert.isTrue(fontRequestEndTime < shiftEvent.ts && fontRequestEndTime >= shiftEvent.ts - INVALIDATION_WINDOW); + // Other shifts should not have font root causes. + const shift1 = layoutShiftEvents.at(0); + assert.isOk(shift1); + assert.isEmpty(shift1[1].fontRequests); + const shift3 = layoutShiftEvents.at(2); + assert.isOk(shift3); + assert.isEmpty(shift3[1].fontRequests); + }); + it('handles potential unsized images root cause correctly', async function () { + const { data, insights } = await processTrace(this, 'unsized-images.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { shifts } = insight; + assert.exists(shifts); + assert.strictEqual(shifts.size, 2); + const unsizedImages = data.LayoutShifts.layoutImageUnsizedEvents; + assert.strictEqual(unsizedImages.length, 2); + const layoutShiftEvents = Array.from(shifts.entries()); + const shift1 = layoutShiftEvents.at(0); + assert.isOk(shift1); + // Root cause should match the nodeId of the unsized images events. + assert.strictEqual(shift1[1].unsizedImages[0], unsizedImages[0].args.data.nodeId); + const shift2 = layoutShiftEvents.at(1); + assert.isOk(shift2); + assert.strictEqual(shift2[1].unsizedImages[0], unsizedImages[1].args.data.nodeId); + }); + }); + }); + describe('clusters', function () { + it('returns clusters correctly', async function () { + const { data, insights } = await processTrace(this, 'iframe-shift.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('CLSCulprits', insights, firstNav); + const { shifts, clusters } = insight; + assert.exists(clusters); + assert.exists(shifts); + assert.strictEqual(clusters.length, 2); + for (const cluster of clusters) { + // Check that the cluster events exist in shifts map. + for (const shiftEvent of cluster.events) { + assert.exists(shifts.get(shiftEvent)); + } + } + }); + it('returns clusters correctly for non-navigations', async function () { + const { insights } = await processTrace(this, 'cls-no-nav.json.gz'); + const insight = getInsightOrError('CLSCulprits', insights); + const { shifts, clusters } = insight; + assert.exists(clusters); + assert.exists(shifts); + assert.strictEqual(clusters.length, 3); + for (const cluster of clusters) { + // Check that the cluster events exist in shifts map. + for (const shiftEvent of cluster.events) { + assert.exists(shifts.get(shiftEvent)); + } + } + }); + }); +}); +//# sourceMappingURL=CLSCulprits.test.js.map \ No newline at end of file diff --git a/public/models/trace/insights/CLSCulprits.test.js.map b/public/models/trace/insights/CLSCulprits.test.js.map new file mode 100644 index 00000000..57c104ab --- /dev/null +++ b/public/models/trace/insights/CLSCulprits.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"CLSCulprits.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CLSCulprits.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, getInsightOrError} 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 {Models} 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('CLSCulprits', 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 = getInsightOrError('CLSCulprits', insights, firstNav);\n const {animationFailures} = insight;\n\n const simpleAnimation = data.Animations.animations.find(animation => {\n return animation.args.data.beginEvent.args.data.displayName === 'simple-animation';\n });\n const top = data.Animations.animations.find(animation => {\n return animation.args.data.beginEvent.args.data.displayName === 'top';\n });\n\n const expected: Models.CLSCulprits.NoncompositedAnimationFailure[] = [\n {\n name: 'simple-animation',\n failureReasons: [Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['color'],\n animation: simpleAnimation,\n },\n {\n name: 'top',\n failureReasons: [\n Models.CLSCulprits.AnimationFailureReasons.TARGET_HAS_INVALID_COMPOSITING_STATE,\n Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,\n ],\n unsupportedProperties: ['top'],\n animation: top,\n },\n ];\n assert.deepStrictEqual(animationFailures, expected);\n });\n // Flaky test.\n it.skip('[crbug.com/370382177]: gets the correct non composited animations for shift', async function() {\n const {data, insights} = await processTrace(this, 'non-composited-animation-shift.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsightOrError('CLSCulprits', insights, firstNav);\n const {shifts, animationFailures} = insight;\n\n const simpleAnimation = data.Animations.animations.find(animation => {\n return animation.args.data.beginEvent.args.data.displayName === 'simple-animation';\n });\n const top = data.Animations.animations.find(animation => {\n return animation.args.data.beginEvent.args.data.displayName === 'top';\n });\n\n const shiftAnimations: Models.CLSCulprits.NoncompositedAnimationFailure[] = [];\n shifts.forEach(entry => {\n shiftAnimations.push(...entry.nonCompositedAnimations);\n });\n const expectedWithShift: Models.CLSCulprits.NoncompositedAnimationFailure[] = [\n {\n name: 'simple-animation',\n failureReasons: [Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['height', 'color', 'top'],\n animation: simpleAnimation,\n },\n ];\n assert.deepStrictEqual(shiftAnimations, expectedWithShift);\n\n const expectedAll: Models.CLSCulprits.NoncompositedAnimationFailure[] = [\n {\n name: 'simple-animation',\n failureReasons: [Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['height', 'color', 'top'],\n animation: simpleAnimation,\n },\n {\n name: 'top',\n failureReasons: [Models.CLSCulprits.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['top'],\n animation: top,\n },\n ];\n // animationFailures should include both root causes failures, and failures without associated shifts.\n assert.deepStrictEqual(animationFailures, expectedAll);\n });\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 = getInsightOrError('CLSCulprits', 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 = getInsightOrError('CLSCulprits', 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 = getInsightOrError('CLSCulprits', 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 = getInsightOrError('CLSCulprits', 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 it('handles potential unsized images root cause correctly', async function() {\n const {data, insights} = await processTrace(this, 'unsized-images.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsightOrError('CLSCulprits', insights, firstNav);\n const {shifts} = insight;\n assert.exists(shifts);\n assert.strictEqual(shifts.size, 2);\n\n const unsizedImages = data.LayoutShifts.layoutImageUnsizedEvents;\n assert.strictEqual(unsizedImages.length, 2);\n\n const layoutShiftEvents = Array.from(shifts.entries());\n const shift1 = layoutShiftEvents.at(0);\n assert.isOk(shift1);\n // Root cause should match the nodeId of the unsized images events.\n assert.strictEqual(shift1[1].unsizedImages[0], unsizedImages[0].args.data.nodeId);\n\n const shift2 = layoutShiftEvents.at(1);\n assert.isOk(shift2);\n assert.strictEqual(shift2[1].unsizedImages[0], unsizedImages[1].args.data.nodeId);\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 = getInsightOrError('CLSCulprits', 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 it('returns clusters correctly for non-navigations', async function() {\n const {insights} = await processTrace(this, 'cls-no-nav.json.gz');\n const insight = getInsightOrError('CLSCulprits', insights);\n const {shifts, clusters} = insight;\n\n assert.exists(clusters);\n assert.exists(shifts);\n assert.strictEqual(clusters.length, 3);\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/Common.d.ts b/public/models/trace/insights/Common.d.ts index bc42edfe..eca74c29 100644 --- a/public/models/trace/insights/Common.d.ts +++ b/public/models/trace/insights/Common.d.ts @@ -1,10 +1,2 @@ -import type * as Handlers from '../handlers/handlers.js'; -import type * as Types from '../types/types.js'; -import type { InsightResults, InsightSetContextWithNavigation, TraceInsightSets } from './types.js'; -export declare function getInsight(insightName: InsightName, insights: TraceInsightSets | null, key: string | null): InsightResults[InsightName] | null; -/** - * Finds a network request given a navigation context and URL. - * Considers redirects. - */ -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; +import type { InsightModels, TraceInsightSets } from './types.js'; +export declare function getInsight(insightName: InsightName, insights: TraceInsightSets | null, key: string | null): InsightModels[InsightName] | null; diff --git a/public/models/trace/insights/Common.js b/public/models/trace/insights/Common.js index 4c428487..72393421 100644 --- a/public/models/trace/insights/Common.js +++ b/public/models/trace/insights/Common.js @@ -1,7 +1,6 @@ // 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 getInsight(insightName, insights, key) { if (!insights || !key) { return null; @@ -10,45 +9,11 @@ export function getInsight(insightName, insights, key) { if (!insightSets) { return null; } - const insight = insightSets.data[insightName]; + const insight = insightSets.model[insightName]; if (insight instanceof Error) { return null; } // For some reason typescript won't narrow the type by removing Error, so do it manually. return insight; } -/** - * Finds a network request given a navigation context and URL. - * Considers redirects. - */ -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, parsedTrace.Meta.navigationsByFrameId); - return nav === context.navigation; - }); - return request ?? null; -} -export function findLCPRequest(parsedTrace, context, lcpEvent) { - const lcpNodeId = lcpEvent.args.data?.nodeId; - if (!lcpNodeId) { - throw new Error('no lcp node id'); - } - const imagePaint = parsedTrace.LargestImagePaint.get(lcpNodeId); - if (!imagePaint) { - return null; - } - const lcpUrl = imagePaint.args.data?.imageUrl; - if (!lcpUrl) { - throw new Error('no lcp url'); - } - const lcpRequest = findRequest(parsedTrace, context, lcpUrl); - if (!lcpRequest) { - throw new Error('no lcp request found'); - } - return lcpRequest; -} //# sourceMappingURL=Common.js.map \ No newline at end of file diff --git a/public/models/trace/insights/Common.js.map b/public/models/trace/insights/Common.js.map index c0b62451..d7e71416 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,MAAM,UAAU,UAAU,CACtB,WAAwB,EAAE,QAA+B,EAAE,GAAgB;IAC7E,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yFAAyF;IACzF,OAAO,OAAsC,CAAC;AAChD,CAAC;AAED;;;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 {InsightResults, InsightSetContextWithNavigation, TraceInsightSets} from './types.js';\n\nexport function getInsight(\n insightName: InsightName, insights: TraceInsightSets|null, key: string|null): InsightResults[InsightName]|null {\n if (!insights || !key) {\n return null;\n }\n\n const insightSets = insights.get(key);\n if (!insightSets) {\n return null;\n }\n\n const insight = insightSets.data[insightName];\n if (insight instanceof Error) {\n return null;\n }\n\n // For some reason typescript won't narrow the type by removing Error, so do it manually.\n return insight as InsightResults[InsightName];\n}\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 +{"version":3,"file":"Common.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Common.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,MAAM,UAAU,UAAU,CACtB,WAAwB,EAAE,QAA+B,EAAE,GAAgB;IAC7E,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yFAAyF;IACzF,OAAO,OAAqC,CAAC;AAC/C,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 {InsightModels, TraceInsightSets} from './types.js';\n\nexport function getInsight(\n insightName: InsightName, insights: TraceInsightSets|null, key: string|null): InsightModels[InsightName]|null {\n if (!insights || !key) {\n return null;\n }\n\n const insightSets = insights.get(key);\n if (!insightSets) {\n return null;\n }\n\n const insight = insightSets.model[insightName];\n if (insight instanceof Error) {\n return null;\n }\n\n // For some reason typescript won't narrow the type by removing Error, so do it manually.\n return insight as InsightModels[InsightName];\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 4eb8ac49..9f308354 100644 --- a/public/models/trace/insights/DocumentLatency.d.ts +++ b/public/models/trace/insights/DocumentLatency.d.ts @@ -1,6 +1,6 @@ import * as Types from '../types/types.js'; -import type { InsightResult, InsightSetContext, RequiredData } from './types.js'; -export type DocumentLatencyInsightResult = InsightResult<{ +import type { InsightModel, InsightSetContext, RequiredData } from './types.js'; +export type DocumentLatencyInsightModel = InsightModel<{ data?: { serverResponseTime: Types.Timing.MilliSeconds; serverResponseTooSlow: boolean; @@ -10,4 +10,4 @@ export type DocumentLatencyInsightResult = InsightResult<{ }; }>; export declare function deps(): ['Meta', 'NetworkRequests']; -export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): DocumentLatencyInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): DocumentLatencyInsightModel; diff --git a/public/models/trace/insights/DocumentLatency.js b/public/models/trace/insights/DocumentLatency.js index 45060097..a71c02b3 100644 --- a/public/models/trace/insights/DocumentLatency.js +++ b/public/models/trace/insights/DocumentLatency.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 Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; +const UIStrings = { + /** + *@description Title of an insight that provides a breakdown for how long it took to download the main document. + */ + title: 'Document request latency', + /** + *@description Description of an insight that provides a breakdown for how long it took to download the main document. + */ + description: 'Your first network request is the most important. Reduce its latency by avoiding redirects, ensuring a fast server response, and enabling text compression.', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/DocumentLatency.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); // Due to the way that DevTools throttling works we cannot see if server response took less than ~570ms. // We set our failure threshold to 600ms to avoid those false positives but we want devs to shoot for 100ms. const TOO_SLOW_THRESHOLD_MS = 600; @@ -81,9 +94,12 @@ function getCompressionSavings(request) { // no percent threshold. return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings; } +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} export function generateInsight(parsedTrace, context) { if (!context.navigation) { - return {}; + return finalize({}); } const documentRequest = parsedTrace.NetworkRequests.byTime.find(req => req.args.data.requestId === context.navigationId); if (!documentRequest) { @@ -104,7 +120,7 @@ export function generateInsight(parsedTrace, context) { FCP: overallSavingsMs, LCP: overallSavingsMs, }; - return { + return finalize({ relatedEvents: [documentRequest], data: { serverResponseTime, @@ -114,6 +130,6 @@ export function generateInsight(parsedTrace, context) { documentRequest, }, metricSavings, - }; + }); } //# sourceMappingURL=DocumentLatency.js.map \ No newline at end of file diff --git a/public/models/trace/insights/DocumentLatency.js.map b/public/models/trace/insights/DocumentLatency.js.map index 36d392ca..d9b26e6e 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 Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightResult, InsightSetContext, 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 getServerResponseTime(request: Types.Events.SyntheticNetworkRequest): Types.Timing.MilliSeconds|null {\n const timing = request.args.data.timing;\n if (!timing) {\n return null;\n }\n\n const ms = Helpers.Timing.microSecondsToMilliseconds(request.args.data.syntheticData.waiting);\n return Math.round(ms) as Types.Timing.MilliSeconds;\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 = getServerResponseTime(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 as Types.Timing.MilliSeconds,\n LCP: overallSavingsMs as Types.Timing.MilliSeconds,\n };\n\n return {\n relatedEvents: [documentRequest],\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 +{"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 i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightModel, InsightSetContext, RequiredData} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Title of an insight that provides a breakdown for how long it took to download the main document.\n */\n title: 'Document request latency',\n /**\n *@description Description of an insight that provides a breakdown for how long it took to download the main document.\n */\n description:\n 'Your first network request is the most important. Reduce its latency by avoiding redirects, ensuring a fast server response, and enabling text compression.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/DocumentLatency.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\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 DocumentLatencyInsightModel = InsightModel<{\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 getServerResponseTime(request: Types.Events.SyntheticNetworkRequest): Types.Timing.MilliSeconds|null {\n const timing = request.args.data.timing;\n if (!timing) {\n return null;\n }\n\n const ms = Helpers.Timing.microSecondsToMilliseconds(request.args.data.syntheticData.waiting);\n return Math.round(ms) as Types.Timing.MilliSeconds;\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\nfunction finalize(partialModel: Omit): DocumentLatencyInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): DocumentLatencyInsightModel {\n if (!context.navigation) {\n return finalize({});\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 = getServerResponseTime(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 as Types.Timing.MilliSeconds,\n LCP: overallSavingsMs as Types.Timing.MilliSeconds,\n };\n\n return finalize({\n relatedEvents: [documentRequest],\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.js b/public/models/trace/insights/DocumentLatency.test.js index 3c918847..e4174f78 100644 --- a/public/models/trace/insights/DocumentLatency.test.js +++ b/public/models/trace/insights/DocumentLatency.test.js @@ -47,7 +47,7 @@ describeWithEnvironment('DocumentLatency', function () { } const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values()); const context = createContextForNavigation(data, navigation, data.Meta.mainFrameId); - const insight = Trace.Insights.InsightRunners.DocumentLatency.generateInsight(data, context); + const insight = Trace.Insights.Models.DocumentLatency.generateInsight(data, context); assert.strictEqual(insight.data?.serverResponseTime, 1043); assert(insight.data?.serverResponseTooSlow); assert.deepEqual(insight.metricSavings, { FCP: 943, LCP: 943 }); @@ -75,7 +75,7 @@ describeWithEnvironment('DocumentLatency', function () { } const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values()); const context = createContextForNavigation(data, navigation, data.Meta.mainFrameId); - const insight = Trace.Insights.InsightRunners.DocumentLatency.generateInsight(data, context); + const insight = Trace.Insights.Models.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 bcb7e8da..9ac1415b 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":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,0BAA0B,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,oCAAoC,CAAC;AAClH,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,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,iBAAiB,EAAE;IACzC,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;QACpF,MAAM,OAAO,GACT,iBAAiB,CAAC,iBAAiB,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAClH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC;QACzD,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAuC,CAAC,CAAC;IACxG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;QAChF,MAAM,OAAO,GACT,iBAAiB,CAAC,iBAAiB,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAClH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QAC7C,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAuC,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK;QACnE,MAAM,WAAW,GAAG,CAAC,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC,CAAC;QACzF,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,qBAAqB,EAAE,CAAC;QAEzE,MAAM,qBAAqB,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,yBAAyB,CAAC,CAAC;QAC/F,MAAM,gBAAgB,GAAG,eAAe,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;QAC7F,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,CAAC;QACD,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB;YAC/C,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;QAC1F,WAAW,CAAC,qBAAqB,CAAC,GAAG,gBAAgB,CAAC;QAEtD,MAAM,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,EAAC,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAC,CAAC,CAAC;QAClF,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7F,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;QAC3D,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QAC5C,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAuC,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;QAChF,MAAM,OAAO,GACT,iBAAiB,CAAC,iBAAiB,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAClH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAuC,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK;QAC3D,MAAM,WAAW,GAAG,CAAC,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC,CAAC;QACzF,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,qBAAqB,EAAE,CAAC;QAEzE,MAAM,qBAAqB,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,yBAAyB,CAAC,CAAC;QAC/F,MAAM,gBAAgB,GAAG,eAAe,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;QAC7F,kCAAkC;QAClC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;QACpH,WAAW,CAAC,qBAAqB,CAAC,GAAG,gBAAgB,CAAC;QAEtD,MAAM,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,EAAC,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAC,CAAC,CAAC;QAClF,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7F,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,yBAAyB,EAAE,KAAK,CAAC,CAAC;QACnE,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAuC,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QAC5E,MAAM,OAAO,GACT,iBAAiB,CAAC,iBAAiB,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAClH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC;QACzD,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,yBAAyB,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;QAC3D,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QAC5C,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAuC,CAAC,CAAC;IACxG,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, getInsightOrError} 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 getInsightOrError('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.redirectDuration, 1779);\n assert.deepEqual(insight.metricSavings, {FCP: 1779, LCP: 1779} as Trace.Insights.Types.MetricSavings);\n });\n\n it('reports no savings for server with fast server response time', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n const insight =\n getInsightOrError('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} as Trace.Insights.Types.MetricSavings);\n });\n\n it('reports savings for server with slow server 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.receiveHeadersEnd =\n Types.Timing.MilliSeconds(mainRequestEvent.args.data.timing.receiveHeadersEnd + 1000);\n traceEvents[mainRequestEventIndex] = mainRequestEvent;\n\n await processor.parse(traceEvents, {isCPUProfile: false, isFreshRecording: true});\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(data, 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} as Trace.Insights.Types.MetricSavings);\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 getInsightOrError('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.uncompressedResponseBytes, 0);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0} as Trace.Insights.Types.MetricSavings);\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, {isCPUProfile: false, isFreshRecording: true});\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(data, 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} as Trace.Insights.Types.MetricSavings);\n });\n\n it('reports savings for main document with many issues, many redirects', async () => {\n const {data, insights} = await processTrace(this, 'many-redirects.json.gz');\n const insight =\n getInsightOrError('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.redirectDuration, 6059);\n assert.strictEqual(insight.data?.uncompressedResponseBytes, 111506);\n assert.strictEqual(insight.data?.serverResponseTime, 2008);\n assert(insight.data?.serverResponseTooSlow);\n assert.deepEqual(insight.metricSavings, {FCP: 7967, LCP: 7967} as Trace.Insights.Types.MetricSavings);\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, getInsightOrError} 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 getInsightOrError('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.redirectDuration, 1779);\n assert.deepEqual(insight.metricSavings, {FCP: 1779, LCP: 1779} as Trace.Insights.Types.MetricSavings);\n });\n\n it('reports no savings for server with fast server response time', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n const insight =\n getInsightOrError('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} as Trace.Insights.Types.MetricSavings);\n });\n\n it('reports savings for server with slow server 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.receiveHeadersEnd =\n Types.Timing.MilliSeconds(mainRequestEvent.args.data.timing.receiveHeadersEnd + 1000);\n traceEvents[mainRequestEventIndex] = mainRequestEvent;\n\n await processor.parse(traceEvents, {isCPUProfile: false, isFreshRecording: true});\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(data, navigation, data.Meta.mainFrameId);\n const insight = Trace.Insights.Models.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} as Trace.Insights.Types.MetricSavings);\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 getInsightOrError('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.uncompressedResponseBytes, 0);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0} as Trace.Insights.Types.MetricSavings);\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, {isCPUProfile: false, isFreshRecording: true});\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(data, navigation, data.Meta.mainFrameId);\n const insight = Trace.Insights.Models.DocumentLatency.generateInsight(data, context);\n assert.strictEqual(insight.data?.uncompressedResponseBytes, 39799);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0} as Trace.Insights.Types.MetricSavings);\n });\n\n it('reports savings for main document with many issues, many redirects', async () => {\n const {data, insights} = await processTrace(this, 'many-redirects.json.gz');\n const insight =\n getInsightOrError('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.redirectDuration, 6059);\n assert.strictEqual(insight.data?.uncompressedResponseBytes, 111506);\n assert.strictEqual(insight.data?.serverResponseTime, 2008);\n assert(insight.data?.serverResponseTooSlow);\n assert.deepEqual(insight.metricSavings, {FCP: 7967, LCP: 7967} as Trace.Insights.Types.MetricSavings);\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 index 1de0a893..09f73713 100644 --- a/public/models/trace/insights/FontDisplay.d.ts +++ b/public/models/trace/insights/FontDisplay.d.ts @@ -1,11 +1,11 @@ import * as Types from '../types/types.js'; -import type { InsightResult, InsightSetContext, RequiredData } from './types.js'; +import type { InsightModel, InsightSetContext, RequiredData } from './types.js'; export declare function deps(): ['Meta', 'NetworkRequests', 'LayoutShifts']; -export type FontDisplayResult = InsightResult<{ +export type FontDisplayInsightModel = InsightModel<{ fonts: Array<{ request: Types.Events.SyntheticNetworkRequest; display: string; wastedTime: Types.Timing.MilliSeconds; }>; }>; -export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): FontDisplayResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): FontDisplayInsightModel; diff --git a/public/models/trace/insights/FontDisplay.js b/public/models/trace/insights/FontDisplay.js index 2abc8e78..b7961333 100644 --- a/public/models/trace/insights/FontDisplay.js +++ b/public/models/trace/insights/FontDisplay.js @@ -1,12 +1,26 @@ // 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 Platform from '../../../core/platform/platform.js'; import * as Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; +const UIStrings = { + /** Title of an insight that provides details about the fonts used on the page, and the value of their `font-display` properties. */ + title: 'Font display', + /** + * @description Text to tell the user about the font-display CSS feature to help improve a the UX of a page. + */ + description: 'Consider setting [`font-display`](https://developer.chrome.com/blog/font-display) to `swap` or `optional` to ensure text is consistently visible. `swap` can be further optimized to mitigate layout shifts with [font metric overrides](https://developer.chrome.com/blog/font-fallbacks).', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/FontDisplay.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export function deps() { return ['Meta', 'NetworkRequests', 'LayoutShifts']; } +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} export function generateInsight(parsedTrace, context) { const fonts = []; for (const event of parsedTrace.LayoutShifts.beginRemoteFontLoadEvents) { @@ -35,10 +49,10 @@ export function generateInsight(parsedTrace, context) { } fonts.sort((a, b) => b.wastedTime - a.wastedTime); const savings = Math.max(...fonts.map(f => f.wastedTime)); - return { + return finalize({ relatedEvents: fonts.map(f => f.request), fonts, metricSavings: { FCP: savings }, - }; + }); } //# 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 index 5a2b2118..ccc21c9f 100644 --- a/public/models/trace/insights/FontDisplay.js.map +++ b/public/models/trace/insights/FontDisplay.js.map @@ -1 +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,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,YAAY,CAAC,yBAAyB,EAAE,CAAC;QACvE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,SAAS;QACX,CAAC;QAED,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,2FAA2F;YAC3F,UAAU,GAAG,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAChF,CAAC;YAC9B,yCAAyC;YACzC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAA8B,CAAC;QACvE,CAAC;QAED,KAAK,CAAC,IAAI,CAAC;YACT,OAAO;YACP,OAAO;YACP,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAA8B,CAAC;IAEvF,OAAO;QACL,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACxC,KAAK;QACL,aAAa,EAAE,EAAC,GAAG,EAAE,OAAO,EAAC;KAC9B,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, InsightSetContext, 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 const fonts = [];\n for (const event of parsedTrace.LayoutShifts.beginRemoteFontLoadEvents) {\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n\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 // TODO(crbug.com/352244504): should really end at the time of the next Commit trace event.\n wastedTime = Platform.NumberUtilities.floor(Helpers.Timing.microSecondsToMilliseconds(wastedTimeMicro), 1 / 5) as\n Types.Timing.MilliSeconds;\n // All browsers wait for no more than 3s.\n wastedTime = Math.min(wastedTime, 3000) as Types.Timing.MilliSeconds;\n }\n\n fonts.push({\n request,\n display,\n wastedTime,\n });\n }\n\n fonts.sort((a, b) => b.wastedTime - a.wastedTime);\n\n const savings = Math.max(...fonts.map(f => f.wastedTime)) as Types.Timing.MilliSeconds;\n\n return {\n relatedEvents: fonts.map(f => f.request),\n fonts,\n metricSavings: {FCP: savings},\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"FontDisplay.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/FontDisplay.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 Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightModel, InsightSetContext, RequiredData} from './types.js';\n\nconst UIStrings = {\n /** Title of an insight that provides details about the fonts used on the page, and the value of their `font-display` properties. */\n title: 'Font display',\n /**\n * @description Text to tell the user about the font-display CSS feature to help improve a the UX of a page.\n */\n description:\n 'Consider setting [`font-display`](https://developer.chrome.com/blog/font-display) to `swap` or `optional` to ensure text is consistently visible. `swap` can be further optimized to mitigate layout shifts with [font metric overrides](https://developer.chrome.com/blog/font-fallbacks).',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/FontDisplay.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'NetworkRequests', 'LayoutShifts'] {\n return ['Meta', 'NetworkRequests', 'LayoutShifts'];\n}\n\nexport type FontDisplayInsightModel = InsightModel<{\n fonts: Array<{\n request: Types.Events.SyntheticNetworkRequest,\n display: string,\n wastedTime: Types.Timing.MilliSeconds,\n }>,\n}>;\n\nfunction finalize(partialModel: Omit): FontDisplayInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): FontDisplayInsightModel {\n const fonts = [];\n for (const event of parsedTrace.LayoutShifts.beginRemoteFontLoadEvents) {\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n\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 // TODO(crbug.com/352244504): should really end at the time of the next Commit trace event.\n wastedTime = Platform.NumberUtilities.floor(Helpers.Timing.microSecondsToMilliseconds(wastedTimeMicro), 1 / 5) as\n Types.Timing.MilliSeconds;\n // All browsers wait for no more than 3s.\n wastedTime = Math.min(wastedTime, 3000) as Types.Timing.MilliSeconds;\n }\n\n fonts.push({\n request,\n display,\n wastedTime,\n });\n }\n\n fonts.sort((a, b) => b.wastedTime - a.wastedTime);\n\n const savings = Math.max(...fonts.map(f => f.wastedTime)) as Types.Timing.MilliSeconds;\n\n return finalize({\n relatedEvents: fonts.map(f => f.request),\n fonts,\n metricSavings: {FCP: savings},\n });\n}\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 32ceb9ca..5e3e3431 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, InsightSetContext, RequiredData } from './types.js'; +import type { InsightModel, InsightSetContext, RequiredData } from './types.js'; export declare function deps(): ['UserInteractions']; -export type INPInsightResult = InsightResult<{ +export type INPInsightModel = InsightModel<{ longestInteractionEvent?: SyntheticInteractionPair; highPercentileInteractionEvent?: SyntheticInteractionPair; }>; -export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): INPInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): INPInsightModel; diff --git a/public/models/trace/insights/InteractionToNextPaint.js b/public/models/trace/insights/InteractionToNextPaint.js index e85ab97b..0ad14f49 100644 --- a/public/models/trace/insights/InteractionToNextPaint.js +++ b/public/models/trace/insights/InteractionToNextPaint.js @@ -1,17 +1,33 @@ // 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 Helpers from '../helpers/helpers.js'; +const UIStrings = { + /** + * @description Text to tell the user about the longest user interaction. + */ + description: 'Start investigating with the longest phase. [Delays can be minimized](https://web.dev/articles/optimize-inp#optimize_interactions). To reduce processing duration, [optimize the main-thread costs](https://web.dev/articles/optimize-long-tasks), often JS.', + /** + * @description Title for the performance insight "INP by phase", which shows a breakdown of INP by phases / sections. + */ + title: 'INP by phase', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/InteractionToNextPaint.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export function deps() { return ['UserInteractions']; } +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} export function generateInsight(parsedTrace, context) { const interactionEvents = parsedTrace.UserInteractions.interactionEventsWithNoNesting.filter(event => { return Helpers.Timing.eventIsInBounds(event, context.bounds); }); if (!interactionEvents.length) { // A valid result, when there is no user interaction. - return {}; + return finalize({}); } const longestByInteractionId = new Map(); for (const event of interactionEvents) { @@ -28,10 +44,10 @@ export function generateInsight(parsedTrace, context) { // last array element. To keep things simpler, sort desc and pick from front. // See https://source.chromium.org/chromium/chromium/src/+/main:components/page_load_metrics/browser/responsiveness_metrics_normalization.cc;l=45-59;drc=cb0f9c8b559d9c7c3cb4ca94fc1118cc015d38ad const highPercentileIndex = Math.min(9, Math.floor(normalizedInteractionEvents.length / 50)); - return { + return finalize({ relatedEvents: [normalizedInteractionEvents[0]], longestInteractionEvent: normalizedInteractionEvents[0], highPercentileInteractionEvent: normalizedInteractionEvents[highPercentileIndex], - }; + }); } //# sourceMappingURL=InteractionToNextPaint.js.map \ No newline at end of file diff --git a/public/models/trace/insights/InteractionToNextPaint.js.map b/public/models/trace/insights/InteractionToNextPaint.js.map index 61ed1396..521d64bb 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;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,8BAA8B,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACnG,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,aAAa,EAAE,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC;QAC/C,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, InsightSetContext, 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.interactionEventsWithNoNesting.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 relatedEvents: [normalizedInteractionEvents[0]],\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,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAKjD,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,WAAW,EACP,8PAA8P;IAClQ;;OAEG;IACH,KAAK,EAAE,cAAc;CACtB,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,iDAAiD,EAAE,SAAS,CAAC,CAAC;AACvG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9B,CAAC;AAOD,SAAS,QAAQ,CAAC,YAA0D;IAC1E,OAAO,EAAC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG,YAAY,EAAC,CAAC;AAC/G,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,WAAsC,EAAE,OAA0B;IAChG,MAAM,iBAAiB,GAAG,WAAW,CAAC,gBAAgB,CAAC,8BAA8B,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACnG,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,QAAQ,CAAC,EAAE,CAAC,CAAC;IACtB,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,QAAQ,CAAC;QACd,aAAa,EAAE,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC;QAC/C,uBAAuB,EAAE,2BAA2B,CAAC,CAAC,CAAC;QACvD,8BAA8B,EAAE,2BAA2B,CAAC,mBAAmB,CAAC;KACjF,CAAC,CAAC;AACL,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 i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type {SyntheticInteractionPair} from '../types/TraceEvents.js';\n\nimport type {InsightModel, InsightSetContext, RequiredData} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user about the longest user interaction.\n */\n description:\n 'Start investigating with the longest phase. [Delays can be minimized](https://web.dev/articles/optimize-inp#optimize_interactions). To reduce processing duration, [optimize the main-thread costs](https://web.dev/articles/optimize-long-tasks), often JS.',\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\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/InteractionToNextPaint.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['UserInteractions'] {\n return ['UserInteractions'];\n}\n\nexport type INPInsightModel = InsightModel<{\n longestInteractionEvent?: SyntheticInteractionPair,\n highPercentileInteractionEvent?: SyntheticInteractionPair,\n}>;\n\nfunction finalize(partialModel: Omit): INPInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): INPInsightModel {\n const interactionEvents = parsedTrace.UserInteractions.interactionEventsWithNoNesting.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 finalize({});\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 finalize({\n relatedEvents: [normalizedInteractionEvents[0]],\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.js b/public/models/trace/insights/InteractionToNextPaint.test.js index d6a3fc89..8f776003 100644 --- a/public/models/trace/insights/InteractionToNextPaint.test.js +++ b/public/models/trace/insights/InteractionToNextPaint.test.js @@ -24,7 +24,7 @@ describeWithEnvironment('InteractionToNextPaint', function () { bounds: data.Meta.traceBounds, frameId: data.Meta.mainFrameId, }; - const insight = Trace.Insights.InsightRunners.InteractionToNextPaint.generateInsight(data, context); + const insight = Trace.Insights.Models.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 3884f47b..16a0ce3d 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,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,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;gBACjG,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(data, 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 +{"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,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;gBACjG,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,MAAM,CAAC,sBAAsB,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5F,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(data, navigation, data.Meta.mainFrameId) : {\n bounds: data.Meta.traceBounds,\n frameId: data.Meta.mainFrameId,\n };\n const insight = Trace.Insights.Models.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/LCPDiscovery.d.ts b/public/models/trace/insights/LCPDiscovery.d.ts new file mode 100644 index 00000000..e445d925 --- /dev/null +++ b/public/models/trace/insights/LCPDiscovery.d.ts @@ -0,0 +1,13 @@ +import * as Types from '../types/types.js'; +import { type InsightModel, type InsightSetContext, type RequiredData } from './types.js'; +export declare function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta']; +export type LCPDiscoveryInsightModel = InsightModel<{ + lcpEvent?: Types.Events.LargestContentfulPaintCandidate; + shouldRemoveLazyLoading?: boolean; + shouldIncreasePriorityHint?: boolean; + shouldPreloadImage?: boolean; + /** The network request for the LCP image, if there was one. */ + lcpRequest?: Types.Events.SyntheticNetworkRequest; + earliestDiscoveryTimeTs?: Types.Timing.MicroSeconds; +}>; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): LCPDiscoveryInsightModel; diff --git a/public/models/trace/insights/LCPDiscovery.js b/public/models/trace/insights/LCPDiscovery.js new file mode 100644 index 00000000..4e404265 --- /dev/null +++ b/public/models/trace/insights/LCPDiscovery.js @@ -0,0 +1,74 @@ +// 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 Handlers from '../handlers/handlers.js'; +import * as Helpers from '../helpers/helpers.js'; +import * as Types from '../types/types.js'; +import { InsightWarning } from './types.js'; +const UIStrings = { + /** + *@description Title of an insight that provides details about the LCP metric, and the network requests necessary to load it. Details how the LCP request was discoverable - in other words, the path necessary to load it (ex: network requests, JavaScript) + */ + title: 'LCP request discovery', + /** + *@description Description of an insight that provides details about the LCP metric, and the network requests necessary to load it. + */ + description: 'Optimize LCP by making the LCP image [discoverable](https://web.dev/articles/optimize-lcp#1_eliminate_resource_load_delay) from the HTML immediately, and [avoiding lazy-loading](https://web.dev/articles/lcp-lazy-loading)', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/LCPDiscovery.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); +export function deps() { + return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta']; +} +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} +export function generateInsight(parsedTrace, context) { + if (!context.navigation) { + return finalize({}); + } + const networkRequests = parsedTrace.NetworkRequests; + const frameMetrics = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId); + if (!frameMetrics) { + throw new Error('no frame metrics'); + } + const navMetrics = frameMetrics.get(context.navigationId); + if (!navMetrics) { + throw new Error('no navigation metrics'); + } + const metricScore = navMetrics.get("LCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); + const lcpEvent = metricScore?.event; + if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) { + return finalize({ warnings: [InsightWarning.NO_LCP] }); + } + const docRequest = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId); + if (!docRequest) { + return finalize({ lcpEvent, warnings: [InsightWarning.NO_DOCUMENT_REQUEST] }); + } + const lcpRequest = parsedTrace.LargestImagePaint.lcpRequestByNavigation.get(context.navigation); + if (!lcpRequest) { + return finalize({ lcpEvent }); + } + const initiatorUrl = lcpRequest.args.data.initiator?.url; + // TODO(b/372319476): Explore using trace event HTMLDocumentParser::FetchQueuedPreloads to determine if the request + // is discovered by the preload scanner. + const initiatedByMainDoc = lcpRequest?.args.data.initiator?.type === 'parser' && docRequest.args.data.url === initiatorUrl; + const imgPreloadedOrFoundInHTML = lcpRequest?.args.data.isLinkPreload || initiatedByMainDoc; + const imageLoadingAttr = lcpEvent.args.data?.loadingAttr; + const imageFetchPriorityHint = lcpRequest?.args.data.fetchPriorityHint; + // This is the earliest discovery time an LCP request could have - it's TTFB. + const earliestDiscoveryTime = docRequest && docRequest.args.data.timing ? + Helpers.Timing.secondsToMicroseconds(docRequest.args.data.timing.requestTime) + + Helpers.Timing.millisecondsToMicroseconds(docRequest.args.data.timing.receiveHeadersStart) : + undefined; + return finalize({ + lcpEvent, + shouldRemoveLazyLoading: imageLoadingAttr === 'lazy', + shouldIncreasePriorityHint: imageFetchPriorityHint !== 'high', + shouldPreloadImage: !imgPreloadedOrFoundInHTML, + lcpRequest, + earliestDiscoveryTimeTs: earliestDiscoveryTime ? Types.Timing.MicroSeconds(earliestDiscoveryTime) : undefined, + }); +} +//# sourceMappingURL=LCPDiscovery.js.map \ No newline at end of file diff --git a/public/models/trace/insights/LCPDiscovery.js.map b/public/models/trace/insights/LCPDiscovery.js.map new file mode 100644 index 00000000..4876e4d1 --- /dev/null +++ b/public/models/trace/insights/LCPDiscovery.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LCPDiscovery.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/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 i18n from '../../../core/i18n/i18n.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type InsightModel, type InsightSetContext, InsightWarning, type RequiredData} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Title of an insight that provides details about the LCP metric, and the network requests necessary to load it. Details how the LCP request was discoverable - in other words, the path necessary to load it (ex: network requests, JavaScript)\n */\n title: 'LCP request discovery',\n /**\n *@description Description of an insight that provides details about the LCP metric, and the network requests necessary to load it.\n */\n description:\n 'Optimize LCP by making the LCP image [discoverable](https://web.dev/articles/optimize-lcp#1_eliminate_resource_load_delay) from the HTML immediately, and [avoiding lazy-loading](https://web.dev/articles/lcp-lazy-loading)',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/LCPDiscovery.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'] {\n return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'];\n}\n\nexport type LCPDiscoveryInsightModel = InsightModel<{\n lcpEvent?: Types.Events.LargestContentfulPaintCandidate,\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 finalize(partialModel: Omit): LCPDiscoveryInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): LCPDiscoveryInsightModel {\n if (!context.navigation) {\n return finalize({});\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 finalize({warnings: [InsightWarning.NO_LCP]});\n }\n\n const docRequest = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!docRequest) {\n return finalize({lcpEvent, warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});\n }\n\n const lcpRequest = parsedTrace.LargestImagePaint.lcpRequestByNavigation.get(context.navigation);\n if (!lcpRequest) {\n return finalize({lcpEvent});\n }\n\n const initiatorUrl = lcpRequest.args.data.initiator?.url;\n // TODO(b/372319476): Explore using trace event HTMLDocumentParser::FetchQueuedPreloads to determine if the request\n // is discovered by the preload scanner.\n const initiatedByMainDoc =\n lcpRequest?.args.data.initiator?.type === 'parser' && docRequest.args.data.url === initiatorUrl;\n const imgPreloadedOrFoundInHTML = lcpRequest?.args.data.isLinkPreload || initiatedByMainDoc;\n\n const imageLoadingAttr = lcpEvent.args.data?.loadingAttr;\n const imageFetchPriorityHint = lcpRequest?.args.data.fetchPriorityHint;\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 finalize({\n lcpEvent,\n shouldRemoveLazyLoading: imageLoadingAttr === 'lazy',\n shouldIncreasePriorityHint: imageFetchPriorityHint !== 'high',\n shouldPreloadImage: !imgPreloadedOrFoundInHTML,\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/LCPDiscovery.test.d.ts b/public/models/trace/insights/LCPDiscovery.test.d.ts new file mode 100644 index 00000000..29614938 --- /dev/null +++ b/public/models/trace/insights/LCPDiscovery.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/LCPDiscovery.test.js b/public/models/trace/insights/LCPDiscovery.test.js new file mode 100644 index 00000000..6dd6b1ae --- /dev/null +++ b/public/models/trace/insights/LCPDiscovery.test.js @@ -0,0 +1,47 @@ +// 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, getInsightOrError } 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('LCPDiscovery', function () { + it('calculates image lcp attributes', async () => { + const { data, insights } = await processTrace(this, 'lcp-images.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPDiscovery', insights, firstNav); + const { shouldIncreasePriorityHint, shouldPreloadImage, shouldRemoveLazyLoading } = insight; + assert.strictEqual(shouldRemoveLazyLoading, false); + assert.strictEqual(shouldPreloadImage, false); + assert.strictEqual(shouldIncreasePriorityHint, true); + }); + 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 = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPDiscovery', insights, firstNav); + assert.strictEqual(insight.earliestDiscoveryTimeTs, + // this is the TTFB for the document request + 122411004828); + }); + describe('warnings', function () { + it('warns when there is no lcp', async () => { + const { data, insights } = await processTrace(this, 'user-timings.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPDiscovery', insights, firstNav); + 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 firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPDiscovery', insights, firstNav); + assert.strictEqual(insight.warnings?.[0], 'NO_DOCUMENT_REQUEST'); + }); + }); +}); +//# sourceMappingURL=LCPDiscovery.test.js.map \ No newline at end of file diff --git a/public/models/trace/insights/LCPDiscovery.test.js.map b/public/models/trace/insights/LCPDiscovery.test.js.map new file mode 100644 index 00000000..ba67794c --- /dev/null +++ b/public/models/trace/insights/LCPDiscovery.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LCPDiscovery.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/LCPDiscovery.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, getInsightOrError} 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('LCPDiscovery', function() {\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 = getInsightOrError('LCPDiscovery', insights, firstNav);\n const {shouldIncreasePriorityHint, shouldPreloadImage, shouldRemoveLazyLoading} = insight;\n\n assert.strictEqual(shouldRemoveLazyLoading, false);\n assert.strictEqual(shouldPreloadImage, false);\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 = getInsightOrError('LCPDiscovery', 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 = getInsightOrError('LCPDiscovery', insights, firstNav);\n\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 = getInsightOrError('LCPDiscovery', insights, firstNav);\n\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/LCPPhases.d.ts b/public/models/trace/insights/LCPPhases.d.ts new file mode 100644 index 00000000..1e7d109e --- /dev/null +++ b/public/models/trace/insights/LCPPhases.d.ts @@ -0,0 +1,34 @@ +import * as Types from '../types/types.js'; +import { type InsightModel, type InsightSetContext, type RequiredData } from './types.js'; +export declare function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta']; +interface LCPPhases { + /** + * The time between when the user initiates loading the page until when + * the browser receives the first byte of the html response. + */ + ttfb: Types.Timing.MilliSeconds; + /** + * The time between ttfb and the LCP request request being started. + * For a text LCP, this is undefined given no request is loaded. + */ + loadDelay?: Types.Timing.MilliSeconds; + /** + * The time it takes to load the LCP request. + */ + loadTime?: Types.Timing.MilliSeconds; + /** + * The time between when the LCP request finishes loading and when + * the LCP element is rendered. + */ + renderDelay: Types.Timing.MilliSeconds; +} +export type LCPPhasesInsightModel = InsightModel<{ + lcpMs?: Types.Timing.MilliSeconds; + lcpTs?: Types.Timing.MilliSeconds; + lcpEvent?: Types.Events.LargestContentfulPaintCandidate; + /** The network request for the LCP image, if there was one. */ + lcpRequest?: Types.Events.SyntheticNetworkRequest; + phases?: LCPPhases; +}>; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): LCPPhasesInsightModel; +export {}; diff --git a/public/models/trace/insights/LCPPhases.js b/public/models/trace/insights/LCPPhases.js new file mode 100644 index 00000000..184d9e3b --- /dev/null +++ b/public/models/trace/insights/LCPPhases.js @@ -0,0 +1,114 @@ +// 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 Handlers from '../handlers/handlers.js'; +import * as Helpers from '../helpers/helpers.js'; +import * as Types from '../types/types.js'; +import { InsightWarning } from './types.js'; +const UIStrings = { + /** + *@description Title of an insight that provides details about the LCP metric, broken down by phases / parts. + */ + title: 'LCP by phase', + /** + * @description Description of a DevTools insight that presents a breakdown for the LCP metric by phases. + * This is displayed after a user expands the section to see more. No character length limits. + */ + description: 'Each [phase has specific improvement strategies](https://web.dev/articles/optimize-lcp#lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/LCPPhases.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); +export function deps() { + return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta']; +} +function anyValuesNaN(...values) { + return values.some(v => Number.isNaN(v)); +} +/** + * Calculates the 4 phases of an LCP and the timings of each. + * Will return `null` if any required values were missing. We don't ever expect + * them to be missing on newer traces, but old trace files may lack some of the + * data we rely on, so we want to handle that case. + */ +function breakdownPhases(nav, docRequest, lcpMs, lcpRequest) { + const docReqTiming = docRequest.args.data.timing; + if (!docReqTiming) { + throw new Error('no timing for document request'); + } + const firstDocByteTs = Helpers.Timing.secondsToMicroseconds(docReqTiming.requestTime) + + Helpers.Timing.millisecondsToMicroseconds(docReqTiming.receiveHeadersStart); + const firstDocByteTiming = Types.Timing.MicroSeconds(firstDocByteTs - nav.ts); + const ttfb = Helpers.Timing.microSecondsToMilliseconds(firstDocByteTiming); + let renderDelay = Types.Timing.MilliSeconds(lcpMs - ttfb); + if (!lcpRequest) { + if (anyValuesNaN(ttfb, renderDelay)) { + return null; + } + return { ttfb, renderDelay }; + } + const lcpStartTs = Types.Timing.MicroSeconds(lcpRequest.ts - nav.ts); + const requestStart = Helpers.Timing.microSecondsToMilliseconds(lcpStartTs); + const lcpReqEndTs = Types.Timing.MicroSeconds(lcpRequest.args.data.syntheticData.finishTime - nav.ts); + const requestEnd = Helpers.Timing.microSecondsToMilliseconds(lcpReqEndTs); + const loadDelay = Types.Timing.MilliSeconds(requestStart - ttfb); + const loadTime = Types.Timing.MilliSeconds(requestEnd - requestStart); + renderDelay = Types.Timing.MilliSeconds(lcpMs - requestEnd); + if (anyValuesNaN(ttfb, loadDelay, loadTime, renderDelay)) { + return null; + } + return { + ttfb, + loadDelay, + loadTime, + renderDelay, + }; +} +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} +export function generateInsight(parsedTrace, context) { + if (!context.navigation) { + return finalize({}); + } + const networkRequests = parsedTrace.NetworkRequests; + const frameMetrics = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId); + if (!frameMetrics) { + throw new Error('no frame metrics'); + } + const navMetrics = frameMetrics.get(context.navigationId); + if (!navMetrics) { + throw new Error('no navigation metrics'); + } + const metricScore = navMetrics.get("LCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); + const lcpEvent = metricScore?.event; + if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) { + return finalize({ 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 = parsedTrace.LargestImagePaint.lcpRequestByNavigation.get(context.navigation); + const docRequest = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId); + if (!docRequest) { + return finalize({ lcpMs, lcpTs, lcpEvent, lcpRequest, warnings: [InsightWarning.NO_DOCUMENT_REQUEST] }); + } + if (!lcpRequest) { + return finalize({ + lcpMs, + lcpTs, + lcpEvent, + lcpRequest, + phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest) ?? undefined, + }); + } + return finalize({ + lcpMs, + lcpTs, + lcpEvent, + lcpRequest, + phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest) ?? undefined, + }); +} +//# sourceMappingURL=LCPPhases.js.map \ No newline at end of file diff --git a/public/models/trace/insights/LCPPhases.js.map b/public/models/trace/insights/LCPPhases.js.map new file mode 100644 index 00000000..5268ba7f --- /dev/null +++ b/public/models/trace/insights/LCPPhases.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LCPPhases.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/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 Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type InsightModel, type InsightSetContext, InsightWarning, type RequiredData} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Title of an insight that provides details about the LCP metric, broken down by phases / parts.\n */\n title: 'LCP by phase',\n /**\n * @description Description of a DevTools insight that presents a breakdown for the LCP metric by phases.\n * This is displayed after a user expands the section to see more. No character length limits.\n */\n description:\n 'Each [phase has specific improvement strategies](https://web.dev/articles/optimize-lcp#lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.',\n};\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/LCPPhases.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\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 LCPPhasesInsightModel = InsightModel<{\n lcpMs?: Types.Timing.MilliSeconds,\n lcpTs?: Types.Timing.MilliSeconds,\n lcpEvent?: Types.Events.LargestContentfulPaintCandidate,\n /** The network request for the LCP image, if there was one. */\n lcpRequest?: Types.Events.SyntheticNetworkRequest,\n phases?: LCPPhases,\n}>;\n\nfunction anyValuesNaN(...values: number[]): boolean {\n return values.some(v => Number.isNaN(v));\n}\n/**\n * Calculates the 4 phases of an LCP and the timings of each.\n * Will return `null` if any required values were missing. We don't ever expect\n * them to be missing on newer traces, but old trace files may lack some of the\n * data we rely on, so we want to handle that case.\n */\nfunction breakdownPhases(\n nav: Types.Events.NavigationStart, docRequest: Types.Events.SyntheticNetworkRequest,\n lcpMs: Types.Timing.MilliSeconds, lcpRequest: Types.Events.SyntheticNetworkRequest|undefined): LCPPhases|null {\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 if (anyValuesNaN(ttfb, renderDelay)) {\n return null;\n }\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 if (anyValuesNaN(ttfb, loadDelay, loadTime, renderDelay)) {\n return null;\n }\n\n return {\n ttfb,\n loadDelay,\n loadTime,\n renderDelay,\n };\n}\n\nfunction finalize(partialModel: Omit): LCPPhasesInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): LCPPhasesInsightModel {\n if (!context.navigation) {\n return finalize({});\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 finalize({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 = parsedTrace.LargestImagePaint.lcpRequestByNavigation.get(context.navigation);\n\n const docRequest = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!docRequest) {\n return finalize({lcpMs, lcpTs, lcpEvent, lcpRequest, warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});\n }\n\n if (!lcpRequest) {\n return finalize({\n lcpMs,\n lcpTs,\n lcpEvent,\n lcpRequest,\n phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest) ?? undefined,\n });\n }\n\n return finalize({\n lcpMs,\n lcpTs,\n lcpEvent,\n lcpRequest,\n phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest) ?? undefined,\n });\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/LCPPhases.test.d.ts b/public/models/trace/insights/LCPPhases.test.d.ts new file mode 100644 index 00000000..29614938 --- /dev/null +++ b/public/models/trace/insights/LCPPhases.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/LCPPhases.test.js b/public/models/trace/insights/LCPPhases.test.js new file mode 100644 index 00000000..f889c532 --- /dev/null +++ b/public/models/trace/insights/LCPPhases.test.js @@ -0,0 +1,67 @@ +// 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, getInsightOrError } from '../../../testing/InsightHelpers.js'; +import { TraceLoader } from '../../../testing/TraceLoader.js'; +import * as Types from '../types/types.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('LCPPhases', function () { + it('calculates text lcp phases', async () => { + const { data, insights } = await processTrace(this, 'lcp-web-font.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPPhases', insights, firstNav); + assert.strictEqual(insight.lcpMs, 106.482); + const wantTtfb = Types.Timing.MilliSeconds(6.115); + const wantRenderDelay = Types.Timing.MilliSeconds(100.367); + assert.deepEqual(insight.phases, { ttfb: wantTtfb, renderDelay: wantRenderDelay }); + }); + it('calculates image lcp phases', async () => { + const { data, insights } = await processTrace(this, 'lcp-images.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPPhases', insights, firstNav); + assert.strictEqual(insight.lcpMs, 109.623); + if (!insight.phases) { + throw new Error('No LCP phases'); + } + const phases = { + ttfb: insight.phases.ttfb?.toFixed(2), + loadTime: insight.phases.loadTime?.toFixed(2), + loadDelay: insight.phases.loadDelay?.toFixed(2), + renderDelay: insight.phases.renderDelay?.toFixed(2), + }; + assert.deepEqual(phases, { ttfb: '6.94', loadTime: '12.09', loadDelay: '33.74', renderDelay: '56.85' }); + }); + describe('warnings', function () { + it('warns when there is no lcp', async () => { + const { data, insights } = await processTrace(this, 'user-timings.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPPhases', 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 firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPPhases', insights, firstNav); + assert.strictEqual(insight.lcpMs, 204.909); + assert.strictEqual(insight.phases, undefined); + assert.strictEqual(insight.warnings?.[0], 'NO_DOCUMENT_REQUEST'); + }); + }); + it('can handle old traces with missing data and return null for breakdowns of the phases', async () => { + const { data, insights } = await processTrace(this, 'multiple-navigations.json.gz'); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsightOrError('LCPPhases', insights, firstNav); + // This insight has invalid phase data, so we expect the value to be undefined. + assert.isUndefined(insight.phases); + }); +}); +//# sourceMappingURL=LCPPhases.test.js.map \ No newline at end of file diff --git a/public/models/trace/insights/LCPPhases.test.js.map b/public/models/trace/insights/LCPPhases.test.js.map new file mode 100644 index 00000000..c5ddc9c4 --- /dev/null +++ b/public/models/trace/insights/LCPPhases.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LCPPhases.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/LCPPhases.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, getInsightOrError} 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('LCPPhases', 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 = getInsightOrError('LCPPhases', 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 = getInsightOrError('LCPPhases', 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 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 = getInsightOrError('LCPPhases', 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 = getInsightOrError('LCPPhases', 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 it('can handle old traces with missing data and return null for breakdowns of the phases', async () => {\n const {data, insights} = await processTrace(this, 'multiple-navigations.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsightOrError('LCPPhases', insights, firstNav);\n // This insight has invalid phase data, so we expect the value to be undefined.\n assert.isUndefined(insight.phases);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/Models.d.ts b/public/models/trace/insights/Models.d.ts new file mode 100644 index 00000000..c71b69e5 --- /dev/null +++ b/public/models/trace/insights/Models.d.ts @@ -0,0 +1,10 @@ +export * as CLSCulprits from './CLSCulprits.js'; +export * as DocumentLatency from './DocumentLatency.js'; +export * as FontDisplay from './FontDisplay.js'; +export * as InteractionToNextPaint from './InteractionToNextPaint.js'; +export * as LCPDiscovery from './LCPDiscovery.js'; +export * as LCPPhases from './LCPPhases.js'; +export * as RenderBlocking from './RenderBlocking.js'; +export * as SlowCSSSelector from './SlowCSSSelector.js'; +export * as ThirdParties from './ThirdParties.js'; +export * as Viewport from './Viewport.js'; diff --git a/public/models/trace/insights/Models.js b/public/models/trace/insights/Models.js new file mode 100644 index 00000000..8e22c8fa --- /dev/null +++ b/public/models/trace/insights/Models.js @@ -0,0 +1,14 @@ +// 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 * as CLSCulprits from './CLSCulprits.js'; +export * as DocumentLatency from './DocumentLatency.js'; +export * as FontDisplay from './FontDisplay.js'; +export * as InteractionToNextPaint from './InteractionToNextPaint.js'; +export * as LCPDiscovery from './LCPDiscovery.js'; +export * as LCPPhases from './LCPPhases.js'; +export * as RenderBlocking from './RenderBlocking.js'; +export * as SlowCSSSelector from './SlowCSSSelector.js'; +export * as ThirdParties from './ThirdParties.js'; +export * as Viewport from './Viewport.js'; +//# sourceMappingURL=Models.js.map \ No newline at end of file diff --git a/public/models/trace/insights/Models.js.map b/public/models/trace/insights/Models.js.map new file mode 100644 index 00000000..d045273e --- /dev/null +++ b/public/models/trace/insights/Models.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Models.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Models.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAC;AAClD,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 CLSCulprits from './CLSCulprits.js';\nexport * as DocumentLatency from './DocumentLatency.js';\nexport * as FontDisplay from './FontDisplay.js';\nexport * as InteractionToNextPaint from './InteractionToNextPaint.js';\nexport * as LCPDiscovery from './LCPDiscovery.js';\nexport * as LCPPhases from './LCPPhases.js';\nexport * as RenderBlocking from './RenderBlocking.js';\nexport * as SlowCSSSelector from './SlowCSSSelector.js';\nexport * as ThirdParties from './ThirdParties.js';\nexport * as Viewport from './Viewport.js';\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 dae638b0..f7512d20 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 InsightSetContext, type RequiredData } from './types.js'; -export type RenderBlockingInsightResult = InsightResult<{ +import type * as Types from '../types/types.js'; +import { type InsightModel, type InsightSetContext, type RequiredData } from './types.js'; +export type RenderBlockingInsightModel = InsightModel<{ renderBlockingRequests: Types.Events.SyntheticNetworkRequest[]; requestIdToWastedMs?: Map; }>; export declare function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint']; -export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): RenderBlockingInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): RenderBlockingInsightModel; diff --git a/public/models/trace/insights/RenderBlocking.js b/public/models/trace/insights/RenderBlocking.js index d8876b3e..2f68ecf7 100644 --- a/public/models/trace/insights/RenderBlocking.js +++ b/public/models/trace/insights/RenderBlocking.js @@ -1,11 +1,24 @@ // 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 Handlers from '../handlers/handlers.js'; import * as Helpers from '../helpers/helpers.js'; -import * as Types from '../types/types.js'; -import { findLCPRequest } from './Common.js'; import { InsightWarning, } from './types.js'; +const UIStrings = { + /** + * @description Title of an insight that provides the user with the list of network requests that blocked and therefore slowed down the page rendering and becoming visible to the user. + */ + title: 'Render blocking requests', + /** + * @description Text to describe that there are requests blocking rendering, which may affect LCP. + */ + description: 'Requests are blocking the page\'s initial render, which may delay LCP. ' + + '[Deferring or inlining](https://web.dev/learn/performance/understanding-the-critical-path#render-blocking_resources/) ' + + 'can move these network requests out of the critical path.', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/RenderBlocking.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); // Because of the way we detect blocking stylesheets, asynchronously loaded // CSS with link[rel=preload] and an onload handler (see https://github.com/filamentgroup/loadCSS) // can be falsely flagged as blocking. Therefore, ignore stylesheets that loaded fast enough @@ -52,20 +65,7 @@ function estimateSavingsWithGraphs(deferredIds, lanternContext) { return Math.round(Math.max(estimateBeforeInline - estimateAfterInline, 0)); } function hasImageLCP(parsedTrace, context) { - const frameMetrics = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId); - if (!frameMetrics) { - throw new Error('no frame metrics'); - } - const navMetrics = frameMetrics.get(context.navigationId); - if (!navMetrics) { - throw new Error('no navigation metrics'); - } - const metricScore = navMetrics.get("LCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); - const lcpEvent = metricScore?.event; - if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) { - return false; - } - return findLCPRequest(parsedTrace, context, lcpEvent) !== null; + return parsedTrace.LargestImagePaint.lcpRequestByNavigation.get(context.navigation) !== undefined; } function computeSavings(parsedTrace, context, renderBlockingRequests) { if (!context.lantern) { @@ -99,21 +99,24 @@ function computeSavings(parsedTrace, context, renderBlockingRequests) { } return { metricSavings, requestIdToWastedMs }; } +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} export function generateInsight(parsedTrace, context) { if (!context.navigation) { - return { + return finalize({ renderBlockingRequests: [], - }; + }); } const firstPaintTs = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId) ?.get(context.navigationId) ?.get("FP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */) ?.event?.ts; if (!firstPaintTs) { - return { + return finalize({ renderBlockingRequests: [], warnings: [InsightWarning.NO_FP], - }; + }); } let renderBlockingRequests = []; for (const req of parsedTrace.NetworkRequests.byTime) { @@ -150,10 +153,10 @@ export function generateInsight(parsedTrace, context) { renderBlockingRequests = renderBlockingRequests.sort((a, b) => { return b.dur - a.dur; }); - return { + return finalize({ relatedEvents: renderBlockingRequests, renderBlockingRequests, ...savings, - }; + }); } //# sourceMappingURL=RenderBlocking.js.map \ No newline at end of file diff --git a/public/models/trace/insights/RenderBlocking.js.map b/public/models/trace/insights/RenderBlocking.js.map index 4ccfd522..6df9a2b1 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 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(\n deferredIds: Set, lanternContext: LanternContext): Types.Timing.MilliSeconds {\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)) as Types.Timing.MilliSeconds;\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 as Types.Timing.MilliSeconds, LCP: 0 as Types.Timing.MilliSeconds};\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 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 (!Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(req)) {\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 relatedEvents: renderBlockingRequests,\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 i18n from '../../../core/i18n/i18n.js';\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 type * as Types from '../types/types.js';\n\nimport {\n type InsightModel,\n type InsightSetContext,\n type InsightSetContextWithNavigation,\n InsightWarning,\n type LanternContext,\n type RequiredData,\n} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Title of an insight that provides the user with the list of network requests that blocked and therefore slowed down the page rendering and becoming visible to the user.\n */\n title: 'Render blocking requests',\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('models/trace/insights/RenderBlocking.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type RenderBlockingInsightModel = InsightModel<{\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(\n deferredIds: Set, lanternContext: LanternContext): Types.Timing.MilliSeconds {\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)) as Types.Timing.MilliSeconds;\n}\n\nfunction hasImageLCP(parsedTrace: RequiredData, context: InsightSetContextWithNavigation): boolean {\n return parsedTrace.LargestImagePaint.lcpRequestByNavigation.get(context.navigation) !== undefined;\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 as Types.Timing.MilliSeconds, LCP: 0 as Types.Timing.MilliSeconds};\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\nfunction finalize(partialModel: Omit): RenderBlockingInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): RenderBlockingInsightModel {\n if (!context.navigation) {\n return finalize({\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 finalize({\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 (!Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(req)) {\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 finalize({\n relatedEvents: renderBlockingRequests,\n renderBlockingRequests,\n ...savings,\n });\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/RenderBlocking.test.js b/public/models/trace/insights/RenderBlocking.test.js index dd22b80f..7d99f3cb 100644 --- a/public/models/trace/insights/RenderBlocking.test.js +++ b/public/models/trace/insights/RenderBlocking.test.js @@ -12,7 +12,7 @@ export async function processTrace(testContext, traceFile) { } return { data: parsedTrace, insights }; } -describeWithEnvironment('RenderBlockingRequests', function () { +describeWithEnvironment('RenderBlocking', function () { it('finds render blocking requests', async () => { const { data, insights } = await processTrace(this, 'load-simple.json.gz'); assert.deepStrictEqual([...insights.keys()], [Trace.Types.Events.NO_NAVIGATION, '0BCFC23BC7D7BEDC9F93E912DCCEC1DA']); diff --git a/public/models/trace/insights/RenderBlocking.test.js.map b/public/models/trace/insights/RenderBlocking.test.js.map index ddbc9c5b..4cd491f2 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 {getInsightOrError} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../../trace/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('RenderBlockingRequests', function() {\n it('finds render blocking requests', async () => {\n const {data, insights} = await processTrace(this, 'load-simple.json.gz');\n assert.deepStrictEqual(\n [...insights.keys()], [Trace.Types.Events.NO_NAVIGATION, '0BCFC23BC7D7BEDC9F93E912DCCEC1DA']);\n const insight =\n getInsightOrError('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 =\n getInsightOrError('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 [Trace.Types.Events.NO_NAVIGATION, '8671F33ECE0C8DBAEFBC2F9A2D1D6107', '1AE2016BBCC48AA090FDAE2CBBA01900']);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insight = getInsightOrError('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 = getInsightOrError('RenderBlocking', insights);\n const insightTwo = getInsightOrError('RenderBlocking', insights, navigations[0]);\n const insightThree = getInsightOrError('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 = getInsightOrError('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 =\n getInsightOrError('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 =\n getInsightOrError('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 // TODO(crbug.com/372674229): when swapping to 'provided' instead of 'simulated', all these test traces give\n // uninteresting results. must get new traces.\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 =\n getInsightOrError('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 0,\n LCP: 0,\n } as Trace.Insights.Types.MetricSavings);\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 });\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 =\n getInsightOrError('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 0,\n LCP: 0,\n } as Trace.Insights.Types.MetricSavings);\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 });\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 {getInsightOrError} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../../trace/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('RenderBlocking', function() {\n it('finds render blocking requests', async () => {\n const {data, insights} = await processTrace(this, 'load-simple.json.gz');\n assert.deepStrictEqual(\n [...insights.keys()], [Trace.Types.Events.NO_NAVIGATION, '0BCFC23BC7D7BEDC9F93E912DCCEC1DA']);\n const insight =\n getInsightOrError('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 =\n getInsightOrError('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 [Trace.Types.Events.NO_NAVIGATION, '8671F33ECE0C8DBAEFBC2F9A2D1D6107', '1AE2016BBCC48AA090FDAE2CBBA01900']);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insight = getInsightOrError('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 = getInsightOrError('RenderBlocking', insights);\n const insightTwo = getInsightOrError('RenderBlocking', insights, navigations[0]);\n const insightThree = getInsightOrError('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 = getInsightOrError('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 =\n getInsightOrError('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 =\n getInsightOrError('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 // TODO(crbug.com/372674229): when swapping to 'provided' instead of 'simulated', all these test traces give\n // uninteresting results. must get new traces.\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 =\n getInsightOrError('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 0,\n LCP: 0,\n } as Trace.Insights.Types.MetricSavings);\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 });\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 =\n getInsightOrError('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 0,\n LCP: 0,\n } as Trace.Insights.Types.MetricSavings);\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 });\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 5e0d9d77..c36af7c7 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, InsightSetContext, RequiredData } from './types.js'; +import type { InsightModel, InsightSetContext, RequiredData } from './types.js'; export declare function deps(): ['SelectorStats']; -export type SlowCSSSelectorInsightResult = InsightResult<{ +export type SlowCSSSelectorInsightModel = InsightModel<{ totalElapsedMs: Types.Timing.MilliSeconds; totalMatchAttempts: number; totalMatchCount: number; topElapsedMs: Types.Events.SelectorTiming[]; topMatchAttempts: Types.Events.SelectorTiming[]; }>; -export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): SlowCSSSelectorInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): SlowCSSSelectorInsightModel; diff --git a/public/models/trace/insights/SlowCSSSelector.js b/public/models/trace/insights/SlowCSSSelector.js index 2632e3bb..219f8751 100644 --- a/public/models/trace/insights/SlowCSSSelector.js +++ b/public/models/trace/insights/SlowCSSSelector.js @@ -1,9 +1,22 @@ // 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 Helpers from '../helpers/helpers.js'; import { SelectorTimingsKey } from '../types/TraceEvents.js'; import * as Types from '../types/types.js'; +const UIStrings = { + /** + *@description Title of an insight that provides details about slow CSS selectors. + */ + title: 'CSS Selector costs', + /** + * @description Text to describe how to improve the performance of CSS selectors. + */ + description: 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/SlowCSSSelector.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export function deps() { return ['SelectorStats']; } @@ -32,6 +45,9 @@ function aggregateSelectorStats(data, context) { } return [...selectorMap.values()]; } +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} export function generateInsight(parsedTrace, context) { const selectorStatsData = parsedTrace.SelectorStats; if (!selectorStatsData) { @@ -54,7 +70,7 @@ export function generateInsight(parsedTrace, context) { const sortByMatchAttempts = selectorTimings.toSorted((a, b) => { return b[SelectorTimingsKey.MatchAttempts] - a[SelectorTimingsKey.MatchAttempts]; }); - return { + return finalize({ // TODO: should we identify UpdateLayout events as linked to this insight? relatedEvents: [], totalElapsedMs: Types.Timing.MilliSeconds(totalElapsedUs / 1000.0), @@ -62,6 +78,6 @@ export function generateInsight(parsedTrace, context) { totalMatchCount, topElapsedMs: sortByElapsedMs.slice(0, 3), topMatchAttempts: sortByMatchAttempts.slice(0, 3), - }; + }); } //# sourceMappingURL=SlowCSSSelector.js.map \ No newline at end of file diff --git a/public/models/trace/insights/SlowCSSSelector.js.map b/public/models/trace/insights/SlowCSSSelector.js.map index 09d77e79..f590e666 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 * as Helpers from '../helpers/helpers.js';\nimport {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightResult, InsightSetContext, 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(\n data: Map,\n context: InsightSetContext): SelectorTiming[] {\n const selectorMap = new Map();\n\n for (const [event, value] of data) {\n if (event.args.beginData?.frame !== context.frameId) {\n continue;\n }\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\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 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 const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent, context);\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 // TODO: should we identify UpdateLayout events as linked to this insight?\n relatedEvents: [],\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 * as i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightModel, InsightSetContext, RequiredData} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Title of an insight that provides details about slow CSS selectors.\n */\n title: 'CSS Selector costs',\n\n /**\n * @description Text to describe how to improve the performance of CSS selectors.\n */\n description:\n 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/SlowCSSSelector.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['SelectorStats'] {\n return ['SelectorStats'];\n}\n\nexport type SlowCSSSelectorInsightModel = InsightModel<{\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(\n data: Map,\n context: InsightSetContext): SelectorTiming[] {\n const selectorMap = new Map();\n\n for (const [event, value] of data) {\n if (event.args.beginData?.frame !== context.frameId) {\n continue;\n }\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\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\nfunction finalize(partialModel: Omit): SlowCSSSelectorInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): SlowCSSSelectorInsightModel {\n const selectorStatsData = parsedTrace.SelectorStats;\n\n if (!selectorStatsData) {\n throw new Error('no selector stats data');\n }\n\n const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent, context);\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 finalize({\n // TODO: should we identify UpdateLayout events as linked to this insight?\n relatedEvents: [],\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/ThirdParties.d.ts b/public/models/trace/insights/ThirdParties.d.ts new file mode 100644 index 00000000..cd6463fd --- /dev/null +++ b/public/models/trace/insights/ThirdParties.d.ts @@ -0,0 +1,13 @@ +import * as Extras from '../extras/extras.js'; +import type * as Types from '../types/types.js'; +import type { InsightModel, InsightSetContext, RequiredData } from './types.js'; +export declare function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting']; +export type ThirdPartiesInsightModel = InsightModel<{ + entityByRequest: Map; + requestsByEntity: Map; + summaryByRequest: Map; + summaryByEntity: Map; + /** The entity for this navigation's URL. Any other entity is from a third party. */ + firstPartyEntity?: Extras.ThirdParties.Entity; +}>; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): ThirdPartiesInsightModel; diff --git a/public/models/trace/insights/ThirdParties.js b/public/models/trace/insights/ThirdParties.js new file mode 100644 index 00000000..170339cd --- /dev/null +++ b/public/models/trace/insights/ThirdParties.js @@ -0,0 +1,58 @@ +// 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 ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js'; +import * as Extras from '../extras/extras.js'; +import * as Helpers from '../helpers/helpers.js'; +const UIStrings = { + /** 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. + */ + description: 'Third party code can significantly impact load performance. ' + + '[Reduce and defer loading of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) to prioritize your page\'s content.', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); +export function deps() { + return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting']; +} +function getRelatedEvents(summaries, firstPartyEntity) { + const events = []; + for (const [entity, requests] of summaries.requestsByEntity.entries()) { + if (entity !== firstPartyEntity) { + events.push(...requests); + } + } + return events; +} +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} +export function generateInsight(parsedTrace, context) { + const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => { + if (!context.navigation) { + return false; + } + if (event.args.data.frame !== context.frameId) { + return false; + } + return Helpers.Timing.eventIsInBounds(event, context.bounds); + }); + const { entityByRequest, madeUpEntityCache, summaries } = Extras.ThirdParties.getSummariesAndEntitiesForTraceBounds(parsedTrace, context.bounds, networkRequests); + const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL; + const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) || + Extras.ThirdParties.makeUpEntity(madeUpEntityCache, firstPartyUrl); + return finalize({ + relatedEvents: getRelatedEvents(summaries, firstPartyEntity), + entityByRequest, + requestsByEntity: summaries.requestsByEntity, + summaryByRequest: summaries.byRequest, + summaryByEntity: summaries.byEntity, + firstPartyEntity, + }); +} +//# sourceMappingURL=ThirdParties.js.map \ No newline at end of file diff --git a/public/models/trace/insights/ThirdParties.js.map b/public/models/trace/insights/ThirdParties.js.map new file mode 100644 index 00000000..f2597689 --- /dev/null +++ b/public/models/trace/insights/ThirdParties.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdParties.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,aAAa,MAAM,yDAAyD,CAAC;AACzF,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAE9C,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAKjD,MAAM,SAAS,GAAG;IAChB,gJAAgJ;IAChJ,KAAK,EAAE,eAAe;IACtB;;;OAGG;IACH,WAAW,EAAE,8DAA8D;QACvE,8MAA8M;CACnN,CAAC;AAEF,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,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;AAClE,CAAC;AAWD,SAAS,gBAAgB,CACrB,SAA0C,EAC1C,gBAAsD;IACxD,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;QACtE,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,QAAQ,CAAC,YAAmE;IACnF,OAAO,EAAC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG,YAAY,EAAC,CAAC;AAC/G,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAsC,EAAE,OAA0B;IACpE,MAAM,eAAe,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACxE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,EAAC,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAC,GAAG,MAAM,CAAC,YAAY,CAAC,qCAAqC,CAC7G,WAAyC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAEhF,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,iBAAiB,IAAI,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC;IACxG,MAAM,gBAAgB,GAAG,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC;QACzE,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAEvE,OAAO,QAAQ,CAAC;QACd,aAAa,EAAE,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,CAAC;QAC5D,eAAe;QACf,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;QAC5C,gBAAgB,EAAE,SAAS,CAAC,SAAS;QACrC,eAAe,EAAE,SAAS,CAAC,QAAQ;QACnC,gBAAgB;KACjB,CAAC,CAAC;AACL,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 i18n from '../../../core/i18n/i18n.js';\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 type * as Types from '../types/types.js';\n\nimport type {InsightModel, InsightSetContext, RequiredData} from './types.js';\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 */\n description: 'Third party code can significantly impact load performance. ' +\n '[Reduce and defer loading of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) to prioritize your page\\'s content.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\nexport type ThirdPartiesInsightModel = InsightModel<{\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?: Extras.ThirdParties.Entity,\n}>;\n\nfunction getRelatedEvents(\n summaries: Extras.ThirdParties.SummaryMaps,\n firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] {\n const events = [];\n\n for (const [entity, requests] of summaries.requestsByEntity.entries()) {\n if (entity !== firstPartyEntity) {\n events.push(...requests);\n }\n }\n\n return events;\n}\n\nfunction finalize(partialModel: Omit): ThirdPartiesInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): ThirdPartiesInsightModel {\n const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => {\n if (!context.navigation) {\n return false;\n }\n\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n const {entityByRequest, madeUpEntityCache, summaries} = Extras.ThirdParties.getSummariesAndEntitiesForTraceBounds(\n parsedTrace as Handlers.Types.ParsedTrace, context.bounds, networkRequests);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||\n Extras.ThirdParties.makeUpEntity(madeUpEntityCache, firstPartyUrl);\n\n return finalize({\n relatedEvents: getRelatedEvents(summaries, firstPartyEntity),\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/ThirdParties.test.d.ts b/public/models/trace/insights/ThirdParties.test.d.ts new file mode 100644 index 00000000..29614938 --- /dev/null +++ b/public/models/trace/insights/ThirdParties.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/ThirdParties.test.js b/public/models/trace/insights/ThirdParties.test.js new file mode 100644 index 00000000..4a5f9e8d --- /dev/null +++ b/public/models/trace/insights/ThirdParties.test.js @@ -0,0 +1,144 @@ +// 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, getInsightOrError } 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('ThirdParties', function () { + it('categorizes third party web requests (simple)', async () => { + const { data, insights } = await processTrace(this, 'load-simple.json.gz'); + assert.strictEqual(insights.size, 2); + const insight = getInsightOrError('ThirdParties', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); + const entityByRequestResult = [...insight.entityByRequest.entries()].map(([request, entity]) => { + return [request.args.data.url, entity.name]; + }); + assert.deepEqual(entityByRequestResult, [ + ['http://localhost:8080/', 'localhost'], + ['https://fonts.googleapis.com/css2?family=Orelega+One&display=swap', 'Google Fonts'], + ['http://localhost:8080/styles.css', 'localhost'], + ['http://localhost:8080/blocking.js', 'localhost'], + ['http://localhost:8080/module.js', 'localhost'], + ['https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2', 'Google Fonts'], + ]); + const requestsByEntityResult = [...insight.requestsByEntity.entries()].map(([entity, requests]) => { + return [entity.name, requests.map(r => r.args.data.url)]; + }); + assert.deepEqual(requestsByEntityResult, [ + [ + 'localhost', + [ + 'http://localhost:8080/', + 'http://localhost:8080/styles.css', + 'http://localhost:8080/blocking.js', + 'http://localhost:8080/module.js', + ], + ], + [ + 'Google Fonts', + [ + 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap', + 'https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2', + ], + ], + ]); + const summaryResult = [...insight.summaryByEntity.entries()].map(([entity, summary]) => { + return [entity.name, summary]; + }); + assert.deepEqual(summaryResult, [ + ['localhost', { transferSize: 751, mainThreadTime: 26381 }], + ['Google Fonts', { transferSize: 0, mainThreadTime: 0 }], + ]); + }); + 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 = getInsightOrError('ThirdParties', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); + const entityNames = [...insight.entityByRequest.values()].map(entity => entity.name); + assert.deepEqual([...new Set(entityNames)], [ + 'paulirish.com', + 'Google Tag Manager', + 'Google Fonts', + 'Google Analytics', + 'Disqus', + 'Firebase', + ]); + const requestsByEntityResult = [...insight.requestsByEntity.entries()].map(([entity, requests]) => { + return [entity.name, requests.map(r => r.args.data.url)]; + }); + assert.deepEqual(requestsByEntityResult, [ + [ + 'paulirish.com', + [ + 'https://www.paulirish.com/', + 'https://www.paulirish.com/assets/wikipedia-flamechart.jpg', + 'https://www.paulirish.com/avatar150.jpg', + 'https://www.paulirish.com/javascripts/modernizr-2.0.js', + 'https://www.paulirish.com/javascripts/ender.js', + 'https://www.paulirish.com/javascripts/octopress.js', + 'https://www.paulirish.com/javascripts/firebase-performance-standalone.js', + 'https://www.paulirish.com/images/noise.png?1418840251', + 'https://www.paulirish.com/images/code_bg.png?1418840251', + 'https://www.paulirish.com/favicon.ico', + ], + ], + [ + 'Google Tag Manager', + [ + 'https://www.googletagmanager.com/gtag/js?id=G-PGXNGYWP8E', + ], + ], + [ + 'Google Fonts', + [ + 'https://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold|PT+Sans:regular,italic,bold|Droid+Sans:400,700|Lato:700,900', + 'https://fonts.gstatic.com/s/droidsans/v18/SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2', + 'https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2', + 'https://fonts.gstatic.com/s/ptsans/v17/jizaRExUiTo99u79D0KExcOPIDU.woff2', + 'https://fonts.gstatic.com/s/ptsans/v17/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2', + 'https://fonts.gstatic.com/s/droidsans/v18/SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2', + 'https://fonts.gstatic.com/s/ptserif/v18/EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2', + ], + ], + [ + 'Google Analytics', + [ + 'https://www.google-analytics.com/analytics.js', + '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', + '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', + ], + ], + [ + 'Disqus', + [ + 'https://paulirish.disqus.com/count.js', + ], + ], + [ + 'Firebase', + [ + 'https://firebaseinstallations.googleapis.com/v1/projects/paulirishcom/installations', + 'https://firebaseremoteconfig.googleapis.com/v1/projects/paulirishcom/namespaces/fireperf:fetch?key=AIzaSyCGxLbbFQxH4BV1fY0RODlxTos9nJa2l_g', + ], + ], + ]); + const summaryResult = [...insight.summaryByEntity.entries()].map(([entity, summary]) => { + return [entity.name, summary]; + }); + assert.deepEqual(summaryResult, [ + ['paulirish.com', { transferSize: 157130, mainThreadTime: 6626 }], + ['Google Tag Manager', { transferSize: 95375, mainThreadTime: 83 }], + ['Google Fonts', { transferSize: 80003, mainThreadTime: 0 }], + ['Google Analytics', { transferSize: 20865, mainThreadTime: 97 }], + ['Disqus', { transferSize: 1551, mainThreadTime: 23 }], + ['Firebase', { transferSize: 2847, mainThreadTime: 0 }], + ]); + }); +}); +//# sourceMappingURL=ThirdParties.test.js.map \ No newline at end of file diff --git a/public/models/trace/insights/ThirdParties.test.js.map b/public/models/trace/insights/ThirdParties.test.js.map new file mode 100644 index 00000000..efb9e482 --- /dev/null +++ b/public/models/trace/insights/ThirdParties.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ThirdParties.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdParties.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, getInsightOrError} 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('ThirdParties', 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 getInsightOrError('ThirdParties', 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 getInsightOrError('ThirdParties', 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 2d289391..2e1c7a48 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 InsightSetContext, type RequiredData } from './types.js'; +import { type InsightModel, type InsightSetContext, type RequiredData } from './types.js'; export declare function deps(): ['Meta', 'UserInteractions']; -export type ViewportInsightResult = InsightResult<{ +export type ViewportInsightModel = InsightModel<{ mobileOptimized: boolean | null; viewportEvent?: Types.Events.ParseMetaViewport; }>; -export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): ViewportInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): ViewportInsightModel; diff --git a/public/models/trace/insights/Viewport.js b/public/models/trace/insights/Viewport.js index 30c1cc28..d666dbe3 100644 --- a/public/models/trace/insights/Viewport.js +++ b/public/models/trace/insights/Viewport.js @@ -1,11 +1,25 @@ // 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 Helpers from '../helpers/helpers.js'; import { InsightWarning } from './types.js'; +const UIStrings = { + /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */ + title: 'Viewport not optimized for mobile', + /** + * @description Text to tell the user how a viewport meta element can improve performance. \xa0 is a non-breaking space + */ + description: 'The page\'s viewport is not mobile-optimized, so tap interactions may be [delayed by up to 300\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/).', +}; +const str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export function deps() { return ['Meta', 'UserInteractions']; } +function finalize(partialModel) { + return { title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel }; +} export function generateInsight(parsedTrace, context) { const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => { if (event.args.frame !== context.frameId) { @@ -15,10 +29,10 @@ export function generateInsight(parsedTrace, context) { }); if (!compositorEvents.length) { // Trace doesn't have the data we need. - return { + return finalize({ mobileOptimized: null, warnings: [InsightWarning.NO_LAYOUT], - }; + }); } const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => { if (event.args.data.frame !== context.frameId) { @@ -29,16 +43,16 @@ export function generateInsight(parsedTrace, context) { // Returns true only if all events are mobile optimized. for (const event of compositorEvents) { if (!event.args.is_mobile_optimized) { - return { + return finalize({ mobileOptimized: false, viewportEvent, metricSavings: { INP: 300 }, - }; + }); } } - return { + return finalize({ mobileOptimized: true, viewportEvent, - }; + }); } //# sourceMappingURL=Viewport.js.map \ No newline at end of file diff --git a/public/models/trace/insights/Viewport.js.map b/public/models/trace/insights/Viewport.js.map index 976c92f2..4f6952dc 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,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,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,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,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,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,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;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAgC,EAAC;aACvD,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 const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\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 return Helpers.Timing.eventIsInBounds(event, context.bounds);\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 metricSavings: {INP: 300 as Types.Timing.MilliSeconds},\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,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAA4C,cAAc,EAAoB,MAAM,YAAY,CAAC;AAExG,MAAM,SAAS,GAAG;IAChB,8GAA8G;IAC9G,KAAK,EAAE,mCAAmC;IAC1C;;OAEG;IACH,WAAW,EACP,sKAAsK;CAC3K,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;AACzF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAOD,SAAS,QAAQ,CAAC,YAA+D;IAC/E,OAAO,EAAC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG,YAAY,EAAC,CAAC;AAC/G,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAsC,EAAE,OAA0B;IACpE,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,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;QAC7B,uCAAuC;QACvC,OAAO,QAAQ,CAAC;YACd,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC,CAAC;IACL,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,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,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,QAAQ,CAAC;gBACd,eAAe,EAAE,KAAK;gBACtB,aAAa;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAgC,EAAC;aACvD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,CAAC,CAAC;AACL,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 i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type InsightModel, type InsightSetContext, InsightWarning, type RequiredData} from './types.js';\n\nconst UIStrings = {\n /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */\n title: 'Viewport not optimized for mobile',\n /**\n * @description Text to tell the user how a viewport meta element can improve performance. \\xa0 is a non-breaking space\n */\n description:\n 'The page\\'s viewport is not mobile-optimized, so tap interactions may be [delayed by up to 300\\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/).',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport type ViewportInsightModel = InsightModel<{\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n}>;\n\nfunction finalize(partialModel: Omit): ViewportInsightModel {\n return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): ViewportInsightModel {\n const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n if (!compositorEvents.length) {\n // Trace doesn't have the data we need.\n return finalize({\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 return Helpers.Timing.eventIsInBounds(event, context.bounds);\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 finalize({\n mobileOptimized: false,\n viewportEvent,\n metricSavings: {INP: 300 as Types.Timing.MilliSeconds},\n });\n }\n }\n\n return finalize({\n mobileOptimized: true,\n viewportEvent,\n });\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/Viewport.test.js b/public/models/trace/insights/Viewport.test.js index 6dac716d..3015cc46 100644 --- a/public/models/trace/insights/Viewport.test.js +++ b/public/models/trace/insights/Viewport.test.js @@ -27,7 +27,7 @@ describeWithEnvironment('Viewport', function () { for (const event of events) { event.args.is_mobile_optimized = false; } - const insight = Trace.Insights.InsightRunners.Viewport.generateInsight(data, context); + const insight = Trace.Insights.Models.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 ce9d36b7..0263ee1e 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,0BAA0B,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,oCAAoC,CAAC;AAClH,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,GACT,iBAAiB,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAE3G,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,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpF,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, getInsightOrError} 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 =\n getInsightOrError('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(data, 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 +{"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,iBAAiB,EAAC,MAAM,oCAAoC,CAAC;AAClH,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,GACT,iBAAiB,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAE3G,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,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpF,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,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9E,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, getInsightOrError} 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 =\n getInsightOrError('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(data, 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.Models.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 eb917a81..977e8925 100644 --- a/public/models/trace/insights/insights-tsconfig.json +++ b/public/models/trace/insights/insights-tsconfig.json @@ -29,16 +29,17 @@ "useUnknownInCatchVariables": false }, "files": [ + "../../../../../../../front_end/models/trace/insights/CLSCulprits.ts", "../../../../../../../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", + "../../../../../../../front_end/models/trace/insights/LCPDiscovery.ts", + "../../../../../../../front_end/models/trace/insights/LCPPhases.ts", + "../../../../../../../front_end/models/trace/insights/Models.ts", "../../../../../../../front_end/models/trace/insights/RenderBlocking.ts", "../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts", - "../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.ts", + "../../../../../../../front_end/models/trace/insights/ThirdParties.ts", "../../../../../../../front_end/models/trace/insights/Viewport.ts", "../../../../../../../front_end/models/trace/insights/types.ts", "../../../../../../../front_end/legacy/legacy-defs.d.ts", diff --git a/public/models/trace/insights/insights.d.ts b/public/models/trace/insights/insights.d.ts index f48f51b6..d665a03e 100644 --- a/public/models/trace/insights/insights.d.ts +++ b/public/models/trace/insights/insights.d.ts @@ -1,3 +1,3 @@ export * as Common from './Common.js'; -export * as InsightRunners from './InsightRunners.js'; +export * as Models from './Models.js'; export * as Types from './types.js'; diff --git a/public/models/trace/insights/insights.js b/public/models/trace/insights/insights.js index 44b72cc0..76746908 100644 --- a/public/models/trace/insights/insights.js +++ b/public/models/trace/insights/insights.js @@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. export * as Common from './Common.js'; -export * as InsightRunners from './InsightRunners.js'; +export * as Models from './Models.js'; export * as Types from './types.js'; //# sourceMappingURL=insights.js.map \ No newline at end of file diff --git a/public/models/trace/insights/insights.js.map b/public/models/trace/insights/insights.js.map index 1cdedf01..e87cf614 100644 --- a/public/models/trace/insights/insights.js.map +++ b/public/models/trace/insights/insights.js.map @@ -1 +1 @@ -{"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/insights.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,YAAY,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 Common from './Common.js';\nexport * as InsightRunners from './InsightRunners.js';\nexport * as Types from './types.js';\n"]} \ No newline at end of file +{"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/insights.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,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 Common from './Common.js';\nexport * as Models from './Models.js';\nexport * as Types from './types.js';\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/types.d.ts b/public/models/trace/insights/types.d.ts index 38956cbc..b06e2e0c 100644 --- a/public/models/trace/insights/types.d.ts +++ b/public/models/trace/insights/types.d.ts @@ -1,7 +1,7 @@ import type * as Handlers from '../handlers/handlers.js'; import type * as Lantern from '../lantern/lantern.js'; import type * as Types from '../types/types.js'; -import type * as InsightsRunners from './InsightRunners.js'; +import type * as Models from './Models.js'; /** * Context for the portion of the trace an insight should look at. */ @@ -23,7 +23,7 @@ export interface LanternContext { simulator: Lantern.Simulation.Simulator; metrics: Record; } -export type InsightRunnersType = typeof InsightsRunners; +export type InsightModelsType = typeof Models; export declare enum InsightWarning { NO_FP = "NO_FP", NO_LCP = "NO_LCP", @@ -37,7 +37,9 @@ export interface MetricSavings { CLS?: number; INP?: Types.Timing.MilliSeconds; } -export type InsightResult> = R & { +export type InsightModel> = R & { + title: string; + description: string; relatedEvents?: Types.Events.Event[]; warnings?: InsightWarning[]; metricSavings?: MetricSavings; @@ -47,21 +49,21 @@ export type InsightResult> = R & { * 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 InsightSets = { +export type InsightSet = { /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */ id: Types.Events.NavigationId; /** The URL to show in the accordion list. */ url: URL; frameId: string; bounds: Types.Timing.TraceWindowMicroSeconds; - data: InsightResults; + model: InsightModels; navigation?: Types.Events.NavigationStart; }; /** - * Contains insights for a specific navigation. + * Contains insights for a specific insight set. */ -export type InsightResults = { - [I in keyof InsightRunnersType]: ReturnType; +export type InsightModels = { + [I in keyof InsightModelsType]: ReturnType; }; /** * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception: @@ -69,7 +71,7 @@ export type InsightResults = { * 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 `Types.Events.NO_NAVIGATION` is used for the key. */ -export type TraceInsightSets = Map; +export type TraceInsightSets = Map; /** * 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.map b/public/models/trace/insights/types.js.map index 1f9e6bdc..5c84d1e8 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;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","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 interface MetricSavings {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: Types.Timing.MilliSeconds;\n LCP?: Types.Timing.MilliSeconds;\n TBT?: Types.Timing.MilliSeconds;\n CLS?: number;\n INP?: Types.Timing.MilliSeconds;\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport type InsightResult> = R&{\n relatedEvents?: Types.Events.Event[],\n warnings?: InsightWarning[],\n metricSavings?: MetricSavings,\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 /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */\n id: Types.Events.NavigationId,\n /** The URL to show in the accordion list. */\n url: URL,\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 `Types.Events.NO_NAVIGATION` is used for the key.\n */\nexport type TraceInsightSets = 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","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 Models from './Models.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 InsightModelsType = typeof Models;\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 interface MetricSavings {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: Types.Timing.MilliSeconds;\n LCP?: Types.Timing.MilliSeconds;\n TBT?: Types.Timing.MilliSeconds;\n CLS?: number;\n INP?: Types.Timing.MilliSeconds;\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport type InsightModel> = R&{\n title: string,\n description: string,\n relatedEvents?: Types.Events.Event[],\n warnings?: InsightWarning[],\n metricSavings?: MetricSavings,\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 InsightSet = {\n /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */\n id: Types.Events.NavigationId,\n /** The URL to show in the accordion list. */\n url: URL,\n frameId: string,\n bounds: Types.Timing.TraceWindowMicroSeconds,\n model: InsightModels,\n navigation?: Types.Events.NavigationStart,\n};\n\n/**\n * Contains insights for a specific insight set.\n */\nexport type InsightModels = {\n [I in keyof InsightModelsType]: 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 `Types.Events.NO_NAVIGATION` is used for the key.\n */\nexport type TraceInsightSets = 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 diff --git a/public/models/trace/insights/unittests-tsconfig.json b/public/models/trace/insights/unittests-tsconfig.json index 66eb89e6..fc0963cc 100644 --- a/public/models/trace/insights/unittests-tsconfig.json +++ b/public/models/trace/insights/unittests-tsconfig.json @@ -38,14 +38,15 @@ "useUnknownInCatchVariables": false }, "files": [ - "../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.test.ts", + "../../../../../../../front_end/models/trace/insights/CLSCulprits.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/LCPDiscovery.test.ts", + "../../../../../../../front_end/models/trace/insights/LCPPhases.test.ts", "../../../../../../../front_end/models/trace/insights/RenderBlocking.test.ts", "../../../../../../../front_end/models/trace/insights/SlowCSSSelector.test.ts", - "../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.test.ts", + "../../../../../../../front_end/models/trace/insights/ThirdParties.test.ts", "../../../../../../../front_end/models/trace/insights/Viewport.test.ts", "../../../../../../../front_end/legacy/legacy-defs.d.ts", "../../../../../../../front_end/global_typings/global_defs.d.ts", diff --git a/public/models/trace/trace-tsconfig.json b/public/models/trace/trace-tsconfig.json index 7086ea7b..5048511e 100644 --- a/public/models/trace/trace-tsconfig.json +++ b/public/models/trace/trace-tsconfig.json @@ -47,6 +47,12 @@ { "path": "../../core/sdk/bundle-tsconfig.json" }, + { + "path": "../../generated/protocol-tsconfig.json" + }, + { + "path": "../cpu_profile/bundle-tsconfig.json" + }, { "path": "extras/bundle-tsconfig.json" }, diff --git a/public/models/trace/types/TraceEvents.d.ts b/public/models/trace/types/TraceEvents.d.ts index 832302b3..3af18ff2 100644 --- a/public/models/trace/types/TraceEvents.d.ts +++ b/public/models/trace/types/TraceEvents.d.ts @@ -26,6 +26,9 @@ export declare const enum Phase { MARK = "R", CLOCK_SYNC = "c" } +export type NonEmptyString = string & { + _tag: 'NonEmptyString'; +}; export declare function isNestableAsyncPhase(phase: Phase): boolean; export declare function isPhaseAsync(phase: Phase): boolean; export declare function isFlowPhase(phase: Phase): boolean; @@ -188,28 +191,34 @@ export interface End extends Event { * the RendererHandler. */ export type SyntheticComplete = Complete; -export interface EventTiming extends Event { - ph: Phase.ASYNC_NESTABLE_START | Phase.ASYNC_NESTABLE_END; +export type EventTimingBeginOrEnd = EventTimingBegin | EventTimingEnd; +export interface EventTimingBegin extends Event { + ph: Phase.ASYNC_NESTABLE_START; name: Name.EVENT_TIMING; id: string; args: Args & { - frame: string; - data?: ArgsData & { + data: ArgsData & { cancelable: boolean; duration: MilliSeconds; - processingEnd: MilliSeconds; - processingStart: MilliSeconds; - timeStamp: MilliSeconds; - interactionId?: number; type: string; + interactionId: number; + interactionOffset: number; + nodeId: Protocol.DOM.BackendNodeId; + frame?: string; + processingEnd?: MilliSeconds; + processingStart?: MilliSeconds; + timeStamp?: MilliSeconds; + enqueuedToMainThreadTime?: MilliSeconds; + commitFinishTime?: MilliSeconds; }; + frame?: string; }; } -export interface EventTimingBegin extends EventTiming { - ph: Phase.ASYNC_NESTABLE_START; -} -export interface EventTimingEnd extends EventTiming { +export interface EventTimingEnd extends Event { ph: Phase.ASYNC_NESTABLE_END; + name: Name.EVENT_TIMING; + id: string; + args: Args; } export interface GPUTask extends Complete { name: 'GPUTask'; @@ -446,11 +455,12 @@ export interface ProcessName extends Metadata { export interface Mark extends Event { ph: Phase.MARK; } -export interface NavigationStart extends Mark { +export interface NavigationStartUnreliable extends Mark { name: 'navigationStart'; args: Args & { data?: ArgsData & { - documentLoaderURL: string; + /** An empty documentLoaderURL means this navigationStart is unreliable noise and can be ignored. */ + documentLoaderURL: never; isLoadingMainFrame: boolean; isOutermostMainFrame?: boolean; navigationId: string; @@ -462,6 +472,14 @@ export interface NavigationStart extends Mark { frame: string; }; } +export interface NavigationStart extends NavigationStartUnreliable { + args: NavigationStartUnreliable['args'] & { + data: NavigationStartUnreliable['args']['data'] & { + /** This navigationStart is valid, as the documentLoaderURL isn't empty. */ + documentLoaderURL: NonEmptyString; + }; + }; +} export interface FirstContentfulPaint extends Mark { name: Name.MARK_FCP; args: Args & { @@ -746,8 +764,9 @@ export interface ResourceChangePriority extends Instant { }; }; } +/** Only sent for navigations. https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_instrumentation.cc;l=1612-1647;drc=ec7daf93d0479b758610c75f4e146fd4d2d6ed2b */ export interface ResourceWillSendRequest extends Instant { - name: 'ResourceWillSendRequest'; + name: Name.RESOURCE_WILL_SEND_REQUEST; args: Args & { data: ArgsData & { requestId: string; @@ -776,6 +795,7 @@ export interface ResourceReceivedData extends Instant { }; }; } +/** See https://mdn.github.io/shared-assets/images/diagrams/api/performance/timestamp-diagram.svg */ interface ResourceReceiveResponseTimingData { connectEnd: MilliSeconds; connectStart: MilliSeconds; @@ -787,6 +807,7 @@ interface ResourceReceiveResponseTimingData { pushStart: MilliSeconds; receiveHeadersEnd: MilliSeconds; receiveHeadersStart: MilliSeconds; + /** When the network service is about to handle a request, ie. just before going to the HTTP cache or going to the network for DNS/connection setup. */ requestTime: Seconds; sendEnd: MilliSeconds; sendStart: MilliSeconds; @@ -1148,7 +1169,7 @@ export type SyntheticPipelineReporterPair = SyntheticEventPair export type SyntheticUserTimingPair = SyntheticEventPair; export type SyntheticConsoleTimingPair = SyntheticEventPair; export type SyntheticAnimationPair = SyntheticEventPair; -export interface SyntheticInteractionPair extends SyntheticEventPair { +export interface SyntheticInteractionPair extends SyntheticEventPair { interactionId: number; type: string; ts: MicroSeconds; @@ -1442,7 +1463,8 @@ 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; +/** @deprecated You probably want `isNavigationStart` instead. */ +export declare function isNavigationStartUnreliable(event: Event): event is NavigationStartUnreliable; 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; @@ -1455,7 +1477,7 @@ 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 isEventTiming(event: Event): event is EventTimingBeginOrEnd; 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; @@ -1473,7 +1495,8 @@ export declare function isSyntheticNetworkRequest(event: Event): event is Synthe 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; +/** A VALID navigation start (as it has a populated documentLoaderURL) */ +export declare function isNavigationStart(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; diff --git a/public/models/trace/types/TraceEvents.js b/public/models/trace/types/TraceEvents.js index f553d8cf..0c2e2644 100644 --- a/public/models/trace/types/TraceEvents.js +++ b/public/models/trace/types/TraceEvents.js @@ -246,7 +246,8 @@ export function isFrameCommittedInBrowser(event) { export function isCommitLoad(event) { return event.name === 'CommitLoad'; } -export function isNavigationStart(event) { +/** @deprecated You probably want `isNavigationStart` instead. */ +export function isNavigationStartUnreliable(event) { return event.name === 'navigationStart'; } export function isAnimation(event) { @@ -347,8 +348,9 @@ export function isNetworkTrackEntry(event) { export function isPrePaint(event) { return event.name === 'PrePaint'; } -export function isNavigationStartWithURL(event) { - return Boolean(isNavigationStart(event) && event.args.data && event.args.data.documentLoaderURL !== ''); +/** A VALID navigation start (as it has a populated documentLoaderURL) */ +export function isNavigationStart(event) { + return Boolean(isNavigationStartUnreliable(event) && event.args.data && event.args.data.documentLoaderURL !== ''); } export function isMainFrameViewport(event) { return event.name === 'PaintTimingVisualizer::Viewport'; diff --git a/public/models/trace/types/TraceEvents.js.map b/public/models/trace/types/TraceEvents.js.map index e3a491c4..e6e31312 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, MilliSeconds, Seconds, 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 /** Server response time (receiveHeadersEnd - sendEnd) */\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 /** Device Pixel Ratio. Added in m128 */\n dpr: 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 /** @deprecated This value will incorrectly overreport for shifts within an iframe. */\n score: number,\n /** This is the preferred \"score\", used for CLS. If `is_main_frame` is true, `score` and `weighted_score_delta` will be equal. But if the shift is from an iframe, `weighted_score_delta` will be appropriately reduced to account for the viewport size of that iframe. https://wicg.github.io/layout-instability/#subframe-weighting-factor and b/275509162 */\n weighted_score_delta: number,\n navigationId?: string,\n /* eslint-enable @typescript-eslint/naming-convention */\n};\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 /** screenshot taken before and after this shift. Before *should* always exist, but after might not at the end of a trace. */\n screenshots: {before: SyntheticScreenshot|null, after: SyntheticScreenshot|null};\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\nexport const NO_NAVIGATION = 'NO_NAVIGATION';\n\n/**\n * This maybe be a navigation id string from Chromium, or `NO_NAVIGATION`, which represents the\n * portion of the trace for which we don't have any navigation event for (as it happeneded prior\n * to the trace start).\n */\nexport type NavigationId = string|typeof NO_NAVIGATION;\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?: NavigationId;\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 =\n 'blocking'|'non_blocking'|'in_body_parser_blocking'|'potentially_blocking'|'dynamically_injected_non_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 /** Added Feb 2024. https://crrev.com/c/5277583 */\n resourceType?: Protocol.Network.ResourceType,\n /** Added Feb 2024. https://crrev.com/c/5297615 */\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}\n\nexport function isRenderFrameImplCreateChildFrame(event: Event): event is RenderFrameImplCreateChildFrame {\n return event.name === Name.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME;\n}\n\nexport interface LayoutImageUnsized extends Event {\n name: Name.LAYOUT_IMAGE_UNSIZED;\n args: Args&{\n data: {\n nodeId: Protocol.DOM.BackendNodeId,\n frameId: string,\n },\n };\n}\n\nexport function isLayoutImageUnsized(event: Event): event is LayoutImageUnsized {\n return event.name === Name.LAYOUT_IMAGE_UNSIZED;\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\nexport interface SchedulePostTaskCallback extends Instant {\n name: Name.SCHEDULE_POST_TASK_CALLBACK;\n args: Args&{\n data: {\n taskId: number,\n priority: 'user-blocking'|'user-visible'|'background',\n delay: MilliSeconds,\n frame?: string,\n stackTrace?: CallFrame,\n },\n };\n}\nexport function isSchedulePostTaskCallback(event: Event): event is SchedulePostTaskCallback {\n return event.name === Name.SCHEDULE_POST_TASK_CALLBACK;\n}\n\nexport interface RunPostTaskCallback extends Complete {\n name: Name.RUN_POST_TASK_CALLBACK;\n args: Args&{\n data: {\n taskId: number,\n priority: 'user-blocking'|'user-visible'|'background',\n delay: MilliSeconds,\n frame?: string,\n },\n };\n}\nexport function isRunPostTaskCallback(event: Event): event is RunPostTaskCallback {\n return event.name === Name.RUN_POST_TASK_CALLBACK;\n}\n\nexport interface AbortPostTaskCallback extends Complete {\n name: Name.ABORT_POST_TASK_CALLBACK;\n args: Args&{\n data: {\n taskId: number,\n frame?: string,\n stackTrace?: CallFrame,\n },\n };\n}\nexport function isAbortPostTaskCallback(event: Event): event is RunPostTaskCallback {\n return event.name === Name.ABORT_POST_TASK_CALLBACK;\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 SCHEDULE_POST_TASK_CALLBACK = 'SchedulePostTaskCallback',\n RUN_POST_TASK_CALLBACK = 'RunPostTaskCallback',\n ABORT_POST_TASK_CALLBACK = 'AbortPostTaskCallback',\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 LAYOUT_IMAGE_UNSIZED = 'LayoutImageUnsized',\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 +{"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, MilliSeconds, Seconds, 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 type NonEmptyString = string&{_tag: 'NonEmptyString'};\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\n// TODO(paulirish): Migrate to the new (Sept 2024) EventTiming trace events.\n// See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;l=900-901;drc=b503c262e425eae59ced4a80d59d176ed07152c7\nexport type EventTimingBeginOrEnd = EventTimingBegin|EventTimingEnd;\n\nexport interface EventTimingBegin extends Event {\n ph: Phase.ASYNC_NESTABLE_START;\n name: Name.EVENT_TIMING;\n id: string;\n args: Args&{\n // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/performance_event_timing.cc;l=297;drc=4f00803ca25c0d0480ed14844d6406933c21e80e\n data: ArgsData & {\n cancelable: boolean,\n duration: MilliSeconds,\n type: string,\n interactionId: number,\n interactionOffset: number,\n nodeId: Protocol.DOM.BackendNodeId,\n frame?: string, // From May 2022 onwards, this is where frame is located. https://chromium-review.googlesource.com/c/chromium/src/+/3632661\n processingEnd?: MilliSeconds,\n processingStart?: MilliSeconds,\n timeStamp?: MilliSeconds,\n enqueuedToMainThreadTime?: MilliSeconds,\n commitFinishTime?: MilliSeconds,\n },\n frame?: string, // Prior to May 2022, `frame` was here in args.\n };\n}\nexport interface EventTimingEnd extends Event {\n ph: Phase.ASYNC_NESTABLE_END;\n name: Name.EVENT_TIMING;\n id: string;\n args: Args;\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 /** Server response time (receiveHeadersEnd - sendEnd) */\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\n// An unreliable and non-legit navigationStart. See NavigationStartWithUrl\nexport interface NavigationStartUnreliable extends Mark {\n name: 'navigationStart';\n args: Args&{\n data?: ArgsData & {\n /** An empty documentLoaderURL means this navigationStart is unreliable noise and can be ignored. */\n documentLoaderURL: never,\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\n// NavigationStart but definitely has a populated documentLoaderURL\nexport interface NavigationStart extends NavigationStartUnreliable {\n args: NavigationStartUnreliable['args']&{\n data: NavigationStartUnreliable['args']['data'] & {\n /** This navigationStart is valid, as the documentLoaderURL isn't empty. */\n documentLoaderURL: NonEmptyString,\n },\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 /** Device Pixel Ratio. Added in m128 */\n dpr: 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 /** @deprecated This value will incorrectly overreport for shifts within an iframe. */\n score: number,\n /** This is the preferred \"score\", used for CLS. If `is_main_frame` is true, `score` and `weighted_score_delta` will be equal. But if the shift is from an iframe, `weighted_score_delta` will be appropriately reduced to account for the viewport size of that iframe. https://wicg.github.io/layout-instability/#subframe-weighting-factor and b/275509162 */\n weighted_score_delta: number,\n navigationId?: string,\n /* eslint-enable @typescript-eslint/naming-convention */\n};\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 /** screenshot taken before and after this shift. Before *should* always exist, but after might not at the end of a trace. */\n screenshots: {before: SyntheticScreenshot|null, after: SyntheticScreenshot|null};\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\nexport const NO_NAVIGATION = 'NO_NAVIGATION';\n\n/**\n * This maybe be a navigation id string from Chromium, or `NO_NAVIGATION`, which represents the\n * portion of the trace for which we don't have any navigation event for (as it happeneded prior\n * to the trace start).\n */\nexport type NavigationId = string|typeof NO_NAVIGATION;\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?: NavigationId;\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 =\n 'blocking'|'non_blocking'|'in_body_parser_blocking'|'potentially_blocking'|'dynamically_injected_non_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 /** Added Feb 2024. https://crrev.com/c/5277583 */\n resourceType?: Protocol.Network.ResourceType,\n /** Added Feb 2024. https://crrev.com/c/5297615 */\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\n/** Only sent for navigations. https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_instrumentation.cc;l=1612-1647;drc=ec7daf93d0479b758610c75f4e146fd4d2d6ed2b */\nexport interface ResourceWillSendRequest extends Instant {\n name: Name.RESOURCE_WILL_SEND_REQUEST;\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\n/** See https://mdn.github.io/shared-assets/images/diagrams/api/performance/timestamp-diagram.svg */\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 /** When the network service is about to handle a request, ie. just before going to the HTTP cache or going to the network for DNS/connection setup. */\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}\n\nexport function isRenderFrameImplCreateChildFrame(event: Event): event is RenderFrameImplCreateChildFrame {\n return event.name === Name.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME;\n}\n\nexport interface LayoutImageUnsized extends Event {\n name: Name.LAYOUT_IMAGE_UNSIZED;\n args: Args&{\n data: {\n nodeId: Protocol.DOM.BackendNodeId,\n frameId: string,\n },\n };\n}\n\nexport function isLayoutImageUnsized(event: Event): event is LayoutImageUnsized {\n return event.name === Name.LAYOUT_IMAGE_UNSIZED;\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\n/** @deprecated You probably want `isNavigationStart` instead. */\nexport function isNavigationStartUnreliable(\n event: Event,\n ): event is NavigationStartUnreliable {\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 EventTimingBeginOrEnd {\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\n/** A VALID navigation start (as it has a populated documentLoaderURL) */\nexport function isNavigationStart(event: Event): event is NavigationStart {\n return Boolean(isNavigationStartUnreliable(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\nexport interface SchedulePostTaskCallback extends Instant {\n name: Name.SCHEDULE_POST_TASK_CALLBACK;\n args: Args&{\n data: {\n taskId: number,\n priority: 'user-blocking'|'user-visible'|'background',\n delay: MilliSeconds,\n frame?: string,\n stackTrace?: CallFrame,\n },\n };\n}\nexport function isSchedulePostTaskCallback(event: Event): event is SchedulePostTaskCallback {\n return event.name === Name.SCHEDULE_POST_TASK_CALLBACK;\n}\n\nexport interface RunPostTaskCallback extends Complete {\n name: Name.RUN_POST_TASK_CALLBACK;\n args: Args&{\n data: {\n taskId: number,\n priority: 'user-blocking'|'user-visible'|'background',\n delay: MilliSeconds,\n frame?: string,\n },\n };\n}\nexport function isRunPostTaskCallback(event: Event): event is RunPostTaskCallback {\n return event.name === Name.RUN_POST_TASK_CALLBACK;\n}\n\nexport interface AbortPostTaskCallback extends Complete {\n name: Name.ABORT_POST_TASK_CALLBACK;\n args: Args&{\n data: {\n taskId: number,\n frame?: string,\n stackTrace?: CallFrame,\n },\n };\n}\nexport function isAbortPostTaskCallback(event: Event): event is RunPostTaskCallback {\n return event.name === Name.ABORT_POST_TASK_CALLBACK;\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 SCHEDULE_POST_TASK_CALLBACK = 'SchedulePostTaskCallback',\n RUN_POST_TASK_CALLBACK = 'RunPostTaskCallback',\n ABORT_POST_TASK_CALLBACK = 'AbortPostTaskCallback',\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 LAYOUT_IMAGE_UNSIZED = 'LayoutImageUnsized',\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/panels/application/SharedStorageItemsView.d.ts b/public/panels/application/SharedStorageItemsView.d.ts index e0de154f..5fd5ca98 100644 --- a/public/panels/application/SharedStorageItemsView.d.ts +++ b/public/panels/application/SharedStorageItemsView.d.ts @@ -17,7 +17,7 @@ export declare namespace SharedStorageItemsDispatcher { } interface ItemEditedEvent { columnIdentifier: string; - oldText: string; + oldText: string | null; newText: string; } type EventTypes = { diff --git a/public/panels/application/SharedStorageItemsView.js b/public/panels/application/SharedStorageItemsView.js index 69270285..c655027b 100644 --- a/public/panels/application/SharedStorageItemsView.js +++ b/public/panels/application/SharedStorageItemsView.js @@ -180,7 +180,9 @@ export class SharedStorageItemsView extends StorageItemsView { return; } if (columnIdentifier === 'key') { - await this.#sharedStorage.deleteEntry(oldText); + if (oldText !== null) { + await this.#sharedStorage.deleteEntry(oldText); + } await this.#sharedStorage.setEntry(newText, editingNode.data.value || '', false); } else { diff --git a/public/panels/application/SharedStorageItemsView.js.map b/public/panels/application/SharedStorageItemsView.js.map index ade3d482..e391186d 100644 --- a/public/panels/application/SharedStorageItemsView.js.map +++ b/public/panels/application/SharedStorageItemsView.js.map @@ -1 +1 @@ -{"version":3,"file":"SharedStorageItemsView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/SharedStorageItemsView.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 i18n from '../../core/i18n/i18n.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as ApplicationComponents from './components/components.js';\nimport {SharedStorageForOrigin} from './SharedStorageModel.js';\nimport {StorageItemsView} from './StorageItemsView.js';\n\nconst UIStrings = {\n /**\n *@description Text in SharedStorage Items View of the Application panel\n */\n sharedStorage: 'Shared storage',\n /**\n *@description Text representing the name of a value stored in the \"Shared Storage Items\" table\n */\n key: 'Key',\n /**\n *@description Text for the value of something\n */\n value: 'Value',\n /**\n *@description Name for the \"Shared Storage Items\" table that shows the content of the Shared Storage.\n */\n sharedStorageItems: 'Shared Storage Items',\n /**\n *@description Text for announcing that the \"Shared Storage Items\" table was cleared, that is, all\n * entries were deleted.\n */\n sharedStorageItemsCleared: 'Shared Storage items cleared',\n /**\n *@description Text for announcing that the filtered \"Shared Storage Items\" table was cleared, that is,\n * all filtered entries were deleted.\n */\n sharedStorageFilteredItemsCleared: 'Shared Storage filtered items cleared',\n /**\n *@description Text in SharedStorage Items View of the Application panel\n */\n selectAValueToPreview: 'Select a value to preview',\n /**\n *@description Text for announcing a Shared Storage key/value item has been deleted\n */\n sharedStorageItemDeleted: 'The storage item was deleted.',\n /**\n *@description Text for announcing a Shared Storage key/value item has been edited\n */\n sharedStorageItemEdited: 'The storage item was edited.',\n /**\n *@description Text for announcing a Shared Storage key/value item edit request has been canceled\n */\n sharedStorageItemEditCanceled: 'The storage item edit was canceled.',\n /**\n *@description Text for announcing number of entries after filtering\n *@example {5} PH1\n */\n sharedStorageNumberEntries: 'Number of entries shown in table: {PH1}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/application/SharedStorageItemsView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ninterface WrappedEntry {\n key: string;\n value: string;\n}\n\nexport namespace SharedStorageItemsDispatcher {\n export const enum Events {\n FILTERED_ITEMS_CLEARED = 'FilteredItemsCleared',\n ITEM_DELETED = 'ItemDeleted',\n ITEM_EDITED = 'ItemEdited',\n ITEMS_CLEARED = 'ItemsCleared',\n ITEMS_REFRESHED = 'ItemsRefreshed',\n }\n\n export interface ItemDeletedEvent {\n key: string;\n }\n\n export interface ItemEditedEvent {\n columnIdentifier: string;\n oldText: string;\n newText: string;\n }\n\n export type EventTypes = {\n [Events.FILTERED_ITEMS_CLEARED]: void,\n [Events.ITEM_DELETED]: ItemDeletedEvent,\n [Events.ITEM_EDITED]: ItemEditedEvent,\n [Events.ITEMS_CLEARED]: void,\n [Events.ITEMS_REFRESHED]: void,\n };\n}\n\nexport class SharedStorageItemsView extends StorageItemsView {\n #sharedStorage: SharedStorageForOrigin;\n readonly outerSplitWidget: UI.SplitWidget.SplitWidget;\n readonly innerSplitWidget: UI.SplitWidget.SplitWidget;\n #metadataView: LegacyWrapper.LegacyWrapper\n .LegacyWrapper;\n readonly dataGrid: DataGrid.DataGrid.DataGridImpl;\n #noDisplayView: UI.Widget.VBox;\n #eventListeners: Common.EventTarget.EventDescriptor[];\n readonly sharedStorageItemsDispatcher: Common.ObjectWrapper.ObjectWrapper;\n\n constructor(sharedStorage: SharedStorageForOrigin) {\n super(i18nString(UIStrings.sharedStorage), 'sharedStoragePanel');\n\n this.#sharedStorage = sharedStorage;\n\n this.element.classList.add('storage-view', 'table');\n\n const columns = ([\n {id: 'key', title: i18nString(UIStrings.key), sortable: false, editable: true, longText: true, weight: 50},\n {id: 'value', title: i18nString(UIStrings.value), sortable: false, editable: true, longText: true, weight: 50},\n ] as DataGrid.DataGrid.ColumnDescriptor[]);\n this.dataGrid = new DataGrid.DataGrid.DataGridImpl({\n displayName: i18nString(UIStrings.sharedStorageItems),\n columns,\n editCallback: this.#editingCallback.bind(this),\n deleteCallback: this.#deleteCallback.bind(this),\n refreshCallback: this.refreshItems.bind(this),\n });\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SELECTED_NODE, event => {\n void this.#previewEntry(event.data);\n });\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.DESELECTED_NODE, () => {\n void this.#previewEntry(null);\n });\n this.dataGrid.setStriped(true);\n this.dataGrid.setName('shared-storage-items-view');\n\n const dataGridWidget = this.dataGrid.asWidget();\n dataGridWidget.setMinimumSize(0, 100);\n\n this.#metadataView = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.VBox,\n new ApplicationComponents.SharedStorageMetadataView.SharedStorageMetadataView(\n sharedStorage, sharedStorage.securityOrigin));\n this.#metadataView.setMinimumSize(0, 275);\n const innerResizer = this.#metadataView.element.createChild('div', 'metadata-view-resizer');\n\n this.innerSplitWidget = new UI.SplitWidget.SplitWidget(\n /* isVertical: */ false, /* secondIsSidebar: */ false, 'shared-storage-inner-split-view-state');\n this.innerSplitWidget.setSidebarWidget(this.#metadataView);\n this.innerSplitWidget.setMainWidget(dataGridWidget);\n this.innerSplitWidget.installResizer(innerResizer);\n\n this.#noDisplayView = new UI.Widget.VBox();\n this.#noDisplayView.setMinimumSize(0, 25);\n this.#noDisplayView.element.setAttribute('jslog', `${VisualLogging.pane('preview').track({resize: true})}`);\n const outerResizer = this.#noDisplayView.element.createChild('div', 'preview-panel-resizer');\n\n this.outerSplitWidget = new UI.SplitWidget.SplitWidget(\n /* isVertical: */ false, /* secondIsSidebar: */ true, 'shared-storage-outer-split-view-state');\n this.outerSplitWidget.show(this.element);\n this.outerSplitWidget.setMainWidget(this.innerSplitWidget);\n this.outerSplitWidget.setSidebarWidget(this.#noDisplayView);\n this.outerSplitWidget.installResizer(outerResizer);\n\n this.#noDisplayView.contentElement.classList.add('placeholder');\n const noDisplayDiv = this.#noDisplayView.contentElement.createChild('div');\n noDisplayDiv.textContent = i18nString(UIStrings.selectAValueToPreview);\n\n this.#eventListeners = [];\n Common.EventTarget.removeEventListeners(this.#eventListeners);\n this.#sharedStorage = sharedStorage;\n this.#eventListeners = [\n this.#sharedStorage.addEventListener(\n SharedStorageForOrigin.Events.SHARED_STORAGE_CHANGED, this.#sharedStorageChanged, this),\n ];\n\n this.sharedStorageItemsDispatcher =\n new Common.ObjectWrapper.ObjectWrapper();\n }\n\n // Use `createView()` instead of the constructor to create a view, so that entries can be awaited asynchronously.\n static async createView(sharedStorage: SharedStorageForOrigin): Promise {\n const view = new SharedStorageItemsView(sharedStorage);\n await view.updateEntriesOnly();\n return view;\n }\n\n async updateEntriesOnly(): Promise {\n if (!this.isShowing()) {\n return;\n }\n const entries = await this.#sharedStorage.getEntries();\n if (entries) {\n this.#showSharedStorageItems(entries);\n }\n }\n\n async #sharedStorageChanged(): Promise {\n await this.refreshItems();\n }\n\n override async refreshItems(): Promise {\n if (!this.isShowing()) {\n return;\n }\n await this.#metadataView.getComponent().render();\n await this.updateEntriesOnly();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED);\n }\n\n override async deleteSelectedItem(): Promise {\n if (!this.dataGrid.selectedNode) {\n return;\n }\n\n await this.#deleteCallback(this.dataGrid.selectedNode);\n }\n\n override async deleteAllItems(): Promise {\n if (!this.hasFilter()) {\n await this.#sharedStorage.clear();\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(SharedStorageItemsDispatcher.Events.ITEMS_CLEARED);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemsCleared));\n return;\n }\n\n await Promise.all(this.dataGrid.rootNode()\n .children.filter(node => node.data.key)\n .map(node => this.#sharedStorage.deleteEntry(node.data.key)));\n\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(\n SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageFilteredItemsCleared));\n }\n\n async #editingCallback(\n editingNode: DataGrid.DataGrid.DataGridNode, columnIdentifier: string,\n oldText: string, newText: string): Promise {\n if (columnIdentifier === 'key' && newText === '') {\n // The Shared Storage backend does not currently allow '' as a key, so we only set a new entry with a new key if its new key is nonempty.\n await this.refreshItems();\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemEditCanceled));\n return;\n }\n if (columnIdentifier === 'key') {\n await this.#sharedStorage.deleteEntry(oldText);\n await this.#sharedStorage.setEntry(newText, editingNode.data.value || '', false);\n } else {\n // The Shared Storage backend does not currently allow '' as a key, so we use ' ' as the default key instead.\n await this.#sharedStorage.setEntry(editingNode.data.key || ' ', newText, false);\n }\n\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(\n SharedStorageItemsDispatcher.Events.ITEM_EDITED,\n {columnIdentifier, oldText, newText} as SharedStorageItemsDispatcher.ItemEditedEvent);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemEdited));\n }\n\n #showSharedStorageItems(items: Protocol.Storage.SharedStorageEntry[]): void {\n const rootNode = this.dataGrid.rootNode();\n const [selectedKey] = rootNode.children.filter(node => node.selected).map(node => node.data.key);\n rootNode.removeChildren();\n let selectedNode: DataGrid.DataGrid.DataGridNode|null = null;\n const filteredItems = (item: Protocol.Storage.SharedStorageEntry): string => `${item.key} ${item.value}`;\n const filteredList = this.filter(items, filteredItems);\n for (const item of filteredList) {\n const node = new DataGrid.DataGrid.DataGridNode({key: item.key, value: item.value}, false);\n node.selectable = true;\n rootNode.appendChild(node);\n if (!selectedNode || item.key === selectedKey) {\n selectedNode = node;\n }\n }\n if (selectedNode) {\n selectedNode.selected = true;\n }\n this.dataGrid.addCreationNode(false);\n this.setCanDeleteSelected(Boolean(selectedNode));\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageNumberEntries, {PH1: filteredList.length}));\n }\n\n async #deleteCallback(node: DataGrid.DataGrid.DataGridNode): Promise {\n if (!node || node.isCreationNode || !this.#sharedStorage) {\n return;\n }\n\n const key = node.data.key;\n await this.#sharedStorage.deleteEntry(key);\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(\n SharedStorageItemsDispatcher.Events.ITEM_DELETED, {key} as SharedStorageItemsDispatcher.ItemDeletedEvent);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemDeleted));\n }\n\n async #previewEntry(entry: DataGrid.DataGrid.DataGridNode|null): Promise {\n const key = entry?.data?.key;\n const value = entry?.data?.value;\n const wrappedEntry = key && {key: key as string, value: value as string || ''} as WrappedEntry;\n if (wrappedEntry) {\n const preview = SourceFrame.JSONView.JSONView.createViewSync(wrappedEntry);\n\n // Selection could've changed while the preview was loaded\n if (entry.selected) {\n this.outerSplitWidget.setSidebarWidget(preview);\n preview.element.setAttribute('jslog', `${VisualLogging.pane('preview').track({resize: true})}`);\n }\n } else {\n this.outerSplitWidget.setSidebarWidget(this.#noDisplayView);\n }\n }\n\n getEntriesForTesting(): Array {\n return this.dataGrid.rootNode()\n .children.filter(node => node.data.key)\n .map(node => (node.data as Protocol.Storage.SharedStorageEntry));\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"SharedStorageItemsView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/SharedStorageItemsView.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 i18n from '../../core/i18n/i18n.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as ApplicationComponents from './components/components.js';\nimport {SharedStorageForOrigin} from './SharedStorageModel.js';\nimport {StorageItemsView} from './StorageItemsView.js';\n\nconst UIStrings = {\n /**\n *@description Text in SharedStorage Items View of the Application panel\n */\n sharedStorage: 'Shared storage',\n /**\n *@description Text representing the name of a value stored in the \"Shared Storage Items\" table\n */\n key: 'Key',\n /**\n *@description Text for the value of something\n */\n value: 'Value',\n /**\n *@description Name for the \"Shared Storage Items\" table that shows the content of the Shared Storage.\n */\n sharedStorageItems: 'Shared Storage Items',\n /**\n *@description Text for announcing that the \"Shared Storage Items\" table was cleared, that is, all\n * entries were deleted.\n */\n sharedStorageItemsCleared: 'Shared Storage items cleared',\n /**\n *@description Text for announcing that the filtered \"Shared Storage Items\" table was cleared, that is,\n * all filtered entries were deleted.\n */\n sharedStorageFilteredItemsCleared: 'Shared Storage filtered items cleared',\n /**\n *@description Text in SharedStorage Items View of the Application panel\n */\n selectAValueToPreview: 'Select a value to preview',\n /**\n *@description Text for announcing a Shared Storage key/value item has been deleted\n */\n sharedStorageItemDeleted: 'The storage item was deleted.',\n /**\n *@description Text for announcing a Shared Storage key/value item has been edited\n */\n sharedStorageItemEdited: 'The storage item was edited.',\n /**\n *@description Text for announcing a Shared Storage key/value item edit request has been canceled\n */\n sharedStorageItemEditCanceled: 'The storage item edit was canceled.',\n /**\n *@description Text for announcing number of entries after filtering\n *@example {5} PH1\n */\n sharedStorageNumberEntries: 'Number of entries shown in table: {PH1}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/application/SharedStorageItemsView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ninterface WrappedEntry {\n key: string;\n value: string;\n}\n\nexport namespace SharedStorageItemsDispatcher {\n export const enum Events {\n FILTERED_ITEMS_CLEARED = 'FilteredItemsCleared',\n ITEM_DELETED = 'ItemDeleted',\n ITEM_EDITED = 'ItemEdited',\n ITEMS_CLEARED = 'ItemsCleared',\n ITEMS_REFRESHED = 'ItemsRefreshed',\n }\n\n export interface ItemDeletedEvent {\n key: string;\n }\n\n export interface ItemEditedEvent {\n columnIdentifier: string;\n oldText: string|null;\n newText: string;\n }\n\n export type EventTypes = {\n [Events.FILTERED_ITEMS_CLEARED]: void,\n [Events.ITEM_DELETED]: ItemDeletedEvent,\n [Events.ITEM_EDITED]: ItemEditedEvent,\n [Events.ITEMS_CLEARED]: void,\n [Events.ITEMS_REFRESHED]: void,\n };\n}\n\nexport class SharedStorageItemsView extends StorageItemsView {\n #sharedStorage: SharedStorageForOrigin;\n readonly outerSplitWidget: UI.SplitWidget.SplitWidget;\n readonly innerSplitWidget: UI.SplitWidget.SplitWidget;\n #metadataView: LegacyWrapper.LegacyWrapper\n .LegacyWrapper;\n readonly dataGrid: DataGrid.DataGrid.DataGridImpl;\n #noDisplayView: UI.Widget.VBox;\n #eventListeners: Common.EventTarget.EventDescriptor[];\n readonly sharedStorageItemsDispatcher: Common.ObjectWrapper.ObjectWrapper;\n\n constructor(sharedStorage: SharedStorageForOrigin) {\n super(i18nString(UIStrings.sharedStorage), 'sharedStoragePanel');\n\n this.#sharedStorage = sharedStorage;\n\n this.element.classList.add('storage-view', 'table');\n\n const columns = ([\n {id: 'key', title: i18nString(UIStrings.key), sortable: false, editable: true, longText: true, weight: 50},\n {id: 'value', title: i18nString(UIStrings.value), sortable: false, editable: true, longText: true, weight: 50},\n ] as DataGrid.DataGrid.ColumnDescriptor[]);\n this.dataGrid = new DataGrid.DataGrid.DataGridImpl({\n displayName: i18nString(UIStrings.sharedStorageItems),\n columns,\n editCallback: this.#editingCallback.bind(this),\n deleteCallback: this.#deleteCallback.bind(this),\n refreshCallback: this.refreshItems.bind(this),\n });\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SELECTED_NODE, event => {\n void this.#previewEntry(event.data);\n });\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.DESELECTED_NODE, () => {\n void this.#previewEntry(null);\n });\n this.dataGrid.setStriped(true);\n this.dataGrid.setName('shared-storage-items-view');\n\n const dataGridWidget = this.dataGrid.asWidget();\n dataGridWidget.setMinimumSize(0, 100);\n\n this.#metadataView = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.VBox,\n new ApplicationComponents.SharedStorageMetadataView.SharedStorageMetadataView(\n sharedStorage, sharedStorage.securityOrigin));\n this.#metadataView.setMinimumSize(0, 275);\n const innerResizer = this.#metadataView.element.createChild('div', 'metadata-view-resizer');\n\n this.innerSplitWidget = new UI.SplitWidget.SplitWidget(\n /* isVertical: */ false, /* secondIsSidebar: */ false, 'shared-storage-inner-split-view-state');\n this.innerSplitWidget.setSidebarWidget(this.#metadataView);\n this.innerSplitWidget.setMainWidget(dataGridWidget);\n this.innerSplitWidget.installResizer(innerResizer);\n\n this.#noDisplayView = new UI.Widget.VBox();\n this.#noDisplayView.setMinimumSize(0, 25);\n this.#noDisplayView.element.setAttribute('jslog', `${VisualLogging.pane('preview').track({resize: true})}`);\n const outerResizer = this.#noDisplayView.element.createChild('div', 'preview-panel-resizer');\n\n this.outerSplitWidget = new UI.SplitWidget.SplitWidget(\n /* isVertical: */ false, /* secondIsSidebar: */ true, 'shared-storage-outer-split-view-state');\n this.outerSplitWidget.show(this.element);\n this.outerSplitWidget.setMainWidget(this.innerSplitWidget);\n this.outerSplitWidget.setSidebarWidget(this.#noDisplayView);\n this.outerSplitWidget.installResizer(outerResizer);\n\n this.#noDisplayView.contentElement.classList.add('placeholder');\n const noDisplayDiv = this.#noDisplayView.contentElement.createChild('div');\n noDisplayDiv.textContent = i18nString(UIStrings.selectAValueToPreview);\n\n this.#eventListeners = [];\n Common.EventTarget.removeEventListeners(this.#eventListeners);\n this.#sharedStorage = sharedStorage;\n this.#eventListeners = [\n this.#sharedStorage.addEventListener(\n SharedStorageForOrigin.Events.SHARED_STORAGE_CHANGED, this.#sharedStorageChanged, this),\n ];\n\n this.sharedStorageItemsDispatcher =\n new Common.ObjectWrapper.ObjectWrapper();\n }\n\n // Use `createView()` instead of the constructor to create a view, so that entries can be awaited asynchronously.\n static async createView(sharedStorage: SharedStorageForOrigin): Promise {\n const view = new SharedStorageItemsView(sharedStorage);\n await view.updateEntriesOnly();\n return view;\n }\n\n async updateEntriesOnly(): Promise {\n if (!this.isShowing()) {\n return;\n }\n const entries = await this.#sharedStorage.getEntries();\n if (entries) {\n this.#showSharedStorageItems(entries);\n }\n }\n\n async #sharedStorageChanged(): Promise {\n await this.refreshItems();\n }\n\n override async refreshItems(): Promise {\n if (!this.isShowing()) {\n return;\n }\n await this.#metadataView.getComponent().render();\n await this.updateEntriesOnly();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED);\n }\n\n override async deleteSelectedItem(): Promise {\n if (!this.dataGrid.selectedNode) {\n return;\n }\n\n await this.#deleteCallback(this.dataGrid.selectedNode);\n }\n\n override async deleteAllItems(): Promise {\n if (!this.hasFilter()) {\n await this.#sharedStorage.clear();\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(SharedStorageItemsDispatcher.Events.ITEMS_CLEARED);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemsCleared));\n return;\n }\n\n await Promise.all(this.dataGrid.rootNode()\n .children.filter(node => node.data.key)\n .map(node => this.#sharedStorage.deleteEntry(node.data.key)));\n\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(\n SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageFilteredItemsCleared));\n }\n\n async #editingCallback(\n editingNode: DataGrid.DataGrid.DataGridNode, columnIdentifier: string,\n oldText: string|null, newText: string): Promise {\n if (columnIdentifier === 'key' && newText === '') {\n // The Shared Storage backend does not currently allow '' as a key, so we only set a new entry with a new key if its new key is nonempty.\n await this.refreshItems();\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemEditCanceled));\n return;\n }\n if (columnIdentifier === 'key') {\n if (oldText !== null) {\n await this.#sharedStorage.deleteEntry(oldText);\n }\n await this.#sharedStorage.setEntry(newText, editingNode.data.value || '', false);\n } else {\n // The Shared Storage backend does not currently allow '' as a key, so we use ' ' as the default key instead.\n await this.#sharedStorage.setEntry(editingNode.data.key || ' ', newText, false);\n }\n\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(\n SharedStorageItemsDispatcher.Events.ITEM_EDITED,\n {columnIdentifier, oldText, newText} as SharedStorageItemsDispatcher.ItemEditedEvent);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemEdited));\n }\n\n #showSharedStorageItems(items: Protocol.Storage.SharedStorageEntry[]): void {\n const rootNode = this.dataGrid.rootNode();\n const [selectedKey] = rootNode.children.filter(node => node.selected).map(node => node.data.key);\n rootNode.removeChildren();\n let selectedNode: DataGrid.DataGrid.DataGridNode|null = null;\n const filteredItems = (item: Protocol.Storage.SharedStorageEntry): string => `${item.key} ${item.value}`;\n const filteredList = this.filter(items, filteredItems);\n for (const item of filteredList) {\n const node = new DataGrid.DataGrid.DataGridNode({key: item.key, value: item.value}, false);\n node.selectable = true;\n rootNode.appendChild(node);\n if (!selectedNode || item.key === selectedKey) {\n selectedNode = node;\n }\n }\n if (selectedNode) {\n selectedNode.selected = true;\n }\n this.dataGrid.addCreationNode(false);\n this.setCanDeleteSelected(Boolean(selectedNode));\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageNumberEntries, {PH1: filteredList.length}));\n }\n\n async #deleteCallback(node: DataGrid.DataGrid.DataGridNode): Promise {\n if (!node || node.isCreationNode || !this.#sharedStorage) {\n return;\n }\n\n const key = node.data.key;\n await this.#sharedStorage.deleteEntry(key);\n await this.refreshItems();\n this.sharedStorageItemsDispatcher.dispatchEventToListeners(\n SharedStorageItemsDispatcher.Events.ITEM_DELETED, {key} as SharedStorageItemsDispatcher.ItemDeletedEvent);\n UI.ARIAUtils.alert(i18nString(UIStrings.sharedStorageItemDeleted));\n }\n\n async #previewEntry(entry: DataGrid.DataGrid.DataGridNode|null): Promise {\n const key = entry?.data?.key;\n const value = entry?.data?.value;\n const wrappedEntry = key && {key: key as string, value: value as string || ''} as WrappedEntry;\n if (wrappedEntry) {\n const preview = SourceFrame.JSONView.JSONView.createViewSync(wrappedEntry);\n\n // Selection could've changed while the preview was loaded\n if (entry.selected) {\n this.outerSplitWidget.setSidebarWidget(preview);\n preview.element.setAttribute('jslog', `${VisualLogging.pane('preview').track({resize: true})}`);\n }\n } else {\n this.outerSplitWidget.setSidebarWidget(this.#noDisplayView);\n }\n }\n\n getEntriesForTesting(): Array {\n return this.dataGrid.rootNode()\n .children.filter(node => node.data.key)\n .map(node => (node.data as Protocol.Storage.SharedStorageEntry));\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/application/SharedStorageItemsView.test.js b/public/panels/application/SharedStorageItemsView.test.js index 7e978118..aef93e64 100644 --- a/public/panels/application/SharedStorageItemsView.test.js +++ b/public/panels/application/SharedStorageItemsView.test.js @@ -847,13 +847,13 @@ describeWithMockConnection('SharedStorageItemsView', function () { view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true); const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key'); assert.exists(cellElement); - // Editing a key will cause `deleteEntry()`, `setEntry()`, `getMetadata()`, and `getEntries()` to be called. + // Editing a key will cause `setEntry()`, `getMetadata()`, and `getEntries()` to be called. const editedPromise = itemsListener.waitForItemsEditedTotal(1); cellElement.textContent = 'key4'; dispatchKeyDownEvent(cellElement, { key: 'Enter' }); await raf(); await editedPromise; - assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ ownerOrigin: TEST_ORIGIN, key: '' })); + assert.isTrue(deleteEntrySpy.notCalled); assert.isTrue(setEntrySpy.calledOnceWithExactly({ ownerOrigin: TEST_ORIGIN, key: 'key4', value: '', ignoreIfPresent: false })); assert.isTrue(getMetadataSpy.calledThrice); assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ ownerOrigin: TEST_ORIGIN })); @@ -861,7 +861,7 @@ describeWithMockConnection('SharedStorageItemsView', function () { assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ ownerOrigin: TEST_ORIGIN })); assert.deepEqual(view.getEntriesForTesting(), ENTRIES_NEW_KEY); assert.deepEqual(itemsListener.editedEvents, [ - { columnIdentifier: 'key', oldText: '', newText: 'key4' }, + { columnIdentifier: 'key', oldText: null, newText: 'key4' }, ]); // Verify that the preview loads. assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView); diff --git a/public/panels/application/SharedStorageItemsView.test.js.map b/public/panels/application/SharedStorageItemsView.test.js.map index ea3f75d7..c3d3e964 100644 --- a/public/panels/application/SharedStorageItemsView.test.js.map +++ b/public/panels/application/SharedStorageItemsView.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SharedStorageItemsView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/SharedStorageItemsView.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAK7B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,+BAA+B,EAC/B,GAAG,GACJ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAC,YAAY,EAAC,MAAM,qCAAqC,CAAC;AACjE,OAAO,EACL,0BAA0B,GAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAC,iCAAiC,EAAE,eAAe,EAAC,MAAM,0CAA0C,CAAC;AAC5G,OAAO,KAAK,WAAW,MAAM,8DAA8D,CAAC;AAE5F,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAEhD,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAG9C,IAAO,IAAI,GAAG,SAAS,CAAC,sBAAsB,CAAC;AAE/C,MAAM,WAAW,GAAG,WAAW,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;AAE/E,MAAM,0BAA0B;IAC9B,WAAW,CAAmF;IAC9F,QAAQ,GAAY,KAAK,CAAC;IAC1B,gBAAgB,GAAY,KAAK,CAAC;IAClC,UAAU,GAAY,KAAK,CAAC;IAC5B,YAAY,GAAkB,EAAE,CAAC;IACjC,aAAa,GAA6D,EAAE,CAAC;IAE7E,YAAY,UAA4F;QACtG,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,gBAAgB,8EAAyD,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACpH,IAAI,CAAC,WAAW,CAAC,gBAAgB,+FACoC,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;QACvG,IAAI,CAAC,WAAW,CAAC,gBAAgB,kFAC6B,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAC1F,IAAI,CAAC,WAAW,CAAC,gBAAgB,4EAAwD,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAClH,IAAI,CAAC,WAAW,CAAC,gBAAgB,0EAAuD,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAClH,CAAC;IAED,OAAO;QACL,IAAI,CAAC,WAAW,CAAC,mBAAmB,8EACwB,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACtF,IAAI,CAAC,WAAW,CAAC,mBAAmB,+FACiC,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;QACvG,IAAI,CAAC,WAAW,CAAC,mBAAmB,kFAC0B,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAC1F,IAAI,CAAC,WAAW,CAAC,mBAAmB,4EACuB,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QACpF,IAAI,CAAC,WAAW,CAAC,mBAAmB,0EAAuD,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACrH,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,aAAa;QACX,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,qBAAqB;QACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAC/B,CAAC;IAED,eAAe;QACb,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,YAAY,CAAC,KAA8F;QACzG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,WAAW,CAAC,KAA6F;QACvG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,6EAAwD,CAAC;QACtF,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,2BAA2B;QAC/B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,8FAAiE,CAAC;QAC/F,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,iFAA0D,CAAC;QACxF,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,wBAAwB,CAAC,KAAa;QAC1C,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;YACxC,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,2EAAuD,CAAC;QACrF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,KAAa;QACzC,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;YACzC,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,yEAAsD,CAAC;QACpF,CAAC;IACH,CAAC;CACF;AAED,0BAA0B,CAAC,wBAAwB,EAAE;IACnD,IAAI,MAAyB,CAAC;IAC9B,IAAI,kBAAwE,CAAC;IAC7E,IAAI,aAAkE,CAAC;IAEvE,MAAM,WAAW,GAAG,eAAe,CAAC;IAEpC,MAAM,QAAQ,GAAG;QACf,YAAY,EAAE,GAAsC;QACpD,MAAM,EAAE,CAAC;QACT,eAAe,EAAE,GAAG;QACpB,SAAS,EAAE,EAAE;KAC4B,CAAC;IAE5C,MAAM,mBAAmB,GAAG;QAC1B,YAAY,EAAE,GAAsC;QACpD,MAAM,EAAE,CAAC;QACT,eAAe,EAAE,GAAG;QACpB,SAAS,EAAE,CAAC;KAC6B,CAAC;IAE5C,MAAM,kBAAkB,GAAG;QACzB,YAAY,EAAE,GAAsC;QACpD,MAAM,EAAE,CAAC;QACT,eAAe,EAAE,GAAG;QACpB,SAAS,EAAE,EAAE;KAC4B,CAAC;IAE5C,MAAM,kBAAkB,GAAG;QACzB,YAAY,EAAE,GAAsC;QACpD,MAAM,EAAE,CAAC;QACT,eAAe,EAAE,GAAG;QACpB,SAAS,EAAE,EAAE;KAC4B,CAAC;IAE5C,MAAM,OAAO,GAAG;QACd;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;KACzC,CAAC;IAEF,MAAM,SAAS,GAAG;QAChB;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;KACzC,CAAC;IAEF,MAAM,SAAS,GAAG;QAChB;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;KACzC,CAAC;IAEF,MAAM,oBAAoB,GAAG;QAC3B;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;KACzC,CAAC;IAEF,MAAM,oBAAoB,GAAG;QAC3B;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;KACzC,CAAC;IAEF,MAAM,oBAAoB,GAAG;QAC3B;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;KACzC,CAAC;IAEF,MAAM,eAAe,GAAG;QACtB;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,GAAG;SAC4B;QACxC;YACE,GAAG,EAAE,MAAM;YACX,KAAK,EAAE,EAAE;SAC6B;KACzC,CAAC;IAEF,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,YAAY,EAAE,CAAC;QACxB,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC;QACnF,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,aAAa,GAAG,IAAI,SAAS,CAAC,kBAAkB,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;QACzG,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC;aACzE,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC;aACpC,QAAQ,CAAC;YACR,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACP,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC;aACxE,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC;aACpC,QAAQ,CAAC;YACR,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAEzE,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,cAAc,CAAC,UACE,CAAC;QAC9E,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAE5B,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QAEzB,MAAM,IAAI,GAAG,+BAA+B,CAAC,YAAY,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QAC7F,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE;YACrB,QAAQ;YACR,eAAe;YACf,mBAAmB;YACnB,sBAAsB;YACtB,kCAAkC;SACnC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,+BAA+B,CAAC,YAAY,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;QACjG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;YACvB,WAAW;YACX,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,cAAc,EAAE;YACtC,GAAG;YACH,IAAI;YACJ,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC;aACxE,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC;aACpC,QAAQ,CAAC;YACR,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAEzE,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAE1D,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,cAAc,CAAC,UACE,CAAC;QAC9E,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAE5B,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QAEzB,MAAM,IAAI,GAAG,+BAA+B,CAAC,YAAY,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QAC7F,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE;YACrB,QAAQ;YACR,eAAe;YACf,mBAAmB;YACnB,sBAAsB;YACtB,kCAAkC;SACnC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,+BAA+B,CAAC,YAAY,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;QACjG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;YACvB,WAAW;YACX,iBAAiB;YACjB,GAAG;YACH,GAAG;YACH,GAAG;SACJ,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC;aACzE,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC;aACpC,QAAQ,CAAC;YACR,QAAQ,EAAE,mBAAmB;YAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACP,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC;aACxE,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC;aACpC,QAAQ,CAAC;YACR,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAEzE,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAC9F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC;QAEjE,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC;aACzE,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC;aACpC,QAAQ,CAAC;YACR,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACP,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC;aACxE,QAAQ,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC;aACpC,QAAQ,CAAC;YACR,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAEzE,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,yBAAyB;QACzB,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,MAAM,GAAG,EAAE,CAAC;QAEZ,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAE3F,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC,QAAQ,CAAC;YAC3G,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAEhE,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,iBAAiB,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,iFAAiF;QACjF,aAAa,CAAC,cAAc,EAAE,CAAC;QAC/B,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAChE,kBAAkB,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,iBAAiB,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,mBAAmB;YAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;QACpG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,kCAAkC,CAAC,CAAC,QAAQ,CAAC;YACxG,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,gGAAgG;QAChG,MAAM,cAAc,GAAG,aAAa,CAAC,mBAAmB,EAAE,CAAC;QAC3D,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,cAAc,CAAC;QAErB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,EAAE,CAAC,CAAC;QAElD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;QACpG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,SAAS;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,SAAS;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAEhE,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,iBAAiB,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,+FAA+F;QAC/F,aAAa,CAAC,cAAc,EAAE,CAAC;QAC/B,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAChE,IAAI,CAAC,UAAU,CAAC,wBAAwB,iEAA6C,GAAG,CAAC,CAAC;QAC1F,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,iBAAiB,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,2CAA2C;QAC3C,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,SAAS,CAAC,CAAC;QAEzD,sGAAsG;QACtG,MAAM,cAAc,GAAG,aAAa,CAAC,2BAA2B,EAAE,CAAC;QACnE,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,cAAc,CAAC;QAErB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,oCAAoC;QACpC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,EAAE,CAAC,CAAC;QAElD,mGAAmG;QACnG,aAAa,CAAC,cAAc,EAAE,CAAC;QAC/B,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAChE,IAAI,CAAC,UAAU,CAAC,wBAAwB,iEAA6C,EAAE,CAAC,CAAC;QACzF,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,iBAAiB,CAAC;QAExB,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,SAAS,CAAC,CAAC;QAEzD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;QACpG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,yBAAyB;QACzB,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,MAAM,GAAG,EAAE,CAAC;QAEZ,2GAA2G;QAC3G,MAAM,cAAc,GAAG,aAAa,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;QACjE,kBAAkB,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,cAAc,CAAC;QAErB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAEtD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;QACpG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,oBAAoB;YAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC,QAAQ,CAAC;YACvG,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,yBAAyB;QACzB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,GAAG,EAAE,CAAC;QAEZ,MAAM,YAAY,GAAG,IAA2E,CAAC;QACjG,IAAI,CAAC,QAAQ,CAAC,4CAA4C,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAEtF,MAAM,WAAW,GAAG,iCAAiC,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;QAC1F,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,6GAA6G;QAC7G,MAAM,aAAa,GAAG,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;QAC/D,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC;QACjC,oBAAoB,CAAC,WAAW,EAAE,EAAC,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC;QAClD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,aAAa,CAAC;QAEpB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,MAAM,CACT,WAAW,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC;QACpH,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,oBAAoB,CAAC,CAAC;QACpE,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,YAAY,EAAE;YAC3C,EAAC,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAsD;SACjH,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;QACpG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,oBAAoB;YAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC,QAAQ,CAAC;YACvG,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,yBAAyB;QACzB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,GAAG,EAAE,CAAC;QAEZ,MAAM,YAAY,GAAG,IAA2E,CAAC;QACjG,IAAI,CAAC,QAAQ,CAAC,4CAA4C,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAEtF,MAAM,WAAW,GAAG,iCAAiC,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;QAC1F,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,4GAA4G;QAC5G,MAAM,aAAa,GAAG,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;QAC/D,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC;QACjC,oBAAoB,CAAC,WAAW,EAAE,EAAC,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC;QAClD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,aAAa,CAAC;QAEpB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,MAAM,CACT,WAAW,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC;QACpH,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,oBAAoB,CAAC,CAAC;QACpE,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,YAAY,EAAE;YAC3C,EAAC,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAsD;SACjH,CAAC,CAAC;QAEH,iCAAiC;QACjC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAE3F,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;QACpG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,oBAAoB;YAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC,QAAQ,CAAC;YACvG,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,yBAAyB;QACzB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,GAAG,EAAE,CAAC;QAEZ,MAAM,YAAY,GAAG,IAA2E,CAAC;QACjG,IAAI,CAAC,QAAQ,CAAC,4CAA4C,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAExF,MAAM,WAAW,GAAG,iCAAiC,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QAC5F,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,6FAA6F;QAC7F,MAAM,aAAa,GAAG,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;QAC/D,WAAW,CAAC,WAAW,GAAG,GAAG,CAAC;QAC9B,oBAAoB,CAAC,WAAW,EAAE,EAAC,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC;QAClD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,aAAa,CAAC;QAEpB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CACT,WAAW,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC;QACpH,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,oBAAoB,CAAC,CAAC;QACpE,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,YAAY,EAAE;YAC3C,EAAC,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAsD;SAC7G,CAAC,CAAC;QAEH,iCAAiC;QACjC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAE3F,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACtG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;QACpG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC,QAAQ,CAAC;YACvG,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAE/D,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,+BAA+B;QAC/B,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,GAAG,EAAE,CAAC;QAEZ,MAAM,YAAY,GAAG,IAA2E,CAAC;QACjG,IAAI,CAAC,QAAQ,CAAC,4CAA4C,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAEtF,MAAM,WAAW,GAAG,iCAAiC,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;QAC1F,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,4GAA4G;QAC5G,MAAM,aAAa,GAAG,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;QAC/D,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC;QACjC,oBAAoB,CAAC,WAAW,EAAE,EAAC,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC;QAClD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,aAAa,CAAC;QAEpB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,EAAC,CAAC,CAAC,CAAC;QACzF,MAAM,CAAC,MAAM,CACT,WAAW,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC;QACnH,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,eAAe,CAAC,CAAC;QAC/D,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,YAAY,EAAE;YAC3C,EAAC,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAsD;SAC7G,CAAC,CAAC;QAEH,iCAAiC;QACjC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAE3F,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC,QAAQ,CAAC;YAC3G,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC,QAAQ,CAAC;YAC7G,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC,QAAQ,CAAC;YACvG,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAC,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEhF,MAAM,aAAa,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACxF,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAEhE,sEAAsE;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,iBAAiB,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,yBAAyB;QACzB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,GAAG,EAAE,CAAC;QAEZ,MAAM,YAAY,GAAG,IAA2E,CAAC;QACjG,IAAI,CAAC,QAAQ,CAAC,4CAA4C,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAEtF,MAAM,WAAW,GAAG,iCAAiC,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;QAC1F,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,mGAAmG;QACnG,aAAa,CAAC,cAAc,EAAE,CAAC;QAC/B,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC;QAChE,WAAW,CAAC,WAAW,GAAG,EAAE,CAAC;QAC7B,oBAAoB,CAAC,WAAW,EAAE,EAAC,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC;QAClD,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,iBAAiB,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAC,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,iCAAiC;QACjC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAE3F,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,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 Common from '../../core/common/common.js';\nimport type * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport {\n dispatchClickEvent,\n dispatchKeyDownEvent,\n getCleanTextContentFromElements,\n raf,\n} from '../../testing/DOMHelpers.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {\n describeWithMockConnection,\n} from '../../testing/MockConnection.js';\nimport {getCellElementFromNodeAndColumnId, selectNodeByKey} from '../../testing/StorageItemsViewHelpers.js';\nimport * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';\nimport type * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Resources from './application.js';\nimport type * as ApplicationComponents from './components/components.js';\n\nimport View = Resources.SharedStorageItemsView;\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nclass SharedStorageItemsListener {\n #dispatcher: Common.ObjectWrapper.ObjectWrapper;\n #cleared: boolean = false;\n #filteredCleared: boolean = false;\n #refreshed: boolean = false;\n #deletedKeys: Array = [];\n #editedEvents: Array = [];\n\n constructor(dispatcher: Common.ObjectWrapper.ObjectWrapper) {\n this.#dispatcher = dispatcher;\n this.#dispatcher.addEventListener(View.SharedStorageItemsDispatcher.Events.ITEMS_CLEARED, this.#itemsCleared, this);\n this.#dispatcher.addEventListener(\n View.SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED, this.#filteredItemsCleared, this);\n this.#dispatcher.addEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED, this.#itemsRefreshed, this);\n this.#dispatcher.addEventListener(View.SharedStorageItemsDispatcher.Events.ITEM_DELETED, this.#itemDeleted, this);\n this.#dispatcher.addEventListener(View.SharedStorageItemsDispatcher.Events.ITEM_EDITED, this.#itemEdited, this);\n }\n\n dispose(): void {\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEMS_CLEARED, this.#itemsCleared, this);\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED, this.#filteredItemsCleared, this);\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED, this.#itemsRefreshed, this);\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEM_DELETED, this.#itemDeleted, this);\n this.#dispatcher.removeEventListener(View.SharedStorageItemsDispatcher.Events.ITEM_EDITED, this.#itemEdited, this);\n }\n\n get deletedKeys(): Array {\n return this.#deletedKeys;\n }\n\n get editedEvents(): Array {\n return this.#editedEvents;\n }\n\n resetRefreshed(): void {\n this.#refreshed = false;\n }\n\n #itemsCleared(): void {\n this.#cleared = true;\n }\n\n #filteredItemsCleared(): void {\n this.#filteredCleared = true;\n }\n\n #itemsRefreshed(): void {\n this.#refreshed = true;\n }\n\n #itemDeleted(event: Common.EventTarget.EventTargetEvent): void {\n this.#deletedKeys.push(event.data.key);\n }\n\n #itemEdited(event: Common.EventTarget.EventTargetEvent): void {\n this.#editedEvents.push(event.data);\n }\n\n async waitForItemsCleared(): Promise {\n if (!this.#cleared) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEMS_CLEARED);\n }\n this.#cleared = true;\n }\n\n async waitForFilteredItemsCleared(): Promise {\n if (!this.#filteredCleared) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED);\n }\n this.#filteredCleared = true;\n }\n\n async waitForItemsRefreshed(): Promise {\n if (!this.#refreshed) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED);\n }\n this.#refreshed = true;\n }\n\n async waitForItemsDeletedTotal(total: number): Promise {\n while (this.#deletedKeys.length < total) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEM_DELETED);\n }\n }\n\n async waitForItemsEditedTotal(total: number): Promise {\n while (this.#editedEvents.length < total) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEM_EDITED);\n }\n }\n}\n\ndescribeWithMockConnection('SharedStorageItemsView', function() {\n let target: SDK.Target.Target;\n let sharedStorageModel: Resources.SharedStorageModel.SharedStorageModel|null;\n let sharedStorage: Resources.SharedStorageModel.SharedStorageForOrigin;\n\n const TEST_ORIGIN = 'http://a.test';\n\n const METADATA = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 3,\n remainingBudget: 2.5,\n bytesUsed: 30,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const METADATA_NO_ENTRIES = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 0,\n remainingBudget: 2.5,\n bytesUsed: 0,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const METADATA_2_ENTRIES = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 2,\n remainingBudget: 2.5,\n bytesUsed: 20,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const METADATA_4_ENTRIES = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 4,\n remainingBudget: 2.5,\n bytesUsed: 38,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const ENTRIES = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key2',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_1 = [\n {\n key: 'key2',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_2 = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_KEY_EDITED_1 = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key0',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_KEY_EDITED_2 = [\n {\n key: 'key1',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_VALUE_EDITED = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key2',\n value: 'd',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_NEW_KEY = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key2',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key4',\n value: '',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n beforeEach(() => {\n target = createTarget();\n sharedStorageModel = target.model(Resources.SharedStorageModel.SharedStorageModel);\n assert.exists(sharedStorageModel);\n sharedStorage = new Resources.SharedStorageModel.SharedStorageForOrigin(sharedStorageModel, TEST_ORIGIN);\n assert.strictEqual(sharedStorage.securityOrigin, TEST_ORIGIN);\n });\n\n it('displays metadata and entries', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n const metadataView = view.innerSplitWidget.sidebarWidget()?.contentElement.firstChild as\n ApplicationComponents.SharedStorageMetadataView.SharedStorageMetadataView;\n assert.exists(metadataView);\n\n assert.isNotNull(metadataView.shadowRoot);\n await coordinator.done();\n\n const keys = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-key');\n assert.deepEqual(keys, [\n 'Origin',\n 'Creation Time',\n 'Number of Entries',\n 'Number of Bytes Used',\n 'Entropy Budget for Fenced Frames',\n ]);\n\n const values = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-value');\n assert.deepEqual(values, [\n TEST_ORIGIN,\n (new Date(100 * 1e3)).toLocaleString(),\n '3',\n '30',\n '2.5',\n ]);\n\n view.detach();\n });\n\n it('displays metadata with placeholder message if origin is not using API', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorage, 'getMetadata').resolves(null);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: [],\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.strictEqual(view.getEntriesForTesting().length, 0);\n\n const metadataView = view.innerSplitWidget.sidebarWidget()?.contentElement.firstChild as\n ApplicationComponents.SharedStorageMetadataView.SharedStorageMetadataView;\n assert.exists(metadataView);\n\n assert.isNotNull(metadataView.shadowRoot);\n await coordinator.done();\n\n const keys = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-key');\n assert.deepEqual(keys, [\n 'Origin',\n 'Creation Time',\n 'Number of Entries',\n 'Number of Bytes Used',\n 'Entropy Budget for Fenced Frames',\n ]);\n\n const values = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-value');\n assert.deepEqual(values, [\n TEST_ORIGIN,\n 'Not yet created',\n '0',\n '0',\n '0',\n ]);\n\n view.detach();\n });\n\n it('has placeholder sidebar when there are no entries', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n metadata: METADATA_NO_ENTRIES,\n getError: () => undefined,\n });\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: [],\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.notInstanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n assert.exists(view.contentElement.querySelector('.placeholder'));\n\n view.detach();\n });\n\n it('updates sidebarWidget upon receiving SelectedNode Event', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n // Select the second row.\n assert.exists(selectNodeByKey(view.dataGrid, 'key2'));\n await raf();\n\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('refreshes when \"Refresh\" is clicked', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata').resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries').resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise1 = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise1;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Clicking \"Refresh\" will cause `getMetadata()` and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise2 = itemsListener.waitForItemsRefreshed();\n dispatchClickEvent(view.refreshButton.element);\n await raf();\n await refreshedPromise2;\n\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n view.detach();\n });\n\n it('clears entries when \"Delete All\" is clicked', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_NO_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: [],\n getError: () => undefined,\n });\n const clearSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_clearSharedStorageEntries').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Clicking \"Delete All\" will cause `clear()`, `getMetadata()`, and `getEntries()` to be called.\n const clearedPromise = itemsListener.waitForItemsCleared();\n dispatchClickEvent(view.deleteAllButton.element);\n await raf();\n await clearedPromise;\n\n assert.isTrue(clearSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), []);\n\n view.detach();\n });\n\n it('clears filtered entries when \"Delete All\" is clicked with a filter set', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(3).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(4).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(2).resolves({\n entries: ENTRIES_2,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(3).resolves({\n entries: ENTRIES_2,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise1 = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise1;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Adding a filter to the text box will cause `getMetadata()`, and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise2 = itemsListener.waitForItemsRefreshed();\n view.filterItem.dispatchEventToListeners(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, 'b');\n await raf();\n await refreshedPromise2;\n\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n // Only the filtered entries are displayed.\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_1);\n\n // Clicking \"Delete All\" will cause `deleteEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const clearedPromise = itemsListener.waitForFilteredItemsCleared();\n dispatchClickEvent(view.deleteAllButton.element);\n await raf();\n await clearedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.strictEqual(getMetadataSpy.callCount, 4);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledThrice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n // The filtered entries are cleared.\n assert.deepEqual(view.getEntriesForTesting(), []);\n\n // Changing the filter in the text box will cause `getMetadata()`, and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise3 = itemsListener.waitForItemsRefreshed();\n view.filterItem.dispatchEventToListeners(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, '');\n await raf();\n await refreshedPromise3;\n\n assert.strictEqual(getMetadataSpy.callCount, 5);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.strictEqual(getEntriesSpy.callCount, 4);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_2);\n\n view.detach();\n });\n\n it('deletes selected entry when \"Delete Selected\" is clicked', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: [],\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n assert.exists(selectNodeByKey(view.dataGrid, 'key2'));\n await raf();\n\n // Clicking \"Delete Selected\" will cause `deleteEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const deletedPromise = itemsListener.waitForItemsDeletedTotal(1);\n dispatchClickEvent(view.deleteSelectedButton.element);\n await raf();\n await deletedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), []);\n assert.deepEqual(itemsListener.deletedKeys, ['key2']);\n\n view.detach();\n });\n\n it('edits key of selected entry to a non-preexisting key', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_KEY_EDITED_1,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key will cause `deleteEntry()`, `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'key0';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key0', value: 'b', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_KEY_EDITED_1);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'key', oldText: 'key2', newText: 'key0'} as View.SharedStorageItemsDispatcher.ItemEditedEvent,\n ]);\n\n view.detach();\n });\n\n it('edits key of selected entry to a preexisting key', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_KEY_EDITED_2,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key will cause `deleteEntry()`, `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'key1';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key1', value: 'b', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_KEY_EDITED_2);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'key', oldText: 'key2', newText: 'key1'} as View.SharedStorageItemsDispatcher.ItemEditedEvent,\n ]);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('edits value of selected entry to a new value', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_VALUE_EDITED,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'value', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'value');\n assert.exists(cellElement);\n\n // Editing a value will cause `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'd';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.notCalled);\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2', value: 'd', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_VALUE_EDITED);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'value', oldText: 'b', newText: 'd'} as View.SharedStorageItemsDispatcher.ItemEditedEvent,\n ]);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('adds an entry when the key cell of the empty data row is edited', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_4_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_NEW_KEY,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the empty (null) row.\n const node = selectNodeByKey(view.dataGrid, null);\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key will cause `deleteEntry()`, `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'key4';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: ''}));\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key4', value: '', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_NEW_KEY);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'key', oldText: '', newText: 'key4'} as View.SharedStorageItemsDispatcher.ItemEditedEvent,\n ]);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('attempting to edit key of selected entry to an empty key cancels the edit', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata').resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries').resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise1 = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise1;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key with the edit canceled will cause `getMetadata()` and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise2 = itemsListener.waitForItemsRefreshed();\n cellElement.textContent = '';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await refreshedPromise2;\n\n assert.isTrue(deleteEntrySpy.notCalled);\n assert.isTrue(setEntrySpy.notCalled);\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"SharedStorageItemsView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/SharedStorageItemsView.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 Common from '../../core/common/common.js';\nimport type * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport {\n dispatchClickEvent,\n dispatchKeyDownEvent,\n getCleanTextContentFromElements,\n raf,\n} from '../../testing/DOMHelpers.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {\n describeWithMockConnection,\n} from '../../testing/MockConnection.js';\nimport {getCellElementFromNodeAndColumnId, selectNodeByKey} from '../../testing/StorageItemsViewHelpers.js';\nimport * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';\nimport type * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Resources from './application.js';\nimport type * as ApplicationComponents from './components/components.js';\n\nimport View = Resources.SharedStorageItemsView;\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nclass SharedStorageItemsListener {\n #dispatcher: Common.ObjectWrapper.ObjectWrapper;\n #cleared: boolean = false;\n #filteredCleared: boolean = false;\n #refreshed: boolean = false;\n #deletedKeys: Array = [];\n #editedEvents: Array = [];\n\n constructor(dispatcher: Common.ObjectWrapper.ObjectWrapper) {\n this.#dispatcher = dispatcher;\n this.#dispatcher.addEventListener(View.SharedStorageItemsDispatcher.Events.ITEMS_CLEARED, this.#itemsCleared, this);\n this.#dispatcher.addEventListener(\n View.SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED, this.#filteredItemsCleared, this);\n this.#dispatcher.addEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED, this.#itemsRefreshed, this);\n this.#dispatcher.addEventListener(View.SharedStorageItemsDispatcher.Events.ITEM_DELETED, this.#itemDeleted, this);\n this.#dispatcher.addEventListener(View.SharedStorageItemsDispatcher.Events.ITEM_EDITED, this.#itemEdited, this);\n }\n\n dispose(): void {\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEMS_CLEARED, this.#itemsCleared, this);\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED, this.#filteredItemsCleared, this);\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED, this.#itemsRefreshed, this);\n this.#dispatcher.removeEventListener(\n View.SharedStorageItemsDispatcher.Events.ITEM_DELETED, this.#itemDeleted, this);\n this.#dispatcher.removeEventListener(View.SharedStorageItemsDispatcher.Events.ITEM_EDITED, this.#itemEdited, this);\n }\n\n get deletedKeys(): Array {\n return this.#deletedKeys;\n }\n\n get editedEvents(): Array {\n return this.#editedEvents;\n }\n\n resetRefreshed(): void {\n this.#refreshed = false;\n }\n\n #itemsCleared(): void {\n this.#cleared = true;\n }\n\n #filteredItemsCleared(): void {\n this.#filteredCleared = true;\n }\n\n #itemsRefreshed(): void {\n this.#refreshed = true;\n }\n\n #itemDeleted(event: Common.EventTarget.EventTargetEvent): void {\n this.#deletedKeys.push(event.data.key);\n }\n\n #itemEdited(event: Common.EventTarget.EventTargetEvent): void {\n this.#editedEvents.push(event.data);\n }\n\n async waitForItemsCleared(): Promise {\n if (!this.#cleared) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEMS_CLEARED);\n }\n this.#cleared = true;\n }\n\n async waitForFilteredItemsCleared(): Promise {\n if (!this.#filteredCleared) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.FILTERED_ITEMS_CLEARED);\n }\n this.#filteredCleared = true;\n }\n\n async waitForItemsRefreshed(): Promise {\n if (!this.#refreshed) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEMS_REFRESHED);\n }\n this.#refreshed = true;\n }\n\n async waitForItemsDeletedTotal(total: number): Promise {\n while (this.#deletedKeys.length < total) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEM_DELETED);\n }\n }\n\n async waitForItemsEditedTotal(total: number): Promise {\n while (this.#editedEvents.length < total) {\n await this.#dispatcher.once(View.SharedStorageItemsDispatcher.Events.ITEM_EDITED);\n }\n }\n}\n\ndescribeWithMockConnection('SharedStorageItemsView', function() {\n let target: SDK.Target.Target;\n let sharedStorageModel: Resources.SharedStorageModel.SharedStorageModel|null;\n let sharedStorage: Resources.SharedStorageModel.SharedStorageForOrigin;\n\n const TEST_ORIGIN = 'http://a.test';\n\n const METADATA = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 3,\n remainingBudget: 2.5,\n bytesUsed: 30,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const METADATA_NO_ENTRIES = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 0,\n remainingBudget: 2.5,\n bytesUsed: 0,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const METADATA_2_ENTRIES = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 2,\n remainingBudget: 2.5,\n bytesUsed: 20,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const METADATA_4_ENTRIES = {\n creationTime: 100 as Protocol.Network.TimeSinceEpoch,\n length: 4,\n remainingBudget: 2.5,\n bytesUsed: 38,\n } as Protocol.Storage.SharedStorageMetadata;\n\n const ENTRIES = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key2',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_1 = [\n {\n key: 'key2',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_2 = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_KEY_EDITED_1 = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key0',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_KEY_EDITED_2 = [\n {\n key: 'key1',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_VALUE_EDITED = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key2',\n value: 'd',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n const ENTRIES_NEW_KEY = [\n {\n key: 'key1',\n value: 'a',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key2',\n value: 'b',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key3',\n value: 'c',\n } as Protocol.Storage.SharedStorageEntry,\n {\n key: 'key4',\n value: '',\n } as Protocol.Storage.SharedStorageEntry,\n ];\n\n beforeEach(() => {\n target = createTarget();\n sharedStorageModel = target.model(Resources.SharedStorageModel.SharedStorageModel);\n assert.exists(sharedStorageModel);\n sharedStorage = new Resources.SharedStorageModel.SharedStorageForOrigin(sharedStorageModel, TEST_ORIGIN);\n assert.strictEqual(sharedStorage.securityOrigin, TEST_ORIGIN);\n });\n\n it('displays metadata and entries', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n const metadataView = view.innerSplitWidget.sidebarWidget()?.contentElement.firstChild as\n ApplicationComponents.SharedStorageMetadataView.SharedStorageMetadataView;\n assert.exists(metadataView);\n\n assert.isNotNull(metadataView.shadowRoot);\n await coordinator.done();\n\n const keys = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-key');\n assert.deepEqual(keys, [\n 'Origin',\n 'Creation Time',\n 'Number of Entries',\n 'Number of Bytes Used',\n 'Entropy Budget for Fenced Frames',\n ]);\n\n const values = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-value');\n assert.deepEqual(values, [\n TEST_ORIGIN,\n (new Date(100 * 1e3)).toLocaleString(),\n '3',\n '30',\n '2.5',\n ]);\n\n view.detach();\n });\n\n it('displays metadata with placeholder message if origin is not using API', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorage, 'getMetadata').resolves(null);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: [],\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.strictEqual(view.getEntriesForTesting().length, 0);\n\n const metadataView = view.innerSplitWidget.sidebarWidget()?.contentElement.firstChild as\n ApplicationComponents.SharedStorageMetadataView.SharedStorageMetadataView;\n assert.exists(metadataView);\n\n assert.isNotNull(metadataView.shadowRoot);\n await coordinator.done();\n\n const keys = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-key');\n assert.deepEqual(keys, [\n 'Origin',\n 'Creation Time',\n 'Number of Entries',\n 'Number of Bytes Used',\n 'Entropy Budget for Fenced Frames',\n ]);\n\n const values = getCleanTextContentFromElements(metadataView.shadowRoot, 'devtools-report-value');\n assert.deepEqual(values, [\n TEST_ORIGIN,\n 'Not yet created',\n '0',\n '0',\n '0',\n ]);\n\n view.detach();\n });\n\n it('has placeholder sidebar when there are no entries', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n metadata: METADATA_NO_ENTRIES,\n getError: () => undefined,\n });\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: [],\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.notInstanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n assert.exists(view.contentElement.querySelector('.placeholder'));\n\n view.detach();\n });\n\n it('updates sidebarWidget upon receiving SelectedNode Event', async () => {\n assert.exists(sharedStorageModel);\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries')\n .withArgs({ownerOrigin: TEST_ORIGIN})\n .resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n // Select the second row.\n assert.exists(selectNodeByKey(view.dataGrid, 'key2'));\n await raf();\n\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('refreshes when \"Refresh\" is clicked', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata').resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries').resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise1 = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise1;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Clicking \"Refresh\" will cause `getMetadata()` and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise2 = itemsListener.waitForItemsRefreshed();\n dispatchClickEvent(view.refreshButton.element);\n await raf();\n await refreshedPromise2;\n\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n view.detach();\n });\n\n it('clears entries when \"Delete All\" is clicked', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_NO_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: [],\n getError: () => undefined,\n });\n const clearSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_clearSharedStorageEntries').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Clicking \"Delete All\" will cause `clear()`, `getMetadata()`, and `getEntries()` to be called.\n const clearedPromise = itemsListener.waitForItemsCleared();\n dispatchClickEvent(view.deleteAllButton.element);\n await raf();\n await clearedPromise;\n\n assert.isTrue(clearSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), []);\n\n view.detach();\n });\n\n it('clears filtered entries when \"Delete All\" is clicked with a filter set', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(3).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(4).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(2).resolves({\n entries: ENTRIES_2,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(3).resolves({\n entries: ENTRIES_2,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise1 = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise1;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Adding a filter to the text box will cause `getMetadata()`, and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise2 = itemsListener.waitForItemsRefreshed();\n view.filterItem.dispatchEventToListeners(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, 'b');\n await raf();\n await refreshedPromise2;\n\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n // Only the filtered entries are displayed.\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_1);\n\n // Clicking \"Delete All\" will cause `deleteEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const clearedPromise = itemsListener.waitForFilteredItemsCleared();\n dispatchClickEvent(view.deleteAllButton.element);\n await raf();\n await clearedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.strictEqual(getMetadataSpy.callCount, 4);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledThrice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n // The filtered entries are cleared.\n assert.deepEqual(view.getEntriesForTesting(), []);\n\n // Changing the filter in the text box will cause `getMetadata()`, and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise3 = itemsListener.waitForItemsRefreshed();\n view.filterItem.dispatchEventToListeners(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, '');\n await raf();\n await refreshedPromise3;\n\n assert.strictEqual(getMetadataSpy.callCount, 5);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.strictEqual(getEntriesSpy.callCount, 4);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_2);\n\n view.detach();\n });\n\n it('deletes selected entry when \"Delete Selected\" is clicked', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: [],\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n assert.exists(selectNodeByKey(view.dataGrid, 'key2'));\n await raf();\n\n // Clicking \"Delete Selected\" will cause `deleteEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const deletedPromise = itemsListener.waitForItemsDeletedTotal(1);\n dispatchClickEvent(view.deleteSelectedButton.element);\n await raf();\n await deletedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), []);\n assert.deepEqual(itemsListener.deletedKeys, ['key2']);\n\n view.detach();\n });\n\n it('edits key of selected entry to a non-preexisting key', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_KEY_EDITED_1,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key will cause `deleteEntry()`, `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'key0';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key0', value: 'b', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_KEY_EDITED_1);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'key', oldText: 'key2', newText: 'key0'} as View.SharedStorageItemsDispatcher.ItemEditedEvent,\n ]);\n\n view.detach();\n });\n\n it('edits key of selected entry to a preexisting key', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_2_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_KEY_EDITED_2,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key will cause `deleteEntry()`, `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'key1';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2'}));\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key1', value: 'b', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_KEY_EDITED_2);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'key', oldText: 'key2', newText: 'key1'} as View.SharedStorageItemsDispatcher.ItemEditedEvent,\n ]);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('edits value of selected entry to a new value', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_VALUE_EDITED,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'value', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'value');\n assert.exists(cellElement);\n\n // Editing a value will cause `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'd';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.notCalled);\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key2', value: 'd', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_VALUE_EDITED);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'value', oldText: 'b', newText: 'd'} as View.SharedStorageItemsDispatcher.ItemEditedEvent,\n ]);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('adds an entry when the key cell of the empty data row is edited', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata');\n getMetadataSpy.onCall(0).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(1).resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n getMetadataSpy.onCall(2).resolves({\n metadata: METADATA_4_ENTRIES,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries');\n getEntriesSpy.onCall(0).resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n getEntriesSpy.onCall(1).resolves({\n entries: ENTRIES_NEW_KEY,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the empty (null) row.\n const node = selectNodeByKey(view.dataGrid, null);\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key will cause `setEntry()`, `getMetadata()`, and `getEntries()` to be called.\n const editedPromise = itemsListener.waitForItemsEditedTotal(1);\n cellElement.textContent = 'key4';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await editedPromise;\n\n assert.isTrue(deleteEntrySpy.notCalled);\n assert.isTrue(\n setEntrySpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN, key: 'key4', value: '', ignoreIfPresent: false}));\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES_NEW_KEY);\n assert.deepEqual(itemsListener.editedEvents, [\n {columnIdentifier: 'key', oldText: null, newText: 'key4'},\n ]);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n\n it('attempting to edit key of selected entry to an empty key cancels the edit', async () => {\n assert.exists(sharedStorageModel);\n const getMetadataSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageMetadata').resolves({\n metadata: METADATA,\n getError: () => undefined,\n });\n const getEntriesSpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_getSharedStorageEntries').resolves({\n entries: ENTRIES,\n getError: () => undefined,\n });\n const deleteEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_deleteSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n const setEntrySpy = sinon.stub(sharedStorageModel.storageAgent, 'invoke_setSharedStorageEntry').resolves({\n getError: () => undefined,\n });\n\n // Creating will cause `getMetadata()` to be called.\n const view = await View.SharedStorageItemsView.createView(sharedStorage);\n await coordinator.done({waitForWork: true});\n assert.isTrue(getMetadataSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n const itemsListener = new SharedStorageItemsListener(view.sharedStorageItemsDispatcher);\n const refreshedPromise1 = itemsListener.waitForItemsRefreshed();\n\n // Showing will cause `getMetadata()` and `getEntries()` to be called.\n view.markAsRoot();\n view.show(document.body);\n await refreshedPromise1;\n\n assert.isTrue(getMetadataSpy.calledTwice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledOnceWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Select the second row.\n const node = selectNodeByKey(view.dataGrid, 'key2');\n assert.exists(node);\n await raf();\n\n const selectedNode = node as DataGrid.DataGrid.DataGridNode;\n view.dataGrid.startEditingNextEditableColumnOfDataGridNode(selectedNode, 'key', true);\n\n const cellElement = getCellElementFromNodeAndColumnId(view.dataGrid, selectedNode, 'key');\n assert.exists(cellElement);\n\n // Editing a key with the edit canceled will cause `getMetadata()` and `getEntries()` to be called.\n itemsListener.resetRefreshed();\n const refreshedPromise2 = itemsListener.waitForItemsRefreshed();\n cellElement.textContent = '';\n dispatchKeyDownEvent(cellElement, {key: 'Enter'});\n await raf();\n await refreshedPromise2;\n\n assert.isTrue(deleteEntrySpy.notCalled);\n assert.isTrue(setEntrySpy.notCalled);\n assert.isTrue(getMetadataSpy.calledThrice);\n assert.isTrue(getMetadataSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n assert.isTrue(getEntriesSpy.calledTwice);\n assert.isTrue(getEntriesSpy.alwaysCalledWithExactly({ownerOrigin: TEST_ORIGIN}));\n\n assert.deepEqual(view.getEntriesForTesting(), ENTRIES);\n\n // Verify that the preview loads.\n assert.instanceOf(view.outerSplitWidget.sidebarWidget(), UI.SearchableView.SearchableView);\n\n view.detach();\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/application/StorageView.js b/public/panels/application/StorageView.js index 8f9cd0d3..99b3a347 100644 --- a/public/panels/application/StorageView.js +++ b/public/panels/application/StorageView.js @@ -437,8 +437,8 @@ export class StorageView extends UI.ThrottledWidget.ThrottledWidget { return; } const quotaOverridden = response.overrideActive; - const quotaAsString = Platform.NumberUtilities.bytesToString(response.quota); - const usageAsString = Platform.NumberUtilities.bytesToString(response.usage); + const quotaAsString = i18n.ByteUtilities.bytesToString(response.quota); + const usageAsString = i18n.ByteUtilities.bytesToString(response.usage); const formattedQuotaAsString = i18nString(UIStrings.storageWithCustomMarker, { PH1: quotaAsString }); const quota = quotaOverridden ? UI.Fragment.Fragment.build `${formattedQuotaAsString}`.element() : quotaAsString; const element = i18n.i18n.getFormatLocalizedString(str_, UIStrings.storageQuotaUsed, { PH1: usageAsString, PH2: quota }); @@ -470,7 +470,7 @@ export class StorageView extends UI.ThrottledWidget.ThrottledWidget { this.pieChart.data = { chartName: i18nString(UIStrings.storageUsage), size: 110, - formatter: Platform.NumberUtilities.bytesToString, + formatter: i18n.ByteUtilities.bytesToString, showLegend: true, total, slices, diff --git a/public/panels/application/StorageView.js.map b/public/panels/application/StorageView.js.map index df8ea1fd..0ccff342 100644 --- a/public/panels/application/StorageView.js.map +++ b/public/panels/application/StorageView.js.map @@ -1 +1 @@ -{"version":3,"file":"StorageView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/StorageView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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 SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport type * as Buttons from '../../ui/components/buttons/buttons.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 {DOMStorageModel} from './DOMStorageModel.js';\nimport {IndexedDBModel} from './IndexedDBModel.js';\nimport storageViewStyles from './storageView.css.js';\n\nconst UIStrings = {\n /**\n * @description Text in the Storage View that expresses the amout of used and available storage quota\n * @example {1.5 MB} PH1\n * @example {123.1 MB} PH2\n */\n storageQuotaUsed: '{PH1} used out of {PH2} storage quota',\n /**\n * @description Tooltip in the Storage View that expresses the precise amout of used and available storage quota\n * @example {200} PH1\n * @example {400} PH2\n */\n storageQuotaUsedWithBytes: '{PH1} bytes used out of {PH2} bytes storage quota',\n /**\n * @description Fragment indicating that a certain data size has been custom configured\n * @example {1.5 MB} PH1\n */\n storageWithCustomMarker: '{PH1} (custom)',\n /**\n * @description Text in Application Panel Sidebar and title text of the Storage View of the Application panel\n */\n storageTitle: 'Storage',\n /**\n * @description Title text in Storage View of the Application panel\n */\n usage: 'Usage',\n /**\n * @description Unit for data size in DevTools\n */\n mb: 'MB',\n /**\n * @description Link to learn more about Progressive Web Apps\n */\n learnMore: 'Learn more',\n /**\n * @description Button text for the button in the Storage View of the Application panel for clearing site-specific storage\n */\n clearSiteData: 'Clear site data',\n /**\n * @description Annouce message when the \"clear site data\" task is complete\n */\n SiteDataCleared: 'Site data cleared',\n /**\n * @description Category description in the Clear Storage section of the Storage View of the Application panel\n */\n application: 'Application',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n unregisterServiceWorker: 'Unregister service workers',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n localAndSessionStorage: 'Local and session storage',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n indexDB: 'IndexedDB',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n webSql: 'Web SQL',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n cookies: 'Cookies',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n cacheStorage: 'Cache storage',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n includingThirdPartyCookies: 'including third-party cookies',\n /**\n * @description Text for error message in Application Quota Override\n * @example {Image} PH1\n */\n sFailedToLoad: '{PH1} (failed to load)',\n /**\n * @description Text for error message in Application Quota Override\n */\n internalError: 'Internal error',\n /**\n * @description Text for error message in Application Quota Override\n */\n pleaseEnterANumber: 'Please enter a number',\n /**\n * @description Text for error message in Application Quota Override\n */\n numberMustBeNonNegative: 'Number must be non-negative',\n /**\n * @description Text for error message in Application Quota Override\n * @example {9000000000000} PH1\n */\n numberMustBeSmaller: 'Number must be smaller than {PH1}',\n /**\n * @description Button text for the \"Clear site data\" button in the Storage View of the Application panel while the clearing action is pending\n */\n clearing: 'Clearing...',\n /**\n * @description Quota row title in Clear Storage View of the Application panel\n */\n storageQuotaIsLimitedIn: 'Storage quota is limited in Incognito mode',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n fileSystem: 'File System',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n other: 'Other',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n storageUsage: 'Storage usage',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n serviceWorkers: 'Service workers',\n /**\n * @description Checkbox label in Application Panel Sidebar of the Application panel.\n * Storage quota refers to the amount of disk available for the website or app.\n */\n simulateCustomStorage: 'Simulate custom storage quota',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/application/StorageView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * @implements {SDK.TargetManager.Observer}\n */\nexport class StorageView extends UI.ThrottledWidget.ThrottledWidget {\n private pieColors: Map;\n private reportView: UI.ReportView.ReportView;\n private target: SDK.Target.Target|null;\n private securityOrigin: string|null;\n private storageKey: string|null;\n private settings: Map>;\n private includeThirdPartyCookiesSetting: Common.Settings.Setting;\n private quotaRow: HTMLElement;\n private quotaUsage: number|null;\n private pieChart: PerfUI.PieChart.PieChart;\n private previousOverrideFieldValue: string;\n private quotaOverrideCheckbox: UI.UIUtils.CheckboxLabel;\n private quotaOverrideControlRow: HTMLElement;\n private quotaOverrideEditor: HTMLInputElement;\n private quotaOverrideErrorMessage: HTMLElement;\n private clearButton: Buttons.Button.Button;\n\n constructor() {\n super(true, 1000);\n\n this.contentElement.classList.add('clear-storage-container');\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('clear-storage')}`);\n this.pieColors = new Map([\n [Protocol.Storage.StorageType.Appcache, 'rgb(110, 161, 226)'], // blue\n [Protocol.Storage.StorageType.Cache_storage, 'rgb(229, 113, 113)'], // red\n [Protocol.Storage.StorageType.Cookies, 'rgb(239, 196, 87)'], // yellow\n [Protocol.Storage.StorageType.Indexeddb, 'rgb(155, 127, 230)'], // purple\n [Protocol.Storage.StorageType.Local_storage, 'rgb(116, 178, 102)'], // green\n [Protocol.Storage.StorageType.Service_workers, 'rgb(255, 167, 36)'], // orange\n [Protocol.Storage.StorageType.Websql, 'rgb(203, 220, 56)'], // lime\n ]);\n\n // TODO(crbug.com/1156978): Replace UI.ReportView.ReportView with ReportView.ts web component.\n this.reportView = new UI.ReportView.ReportView(i18nString(UIStrings.storageTitle));\n\n this.reportView.element.classList.add('clear-storage-header');\n this.reportView.show(this.contentElement);\n this.target = null;\n this.securityOrigin = null;\n this.storageKey = null;\n\n this.settings = new Map();\n for (const type of AllStorageTypes) {\n this.settings.set(\n type,\n Common.Settings.Settings.instance().createSetting(\n 'clear-storage-' + Platform.StringUtilities.toKebabCase(type), true));\n }\n\n this.includeThirdPartyCookiesSetting =\n Common.Settings.Settings.instance().createSetting('clear-storage-include-third-party-cookies', false);\n\n const quota = this.reportView.appendSection(i18nString(UIStrings.usage));\n quota.element.setAttribute('jslog', `${VisualLogging.section('usage')}`);\n this.quotaRow = quota.appendSelectableRow();\n this.quotaRow.classList.add('quota-usage-row');\n const learnMoreRow = quota.appendRow();\n const learnMore = UI.XLink.XLink.create(\n 'https://developer.chrome.com/docs/devtools/progressive-web-apps#opaque-responses',\n i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more');\n learnMoreRow.appendChild(learnMore);\n this.quotaUsage = null;\n this.pieChart = new PerfUI.PieChart.PieChart();\n this.populatePieChart(0, []);\n const usageBreakdownRow = quota.appendRow();\n usageBreakdownRow.classList.add('usage-breakdown-row');\n usageBreakdownRow.appendChild(this.pieChart);\n\n this.previousOverrideFieldValue = '';\n const quotaOverrideCheckboxRow = quota.appendRow();\n quotaOverrideCheckboxRow.classList.add('quota-override-row');\n this.quotaOverrideCheckbox =\n UI.UIUtils.CheckboxLabel.create(i18nString(UIStrings.simulateCustomStorage), false, '');\n this.quotaOverrideCheckbox.setAttribute(\n 'jslog', `${VisualLogging.toggle('simulate-custom-quota').track({change: true})}`);\n quotaOverrideCheckboxRow.appendChild(this.quotaOverrideCheckbox);\n this.quotaOverrideCheckbox.checkboxElement.addEventListener('click', this.onClickCheckbox.bind(this), false);\n this.quotaOverrideControlRow = quota.appendRow();\n this.quotaOverrideEditor =\n this.quotaOverrideControlRow.createChild('input', 'quota-override-notification-editor') as HTMLInputElement;\n this.quotaOverrideEditor.setAttribute(\n 'jslog', `${VisualLogging.textField('quota-override').track({change: true})}`);\n this.quotaOverrideControlRow.appendChild(UI.UIUtils.createLabel(i18nString(UIStrings.mb)));\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideEditor.addEventListener('keyup', event => {\n if (event.key === 'Enter') {\n void this.applyQuotaOverrideFromInputField();\n event.consume(true);\n }\n });\n this.quotaOverrideEditor.addEventListener('focusout', event => {\n void this.applyQuotaOverrideFromInputField();\n event.consume(true);\n });\n\n const errorMessageRow = quota.appendRow();\n this.quotaOverrideErrorMessage = errorMessageRow.createChild('div', 'quota-override-error');\n\n const clearButtonSection = this.reportView.appendSection('', 'clear-storage-button').appendRow();\n this.clearButton = UI.UIUtils.createTextButton(\n i18nString(UIStrings.clearSiteData), this.clear.bind(this), {jslogContext: 'storage.clear-site-data'});\n this.clearButton.id = 'storage-view-clear-button';\n clearButtonSection.appendChild(this.clearButton);\n\n const includeThirdPartyCookiesCheckbox = UI.SettingsUI.createSettingCheckbox(\n i18nString(UIStrings.includingThirdPartyCookies), this.includeThirdPartyCookiesSetting, true);\n includeThirdPartyCookiesCheckbox.classList.add('include-third-party-cookies');\n clearButtonSection.appendChild(includeThirdPartyCookiesCheckbox);\n\n const application = this.reportView.appendSection(i18nString(UIStrings.application));\n application.element.setAttribute('jslog', `${VisualLogging.section('application')}`);\n this.appendItem(\n application, i18nString(UIStrings.unregisterServiceWorker), Protocol.Storage.StorageType.Service_workers);\n application.markFieldListAsGroup();\n\n const storage = this.reportView.appendSection(i18nString(UIStrings.storageTitle));\n storage.element.setAttribute('jslog', `${VisualLogging.section('storage')}`);\n this.appendItem(storage, i18nString(UIStrings.localAndSessionStorage), Protocol.Storage.StorageType.Local_storage);\n this.appendItem(storage, i18nString(UIStrings.indexDB), Protocol.Storage.StorageType.Indexeddb);\n this.appendItem(storage, i18nString(UIStrings.webSql), Protocol.Storage.StorageType.Websql);\n this.appendItem(storage, i18nString(UIStrings.cookies), Protocol.Storage.StorageType.Cookies);\n this.appendItem(storage, i18nString(UIStrings.cacheStorage), Protocol.Storage.StorageType.Cache_storage);\n storage.markFieldListAsGroup();\n\n SDK.TargetManager.TargetManager.instance().observeTargets(this);\n }\n\n private appendItem(section: UI.ReportView.Section, title: string, settingName: Protocol.Storage.StorageType): void {\n const row = section.appendRow();\n const setting = this.settings.get(settingName);\n if (setting) {\n row.appendChild(UI.SettingsUI.createSettingCheckbox(title, setting, true));\n }\n }\n\n targetAdded(target: SDK.Target.Target): void {\n if (target !== SDK.TargetManager.TargetManager.instance().primaryPageTarget()) {\n return;\n }\n this.target = target;\n const securityOriginManager = target.model(SDK.SecurityOriginManager.SecurityOriginManager) as\n SDK.SecurityOriginManager.SecurityOriginManager;\n this.updateOrigin(\n securityOriginManager.mainSecurityOrigin(), securityOriginManager.unreachableMainSecurityOrigin());\n securityOriginManager.addEventListener(\n SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this.originChanged, this);\n const storageKeyManager =\n target.model(SDK.StorageKeyManager.StorageKeyManager) as SDK.StorageKeyManager.StorageKeyManager;\n this.updateStorageKey(storageKeyManager.mainStorageKey());\n storageKeyManager.addEventListener(\n SDK.StorageKeyManager.Events.MAIN_STORAGE_KEY_CHANGED, this.storageKeyChanged, this);\n }\n\n targetRemoved(target: SDK.Target.Target): void {\n if (this.target !== target) {\n return;\n }\n const securityOriginManager = target.model(SDK.SecurityOriginManager.SecurityOriginManager) as\n SDK.SecurityOriginManager.SecurityOriginManager;\n securityOriginManager.removeEventListener(\n SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this.originChanged, this);\n const storageKeyManager =\n target.model(SDK.StorageKeyManager.StorageKeyManager) as SDK.StorageKeyManager.StorageKeyManager;\n storageKeyManager.removeEventListener(\n SDK.StorageKeyManager.Events.MAIN_STORAGE_KEY_CHANGED, this.storageKeyChanged, this);\n }\n\n private originChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const {mainSecurityOrigin, unreachableMainSecurityOrigin} = event.data;\n this.updateOrigin(mainSecurityOrigin, unreachableMainSecurityOrigin);\n }\n\n private storageKeyChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const {mainStorageKey} = event.data;\n this.updateStorageKey(mainStorageKey);\n }\n\n private updateOrigin(mainOrigin: string, unreachableMainOrigin: string|null): void {\n const oldOrigin = this.securityOrigin;\n if (unreachableMainOrigin) {\n this.securityOrigin = unreachableMainOrigin;\n this.reportView.setSubtitle(i18nString(UIStrings.sFailedToLoad, {PH1: unreachableMainOrigin}));\n } else {\n this.securityOrigin = mainOrigin;\n this.reportView.setSubtitle(mainOrigin);\n }\n\n if (oldOrigin !== this.securityOrigin) {\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = false;\n this.quotaOverrideErrorMessage.textContent = '';\n }\n void this.doUpdate();\n }\n\n private updateStorageKey(mainStorageKey: string): void {\n const oldStorageKey = this.storageKey;\n\n this.storageKey = mainStorageKey;\n this.reportView.setSubtitle(mainStorageKey);\n\n if (oldStorageKey !== this.storageKey) {\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = false;\n this.quotaOverrideErrorMessage.textContent = '';\n }\n void this.doUpdate();\n }\n\n private async applyQuotaOverrideFromInputField(): Promise {\n if (!this.target || !this.securityOrigin) {\n this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.internalError);\n return;\n }\n this.quotaOverrideErrorMessage.textContent = '';\n const editorString = this.quotaOverrideEditor.value;\n if (editorString === '') {\n await this.clearQuotaForOrigin(this.target, this.securityOrigin);\n this.previousOverrideFieldValue = '';\n return;\n }\n const quota = parseFloat(editorString);\n if (!Number.isFinite(quota)) {\n this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.pleaseEnterANumber);\n return;\n }\n if (quota < 0) {\n this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.numberMustBeNonNegative);\n return;\n }\n const cutoff = 9_000_000_000_000;\n if (quota >= cutoff) {\n this.quotaOverrideErrorMessage.textContent =\n i18nString(UIStrings.numberMustBeSmaller, {PH1: cutoff.toLocaleString()});\n return;\n }\n const bytesPerMB = 1000 * 1000;\n const quotaInBytes = Math.round(quota * bytesPerMB);\n const quotaFieldValue = `${quotaInBytes / bytesPerMB}`;\n this.quotaOverrideEditor.value = quotaFieldValue;\n this.previousOverrideFieldValue = quotaFieldValue;\n await this.target.storageAgent().invoke_overrideQuotaForOrigin(\n {origin: this.securityOrigin, quotaSize: quotaInBytes});\n }\n\n private async clearQuotaForOrigin(target: SDK.Target.Target, origin: string): Promise {\n await target.storageAgent().invoke_overrideQuotaForOrigin({origin});\n }\n\n private async onClickCheckbox(): Promise {\n if (this.quotaOverrideControlRow.classList.contains('hidden')) {\n this.quotaOverrideControlRow.classList.remove('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = true;\n this.quotaOverrideEditor.value = this.previousOverrideFieldValue;\n this.quotaOverrideEditor.focus();\n } else if (this.target && this.securityOrigin) {\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = false;\n await this.clearQuotaForOrigin(this.target, this.securityOrigin);\n this.quotaOverrideErrorMessage.textContent = '';\n }\n }\n\n private clear(): void {\n if (!this.securityOrigin) {\n return;\n }\n const selectedStorageTypes = [];\n for (const type of this.settings.keys()) {\n const setting = this.settings.get(type);\n if (setting && setting.get()) {\n selectedStorageTypes.push(type);\n }\n }\n\n if (this.target) {\n const includeThirdPartyCookies = this.includeThirdPartyCookiesSetting.get();\n StorageView.clear(\n this.target, this.storageKey, this.securityOrigin, selectedStorageTypes, includeThirdPartyCookies);\n }\n\n this.clearButton.disabled = true;\n const label = this.clearButton.textContent;\n this.clearButton.textContent = i18nString(UIStrings.clearing);\n window.setTimeout(() => {\n this.clearButton.disabled = false;\n this.clearButton.textContent = label;\n this.clearButton.focus();\n }, 500);\n\n UI.ARIAUtils.alert(i18nString(UIStrings.SiteDataCleared));\n }\n\n static clear(\n target: SDK.Target.Target, storageKey: string|null, originForCookies: string|null, selectedStorageTypes: string[],\n includeThirdPartyCookies: boolean): void {\n console.assert(Boolean(storageKey));\n if (!storageKey) {\n return;\n }\n void target.storageAgent().invoke_clearDataForStorageKey(\n {storageKey, storageTypes: selectedStorageTypes.join(',')});\n\n const set = new Set(selectedStorageTypes);\n const hasAll = set.has(Protocol.Storage.StorageType.All);\n\n if (set.has(Protocol.Storage.StorageType.Local_storage) || hasAll) {\n const storageModel = target.model(DOMStorageModel);\n if (storageModel) {\n storageModel.clearForStorageKey(storageKey);\n }\n }\n\n if (set.has(Protocol.Storage.StorageType.Indexeddb) || hasAll) {\n for (const target of SDK.TargetManager.TargetManager.instance().targets()) {\n const indexedDBModel = target.model(IndexedDBModel);\n if (indexedDBModel) {\n indexedDBModel.clearForStorageKey(storageKey);\n }\n }\n }\n\n if (originForCookies && (set.has(Protocol.Storage.StorageType.Cookies) || hasAll)) {\n void target.storageAgent().invoke_clearDataForOrigin(\n {origin: originForCookies, storageTypes: Protocol.Storage.StorageType.Cookies});\n const cookieModel = target.model(SDK.CookieModel.CookieModel);\n if (cookieModel) {\n void cookieModel.clear(undefined, includeThirdPartyCookies ? undefined : originForCookies);\n }\n }\n\n if (set.has(Protocol.Storage.StorageType.Cache_storage) || hasAll) {\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const model = target && target.model(SDK.ServiceWorkerCacheModel.ServiceWorkerCacheModel);\n if (model) {\n model.clearForStorageKey(storageKey);\n }\n }\n }\n\n override async doUpdate(): Promise {\n if (!this.securityOrigin || !this.target) {\n this.quotaRow.textContent = '';\n this.populatePieChart(0, []);\n return;\n }\n\n const securityOrigin = this.securityOrigin;\n const response = await this.target.storageAgent().invoke_getUsageAndQuota({origin: securityOrigin});\n this.quotaRow.textContent = '';\n if (response.getError()) {\n this.populatePieChart(0, []);\n return;\n }\n const quotaOverridden = response.overrideActive;\n const quotaAsString = Platform.NumberUtilities.bytesToString(response.quota);\n const usageAsString = Platform.NumberUtilities.bytesToString(response.usage);\n const formattedQuotaAsString = i18nString(UIStrings.storageWithCustomMarker, {PH1: quotaAsString});\n const quota =\n quotaOverridden ? UI.Fragment.Fragment.build`${formattedQuotaAsString}`.element() : quotaAsString;\n const element =\n i18n.i18n.getFormatLocalizedString(str_, UIStrings.storageQuotaUsed, {PH1: usageAsString, PH2: quota});\n this.quotaRow.appendChild(element);\n UI.Tooltip.Tooltip.install(\n this.quotaRow,\n i18nString(\n UIStrings.storageQuotaUsedWithBytes,\n {PH1: response.usage.toLocaleString(), PH2: response.quota.toLocaleString()}));\n\n if (!response.overrideActive && response.quota < 125829120) { // 120 MB\n const icon = new IconButton.Icon.Icon();\n icon.data = {iconName: 'info', color: 'var(--icon-info)', width: '14px', height: '14px'};\n UI.Tooltip.Tooltip.install(this.quotaRow, i18nString(UIStrings.storageQuotaIsLimitedIn));\n this.quotaRow.appendChild(icon);\n }\n\n if (this.quotaUsage === null || this.quotaUsage !== response.usage) {\n this.quotaUsage = response.usage;\n const slices: PerfUI.PieChart.Slice[] = [];\n for (const usageForType of response.usageBreakdown.sort((a, b) => b.usage - a.usage)) {\n const value = usageForType.usage;\n if (!value) {\n continue;\n }\n const title = this.getStorageTypeName(usageForType.storageType);\n const color = this.pieColors.get(usageForType.storageType) || '#ccc';\n slices.push({value, color, title});\n }\n this.populatePieChart(response.usage, slices);\n }\n\n this.update();\n }\n\n private populatePieChart(total: number, slices: PerfUI.PieChart.Slice[]): void {\n this.pieChart.data = {\n chartName: i18nString(UIStrings.storageUsage),\n size: 110,\n formatter: Platform.NumberUtilities.bytesToString,\n showLegend: true,\n total,\n slices,\n };\n }\n\n private getStorageTypeName(type: Protocol.Storage.StorageType): string {\n switch (type) {\n case Protocol.Storage.StorageType.File_systems:\n return i18nString(UIStrings.fileSystem);\n case Protocol.Storage.StorageType.Websql:\n return i18nString(UIStrings.webSql);\n case Protocol.Storage.StorageType.Appcache:\n return i18nString(UIStrings.application);\n case Protocol.Storage.StorageType.Indexeddb:\n return i18nString(UIStrings.indexDB);\n case Protocol.Storage.StorageType.Cache_storage:\n return i18nString(UIStrings.cacheStorage);\n case Protocol.Storage.StorageType.Service_workers:\n return i18nString(UIStrings.serviceWorkers);\n default:\n return i18nString(UIStrings.other);\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.reportView.registerCSSFiles([storageViewStyles]);\n this.registerCSSFiles([storageViewStyles]);\n }\n}\n\nexport const AllStorageTypes = [\n Protocol.Storage.StorageType.Appcache,\n Protocol.Storage.StorageType.Cache_storage,\n Protocol.Storage.StorageType.Cookies,\n Protocol.Storage.StorageType.Indexeddb,\n Protocol.Storage.StorageType.Local_storage,\n Protocol.Storage.StorageType.Service_workers,\n Protocol.Storage.StorageType.Websql,\n];\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(_context: UI.Context.Context, actionId: string): boolean {\n switch (actionId) {\n case 'resources.clear':\n return this.handleClear(false);\n case 'resources.clear-incl-third-party-cookies':\n return this.handleClear(true);\n }\n return false;\n }\n\n private handleClear(includeThirdPartyCookies: boolean): boolean {\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!target) {\n return false;\n }\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceTreeModel) {\n return false;\n }\n const securityOrigin = resourceTreeModel.getMainSecurityOrigin();\n resourceTreeModel.getMainStorageKey().then(storageKey => {\n StorageView.clear(target, storageKey, securityOrigin, AllStorageTypes, includeThirdPartyCookies);\n }, _ => {});\n return true;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"StorageView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/StorageView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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 SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport type * as Buttons from '../../ui/components/buttons/buttons.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 {DOMStorageModel} from './DOMStorageModel.js';\nimport {IndexedDBModel} from './IndexedDBModel.js';\nimport storageViewStyles from './storageView.css.js';\n\nconst UIStrings = {\n /**\n * @description Text in the Storage View that expresses the amout of used and available storage quota\n * @example {1.5 MB} PH1\n * @example {123.1 MB} PH2\n */\n storageQuotaUsed: '{PH1} used out of {PH2} storage quota',\n /**\n * @description Tooltip in the Storage View that expresses the precise amout of used and available storage quota\n * @example {200} PH1\n * @example {400} PH2\n */\n storageQuotaUsedWithBytes: '{PH1} bytes used out of {PH2} bytes storage quota',\n /**\n * @description Fragment indicating that a certain data size has been custom configured\n * @example {1.5 MB} PH1\n */\n storageWithCustomMarker: '{PH1} (custom)',\n /**\n * @description Text in Application Panel Sidebar and title text of the Storage View of the Application panel\n */\n storageTitle: 'Storage',\n /**\n * @description Title text in Storage View of the Application panel\n */\n usage: 'Usage',\n /**\n * @description Unit for data size in DevTools\n */\n mb: 'MB',\n /**\n * @description Link to learn more about Progressive Web Apps\n */\n learnMore: 'Learn more',\n /**\n * @description Button text for the button in the Storage View of the Application panel for clearing site-specific storage\n */\n clearSiteData: 'Clear site data',\n /**\n * @description Annouce message when the \"clear site data\" task is complete\n */\n SiteDataCleared: 'Site data cleared',\n /**\n * @description Category description in the Clear Storage section of the Storage View of the Application panel\n */\n application: 'Application',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n unregisterServiceWorker: 'Unregister service workers',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n localAndSessionStorage: 'Local and session storage',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n indexDB: 'IndexedDB',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n webSql: 'Web SQL',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n cookies: 'Cookies',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n cacheStorage: 'Cache storage',\n /**\n * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel\n */\n includingThirdPartyCookies: 'including third-party cookies',\n /**\n * @description Text for error message in Application Quota Override\n * @example {Image} PH1\n */\n sFailedToLoad: '{PH1} (failed to load)',\n /**\n * @description Text for error message in Application Quota Override\n */\n internalError: 'Internal error',\n /**\n * @description Text for error message in Application Quota Override\n */\n pleaseEnterANumber: 'Please enter a number',\n /**\n * @description Text for error message in Application Quota Override\n */\n numberMustBeNonNegative: 'Number must be non-negative',\n /**\n * @description Text for error message in Application Quota Override\n * @example {9000000000000} PH1\n */\n numberMustBeSmaller: 'Number must be smaller than {PH1}',\n /**\n * @description Button text for the \"Clear site data\" button in the Storage View of the Application panel while the clearing action is pending\n */\n clearing: 'Clearing...',\n /**\n * @description Quota row title in Clear Storage View of the Application panel\n */\n storageQuotaIsLimitedIn: 'Storage quota is limited in Incognito mode',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n fileSystem: 'File System',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n other: 'Other',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n storageUsage: 'Storage usage',\n /**\n * @description Text in Application Panel Sidebar of the Application panel\n */\n serviceWorkers: 'Service workers',\n /**\n * @description Checkbox label in Application Panel Sidebar of the Application panel.\n * Storage quota refers to the amount of disk available for the website or app.\n */\n simulateCustomStorage: 'Simulate custom storage quota',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/application/StorageView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * @implements {SDK.TargetManager.Observer}\n */\nexport class StorageView extends UI.ThrottledWidget.ThrottledWidget {\n private pieColors: Map;\n private reportView: UI.ReportView.ReportView;\n private target: SDK.Target.Target|null;\n private securityOrigin: string|null;\n private storageKey: string|null;\n private settings: Map>;\n private includeThirdPartyCookiesSetting: Common.Settings.Setting;\n private quotaRow: HTMLElement;\n private quotaUsage: number|null;\n private pieChart: PerfUI.PieChart.PieChart;\n private previousOverrideFieldValue: string;\n private quotaOverrideCheckbox: UI.UIUtils.CheckboxLabel;\n private quotaOverrideControlRow: HTMLElement;\n private quotaOverrideEditor: HTMLInputElement;\n private quotaOverrideErrorMessage: HTMLElement;\n private clearButton: Buttons.Button.Button;\n\n constructor() {\n super(true, 1000);\n\n this.contentElement.classList.add('clear-storage-container');\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('clear-storage')}`);\n this.pieColors = new Map([\n [Protocol.Storage.StorageType.Appcache, 'rgb(110, 161, 226)'], // blue\n [Protocol.Storage.StorageType.Cache_storage, 'rgb(229, 113, 113)'], // red\n [Protocol.Storage.StorageType.Cookies, 'rgb(239, 196, 87)'], // yellow\n [Protocol.Storage.StorageType.Indexeddb, 'rgb(155, 127, 230)'], // purple\n [Protocol.Storage.StorageType.Local_storage, 'rgb(116, 178, 102)'], // green\n [Protocol.Storage.StorageType.Service_workers, 'rgb(255, 167, 36)'], // orange\n [Protocol.Storage.StorageType.Websql, 'rgb(203, 220, 56)'], // lime\n ]);\n\n // TODO(crbug.com/1156978): Replace UI.ReportView.ReportView with ReportView.ts web component.\n this.reportView = new UI.ReportView.ReportView(i18nString(UIStrings.storageTitle));\n\n this.reportView.element.classList.add('clear-storage-header');\n this.reportView.show(this.contentElement);\n this.target = null;\n this.securityOrigin = null;\n this.storageKey = null;\n\n this.settings = new Map();\n for (const type of AllStorageTypes) {\n this.settings.set(\n type,\n Common.Settings.Settings.instance().createSetting(\n 'clear-storage-' + Platform.StringUtilities.toKebabCase(type), true));\n }\n\n this.includeThirdPartyCookiesSetting =\n Common.Settings.Settings.instance().createSetting('clear-storage-include-third-party-cookies', false);\n\n const quota = this.reportView.appendSection(i18nString(UIStrings.usage));\n quota.element.setAttribute('jslog', `${VisualLogging.section('usage')}`);\n this.quotaRow = quota.appendSelectableRow();\n this.quotaRow.classList.add('quota-usage-row');\n const learnMoreRow = quota.appendRow();\n const learnMore = UI.XLink.XLink.create(\n 'https://developer.chrome.com/docs/devtools/progressive-web-apps#opaque-responses',\n i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more');\n learnMoreRow.appendChild(learnMore);\n this.quotaUsage = null;\n this.pieChart = new PerfUI.PieChart.PieChart();\n this.populatePieChart(0, []);\n const usageBreakdownRow = quota.appendRow();\n usageBreakdownRow.classList.add('usage-breakdown-row');\n usageBreakdownRow.appendChild(this.pieChart);\n\n this.previousOverrideFieldValue = '';\n const quotaOverrideCheckboxRow = quota.appendRow();\n quotaOverrideCheckboxRow.classList.add('quota-override-row');\n this.quotaOverrideCheckbox =\n UI.UIUtils.CheckboxLabel.create(i18nString(UIStrings.simulateCustomStorage), false, '');\n this.quotaOverrideCheckbox.setAttribute(\n 'jslog', `${VisualLogging.toggle('simulate-custom-quota').track({change: true})}`);\n quotaOverrideCheckboxRow.appendChild(this.quotaOverrideCheckbox);\n this.quotaOverrideCheckbox.checkboxElement.addEventListener('click', this.onClickCheckbox.bind(this), false);\n this.quotaOverrideControlRow = quota.appendRow();\n this.quotaOverrideEditor =\n this.quotaOverrideControlRow.createChild('input', 'quota-override-notification-editor') as HTMLInputElement;\n this.quotaOverrideEditor.setAttribute(\n 'jslog', `${VisualLogging.textField('quota-override').track({change: true})}`);\n this.quotaOverrideControlRow.appendChild(UI.UIUtils.createLabel(i18nString(UIStrings.mb)));\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideEditor.addEventListener('keyup', event => {\n if (event.key === 'Enter') {\n void this.applyQuotaOverrideFromInputField();\n event.consume(true);\n }\n });\n this.quotaOverrideEditor.addEventListener('focusout', event => {\n void this.applyQuotaOverrideFromInputField();\n event.consume(true);\n });\n\n const errorMessageRow = quota.appendRow();\n this.quotaOverrideErrorMessage = errorMessageRow.createChild('div', 'quota-override-error');\n\n const clearButtonSection = this.reportView.appendSection('', 'clear-storage-button').appendRow();\n this.clearButton = UI.UIUtils.createTextButton(\n i18nString(UIStrings.clearSiteData), this.clear.bind(this), {jslogContext: 'storage.clear-site-data'});\n this.clearButton.id = 'storage-view-clear-button';\n clearButtonSection.appendChild(this.clearButton);\n\n const includeThirdPartyCookiesCheckbox = UI.SettingsUI.createSettingCheckbox(\n i18nString(UIStrings.includingThirdPartyCookies), this.includeThirdPartyCookiesSetting, true);\n includeThirdPartyCookiesCheckbox.classList.add('include-third-party-cookies');\n clearButtonSection.appendChild(includeThirdPartyCookiesCheckbox);\n\n const application = this.reportView.appendSection(i18nString(UIStrings.application));\n application.element.setAttribute('jslog', `${VisualLogging.section('application')}`);\n this.appendItem(\n application, i18nString(UIStrings.unregisterServiceWorker), Protocol.Storage.StorageType.Service_workers);\n application.markFieldListAsGroup();\n\n const storage = this.reportView.appendSection(i18nString(UIStrings.storageTitle));\n storage.element.setAttribute('jslog', `${VisualLogging.section('storage')}`);\n this.appendItem(storage, i18nString(UIStrings.localAndSessionStorage), Protocol.Storage.StorageType.Local_storage);\n this.appendItem(storage, i18nString(UIStrings.indexDB), Protocol.Storage.StorageType.Indexeddb);\n this.appendItem(storage, i18nString(UIStrings.webSql), Protocol.Storage.StorageType.Websql);\n this.appendItem(storage, i18nString(UIStrings.cookies), Protocol.Storage.StorageType.Cookies);\n this.appendItem(storage, i18nString(UIStrings.cacheStorage), Protocol.Storage.StorageType.Cache_storage);\n storage.markFieldListAsGroup();\n\n SDK.TargetManager.TargetManager.instance().observeTargets(this);\n }\n\n private appendItem(section: UI.ReportView.Section, title: string, settingName: Protocol.Storage.StorageType): void {\n const row = section.appendRow();\n const setting = this.settings.get(settingName);\n if (setting) {\n row.appendChild(UI.SettingsUI.createSettingCheckbox(title, setting, true));\n }\n }\n\n targetAdded(target: SDK.Target.Target): void {\n if (target !== SDK.TargetManager.TargetManager.instance().primaryPageTarget()) {\n return;\n }\n this.target = target;\n const securityOriginManager = target.model(SDK.SecurityOriginManager.SecurityOriginManager) as\n SDK.SecurityOriginManager.SecurityOriginManager;\n this.updateOrigin(\n securityOriginManager.mainSecurityOrigin(), securityOriginManager.unreachableMainSecurityOrigin());\n securityOriginManager.addEventListener(\n SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this.originChanged, this);\n const storageKeyManager =\n target.model(SDK.StorageKeyManager.StorageKeyManager) as SDK.StorageKeyManager.StorageKeyManager;\n this.updateStorageKey(storageKeyManager.mainStorageKey());\n storageKeyManager.addEventListener(\n SDK.StorageKeyManager.Events.MAIN_STORAGE_KEY_CHANGED, this.storageKeyChanged, this);\n }\n\n targetRemoved(target: SDK.Target.Target): void {\n if (this.target !== target) {\n return;\n }\n const securityOriginManager = target.model(SDK.SecurityOriginManager.SecurityOriginManager) as\n SDK.SecurityOriginManager.SecurityOriginManager;\n securityOriginManager.removeEventListener(\n SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this.originChanged, this);\n const storageKeyManager =\n target.model(SDK.StorageKeyManager.StorageKeyManager) as SDK.StorageKeyManager.StorageKeyManager;\n storageKeyManager.removeEventListener(\n SDK.StorageKeyManager.Events.MAIN_STORAGE_KEY_CHANGED, this.storageKeyChanged, this);\n }\n\n private originChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const {mainSecurityOrigin, unreachableMainSecurityOrigin} = event.data;\n this.updateOrigin(mainSecurityOrigin, unreachableMainSecurityOrigin);\n }\n\n private storageKeyChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const {mainStorageKey} = event.data;\n this.updateStorageKey(mainStorageKey);\n }\n\n private updateOrigin(mainOrigin: string, unreachableMainOrigin: string|null): void {\n const oldOrigin = this.securityOrigin;\n if (unreachableMainOrigin) {\n this.securityOrigin = unreachableMainOrigin;\n this.reportView.setSubtitle(i18nString(UIStrings.sFailedToLoad, {PH1: unreachableMainOrigin}));\n } else {\n this.securityOrigin = mainOrigin;\n this.reportView.setSubtitle(mainOrigin);\n }\n\n if (oldOrigin !== this.securityOrigin) {\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = false;\n this.quotaOverrideErrorMessage.textContent = '';\n }\n void this.doUpdate();\n }\n\n private updateStorageKey(mainStorageKey: string): void {\n const oldStorageKey = this.storageKey;\n\n this.storageKey = mainStorageKey;\n this.reportView.setSubtitle(mainStorageKey);\n\n if (oldStorageKey !== this.storageKey) {\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = false;\n this.quotaOverrideErrorMessage.textContent = '';\n }\n void this.doUpdate();\n }\n\n private async applyQuotaOverrideFromInputField(): Promise {\n if (!this.target || !this.securityOrigin) {\n this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.internalError);\n return;\n }\n this.quotaOverrideErrorMessage.textContent = '';\n const editorString = this.quotaOverrideEditor.value;\n if (editorString === '') {\n await this.clearQuotaForOrigin(this.target, this.securityOrigin);\n this.previousOverrideFieldValue = '';\n return;\n }\n const quota = parseFloat(editorString);\n if (!Number.isFinite(quota)) {\n this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.pleaseEnterANumber);\n return;\n }\n if (quota < 0) {\n this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.numberMustBeNonNegative);\n return;\n }\n const cutoff = 9_000_000_000_000;\n if (quota >= cutoff) {\n this.quotaOverrideErrorMessage.textContent =\n i18nString(UIStrings.numberMustBeSmaller, {PH1: cutoff.toLocaleString()});\n return;\n }\n const bytesPerMB = 1000 * 1000;\n const quotaInBytes = Math.round(quota * bytesPerMB);\n const quotaFieldValue = `${quotaInBytes / bytesPerMB}`;\n this.quotaOverrideEditor.value = quotaFieldValue;\n this.previousOverrideFieldValue = quotaFieldValue;\n await this.target.storageAgent().invoke_overrideQuotaForOrigin(\n {origin: this.securityOrigin, quotaSize: quotaInBytes});\n }\n\n private async clearQuotaForOrigin(target: SDK.Target.Target, origin: string): Promise {\n await target.storageAgent().invoke_overrideQuotaForOrigin({origin});\n }\n\n private async onClickCheckbox(): Promise {\n if (this.quotaOverrideControlRow.classList.contains('hidden')) {\n this.quotaOverrideControlRow.classList.remove('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = true;\n this.quotaOverrideEditor.value = this.previousOverrideFieldValue;\n this.quotaOverrideEditor.focus();\n } else if (this.target && this.securityOrigin) {\n this.quotaOverrideControlRow.classList.add('hidden');\n this.quotaOverrideCheckbox.checkboxElement.checked = false;\n await this.clearQuotaForOrigin(this.target, this.securityOrigin);\n this.quotaOverrideErrorMessage.textContent = '';\n }\n }\n\n private clear(): void {\n if (!this.securityOrigin) {\n return;\n }\n const selectedStorageTypes = [];\n for (const type of this.settings.keys()) {\n const setting = this.settings.get(type);\n if (setting && setting.get()) {\n selectedStorageTypes.push(type);\n }\n }\n\n if (this.target) {\n const includeThirdPartyCookies = this.includeThirdPartyCookiesSetting.get();\n StorageView.clear(\n this.target, this.storageKey, this.securityOrigin, selectedStorageTypes, includeThirdPartyCookies);\n }\n\n this.clearButton.disabled = true;\n const label = this.clearButton.textContent;\n this.clearButton.textContent = i18nString(UIStrings.clearing);\n window.setTimeout(() => {\n this.clearButton.disabled = false;\n this.clearButton.textContent = label;\n this.clearButton.focus();\n }, 500);\n\n UI.ARIAUtils.alert(i18nString(UIStrings.SiteDataCleared));\n }\n\n static clear(\n target: SDK.Target.Target, storageKey: string|null, originForCookies: string|null, selectedStorageTypes: string[],\n includeThirdPartyCookies: boolean): void {\n console.assert(Boolean(storageKey));\n if (!storageKey) {\n return;\n }\n void target.storageAgent().invoke_clearDataForStorageKey(\n {storageKey, storageTypes: selectedStorageTypes.join(',')});\n\n const set = new Set(selectedStorageTypes);\n const hasAll = set.has(Protocol.Storage.StorageType.All);\n\n if (set.has(Protocol.Storage.StorageType.Local_storage) || hasAll) {\n const storageModel = target.model(DOMStorageModel);\n if (storageModel) {\n storageModel.clearForStorageKey(storageKey);\n }\n }\n\n if (set.has(Protocol.Storage.StorageType.Indexeddb) || hasAll) {\n for (const target of SDK.TargetManager.TargetManager.instance().targets()) {\n const indexedDBModel = target.model(IndexedDBModel);\n if (indexedDBModel) {\n indexedDBModel.clearForStorageKey(storageKey);\n }\n }\n }\n\n if (originForCookies && (set.has(Protocol.Storage.StorageType.Cookies) || hasAll)) {\n void target.storageAgent().invoke_clearDataForOrigin(\n {origin: originForCookies, storageTypes: Protocol.Storage.StorageType.Cookies});\n const cookieModel = target.model(SDK.CookieModel.CookieModel);\n if (cookieModel) {\n void cookieModel.clear(undefined, includeThirdPartyCookies ? undefined : originForCookies);\n }\n }\n\n if (set.has(Protocol.Storage.StorageType.Cache_storage) || hasAll) {\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const model = target && target.model(SDK.ServiceWorkerCacheModel.ServiceWorkerCacheModel);\n if (model) {\n model.clearForStorageKey(storageKey);\n }\n }\n }\n\n override async doUpdate(): Promise {\n if (!this.securityOrigin || !this.target) {\n this.quotaRow.textContent = '';\n this.populatePieChart(0, []);\n return;\n }\n\n const securityOrigin = this.securityOrigin;\n const response = await this.target.storageAgent().invoke_getUsageAndQuota({origin: securityOrigin});\n this.quotaRow.textContent = '';\n if (response.getError()) {\n this.populatePieChart(0, []);\n return;\n }\n const quotaOverridden = response.overrideActive;\n const quotaAsString = i18n.ByteUtilities.bytesToString(response.quota);\n const usageAsString = i18n.ByteUtilities.bytesToString(response.usage);\n const formattedQuotaAsString = i18nString(UIStrings.storageWithCustomMarker, {PH1: quotaAsString});\n const quota =\n quotaOverridden ? UI.Fragment.Fragment.build`${formattedQuotaAsString}`.element() : quotaAsString;\n const element =\n i18n.i18n.getFormatLocalizedString(str_, UIStrings.storageQuotaUsed, {PH1: usageAsString, PH2: quota});\n this.quotaRow.appendChild(element);\n UI.Tooltip.Tooltip.install(\n this.quotaRow,\n i18nString(\n UIStrings.storageQuotaUsedWithBytes,\n {PH1: response.usage.toLocaleString(), PH2: response.quota.toLocaleString()}));\n\n if (!response.overrideActive && response.quota < 125829120) { // 120 MB\n const icon = new IconButton.Icon.Icon();\n icon.data = {iconName: 'info', color: 'var(--icon-info)', width: '14px', height: '14px'};\n UI.Tooltip.Tooltip.install(this.quotaRow, i18nString(UIStrings.storageQuotaIsLimitedIn));\n this.quotaRow.appendChild(icon);\n }\n\n if (this.quotaUsage === null || this.quotaUsage !== response.usage) {\n this.quotaUsage = response.usage;\n const slices: PerfUI.PieChart.Slice[] = [];\n for (const usageForType of response.usageBreakdown.sort((a, b) => b.usage - a.usage)) {\n const value = usageForType.usage;\n if (!value) {\n continue;\n }\n const title = this.getStorageTypeName(usageForType.storageType);\n const color = this.pieColors.get(usageForType.storageType) || '#ccc';\n slices.push({value, color, title});\n }\n this.populatePieChart(response.usage, slices);\n }\n\n this.update();\n }\n\n private populatePieChart(total: number, slices: PerfUI.PieChart.Slice[]): void {\n this.pieChart.data = {\n chartName: i18nString(UIStrings.storageUsage),\n size: 110,\n formatter: i18n.ByteUtilities.bytesToString,\n showLegend: true,\n total,\n slices,\n };\n }\n\n private getStorageTypeName(type: Protocol.Storage.StorageType): string {\n switch (type) {\n case Protocol.Storage.StorageType.File_systems:\n return i18nString(UIStrings.fileSystem);\n case Protocol.Storage.StorageType.Websql:\n return i18nString(UIStrings.webSql);\n case Protocol.Storage.StorageType.Appcache:\n return i18nString(UIStrings.application);\n case Protocol.Storage.StorageType.Indexeddb:\n return i18nString(UIStrings.indexDB);\n case Protocol.Storage.StorageType.Cache_storage:\n return i18nString(UIStrings.cacheStorage);\n case Protocol.Storage.StorageType.Service_workers:\n return i18nString(UIStrings.serviceWorkers);\n default:\n return i18nString(UIStrings.other);\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.reportView.registerCSSFiles([storageViewStyles]);\n this.registerCSSFiles([storageViewStyles]);\n }\n}\n\nexport const AllStorageTypes = [\n Protocol.Storage.StorageType.Appcache,\n Protocol.Storage.StorageType.Cache_storage,\n Protocol.Storage.StorageType.Cookies,\n Protocol.Storage.StorageType.Indexeddb,\n Protocol.Storage.StorageType.Local_storage,\n Protocol.Storage.StorageType.Service_workers,\n Protocol.Storage.StorageType.Websql,\n];\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(_context: UI.Context.Context, actionId: string): boolean {\n switch (actionId) {\n case 'resources.clear':\n return this.handleClear(false);\n case 'resources.clear-incl-third-party-cookies':\n return this.handleClear(true);\n }\n return false;\n }\n\n private handleClear(includeThirdPartyCookies: boolean): boolean {\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!target) {\n return false;\n }\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceTreeModel) {\n return false;\n }\n const securityOrigin = resourceTreeModel.getMainSecurityOrigin();\n resourceTreeModel.getMainStorageKey().then(storageKey => {\n StorageView.clear(target, storageKey, securityOrigin, AllStorageTypes, includeThirdPartyCookies);\n }, _ => {});\n return true;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/application/components/StorageMetadataView.js b/public/panels/application/components/StorageMetadataView.js index 7eb24f38..77051d5b 100644 --- a/public/panels/application/components/StorageMetadataView.js +++ b/public/panels/application/components/StorageMetadataView.js @@ -3,7 +3,6 @@ // found in the LICENSE file. import '../../../ui/components/report_view/report_view.js'; 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 Buttons from '../../../ui/components/buttons/buttons.js'; import * as LegacyWrapper from '../../../ui/components/legacy_wrapper/legacy_wrapper.js'; @@ -196,7 +195,7 @@ export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableCo ${this.key(i18nString(UIStrings.durability))} ${this.value(durability)} ${this.key(i18nString(UIStrings.quota))} - ${this.value(Platform.NumberUtilities.bytesToString(quota))} + ${this.value(i18n.ByteUtilities.bytesToString(quota))} ${this.key(i18nString(UIStrings.expiration))} ${this.value(this.#getExpirationString())}`; } diff --git a/public/panels/application/components/StorageMetadataView.js.map b/public/panels/application/components/StorageMetadataView.js.map index c45a851e..a88be14d 100644 --- a/public/panels/application/components/StorageMetadataView.js.map +++ b/public/panels/application/components/StorageMetadataView.js.map @@ -1 +1 @@ -{"version":3,"file":"StorageMetadataView.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/application/components/StorageMetadataView.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 '../../../ui/components/report_view/report_view.js';\n\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 type * as Protocol from '../../../generated/protocol.js';\nimport * as Buttons from '../../../ui/components/buttons/buttons.js';\nimport * as LegacyWrapper from '../../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as Coordinator from '../../../ui/components/render_coordinator/render_coordinator.js';\nimport * as UI from '../../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\n\nconst {html} = LitHtml;\n\nconst UIStrings = {\n /**\n *@description The origin of a URL (https://web.dev/same-site-same-origin/#origin).\n *(for a lot of languages this does not need to be translated, please translate only where necessary)\n */\n origin: 'Origin',\n /**\n *@description Site (https://web.dev/same-site-same-origin/#site) for the URL the user sees in the omnibox.\n */\n topLevelSite: 'Top-level site',\n /**\n *@description Text to show in the top-level site row, in case the value is opaque (https://html.spec.whatwg.org/#concept-origin-opaque).\n */\n opaque: '(opaque)',\n /**\n *@description Whether the storage corresponds to an opaque key (similar to https://html.spec.whatwg.org/#concept-origin-opaque).\n */\n isOpaque: 'Is opaque',\n /**\n *@description Whether the storage corresponds to a third-party origin (https://web.dev/learn/privacy/third-parties/).\n */\n isThirdParty: 'Is third-party',\n /**\n *@description Text indicating that the condition holds.\n */\n yes: 'Yes',\n /**\n *@description Text indicating that the condition does not hold.\n */\n no: 'No',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because top-level site is opaque.\n */\n yesBecauseTopLevelIsOpaque: 'Yes, because the top-level site is opaque',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because the storage key is opaque.\n */\n yesBecauseKeyIsOpaque: 'Yes, because the storage key is opaque',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because the origin doesn't match the top-level site.\n */\n yesBecauseOriginNotInTopLevelSite: 'Yes, because the origin is outside of the top-level site',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because the was a third-party origin in the ancestry chain.\n */\n yesBecauseAncestorChainHasCrossSite: 'Yes, because the ancestry chain contains a third-party origin',\n /**\n *@description Text when something is loading.\n */\n loading: 'Loading…',\n /**\n *@description The storage bucket name (https://wicg.github.io/storage-buckets/explainer#bucket-names)\n */\n bucketName: 'Bucket name',\n /**\n *@description The name of the default bucket (https://wicg.github.io/storage-buckets/explainer#the-default-bucket)\n *(This should not be a valid bucket name (https://wicg.github.io/storage-buckets/explainer#bucket-names))\n */\n defaultBucket: 'Default bucket',\n /**\n *@description Text indicating that the storage is persistent (https://wicg.github.io/storage-buckets/explainer#storage-policy-persistence)\n */\n persistent: 'Is persistent',\n /**\n *@description The storage durability policy (https://wicg.github.io/storage-buckets/explainer#storage-policy-durability)\n */\n durability: 'Durability',\n /**\n *@description The storage quota (https://wicg.github.io/storage-buckets/explainer#storage-policy-quota)\n */\n quota: 'Quota',\n /**\n *@description The storage expiration (https://wicg.github.io/storage-buckets/explainer#storage-policy-expiration)\n */\n expiration: 'Expiration',\n /**\n *@description Text indicating that no value is set\n */\n none: 'None',\n /**\n * @description Label of the button that triggers the Storage Bucket to be deleted.\n */\n deleteBucket: 'Delete bucket',\n /**\n *@description Text shown in the confirmation dialogue that displays before deleting the bucket.\n *@example {bucket} PH1\n */\n confirmBucketDeletion: 'Delete the \"{PH1}\" bucket?',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/application/components/StorageMetadataView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nexport class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableComponent {\n readonly #shadow = this.attachShadow({mode: 'open'});\n #storageBucketsModel?: SDK.StorageBucketsModel.StorageBucketsModel;\n #storageKey: SDK.StorageKeyManager.StorageKey|null = null;\n #storageBucket: Protocol.Storage.StorageBucketInfo|null = null;\n\n getShadow(): ShadowRoot {\n return this.#shadow;\n }\n\n setStorageKey(storageKey: string): void {\n this.#storageKey = SDK.StorageKeyManager.parseStorageKey(storageKey);\n void this.render();\n }\n\n setStorageBucket(storageBucket: Protocol.Storage.StorageBucketInfo): void {\n this.#storageBucket = storageBucket;\n this.setStorageKey(storageBucket.bucket.storageKey);\n }\n\n enableStorageBucketControls(model: SDK.StorageBucketsModel.StorageBucketsModel): void {\n this.#storageBucketsModel = model;\n if (this.#storageKey) {\n void this.render();\n }\n }\n\n override render(): Promise {\n return coordinator.write('StorageMetadataView render', async () => {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n LitHtml.render(html`\n \n ${await this.renderReportContent()}\n `, this.#shadow, {host: this});\n // clang-format on\n });\n }\n\n getTitle(): string|undefined {\n if (!this.#storageKey) {\n return;\n }\n const origin = this.#storageKey.origin;\n const bucketName = this.#storageBucket?.bucket.name || i18nString(UIStrings.defaultBucket);\n return this.#storageBucketsModel ? `${bucketName} - ${origin}` : origin;\n }\n\n key(content: string|LitHtml.TemplateResult): LitHtml.TemplateResult {\n return html`${content}`;\n }\n\n value(content: string|LitHtml.TemplateResult): LitHtml.TemplateResult {\n return html`${content}`;\n }\n\n async renderReportContent(): Promise {\n if (!this.#storageKey) {\n return LitHtml.nothing;\n }\n const origin = this.#storageKey.origin;\n const ancestorChainHasCrossSite =\n Boolean(this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.ANCESTOR_CHAIN_BIT));\n const hasNonce = Boolean(this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.NONCE_HIGH));\n const topLevelSiteIsOpaque = Boolean(\n this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.TOP_LEVEL_SITE_OPAQUE_NONCE_HIGH));\n const topLevelSite = this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.TOP_LEVEL_SITE);\n const thirdPartyReason = ancestorChainHasCrossSite ? i18nString(UIStrings.yesBecauseAncestorChainHasCrossSite) :\n hasNonce ? i18nString(UIStrings.yesBecauseKeyIsOpaque) :\n topLevelSiteIsOpaque ? i18nString(UIStrings.yesBecauseTopLevelIsOpaque) :\n (topLevelSite && origin !== topLevelSite) ? i18nString(UIStrings.yesBecauseOriginNotInTopLevelSite) :\n null;\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return html`\n ${this.key(i18nString(UIStrings.origin))}\n ${this.value(html`
${origin}
`)}\n ${(topLevelSite || topLevelSiteIsOpaque) ? this.key(i18nString(UIStrings.topLevelSite)) : LitHtml.nothing}\n ${topLevelSite ? this.value(topLevelSite) : LitHtml.nothing}\n ${topLevelSiteIsOpaque ? this.value(i18nString(UIStrings.opaque)) : LitHtml.nothing}\n ${thirdPartyReason ? html`${this.key(i18nString(UIStrings.isThirdParty))}${this.value(thirdPartyReason)}` : LitHtml.nothing}\n ${hasNonce || topLevelSiteIsOpaque ?\n this.key(i18nString(UIStrings.isOpaque)) : LitHtml.nothing}\n ${hasNonce ? this.value(i18nString(UIStrings.yes)) : LitHtml.nothing}\n ${topLevelSiteIsOpaque ?\n this.value(i18nString(UIStrings.yesBecauseTopLevelIsOpaque)) : LitHtml.nothing}\n ${this.#storageBucket ? this.#renderStorageBucketInfo() : LitHtml.nothing}\n ${this.#storageBucketsModel ? this.#renderBucketControls() : LitHtml.nothing}`;\n // clang-format on\n }\n\n #renderStorageBucketInfo(): LitHtml.LitTemplate {\n if (!this.#storageBucket) {\n throw new Error('Should not call #renderStorageBucketInfo if #bucket is null.');\n }\n const {bucket: {name}, persistent, durability, quota} = this.#storageBucket;\n\n // clang-format off\n return html`\n ${this.key(i18nString(UIStrings.bucketName))}\n ${this.value(name || 'default')}\n ${this.key(i18nString(UIStrings.persistent))}\n ${this.value(persistent ? i18nString(UIStrings.yes) : i18nString(UIStrings.no))}\n ${this.key(i18nString(UIStrings.durability))}\n ${this.value(durability)}\n ${this.key(i18nString(UIStrings.quota))}\n ${this.value(Platform.NumberUtilities.bytesToString(quota))}\n ${this.key(i18nString(UIStrings.expiration))}\n ${this.value(this.#getExpirationString())}`;\n }\n\n #getExpirationString(): string {\n if (!this.#storageBucket) {\n throw new Error('Should not call #getExpirationString if #bucket is null.');\n }\n\n const {expiration} = this.#storageBucket;\n\n if (expiration === 0) {\n return i18nString(UIStrings.none);\n }\n\n return (new Date(expiration * 1000)).toLocaleString();\n }\n\n #renderBucketControls(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n \n \n ${i18nString(UIStrings.deleteBucket)}\n \n `;\n // clang-format on\n }\n\n async #deleteBucket(): Promise {\n if (!this.#storageBucketsModel || !this.#storageBucket) {\n throw new Error('Should not call #deleteBucket if #storageBucketsModel or #storageBucket is null.');\n }\n const ok = await UI.UIUtils.ConfirmDialog.show(\n i18nString(UIStrings.confirmBucketDeletion, {PH1: this.#storageBucket.bucket.name || ''}), this,\n {jslogContext: 'delete-bucket-confirmation'});\n if (ok) {\n this.#storageBucketsModel.deleteBucket(this.#storageBucket.bucket);\n }\n }\n}\n\ncustomElements.define('devtools-storage-metadata-view', StorageMetadataView);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-storage-metadata-view': StorageMetadataView;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"StorageMetadataView.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/application/components/StorageMetadataView.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,mDAAmD,CAAC;AAE3D,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAEhD,OAAO,KAAK,OAAO,MAAM,2CAA2C,CAAC;AACrE,OAAO,KAAK,aAAa,MAAM,yDAAyD,CAAC;AACzF,OAAO,KAAK,WAAW,MAAM,iEAAiE,CAAC;AAC/F,OAAO,KAAK,EAAE,MAAM,8BAA8B,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,kCAAkC,CAAC;AAE5D,MAAM,EAAC,IAAI,EAAC,GAAG,OAAO,CAAC;AAEvB,MAAM,SAAS,GAAG;IAChB;;;OAGG;IACH,MAAM,EAAE,QAAQ;IAChB;;OAEG;IACH,YAAY,EAAE,gBAAgB;IAC9B;;OAEG;IACH,MAAM,EAAE,UAAU;IAClB;;OAEG;IACH,QAAQ,EAAE,WAAW;IACrB;;OAEG;IACH,YAAY,EAAE,gBAAgB;IAC9B;;OAEG;IACH,GAAG,EAAE,KAAK;IACV;;OAEG;IACH,EAAE,EAAE,IAAI;IACR;;OAEG;IACH,0BAA0B,EAAE,2CAA2C;IACvE;;OAEG;IACH,qBAAqB,EAAE,wCAAwC;IAC/D;;OAEG;IACH,iCAAiC,EAAE,0DAA0D;IAC7F;;OAEG;IACH,mCAAmC,EAAE,+DAA+D;IACpG;;OAEG;IACH,OAAO,EAAE,UAAU;IACnB;;OAEG;IACH,UAAU,EAAE,aAAa;IACzB;;;OAGG;IACH,aAAa,EAAE,gBAAgB;IAC/B;;OAEG;IACH,UAAU,EAAE,eAAe;IAC3B;;OAEG;IACH,UAAU,EAAE,YAAY;IACxB;;OAEG;IACH,KAAK,EAAE,OAAO;IACd;;OAEG;IACH,UAAU,EAAE,YAAY;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM;IACZ;;OAEG;IACH,YAAY,EAAE,eAAe;IAC7B;;;OAGG;IACH,qBAAqB,EAAE,4BAA4B;CACpD,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,sDAAsD,EAAE,SAAS,CAAC,CAAC;AAC5G,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACtE,MAAM,WAAW,GAAG,WAAW,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;AAE/E,MAAM,OAAO,mBAAoB,SAAQ,aAAa,CAAC,aAAa,CAAC,kBAAkB;IAC5E,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;IACrD,oBAAoB,CAA+C;IACnE,WAAW,GAA0C,IAAI,CAAC;IAC1D,cAAc,GAA4C,IAAI,CAAC;IAE/D,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,aAAa,CAAC,UAAkB;QAC9B,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,iBAAiB,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACrE,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAED,gBAAgB,CAAC,aAAiD;QAChE,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACtD,CAAC;IAED,2BAA2B,CAAC,KAAkD;QAC5E,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAClC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAEQ,MAAM;QACb,OAAO,WAAW,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAChE,qDAAqD;YACrD,mBAAmB;YACnB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAA;iCACQ,EAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,EAAC;YACpF,MAAM,IAAI,CAAC,mBAAmB,EAAE;2BACjB,EAAE,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;YACnD,kBAAkB;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,IAAI,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,UAAU,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1E,CAAC;IAED,GAAG,CAAC,OAAsC;QACxC,OAAO,IAAI,CAAA,wBAAwB,OAAO,wBAAwB,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,OAAsC;QAC1C,OAAO,IAAI,CAAA,0BAA0B,OAAO,0BAA0B,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,OAAO,CAAC,OAAO,CAAC;QACzB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACvC,MAAM,yBAAyB,GAC3B,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,wEAA8D,CAAC,CAAC;QAC3G,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,gEAAsD,CAAC,CAAC;QAChH,MAAM,oBAAoB,GAAG,OAAO,CAChC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,sFAA4E,CAAC,CAAC;QACjH,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,oEAA0D,CAAC;QAC/G,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC,CAAC;YAC5G,QAAQ,CAAuC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAAC;gBAC9F,oBAAoB,CAA2B,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC,CAAC;oBACnG,CAAC,YAAY,IAAI,MAAM,KAAK,YAAY,CAAC,CAAM,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC,CAAC;wBACzD,IAAI,CAAC;QAC1D,qDAAqD;QACrD,mBAAmB;QACnB,OAAO,IAAI,CAAA;UACL,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;UACtC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA,oCAAoC,MAAM,IAAI,MAAM,QAAQ,CAAC;UAC5E,CAAC,YAAY,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UACvG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UACzD,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UACjF,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UACzH,QAAQ,IAAI,oBAAoB,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UACxD,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UAClE,oBAAoB,CAAC,CAAC;YACxB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UAC5E,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;UACvE,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACnF,kBAAkB;IACpB,CAAC;IAED,wBAAwB;QACtB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,EAAC,MAAM,EAAE,EAAC,IAAI,EAAC,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAC,GAAG,IAAI,CAAC,cAAc,CAAC;QAE5E,mBAAmB;QACnB,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC7E,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,oBAAoB;QAClB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,EAAC,UAAU,EAAC,GAAG,IAAI,CAAC,cAAc,CAAC;QAEzC,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,CAAC,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;IACxD,CAAC;IAED,qBAAqB;QACnB,mBAAmB;QACnB,OAAO,IAAI,CAAA;;;uBAGQ,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;qBACpC,8CAA8B;mBAChC,IAAI,CAAC,aAAa;YACzB,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;;iCAEb,CAAC;QAC9B,kBAAkB;IACpB,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;QACtG,CAAC;QACD,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAC1C,UAAU,CAAC,SAAS,CAAC,qBAAqB,EAAE,EAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,EAAC,CAAC,EAAE,IAAI,EAC/F,EAAC,YAAY,EAAE,4BAA4B,EAAC,CAAC,CAAC;QAClD,IAAI,EAAE,EAAE,CAAC;YACP,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;CACF;AAED,cAAc,CAAC,MAAM,CAAC,gCAAgC,EAAE,mBAAmB,CAAC,CAAC","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 '../../../ui/components/report_view/report_view.js';\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as Buttons from '../../../ui/components/buttons/buttons.js';\nimport * as LegacyWrapper from '../../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as Coordinator from '../../../ui/components/render_coordinator/render_coordinator.js';\nimport * as UI from '../../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\n\nconst {html} = LitHtml;\n\nconst UIStrings = {\n /**\n *@description The origin of a URL (https://web.dev/same-site-same-origin/#origin).\n *(for a lot of languages this does not need to be translated, please translate only where necessary)\n */\n origin: 'Origin',\n /**\n *@description Site (https://web.dev/same-site-same-origin/#site) for the URL the user sees in the omnibox.\n */\n topLevelSite: 'Top-level site',\n /**\n *@description Text to show in the top-level site row, in case the value is opaque (https://html.spec.whatwg.org/#concept-origin-opaque).\n */\n opaque: '(opaque)',\n /**\n *@description Whether the storage corresponds to an opaque key (similar to https://html.spec.whatwg.org/#concept-origin-opaque).\n */\n isOpaque: 'Is opaque',\n /**\n *@description Whether the storage corresponds to a third-party origin (https://web.dev/learn/privacy/third-parties/).\n */\n isThirdParty: 'Is third-party',\n /**\n *@description Text indicating that the condition holds.\n */\n yes: 'Yes',\n /**\n *@description Text indicating that the condition does not hold.\n */\n no: 'No',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because top-level site is opaque.\n */\n yesBecauseTopLevelIsOpaque: 'Yes, because the top-level site is opaque',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because the storage key is opaque.\n */\n yesBecauseKeyIsOpaque: 'Yes, because the storage key is opaque',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because the origin doesn't match the top-level site.\n */\n yesBecauseOriginNotInTopLevelSite: 'Yes, because the origin is outside of the top-level site',\n /**\n *@description Text indicating that the storage corresponds to a third-party origin because the was a third-party origin in the ancestry chain.\n */\n yesBecauseAncestorChainHasCrossSite: 'Yes, because the ancestry chain contains a third-party origin',\n /**\n *@description Text when something is loading.\n */\n loading: 'Loading…',\n /**\n *@description The storage bucket name (https://wicg.github.io/storage-buckets/explainer#bucket-names)\n */\n bucketName: 'Bucket name',\n /**\n *@description The name of the default bucket (https://wicg.github.io/storage-buckets/explainer#the-default-bucket)\n *(This should not be a valid bucket name (https://wicg.github.io/storage-buckets/explainer#bucket-names))\n */\n defaultBucket: 'Default bucket',\n /**\n *@description Text indicating that the storage is persistent (https://wicg.github.io/storage-buckets/explainer#storage-policy-persistence)\n */\n persistent: 'Is persistent',\n /**\n *@description The storage durability policy (https://wicg.github.io/storage-buckets/explainer#storage-policy-durability)\n */\n durability: 'Durability',\n /**\n *@description The storage quota (https://wicg.github.io/storage-buckets/explainer#storage-policy-quota)\n */\n quota: 'Quota',\n /**\n *@description The storage expiration (https://wicg.github.io/storage-buckets/explainer#storage-policy-expiration)\n */\n expiration: 'Expiration',\n /**\n *@description Text indicating that no value is set\n */\n none: 'None',\n /**\n * @description Label of the button that triggers the Storage Bucket to be deleted.\n */\n deleteBucket: 'Delete bucket',\n /**\n *@description Text shown in the confirmation dialogue that displays before deleting the bucket.\n *@example {bucket} PH1\n */\n confirmBucketDeletion: 'Delete the \"{PH1}\" bucket?',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/application/components/StorageMetadataView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nexport class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableComponent {\n readonly #shadow = this.attachShadow({mode: 'open'});\n #storageBucketsModel?: SDK.StorageBucketsModel.StorageBucketsModel;\n #storageKey: SDK.StorageKeyManager.StorageKey|null = null;\n #storageBucket: Protocol.Storage.StorageBucketInfo|null = null;\n\n getShadow(): ShadowRoot {\n return this.#shadow;\n }\n\n setStorageKey(storageKey: string): void {\n this.#storageKey = SDK.StorageKeyManager.parseStorageKey(storageKey);\n void this.render();\n }\n\n setStorageBucket(storageBucket: Protocol.Storage.StorageBucketInfo): void {\n this.#storageBucket = storageBucket;\n this.setStorageKey(storageBucket.bucket.storageKey);\n }\n\n enableStorageBucketControls(model: SDK.StorageBucketsModel.StorageBucketsModel): void {\n this.#storageBucketsModel = model;\n if (this.#storageKey) {\n void this.render();\n }\n }\n\n override render(): Promise {\n return coordinator.write('StorageMetadataView render', async () => {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n LitHtml.render(html`\n \n ${await this.renderReportContent()}\n `, this.#shadow, {host: this});\n // clang-format on\n });\n }\n\n getTitle(): string|undefined {\n if (!this.#storageKey) {\n return;\n }\n const origin = this.#storageKey.origin;\n const bucketName = this.#storageBucket?.bucket.name || i18nString(UIStrings.defaultBucket);\n return this.#storageBucketsModel ? `${bucketName} - ${origin}` : origin;\n }\n\n key(content: string|LitHtml.TemplateResult): LitHtml.TemplateResult {\n return html`${content}`;\n }\n\n value(content: string|LitHtml.TemplateResult): LitHtml.TemplateResult {\n return html`${content}`;\n }\n\n async renderReportContent(): Promise {\n if (!this.#storageKey) {\n return LitHtml.nothing;\n }\n const origin = this.#storageKey.origin;\n const ancestorChainHasCrossSite =\n Boolean(this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.ANCESTOR_CHAIN_BIT));\n const hasNonce = Boolean(this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.NONCE_HIGH));\n const topLevelSiteIsOpaque = Boolean(\n this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.TOP_LEVEL_SITE_OPAQUE_NONCE_HIGH));\n const topLevelSite = this.#storageKey.components.get(SDK.StorageKeyManager.StorageKeyComponent.TOP_LEVEL_SITE);\n const thirdPartyReason = ancestorChainHasCrossSite ? i18nString(UIStrings.yesBecauseAncestorChainHasCrossSite) :\n hasNonce ? i18nString(UIStrings.yesBecauseKeyIsOpaque) :\n topLevelSiteIsOpaque ? i18nString(UIStrings.yesBecauseTopLevelIsOpaque) :\n (topLevelSite && origin !== topLevelSite) ? i18nString(UIStrings.yesBecauseOriginNotInTopLevelSite) :\n null;\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return html`\n ${this.key(i18nString(UIStrings.origin))}\n ${this.value(html`
${origin}
`)}\n ${(topLevelSite || topLevelSiteIsOpaque) ? this.key(i18nString(UIStrings.topLevelSite)) : LitHtml.nothing}\n ${topLevelSite ? this.value(topLevelSite) : LitHtml.nothing}\n ${topLevelSiteIsOpaque ? this.value(i18nString(UIStrings.opaque)) : LitHtml.nothing}\n ${thirdPartyReason ? html`${this.key(i18nString(UIStrings.isThirdParty))}${this.value(thirdPartyReason)}` : LitHtml.nothing}\n ${hasNonce || topLevelSiteIsOpaque ?\n this.key(i18nString(UIStrings.isOpaque)) : LitHtml.nothing}\n ${hasNonce ? this.value(i18nString(UIStrings.yes)) : LitHtml.nothing}\n ${topLevelSiteIsOpaque ?\n this.value(i18nString(UIStrings.yesBecauseTopLevelIsOpaque)) : LitHtml.nothing}\n ${this.#storageBucket ? this.#renderStorageBucketInfo() : LitHtml.nothing}\n ${this.#storageBucketsModel ? this.#renderBucketControls() : LitHtml.nothing}`;\n // clang-format on\n }\n\n #renderStorageBucketInfo(): LitHtml.LitTemplate {\n if (!this.#storageBucket) {\n throw new Error('Should not call #renderStorageBucketInfo if #bucket is null.');\n }\n const {bucket: {name}, persistent, durability, quota} = this.#storageBucket;\n\n // clang-format off\n return html`\n ${this.key(i18nString(UIStrings.bucketName))}\n ${this.value(name || 'default')}\n ${this.key(i18nString(UIStrings.persistent))}\n ${this.value(persistent ? i18nString(UIStrings.yes) : i18nString(UIStrings.no))}\n ${this.key(i18nString(UIStrings.durability))}\n ${this.value(durability)}\n ${this.key(i18nString(UIStrings.quota))}\n ${this.value(i18n.ByteUtilities.bytesToString(quota))}\n ${this.key(i18nString(UIStrings.expiration))}\n ${this.value(this.#getExpirationString())}`;\n }\n\n #getExpirationString(): string {\n if (!this.#storageBucket) {\n throw new Error('Should not call #getExpirationString if #bucket is null.');\n }\n\n const {expiration} = this.#storageBucket;\n\n if (expiration === 0) {\n return i18nString(UIStrings.none);\n }\n\n return (new Date(expiration * 1000)).toLocaleString();\n }\n\n #renderBucketControls(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n \n \n ${i18nString(UIStrings.deleteBucket)}\n \n `;\n // clang-format on\n }\n\n async #deleteBucket(): Promise {\n if (!this.#storageBucketsModel || !this.#storageBucket) {\n throw new Error('Should not call #deleteBucket if #storageBucketsModel or #storageBucket is null.');\n }\n const ok = await UI.UIUtils.ConfirmDialog.show(\n i18nString(UIStrings.confirmBucketDeletion, {PH1: this.#storageBucket.bucket.name || ''}), this,\n {jslogContext: 'delete-bucket-confirmation'});\n if (ok) {\n this.#storageBucketsModel.deleteBucket(this.#storageBucket.bucket);\n }\n }\n}\n\ncustomElements.define('devtools-storage-metadata-view', StorageMetadataView);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-storage-metadata-view': StorageMetadataView;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js b/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js index 939e4407..9de2510e 100644 --- a/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js +++ b/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js @@ -113,17 +113,17 @@ export class XHRBreakpointsSidebarPane extends UI.Widget.VBox { const inputElement = inputElementContainer.createChild('span', 'breakpoint-condition-input'); UI.ARIAUtils.setLabel(inputElement, i18nString(UIStrings.urlBreakpoint)); this.addListElement(inputElementContainer, this.#list.element.firstChild); - function finishEditing(accept, e, text) { + const commit = (_element, newText) => { this.removeListElement(inputElementContainer); - if (accept) { - SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(text, true); - this.setBreakpoint(text); - } + SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(newText, true); + this.setBreakpoint(newText); this.update(); - } - const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false)); - // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration) - // eslint-disable-next-line @typescript-eslint/no-explicit-any + }; + const cancel = () => { + this.removeListElement(inputElementContainer); + this.update(); + }; + const config = new UI.InplaceEditor.Config(commit, cancel, undefined); UI.InplaceEditor.InplaceEditor.startEditing(inputElement, config); } heightForItem(_item) { @@ -287,31 +287,31 @@ export class XHRBreakpointsSidebarPane extends UI.Widget.VBox { this.#list.element.insertBefore(inputElement, element); element.classList.add('hidden'); } - function finishEditing(accept, e, text) { + const commit = (inputElement, newText, _oldText, element) => { this.removeListElement(inputElement); - if (accept) { - SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(breakKeyword); - this.removeBreakpoint(breakKeyword); - let enabled = true; - if (element) { - const breakpointEntryElement = containerToBreakpointEntry.get(element); - const checkboxElement = breakpointEntryElement ? breakpointEntryToCheckbox.get(breakpointEntryElement) : undefined; - if (checkboxElement) { - enabled = checkboxElement.checked; - } + SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(breakKeyword); + this.removeBreakpoint(breakKeyword); + let enabled = true; + if (element) { + const breakpointEntryElement = containerToBreakpointEntry.get(element); + const checkboxElement = breakpointEntryElement ? breakpointEntryToCheckbox.get(breakpointEntryElement) : undefined; + if (checkboxElement) { + enabled = checkboxElement.checked; } - SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(text, enabled); - this.setBreakpoint(text); - this.#list.selectItem(text); } - else if (element) { + SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(newText, enabled); + this.setBreakpoint(newText); + this.#list.selectItem(newText); + this.focus(); + }; + const cancel = (inputElement, element) => { + this.removeListElement(inputElement); + if (element) { element.classList.remove('hidden'); } this.focus(); - } - const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false)); - // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration) - // eslint-disable-next-line @typescript-eslint/no-explicit-any + }; + const config = new UI.InplaceEditor.Config(commit, cancel, element); UI.InplaceEditor.InplaceEditor.startEditing(inputElement, config); } flavorChanged(_object) { diff --git a/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js.map b/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js.map index 9e2f61d9..7b391c20 100644 --- a/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js.map +++ b/public/panels/browser_debugger/XHRBreakpointsSidebarPane.js.map @@ -1 +1 @@ -{"version":3,"file":"XHRBreakpointsSidebarPane.js","sourceRoot":"","sources":["../../../../../../front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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 i18n from '../../core/i18n/i18n.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport xhrBreakpointsSidebarPaneStyles from './xhrBreakpointsSidebarPane.css.js';\n\nconst UIStrings = {\n /**\n *@description Title of the 'XHR/fetch Breakpoints' tool in the bottom sidebar of the Sources tool\n */\n xhrfetchBreakpoints: 'XHR/fetch Breakpoints',\n /**\n *@description Text to indicate there are no breakpoints\n */\n noBreakpoints: 'No breakpoints',\n /**\n *@description Label for a button in the Sources panel that opens the input field to create a new XHR/fetch breakpoint.\n */\n addXhrfetchBreakpoint: 'Add XHR/fetch breakpoint',\n /**\n *@description Text to add a breakpoint\n */\n addBreakpoint: 'Add breakpoint',\n /**\n *@description Input element container text content in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel\n */\n breakWhenUrlContains: 'Break when URL contains:',\n /**\n *@description Accessible label for XHR/fetch breakpoint text input\n */\n urlBreakpoint: 'URL Breakpoint',\n /**\n *@description Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel\n *@example {example.com} PH1\n */\n urlContainsS: 'URL contains \"{PH1}\"',\n /**\n *@description Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel\n */\n anyXhrOrFetch: 'Any XHR or fetch',\n /**\n *@description Screen reader description of a hit breakpoint in the Sources panel\n */\n breakpointHit: 'breakpoint hit',\n /**\n *@description Text to remove all breakpoints\n */\n removeAllBreakpoints: 'Remove all breakpoints',\n /**\n *@description Text to remove a breakpoint\n */\n removeBreakpoint: 'Remove breakpoint',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/browser_debugger/XHRBreakpointsSidebarPane.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nconst containerToBreakpointEntry = new WeakMap();\n\nconst breakpointEntryToCheckbox = new WeakMap();\n\nlet xhrBreakpointsSidebarPaneInstance: XHRBreakpointsSidebarPane;\n\nexport class XHRBreakpointsSidebarPane extends UI.Widget.VBox implements UI.ContextFlavorListener.ContextFlavorListener,\n UI.Toolbar.ItemsProvider,\n UI.ListControl.ListDelegate {\n readonly #breakpoints: UI.ListModel.ListModel;\n #list: UI.ListControl.ListControl;\n readonly #emptyElement: HTMLElement;\n readonly #breakpointElements: Map;\n readonly #addButton: UI.Toolbar.ToolbarButton;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #hitBreakpoint?: any;\n\n private constructor() {\n super(true);\n\n this.#breakpoints = new UI.ListModel.ListModel();\n this.#list = new UI.ListControl.ListControl(this.#breakpoints, this, UI.ListControl.ListMode.NonViewport);\n this.contentElement.setAttribute('jslog', `${VisualLogging.section('source.xhr-breakpoints')}`);\n this.contentElement.appendChild(this.#list.element);\n this.#list.element.classList.add('breakpoint-list', 'hidden');\n UI.ARIAUtils.markAsList(this.#list.element);\n UI.ARIAUtils.setLabel(this.#list.element, i18nString(UIStrings.xhrfetchBreakpoints));\n this.#emptyElement = this.contentElement.createChild('div', 'gray-info-message');\n this.#emptyElement.textContent = i18nString(UIStrings.noBreakpoints);\n\n this.#breakpointElements = new Map();\n\n this.#addButton = new UI.Toolbar.ToolbarButton(\n i18nString(UIStrings.addXhrfetchBreakpoint), 'plus', undefined, 'sources.add-xhr-fetch-breakpoint');\n this.#addButton.setSize(Buttons.Button.Size.SMALL);\n this.#addButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n void this.addButtonClicked();\n });\n\n this.#emptyElement.addEventListener('contextmenu', this.emptyElementContextMenu.bind(this), true);\n this.#emptyElement.tabIndex = -1;\n this.restoreBreakpoints();\n this.update();\n }\n\n static instance(): XHRBreakpointsSidebarPane {\n if (!xhrBreakpointsSidebarPaneInstance) {\n xhrBreakpointsSidebarPaneInstance = new XHRBreakpointsSidebarPane();\n }\n return xhrBreakpointsSidebarPaneInstance;\n }\n\n toolbarItems(): UI.Toolbar.ToolbarItem[] {\n return [this.#addButton];\n }\n\n private emptyElementContextMenu(event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.addBreakpoint), this.addButtonClicked.bind(this),\n {jslogContext: 'sources.add-xhr-fetch-breakpoint'});\n void contextMenu.show();\n }\n\n private async addButtonClicked(): Promise {\n await UI.ViewManager.ViewManager.instance().showView('sources.xhr-breakpoints');\n\n const inputElementContainer = document.createElement('p');\n inputElementContainer.classList.add('breakpoint-condition');\n inputElementContainer.textContent = i18nString(UIStrings.breakWhenUrlContains);\n inputElementContainer.setAttribute('jslog', `${VisualLogging.value('condition').track({change: true})}`);\n\n const inputElement = inputElementContainer.createChild('span', 'breakpoint-condition-input');\n UI.ARIAUtils.setLabel(inputElement, i18nString(UIStrings.urlBreakpoint));\n this.addListElement(inputElementContainer, this.#list.element.firstChild as Element | null);\n\n function finishEditing(this: XHRBreakpointsSidebarPane, accept: boolean, e: Element, text: string): void {\n this.removeListElement(inputElementContainer);\n if (accept) {\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(text, true);\n this.setBreakpoint(text);\n }\n this.update();\n }\n\n const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n UI.InplaceEditor.InplaceEditor.startEditing(inputElement, config as UI.InplaceEditor.Config);\n }\n\n heightForItem(_item: string): number {\n return 0;\n }\n\n isItemSelectable(_item: string): boolean {\n return true;\n }\n\n private setBreakpoint(breakKeyword: string): void {\n if (this.#breakpoints.indexOf(breakKeyword) !== -1) {\n this.#list.refreshItem(breakKeyword);\n } else {\n this.#breakpoints.insertWithComparator(breakKeyword, (a, b) => {\n if (a > b) {\n return 1;\n }\n if (a < b) {\n return -1;\n }\n return 0;\n });\n }\n if (!this.#list.selectedItem() || !this.hasFocus()) {\n this.#list.selectItem(this.#breakpoints.at(0));\n }\n }\n\n createElementForItem(item: string): Element {\n const listItemElement = document.createElement('div');\n UI.ARIAUtils.markAsListitem(listItemElement);\n const element = listItemElement.createChild('div', 'breakpoint-entry') as HTMLElement;\n containerToBreakpointEntry.set(listItemElement, element);\n const enabled = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().xhrBreakpoints().get(item) || false;\n UI.ARIAUtils.markAsCheckbox(element);\n UI.ARIAUtils.setChecked(element, enabled);\n element.addEventListener('contextmenu', this.contextMenu.bind(this, item), true);\n\n const title = item ? i18nString(UIStrings.urlContainsS, {PH1: item}) : i18nString(UIStrings.anyXhrOrFetch);\n const label = UI.UIUtils.CheckboxLabel.create(title, enabled, undefined, undefined, /* small */ true);\n UI.ARIAUtils.markAsHidden(label);\n UI.ARIAUtils.setLabel(element, title);\n element.appendChild(label);\n label.checkboxElement.addEventListener('click', this.checkboxClicked.bind(this, item, enabled), false);\n element.addEventListener('click', event => {\n if (event.target === element) {\n this.checkboxClicked(item, enabled);\n }\n }, false);\n breakpointEntryToCheckbox.set(element, label.checkboxElement);\n label.checkboxElement.tabIndex = -1;\n element.tabIndex = -1;\n if (item === this.#list.selectedItem()) {\n element.tabIndex = 0;\n this.setDefaultFocusedElement(element);\n }\n element.addEventListener('keydown', event => {\n let handled = false;\n if (event.key === ' ') {\n this.checkboxClicked(item, enabled);\n handled = true;\n } else if (event.key === 'Enter') {\n this.labelClicked(item);\n handled = true;\n }\n\n if (handled) {\n event.consume(true);\n }\n });\n\n if (item === this.#hitBreakpoint) {\n element.classList.add('breakpoint-hit');\n UI.ARIAUtils.setDescription(element, i18nString(UIStrings.breakpointHit));\n }\n\n label.classList.add('cursor-auto');\n label.textElement.addEventListener('dblclick', this.labelClicked.bind(this, item), false);\n this.#breakpointElements.set(item, listItemElement);\n listItemElement.setAttribute('jslog', `${VisualLogging.item().track({\n click: true,\n dblclick: true,\n keydown: 'ArrowUp|ArrowDown|PageUp|PageDown|Enter|Space',\n })}`);\n return listItemElement;\n }\n\n selectedItemChanged(from: string|null, to: string|null, fromElement: HTMLElement|null, toElement: HTMLElement|null):\n void {\n if (fromElement) {\n const breakpointEntryElement = containerToBreakpointEntry.get(fromElement);\n if (!breakpointEntryElement) {\n throw new Error('Expected breakpoint entry to be found for an element');\n }\n breakpointEntryElement.tabIndex = -1;\n }\n if (toElement) {\n const breakpointEntryElement = containerToBreakpointEntry.get(toElement);\n if (!breakpointEntryElement) {\n throw new Error('Expected breakpoint entry to be found for an element');\n }\n this.setDefaultFocusedElement(breakpointEntryElement);\n breakpointEntryElement.tabIndex = 0;\n if (this.hasFocus()) {\n breakpointEntryElement.focus();\n }\n }\n }\n\n updateSelectedItemARIA(_fromElement: Element|null, _toElement: Element|null): boolean {\n return true;\n }\n\n private removeBreakpoint(breakKeyword: string): void {\n const index = this.#breakpoints.indexOf(breakKeyword);\n if (index >= 0) {\n this.#breakpoints.remove(index);\n }\n this.#breakpointElements.delete(breakKeyword);\n this.update();\n }\n\n private addListElement(element: Element, beforeNode: Node|null): void {\n this.#list.element.insertBefore(element, beforeNode);\n this.#emptyElement.classList.add('hidden');\n this.#list.element.classList.remove('hidden');\n }\n\n private removeListElement(element: Element): void {\n this.#list.element.removeChild(element);\n if (!this.#list.element.firstElementChild) {\n this.#emptyElement.classList.remove('hidden');\n this.#list.element.classList.add('hidden');\n }\n }\n\n private contextMenu(breakKeyword: string, event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n\n function removeBreakpoint(this: XHRBreakpointsSidebarPane): void {\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(breakKeyword);\n this.removeBreakpoint(breakKeyword);\n }\n\n function removeAllBreakpoints(this: XHRBreakpointsSidebarPane): void {\n for (const url of this.#breakpointElements.keys()) {\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(url);\n this.removeBreakpoint(url);\n }\n this.update();\n }\n const removeAllTitle = i18nString(UIStrings.removeAllBreakpoints);\n\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.addBreakpoint), this.addButtonClicked.bind(this),\n {jslogContext: 'sources.add-xhr-fetch-breakpoint'});\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.removeBreakpoint), removeBreakpoint.bind(this),\n {jslogContext: 'sources.remove-xhr-fetch-breakpoint'});\n contextMenu.defaultSection().appendItem(\n removeAllTitle, removeAllBreakpoints.bind(this), {jslogContext: 'sources.remove-all-xhr-fetch-breakpoints'});\n void contextMenu.show();\n }\n\n private checkboxClicked(breakKeyword: string, checked: boolean): void {\n const hadFocus = this.hasFocus();\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().toggleXHRBreakpoint(breakKeyword, !checked);\n this.#list.refreshItem(breakKeyword);\n this.#list.selectItem(breakKeyword);\n if (hadFocus) {\n this.focus();\n }\n }\n\n private labelClicked(breakKeyword: string): void {\n const element = this.#breakpointElements.get(breakKeyword);\n const inputElement = document.createElement('span');\n inputElement.classList.add('breakpoint-condition');\n inputElement.textContent = breakKeyword;\n inputElement.setAttribute('jslog', `${VisualLogging.value('condition').track({change: true})}`);\n if (element) {\n this.#list.element.insertBefore(inputElement, element);\n element.classList.add('hidden');\n }\n\n function finishEditing(this: XHRBreakpointsSidebarPane, accept: boolean, e: Element, text: string): void {\n this.removeListElement(inputElement);\n if (accept) {\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(breakKeyword);\n this.removeBreakpoint(breakKeyword);\n let enabled = true;\n if (element) {\n const breakpointEntryElement = containerToBreakpointEntry.get(element);\n const checkboxElement =\n breakpointEntryElement ? breakpointEntryToCheckbox.get(breakpointEntryElement) : undefined;\n if (checkboxElement) {\n enabled = checkboxElement.checked;\n }\n }\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(text, enabled);\n this.setBreakpoint(text);\n this.#list.selectItem(text);\n } else if (element) {\n element.classList.remove('hidden');\n }\n this.focus();\n }\n\n const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n UI.InplaceEditor.InplaceEditor.startEditing(inputElement, config as UI.InplaceEditor.Config);\n }\n\n flavorChanged(_object: Object|null): void {\n this.update();\n }\n\n private update(): void {\n const isEmpty = this.#breakpoints.length === 0;\n this.#list.element.classList.toggle('hidden', isEmpty);\n this.#emptyElement.classList.toggle('hidden', !isEmpty);\n\n const details = UI.Context.Context.instance().flavor(SDK.DebuggerModel.DebuggerPausedDetails);\n if (!details || details.reason !== Protocol.Debugger.PausedEventReason.XHR) {\n if (this.#hitBreakpoint) {\n const oldHitBreakpoint = this.#hitBreakpoint;\n this.#hitBreakpoint = undefined;\n if (this.#breakpoints.indexOf(oldHitBreakpoint) >= 0) {\n this.#list.refreshItem(oldHitBreakpoint);\n }\n }\n return;\n }\n const url = details.auxData && details.auxData['breakpointURL'];\n this.#hitBreakpoint = url;\n if (this.#breakpoints.indexOf(url) < 0) {\n return;\n }\n this.#list.refreshItem(url);\n void UI.ViewManager.ViewManager.instance().showView('sources.xhr-breakpoints');\n }\n\n private restoreBreakpoints(): void {\n const breakpoints = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().xhrBreakpoints();\n for (const url of breakpoints.keys()) {\n this.setBreakpoint(url);\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([xhrBreakpointsSidebarPaneStyles]);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"XHRBreakpointsSidebarPane.js","sourceRoot":"","sources":["../../../../../../front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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 i18n from '../../core/i18n/i18n.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport xhrBreakpointsSidebarPaneStyles from './xhrBreakpointsSidebarPane.css.js';\n\nconst UIStrings = {\n /**\n *@description Title of the 'XHR/fetch Breakpoints' tool in the bottom sidebar of the Sources tool\n */\n xhrfetchBreakpoints: 'XHR/fetch Breakpoints',\n /**\n *@description Text to indicate there are no breakpoints\n */\n noBreakpoints: 'No breakpoints',\n /**\n *@description Label for a button in the Sources panel that opens the input field to create a new XHR/fetch breakpoint.\n */\n addXhrfetchBreakpoint: 'Add XHR/fetch breakpoint',\n /**\n *@description Text to add a breakpoint\n */\n addBreakpoint: 'Add breakpoint',\n /**\n *@description Input element container text content in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel\n */\n breakWhenUrlContains: 'Break when URL contains:',\n /**\n *@description Accessible label for XHR/fetch breakpoint text input\n */\n urlBreakpoint: 'URL Breakpoint',\n /**\n *@description Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel\n *@example {example.com} PH1\n */\n urlContainsS: 'URL contains \"{PH1}\"',\n /**\n *@description Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel\n */\n anyXhrOrFetch: 'Any XHR or fetch',\n /**\n *@description Screen reader description of a hit breakpoint in the Sources panel\n */\n breakpointHit: 'breakpoint hit',\n /**\n *@description Text to remove all breakpoints\n */\n removeAllBreakpoints: 'Remove all breakpoints',\n /**\n *@description Text to remove a breakpoint\n */\n removeBreakpoint: 'Remove breakpoint',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/browser_debugger/XHRBreakpointsSidebarPane.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nconst containerToBreakpointEntry = new WeakMap();\n\nconst breakpointEntryToCheckbox = new WeakMap();\n\nlet xhrBreakpointsSidebarPaneInstance: XHRBreakpointsSidebarPane;\n\nexport class XHRBreakpointsSidebarPane extends UI.Widget.VBox implements UI.ContextFlavorListener.ContextFlavorListener,\n UI.Toolbar.ItemsProvider,\n UI.ListControl.ListDelegate {\n readonly #breakpoints: UI.ListModel.ListModel;\n #list: UI.ListControl.ListControl;\n readonly #emptyElement: HTMLElement;\n readonly #breakpointElements: Map;\n readonly #addButton: UI.Toolbar.ToolbarButton;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #hitBreakpoint?: any;\n\n private constructor() {\n super(true);\n\n this.#breakpoints = new UI.ListModel.ListModel();\n this.#list = new UI.ListControl.ListControl(this.#breakpoints, this, UI.ListControl.ListMode.NonViewport);\n this.contentElement.setAttribute('jslog', `${VisualLogging.section('source.xhr-breakpoints')}`);\n this.contentElement.appendChild(this.#list.element);\n this.#list.element.classList.add('breakpoint-list', 'hidden');\n UI.ARIAUtils.markAsList(this.#list.element);\n UI.ARIAUtils.setLabel(this.#list.element, i18nString(UIStrings.xhrfetchBreakpoints));\n this.#emptyElement = this.contentElement.createChild('div', 'gray-info-message');\n this.#emptyElement.textContent = i18nString(UIStrings.noBreakpoints);\n\n this.#breakpointElements = new Map();\n\n this.#addButton = new UI.Toolbar.ToolbarButton(\n i18nString(UIStrings.addXhrfetchBreakpoint), 'plus', undefined, 'sources.add-xhr-fetch-breakpoint');\n this.#addButton.setSize(Buttons.Button.Size.SMALL);\n this.#addButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n void this.addButtonClicked();\n });\n\n this.#emptyElement.addEventListener('contextmenu', this.emptyElementContextMenu.bind(this), true);\n this.#emptyElement.tabIndex = -1;\n this.restoreBreakpoints();\n this.update();\n }\n\n static instance(): XHRBreakpointsSidebarPane {\n if (!xhrBreakpointsSidebarPaneInstance) {\n xhrBreakpointsSidebarPaneInstance = new XHRBreakpointsSidebarPane();\n }\n return xhrBreakpointsSidebarPaneInstance;\n }\n\n toolbarItems(): UI.Toolbar.ToolbarItem[] {\n return [this.#addButton];\n }\n\n private emptyElementContextMenu(event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.addBreakpoint), this.addButtonClicked.bind(this),\n {jslogContext: 'sources.add-xhr-fetch-breakpoint'});\n void contextMenu.show();\n }\n\n private async addButtonClicked(): Promise {\n await UI.ViewManager.ViewManager.instance().showView('sources.xhr-breakpoints');\n\n const inputElementContainer = document.createElement('p');\n inputElementContainer.classList.add('breakpoint-condition');\n inputElementContainer.textContent = i18nString(UIStrings.breakWhenUrlContains);\n inputElementContainer.setAttribute('jslog', `${VisualLogging.value('condition').track({change: true})}`);\n\n const inputElement = inputElementContainer.createChild('span', 'breakpoint-condition-input');\n UI.ARIAUtils.setLabel(inputElement, i18nString(UIStrings.urlBreakpoint));\n this.addListElement(inputElementContainer, this.#list.element.firstChild as Element | null);\n\n const commit = (_element: Element, newText: string): void => {\n this.removeListElement(inputElementContainer);\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(newText, true);\n this.setBreakpoint(newText);\n this.update();\n };\n\n const cancel = (): void => {\n this.removeListElement(inputElementContainer);\n this.update();\n };\n\n const config = new UI.InplaceEditor.Config(commit, cancel, undefined);\n UI.InplaceEditor.InplaceEditor.startEditing(inputElement, config);\n }\n\n heightForItem(_item: string): number {\n return 0;\n }\n\n isItemSelectable(_item: string): boolean {\n return true;\n }\n\n private setBreakpoint(breakKeyword: string): void {\n if (this.#breakpoints.indexOf(breakKeyword) !== -1) {\n this.#list.refreshItem(breakKeyword);\n } else {\n this.#breakpoints.insertWithComparator(breakKeyword, (a, b) => {\n if (a > b) {\n return 1;\n }\n if (a < b) {\n return -1;\n }\n return 0;\n });\n }\n if (!this.#list.selectedItem() || !this.hasFocus()) {\n this.#list.selectItem(this.#breakpoints.at(0));\n }\n }\n\n createElementForItem(item: string): Element {\n const listItemElement = document.createElement('div');\n UI.ARIAUtils.markAsListitem(listItemElement);\n const element = listItemElement.createChild('div', 'breakpoint-entry') as HTMLElement;\n containerToBreakpointEntry.set(listItemElement, element);\n const enabled = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().xhrBreakpoints().get(item) || false;\n UI.ARIAUtils.markAsCheckbox(element);\n UI.ARIAUtils.setChecked(element, enabled);\n element.addEventListener('contextmenu', this.contextMenu.bind(this, item), true);\n\n const title = item ? i18nString(UIStrings.urlContainsS, {PH1: item}) : i18nString(UIStrings.anyXhrOrFetch);\n const label = UI.UIUtils.CheckboxLabel.create(title, enabled, undefined, undefined, /* small */ true);\n UI.ARIAUtils.markAsHidden(label);\n UI.ARIAUtils.setLabel(element, title);\n element.appendChild(label);\n label.checkboxElement.addEventListener('click', this.checkboxClicked.bind(this, item, enabled), false);\n element.addEventListener('click', event => {\n if (event.target === element) {\n this.checkboxClicked(item, enabled);\n }\n }, false);\n breakpointEntryToCheckbox.set(element, label.checkboxElement);\n label.checkboxElement.tabIndex = -1;\n element.tabIndex = -1;\n if (item === this.#list.selectedItem()) {\n element.tabIndex = 0;\n this.setDefaultFocusedElement(element);\n }\n element.addEventListener('keydown', event => {\n let handled = false;\n if (event.key === ' ') {\n this.checkboxClicked(item, enabled);\n handled = true;\n } else if (event.key === 'Enter') {\n this.labelClicked(item);\n handled = true;\n }\n\n if (handled) {\n event.consume(true);\n }\n });\n\n if (item === this.#hitBreakpoint) {\n element.classList.add('breakpoint-hit');\n UI.ARIAUtils.setDescription(element, i18nString(UIStrings.breakpointHit));\n }\n\n label.classList.add('cursor-auto');\n label.textElement.addEventListener('dblclick', this.labelClicked.bind(this, item), false);\n this.#breakpointElements.set(item, listItemElement);\n listItemElement.setAttribute('jslog', `${VisualLogging.item().track({\n click: true,\n dblclick: true,\n keydown: 'ArrowUp|ArrowDown|PageUp|PageDown|Enter|Space',\n })}`);\n return listItemElement;\n }\n\n selectedItemChanged(from: string|null, to: string|null, fromElement: HTMLElement|null, toElement: HTMLElement|null):\n void {\n if (fromElement) {\n const breakpointEntryElement = containerToBreakpointEntry.get(fromElement);\n if (!breakpointEntryElement) {\n throw new Error('Expected breakpoint entry to be found for an element');\n }\n breakpointEntryElement.tabIndex = -1;\n }\n if (toElement) {\n const breakpointEntryElement = containerToBreakpointEntry.get(toElement);\n if (!breakpointEntryElement) {\n throw new Error('Expected breakpoint entry to be found for an element');\n }\n this.setDefaultFocusedElement(breakpointEntryElement);\n breakpointEntryElement.tabIndex = 0;\n if (this.hasFocus()) {\n breakpointEntryElement.focus();\n }\n }\n }\n\n updateSelectedItemARIA(_fromElement: Element|null, _toElement: Element|null): boolean {\n return true;\n }\n\n private removeBreakpoint(breakKeyword: string): void {\n const index = this.#breakpoints.indexOf(breakKeyword);\n if (index >= 0) {\n this.#breakpoints.remove(index);\n }\n this.#breakpointElements.delete(breakKeyword);\n this.update();\n }\n\n private addListElement(element: Element, beforeNode: Node|null): void {\n this.#list.element.insertBefore(element, beforeNode);\n this.#emptyElement.classList.add('hidden');\n this.#list.element.classList.remove('hidden');\n }\n\n private removeListElement(element: Element): void {\n this.#list.element.removeChild(element);\n if (!this.#list.element.firstElementChild) {\n this.#emptyElement.classList.remove('hidden');\n this.#list.element.classList.add('hidden');\n }\n }\n\n private contextMenu(breakKeyword: string, event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n\n function removeBreakpoint(this: XHRBreakpointsSidebarPane): void {\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(breakKeyword);\n this.removeBreakpoint(breakKeyword);\n }\n\n function removeAllBreakpoints(this: XHRBreakpointsSidebarPane): void {\n for (const url of this.#breakpointElements.keys()) {\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(url);\n this.removeBreakpoint(url);\n }\n this.update();\n }\n const removeAllTitle = i18nString(UIStrings.removeAllBreakpoints);\n\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.addBreakpoint), this.addButtonClicked.bind(this),\n {jslogContext: 'sources.add-xhr-fetch-breakpoint'});\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.removeBreakpoint), removeBreakpoint.bind(this),\n {jslogContext: 'sources.remove-xhr-fetch-breakpoint'});\n contextMenu.defaultSection().appendItem(\n removeAllTitle, removeAllBreakpoints.bind(this), {jslogContext: 'sources.remove-all-xhr-fetch-breakpoints'});\n void contextMenu.show();\n }\n\n private checkboxClicked(breakKeyword: string, checked: boolean): void {\n const hadFocus = this.hasFocus();\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().toggleXHRBreakpoint(breakKeyword, !checked);\n this.#list.refreshItem(breakKeyword);\n this.#list.selectItem(breakKeyword);\n if (hadFocus) {\n this.focus();\n }\n }\n\n private labelClicked(breakKeyword: string): void {\n const element = this.#breakpointElements.get(breakKeyword);\n const inputElement = document.createElement('span');\n inputElement.classList.add('breakpoint-condition');\n inputElement.textContent = breakKeyword;\n inputElement.setAttribute('jslog', `${VisualLogging.value('condition').track({change: true})}`);\n if (element) {\n this.#list.element.insertBefore(inputElement, element);\n element.classList.add('hidden');\n }\n\n const commit = (inputElement: Element, newText: string, _oldText: string|null, element?: Element): void => {\n this.removeListElement(inputElement);\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().removeXHRBreakpoint(breakKeyword);\n this.removeBreakpoint(breakKeyword);\n let enabled = true;\n if (element) {\n const breakpointEntryElement = containerToBreakpointEntry.get(element);\n const checkboxElement =\n breakpointEntryElement ? breakpointEntryToCheckbox.get(breakpointEntryElement) : undefined;\n if (checkboxElement) {\n enabled = checkboxElement.checked;\n }\n }\n SDK.DOMDebuggerModel.DOMDebuggerManager.instance().addXHRBreakpoint(newText, enabled);\n this.setBreakpoint(newText);\n this.#list.selectItem(newText);\n this.focus();\n };\n\n const cancel = (inputElement: Element, element?: Element): void => {\n this.removeListElement(inputElement);\n if (element) {\n element.classList.remove('hidden');\n }\n this.focus();\n };\n\n const config = new UI.InplaceEditor.Config(commit, cancel, element);\n UI.InplaceEditor.InplaceEditor.startEditing(inputElement, config);\n }\n\n flavorChanged(_object: Object|null): void {\n this.update();\n }\n\n private update(): void {\n const isEmpty = this.#breakpoints.length === 0;\n this.#list.element.classList.toggle('hidden', isEmpty);\n this.#emptyElement.classList.toggle('hidden', !isEmpty);\n\n const details = UI.Context.Context.instance().flavor(SDK.DebuggerModel.DebuggerPausedDetails);\n if (!details || details.reason !== Protocol.Debugger.PausedEventReason.XHR) {\n if (this.#hitBreakpoint) {\n const oldHitBreakpoint = this.#hitBreakpoint;\n this.#hitBreakpoint = undefined;\n if (this.#breakpoints.indexOf(oldHitBreakpoint) >= 0) {\n this.#list.refreshItem(oldHitBreakpoint);\n }\n }\n return;\n }\n const url = details.auxData && details.auxData['breakpointURL'];\n this.#hitBreakpoint = url;\n if (this.#breakpoints.indexOf(url) < 0) {\n return;\n }\n this.#list.refreshItem(url);\n void UI.ViewManager.ViewManager.instance().showView('sources.xhr-breakpoints');\n }\n\n private restoreBreakpoints(): void {\n const breakpoints = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().xhrBreakpoints();\n for (const url of breakpoints.keys()) {\n this.setBreakpoint(url);\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([xhrBreakpointsSidebarPaneStyles]);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/coverage/CoverageView.js b/public/panels/coverage/CoverageView.js index 94becd73..38ea023c 100644 --- a/public/panels/coverage/CoverageView.js +++ b/public/panels/coverage/CoverageView.js @@ -474,10 +474,10 @@ export class CoverageView extends UI.Widget.VBox { const used = total - unused; const percentUsed = total ? Math.round(100 * used / total) : 0; return i18nString(UIStrings.sOfSSUsedSoFarSUnused, { - PH1: Platform.NumberUtilities.bytesToString(used), - PH2: Platform.NumberUtilities.bytesToString(total), + PH1: i18n.ByteUtilities.bytesToString(used), + PH2: i18n.ByteUtilities.bytesToString(total), PH3: percentUsed, - PH4: Platform.NumberUtilities.bytesToString(unused), + PH4: i18n.ByteUtilities.bytesToString(unused), }); } } diff --git a/public/panels/coverage/CoverageView.js.map b/public/panels/coverage/CoverageView.js.map index b953e199..7065fe4c 100644 --- a/public/panels/coverage/CoverageView.js.map +++ b/public/panels/coverage/CoverageView.js.map @@ -1 +1 @@ -{"version":3,"file":"CoverageView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/coverage/CoverageView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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 * 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 Workspace from '../../models/workspace/workspace.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {CoverageDecorationManager} from './CoverageDecorationManager.js';\nimport {CoverageListView} from './CoverageListView.js';\nimport {type CoverageInfo, CoverageModel, CoverageType, Events, type URLCoverageInfo} from './CoverageModel.js';\nimport coverageViewStyles from './coverageView.css.js';\n\nconst UIStrings = {\n /**\n *@description Tooltip in Coverage List View of the Coverage tab for selecting JavaScript coverage mode\n */\n chooseCoverageGranularityPer:\n 'Choose coverage granularity: Per function has low overhead, per block has significant overhead.',\n /**\n *@description Text in Coverage List View of the Coverage tab\n */\n perFunction: 'Per function',\n /**\n *@description Text in Coverage List View of the Coverage tab\n */\n perBlock: 'Per block',\n /**\n *@description Text in Coverage View of the Coverage tab\n */\n filterByUrl: 'Filter by URL',\n /**\n *@description Label for the type filter in the Converage Panel\n */\n filterCoverageByType: 'Filter coverage by type',\n /**\n *@description Text for everything\n */\n all: 'All',\n /**\n *@description Text that appears on a button for the css resource type filter.\n */\n css: 'CSS',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n javascript: 'JavaScript',\n /**\n *@description Tooltip text that appears on the setting when hovering over it in Coverage View of the Coverage tab\n */\n includeExtensionContentScripts: 'Include extension content scripts',\n /**\n *@description Title for a type of source files\n */\n contentScripts: 'Content scripts',\n /**\n *@description Message in Coverage View of the Coverage tab\n *@example {record button icon} PH1\n */\n clickTheReloadButtonSToReloadAnd: 'Click the reload button {PH1} to reload and start capturing coverage.',\n /**\n *@description Message in Coverage View of the Coverage tab\n *@example {record button icon} PH1\n */\n clickTheRecordButtonSToStart: 'Click the record button {PH1} to start capturing coverage.',\n /**\n *@description Message in the Coverage View explaining that DevTools could not capture coverage.\n */\n bfcacheNoCapture: 'Could not capture coverage info because the page was served from the back/forward cache.',\n /**\n *@description Message in the Coverage View explaining that DevTools could not capture coverage.\n */\n activationNoCapture: 'Could not capture coverage info because the page was prerendered in the background.',\n /**\n *@description Message in the Coverage View prompting the user to reload the page.\n *@example {reload button icon} PH1\n */\n reloadPrompt: 'Click the reload button {PH1} to reload and get coverage.',\n\n /**\n *@description Footer message in Coverage View of the Coverage tab\n *@example {300k used, 600k unused} PH1\n *@example {500k used, 800k unused} PH2\n */\n filteredSTotalS: 'Filtered: {PH1} Total: {PH2}',\n /**\n *@description Footer message in Coverage View of the Coverage tab\n *@example {1.5 MB} PH1\n *@example {2.1 MB} PH2\n *@example {71%} PH3\n *@example {29%} PH4\n */\n sOfSSUsedSoFarSUnused: '{PH1} of {PH2} ({PH3}%) used so far, {PH4} unused.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/coverage/CoverageView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nlet coverageViewInstance: CoverageView|undefined;\n\nexport class CoverageView extends UI.Widget.VBox {\n private model: CoverageModel|null;\n private decorationManager: CoverageDecorationManager|null;\n private readonly coverageTypeComboBox: UI.Toolbar.ToolbarComboBox;\n private readonly coverageTypeComboBoxSetting: Common.Settings.Setting;\n private toggleRecordAction: UI.ActionRegistration.Action;\n private readonly toggleRecordButton: UI.Toolbar.ToolbarButton;\n private inlineReloadButton: Element|null;\n private readonly startWithReloadButton: UI.Toolbar.ToolbarButton|undefined;\n private readonly clearAction: UI.ActionRegistration.Action;\n private readonly exportAction: UI.ActionRegistration.Action;\n private textFilterRegExp: RegExp|null;\n private readonly filterInput: UI.Toolbar.ToolbarInput;\n private typeFilterValue: number|null;\n private readonly filterByTypeComboBox: UI.Toolbar.ToolbarComboBox;\n private showContentScriptsSetting: Common.Settings.Setting;\n private readonly contentScriptsCheckbox: UI.Toolbar.ToolbarSettingCheckbox;\n private readonly coverageResultsElement: HTMLElement;\n private readonly landingPage: UI.Widget.VBox;\n private readonly bfcacheReloadPromptPage: UI.Widget.VBox;\n private readonly activationReloadPromptPage: UI.Widget.VBox;\n private listView: CoverageListView;\n private readonly statusToolbarElement: HTMLElement;\n private statusMessageElement: HTMLElement;\n\n constructor() {\n super(true);\n\n this.element.setAttribute('jslog', `${VisualLogging.panel('coverage').track({resize: true})}`);\n\n this.model = null;\n this.decorationManager = null;\n\n const toolbarContainer = this.contentElement.createChild('div', 'coverage-toolbar-container');\n toolbarContainer.setAttribute('jslog', `${VisualLogging.toolbar()}`);\n const toolbar = new UI.Toolbar.Toolbar('coverage-toolbar', toolbarContainer);\n toolbar.makeWrappable(true);\n\n this.coverageTypeComboBox = new UI.Toolbar.ToolbarComboBox(\n this.onCoverageTypeComboBoxSelectionChanged.bind(this), i18nString(UIStrings.chooseCoverageGranularityPer),\n undefined, 'coverage-type');\n const coverageTypes = [\n {\n label: i18nString(UIStrings.perFunction),\n value: CoverageType.JAVA_SCRIPT | CoverageType.JAVA_SCRIPT_PER_FUNCTION,\n },\n {\n label: i18nString(UIStrings.perBlock),\n value: CoverageType.JAVA_SCRIPT,\n },\n ];\n for (const type of coverageTypes) {\n this.coverageTypeComboBox.addOption(this.coverageTypeComboBox.createOption(type.label, `${type.value}`));\n }\n this.coverageTypeComboBoxSetting =\n Common.Settings.Settings.instance().createSetting('coverage-view-coverage-type', 0);\n this.coverageTypeComboBox.setSelectedIndex(this.coverageTypeComboBoxSetting.get());\n this.coverageTypeComboBox.setEnabled(true);\n toolbar.appendToolbarItem(this.coverageTypeComboBox);\n this.toggleRecordAction = UI.ActionRegistry.ActionRegistry.instance().getAction('coverage.toggle-recording');\n this.toggleRecordButton = UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction);\n toolbar.appendToolbarItem(this.toggleRecordButton);\n\n const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const mainTargetSupportsRecordOnReload = mainTarget && mainTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);\n this.inlineReloadButton = null;\n if (mainTargetSupportsRecordOnReload) {\n this.startWithReloadButton = UI.Toolbar.Toolbar.createActionButtonForId('coverage.start-with-reload');\n toolbar.appendToolbarItem(this.startWithReloadButton);\n this.toggleRecordButton.setEnabled(false);\n this.toggleRecordButton.setVisible(false);\n }\n this.clearAction = UI.ActionRegistry.ActionRegistry.instance().getAction('coverage.clear');\n this.clearAction.setEnabled(false);\n toolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.clearAction));\n\n toolbar.appendSeparator();\n this.exportAction = UI.ActionRegistry.ActionRegistry.instance().getAction('coverage.export');\n this.exportAction.setEnabled(false);\n toolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.exportAction));\n\n this.textFilterRegExp = null;\n toolbar.appendSeparator();\n this.filterInput = new UI.Toolbar.ToolbarFilter(i18nString(UIStrings.filterByUrl), 0.4, 1);\n this.filterInput.setEnabled(false);\n this.filterInput.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.onFilterChanged, this);\n toolbar.appendToolbarItem(this.filterInput);\n\n toolbar.appendSeparator();\n\n this.typeFilterValue = null;\n this.filterByTypeComboBox = new UI.Toolbar.ToolbarComboBox(\n this.onFilterByTypeChanged.bind(this), i18nString(UIStrings.filterCoverageByType), undefined,\n 'coverage-by-type');\n const options = [\n {\n label: i18nString(UIStrings.all),\n value: '',\n },\n {\n label: i18nString(UIStrings.css),\n value: CoverageType.CSS,\n },\n {\n label: i18nString(UIStrings.javascript),\n value: CoverageType.JAVA_SCRIPT | CoverageType.JAVA_SCRIPT_PER_FUNCTION,\n },\n ];\n for (const option of options) {\n this.filterByTypeComboBox.addOption(this.filterByTypeComboBox.createOption(option.label, `${option.value}`));\n }\n\n this.filterByTypeComboBox.setSelectedIndex(0);\n this.filterByTypeComboBox.setEnabled(false);\n toolbar.appendToolbarItem(this.filterByTypeComboBox);\n\n toolbar.appendSeparator();\n this.showContentScriptsSetting = Common.Settings.Settings.instance().createSetting('show-content-scripts', false);\n this.showContentScriptsSetting.addChangeListener(this.onFilterChanged, this);\n this.contentScriptsCheckbox = new UI.Toolbar.ToolbarSettingCheckbox(\n this.showContentScriptsSetting, i18nString(UIStrings.includeExtensionContentScripts),\n i18nString(UIStrings.contentScripts));\n this.contentScriptsCheckbox.setEnabled(false);\n toolbar.appendToolbarItem(this.contentScriptsCheckbox);\n\n this.coverageResultsElement = this.contentElement.createChild('div', 'coverage-results');\n this.landingPage = this.buildLandingPage();\n this.bfcacheReloadPromptPage = this.buildReloadPromptPage(i18nString(UIStrings.bfcacheNoCapture), 'bfcache-page');\n this.activationReloadPromptPage =\n this.buildReloadPromptPage(i18nString(UIStrings.activationNoCapture), 'prerender-page');\n this.listView = new CoverageListView(this.isVisible.bind(this, false));\n\n this.statusToolbarElement = this.contentElement.createChild('div', 'coverage-toolbar-summary');\n this.statusMessageElement = this.statusToolbarElement.createChild('div', 'coverage-message');\n this.landingPage.show(this.coverageResultsElement);\n }\n\n static instance(): CoverageView {\n if (!coverageViewInstance) {\n coverageViewInstance = new CoverageView();\n }\n return coverageViewInstance;\n }\n\n static removeInstance(): void {\n coverageViewInstance = undefined;\n }\n\n private buildLandingPage(): UI.Widget.VBox {\n const widget = new UI.Widget.VBox();\n let message;\n if (this.startWithReloadButton) {\n this.inlineReloadButton =\n UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButtonForId('coverage.start-with-reload'));\n message = i18n.i18n.getFormatLocalizedString(\n str_, UIStrings.clickTheReloadButtonSToReloadAnd, {PH1: this.inlineReloadButton});\n } else {\n const recordButton =\n UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction));\n message = i18n.i18n.getFormatLocalizedString(str_, UIStrings.clickTheRecordButtonSToStart, {PH1: recordButton});\n }\n message.classList.add('message');\n widget.contentElement.appendChild(message);\n widget.element.classList.add('landing-page');\n return widget;\n }\n\n private buildReloadPromptPage(message: Common.UIString.LocalizedString, className: string): UI.Widget.VBox {\n const widget = new UI.Widget.VBox();\n const reasonDiv = document.createElement('div');\n reasonDiv.classList.add('message');\n reasonDiv.textContent = message;\n widget.contentElement.appendChild(reasonDiv);\n this.inlineReloadButton =\n UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButtonForId('inspector-main.reload'));\n const messageElement =\n i18n.i18n.getFormatLocalizedString(str_, UIStrings.reloadPrompt, {PH1: this.inlineReloadButton});\n messageElement.classList.add('message');\n widget.contentElement.appendChild(messageElement);\n widget.element.classList.add(className);\n return widget;\n }\n\n clear(): void {\n if (this.model) {\n this.model.reset();\n }\n this.reset();\n }\n\n private reset(): void {\n if (this.decorationManager) {\n this.decorationManager.dispose();\n this.decorationManager = null;\n }\n this.listView.reset();\n this.listView.detach();\n this.landingPage.show(this.coverageResultsElement);\n this.statusMessageElement.textContent = '';\n this.filterInput.setEnabled(false);\n this.filterByTypeComboBox.setEnabled(false);\n this.contentScriptsCheckbox.setEnabled(false);\n this.exportAction.setEnabled(false);\n }\n\n toggleRecording(): void {\n const enable = !this.toggleRecordAction.toggled();\n\n if (enable) {\n void this.startRecording({reload: false, jsCoveragePerBlock: this.isBlockCoverageSelected()});\n } else {\n void this.stopRecording();\n }\n }\n\n isBlockCoverageSelected(): boolean {\n const option = this.coverageTypeComboBox.selectedOption();\n const coverageType = Number(option ? option.value : Number.NaN);\n // Check that Coverage.CoverageType.JavaScriptPerFunction is not present.\n return coverageType === CoverageType.JAVA_SCRIPT;\n }\n\n private selectCoverageType(jsCoveragePerBlock: boolean): void {\n const selectedIndex = jsCoveragePerBlock ? 1 : 0;\n this.coverageTypeComboBox.setSelectedIndex(selectedIndex);\n }\n\n private onCoverageTypeComboBoxSelectionChanged(): void {\n this.coverageTypeComboBoxSetting.set(this.coverageTypeComboBox.selectedIndex());\n }\n\n async ensureRecordingStarted(): Promise {\n const enabled = this.toggleRecordAction.toggled();\n\n if (enabled) {\n await this.stopRecording();\n }\n await this.startRecording({reload: false, jsCoveragePerBlock: false});\n }\n\n async startRecording(options: {reload: (boolean|undefined), jsCoveragePerBlock: (boolean|undefined)}|\n null): Promise {\n let hadFocus, reloadButtonFocused;\n if ((this.startWithReloadButton && this.startWithReloadButton.element.hasFocus()) ||\n (this.inlineReloadButton && this.inlineReloadButton.hasFocus())) {\n reloadButtonFocused = true;\n } else if (this.hasFocus()) {\n hadFocus = true;\n }\n\n this.reset();\n const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!mainTarget) {\n return;\n }\n\n const {reload, jsCoveragePerBlock} = {reload: false, jsCoveragePerBlock: false, ...options};\n\n if (!this.model || reload) {\n this.model = mainTarget.model(CoverageModel);\n }\n if (!this.model) {\n return;\n }\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageStarted);\n if (jsCoveragePerBlock) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageStartedPerBlock);\n }\n const success = await this.model.start(Boolean(jsCoveragePerBlock));\n if (!success) {\n return;\n }\n this.selectCoverageType(Boolean(jsCoveragePerBlock));\n this.model.addEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n this.model.addEventListener(Events.SourceMapResolved, this.updateListView, this);\n const resourceTreeModel =\n mainTarget.model(SDK.ResourceTreeModel.ResourceTreeModel) as SDK.ResourceTreeModel.ResourceTreeModel | null;\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,\n this.onPrimaryPageChanged, this);\n this.decorationManager = new CoverageDecorationManager(\n this.model, Workspace.Workspace.WorkspaceImpl.instance(),\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(),\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance());\n this.toggleRecordAction.setToggled(true);\n this.clearAction.setEnabled(false);\n if (this.startWithReloadButton) {\n this.startWithReloadButton.setEnabled(false);\n this.startWithReloadButton.setVisible(false);\n this.toggleRecordButton.setEnabled(true);\n this.toggleRecordButton.setVisible(true);\n if (reloadButtonFocused) {\n this.toggleRecordButton.focus();\n }\n }\n this.coverageTypeComboBox.setEnabled(false);\n this.filterInput.setEnabled(true);\n this.filterByTypeComboBox.setEnabled(true);\n this.contentScriptsCheckbox.setEnabled(true);\n if (this.landingPage.isShowing()) {\n this.landingPage.detach();\n }\n this.listView.show(this.coverageResultsElement);\n if (hadFocus && !reloadButtonFocused) {\n this.listView.focus();\n }\n if (reload && resourceTreeModel) {\n resourceTreeModel.reloadPage();\n } else {\n void this.model.startPolling();\n }\n }\n\n private onCoverageDataReceived(event: Common.EventTarget.EventTargetEvent): void {\n const data = event.data;\n this.updateViews(data);\n }\n\n private updateListView(): void {\n this.listView.update(this.model && this.model.entries() || []);\n }\n\n async stopRecording(): Promise {\n SDK.TargetManager.TargetManager.instance().removeModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,\n this.onPrimaryPageChanged, this);\n if (this.hasFocus()) {\n this.listView.focus();\n }\n // Stopping the model triggers one last poll to get the final data.\n if (this.model) {\n await this.model.stop();\n this.model.removeEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n }\n this.toggleRecordAction.setToggled(false);\n this.coverageTypeComboBox.setEnabled(true);\n if (this.startWithReloadButton) {\n this.startWithReloadButton.setEnabled(true);\n this.startWithReloadButton.setVisible(true);\n this.toggleRecordButton.setEnabled(false);\n this.toggleRecordButton.setVisible(false);\n }\n this.clearAction.setEnabled(true);\n }\n\n processBacklog(): void {\n this.model && void this.model.processJSBacklog();\n }\n\n private async onPrimaryPageChanged(\n event: Common.EventTarget.EventTargetEvent<\n {frame: SDK.ResourceTreeModel.ResourceTreeFrame, type: SDK.ResourceTreeModel.PrimaryPageChangeType}>):\n Promise {\n const frame = event.data.frame;\n const coverageModel = frame.resourceTreeModel().target().model(CoverageModel);\n if (!coverageModel) {\n return;\n }\n // If the primary page target has changed (due to MPArch activation), switch to new CoverageModel.\n if (this.model !== coverageModel) {\n if (this.model) {\n await this.model.stop();\n this.model.removeEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n }\n this.model = coverageModel;\n const success = await this.model.start(this.isBlockCoverageSelected());\n if (!success) {\n return;\n }\n\n this.model.addEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n this.decorationManager = new CoverageDecorationManager(\n this.model, Workspace.Workspace.WorkspaceImpl.instance(),\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(),\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance());\n }\n\n if (this.bfcacheReloadPromptPage.isShowing()) {\n this.bfcacheReloadPromptPage.detach();\n this.listView.show(this.coverageResultsElement);\n }\n if (this.activationReloadPromptPage.isShowing()) {\n this.activationReloadPromptPage.detach();\n this.listView.show(this.coverageResultsElement);\n }\n if (frame.backForwardCacheDetails.restoredFromCache) {\n this.listView.detach();\n this.bfcacheReloadPromptPage.show(this.coverageResultsElement);\n }\n if (event.data.type === SDK.ResourceTreeModel.PrimaryPageChangeType.ACTIVATION) {\n this.listView.detach();\n this.activationReloadPromptPage.show(this.coverageResultsElement);\n }\n\n this.model.reset();\n this.decorationManager && this.decorationManager.reset();\n this.listView.reset();\n void this.model.startPolling();\n }\n\n private updateViews(updatedEntries: CoverageInfo[]): void {\n this.updateStats();\n this.listView.update(this.model && this.model.entries() || []);\n this.exportAction.setEnabled(this.model !== null && this.model.entries().length > 0);\n this.decorationManager && this.decorationManager.update(updatedEntries);\n }\n\n private updateStats(): void {\n const all = {total: 0, unused: 0};\n const filtered = {total: 0, unused: 0};\n const filterApplied = this.textFilterRegExp !== null;\n if (this.model) {\n for (const info of this.model.entries()) {\n all.total += info.size();\n all.unused += info.unusedSize();\n if (this.isVisible(false, info)) {\n if (this.textFilterRegExp?.test(info.url())) {\n filtered.total += info.size();\n filtered.unused += info.unusedSize();\n } else {\n // If it doesn't match the filter, calculate the stats from visible children if there are any\n for (const childInfo of info.sourcesURLCoverageInfo.values()) {\n if (this.isVisible(false, childInfo)) {\n filtered.total += childInfo.size();\n filtered.unused += childInfo.unusedSize();\n }\n }\n }\n }\n }\n }\n this.statusMessageElement.textContent = filterApplied ?\n i18nString(UIStrings.filteredSTotalS, {PH1: formatStat(filtered), PH2: formatStat(all)}) :\n formatStat(all);\n\n function formatStat({total, unused}: {total: number, unused: number}): string {\n const used = total - unused;\n const percentUsed = total ? Math.round(100 * used / total) : 0;\n return i18nString(UIStrings.sOfSSUsedSoFarSUnused, {\n PH1: Platform.NumberUtilities.bytesToString(used),\n PH2: Platform.NumberUtilities.bytesToString(total),\n PH3: percentUsed,\n PH4: Platform.NumberUtilities.bytesToString(unused),\n });\n }\n }\n\n private onFilterChanged(): void {\n if (!this.listView) {\n return;\n }\n const text = this.filterInput.value();\n this.textFilterRegExp = text ? Platform.StringUtilities.createPlainTextSearchRegex(text, 'i') : null;\n this.listView.updateFilterAndHighlight(this.textFilterRegExp);\n this.updateStats();\n }\n\n private onFilterByTypeChanged(): void {\n if (!this.listView) {\n return;\n }\n\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageReportFiltered);\n\n const option = this.filterByTypeComboBox.selectedOption();\n const type = option && option.value;\n this.typeFilterValue = parseInt(type || '', 10) || null;\n this.listView.updateFilterAndHighlight(this.textFilterRegExp);\n this.updateStats();\n }\n\n private isVisible(ignoreTextFilter: boolean, coverageInfo: URLCoverageInfo): boolean {\n const url = coverageInfo.url();\n if (url.startsWith(CoverageView.EXTENSION_BINDINGS_URL_PREFIX)) {\n return false;\n }\n if (coverageInfo.isContentScript() && !this.showContentScriptsSetting.get()) {\n return false;\n }\n if (this.typeFilterValue && !(coverageInfo.type() & this.typeFilterValue)) {\n return false;\n }\n // If it's a parent, check if any children are visible\n if (coverageInfo.sourcesURLCoverageInfo.size > 0) {\n for (const sourceURLCoverageInfo of coverageInfo.sourcesURLCoverageInfo.values()) {\n if (this.isVisible(ignoreTextFilter, sourceURLCoverageInfo)) {\n return true;\n }\n }\n }\n\n return ignoreTextFilter || !this.textFilterRegExp || this.textFilterRegExp.test(url);\n }\n\n async exportReport(): Promise {\n const fos = new Bindings.FileUtils.FileOutputStream();\n const fileName =\n `Coverage-${Platform.DateUtilities.toISO8601Compact(new Date())}.json` as Platform.DevToolsPath.RawPathString;\n const accepted = await fos.open(fileName);\n if (!accepted) {\n return;\n }\n this.model && await this.model.exportReport(fos);\n }\n\n selectCoverageItemByUrl(url: string): void {\n this.listView.selectByUrl(url);\n }\n\n static readonly EXTENSION_BINDINGS_URL_PREFIX = 'extensions::';\n\n override wasShown(): void {\n UI.Context.Context.instance().setFlavor(CoverageView, this);\n super.wasShown();\n this.registerCSSFiles([coverageViewStyles]);\n }\n\n override willHide(): void {\n super.willHide();\n UI.Context.Context.instance().setFlavor(CoverageView, null);\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(_context: UI.Context.Context, actionId: string): boolean {\n const coverageViewId = 'coverage';\n void UI.ViewManager.ViewManager.instance()\n .showView(coverageViewId, /** userGesture= */ false, /** omitFocus= */ true)\n .then(() => {\n const view = UI.ViewManager.ViewManager.instance().view(coverageViewId);\n return view && view.widget();\n })\n .then(widget => this.innerHandleAction(widget as CoverageView, actionId));\n\n return true;\n }\n\n private innerHandleAction(coverageView: CoverageView, actionId: string): void {\n switch (actionId) {\n case 'coverage.toggle-recording':\n coverageView.toggleRecording();\n break;\n case 'coverage.start-with-reload':\n void coverageView.startRecording({reload: true, jsCoveragePerBlock: coverageView.isBlockCoverageSelected()});\n break;\n case 'coverage.clear':\n coverageView.clear();\n break;\n case 'coverage.export':\n void coverageView.exportReport();\n break;\n default:\n console.assert(false, `Unknown action: ${actionId}`);\n }\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"CoverageView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/coverage/CoverageView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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 * 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 Workspace from '../../models/workspace/workspace.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {CoverageDecorationManager} from './CoverageDecorationManager.js';\nimport {CoverageListView} from './CoverageListView.js';\nimport {type CoverageInfo, CoverageModel, CoverageType, Events, type URLCoverageInfo} from './CoverageModel.js';\nimport coverageViewStyles from './coverageView.css.js';\n\nconst UIStrings = {\n /**\n *@description Tooltip in Coverage List View of the Coverage tab for selecting JavaScript coverage mode\n */\n chooseCoverageGranularityPer:\n 'Choose coverage granularity: Per function has low overhead, per block has significant overhead.',\n /**\n *@description Text in Coverage List View of the Coverage tab\n */\n perFunction: 'Per function',\n /**\n *@description Text in Coverage List View of the Coverage tab\n */\n perBlock: 'Per block',\n /**\n *@description Text in Coverage View of the Coverage tab\n */\n filterByUrl: 'Filter by URL',\n /**\n *@description Label for the type filter in the Converage Panel\n */\n filterCoverageByType: 'Filter coverage by type',\n /**\n *@description Text for everything\n */\n all: 'All',\n /**\n *@description Text that appears on a button for the css resource type filter.\n */\n css: 'CSS',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n javascript: 'JavaScript',\n /**\n *@description Tooltip text that appears on the setting when hovering over it in Coverage View of the Coverage tab\n */\n includeExtensionContentScripts: 'Include extension content scripts',\n /**\n *@description Title for a type of source files\n */\n contentScripts: 'Content scripts',\n /**\n *@description Message in Coverage View of the Coverage tab\n *@example {record button icon} PH1\n */\n clickTheReloadButtonSToReloadAnd: 'Click the reload button {PH1} to reload and start capturing coverage.',\n /**\n *@description Message in Coverage View of the Coverage tab\n *@example {record button icon} PH1\n */\n clickTheRecordButtonSToStart: 'Click the record button {PH1} to start capturing coverage.',\n /**\n *@description Message in the Coverage View explaining that DevTools could not capture coverage.\n */\n bfcacheNoCapture: 'Could not capture coverage info because the page was served from the back/forward cache.',\n /**\n *@description Message in the Coverage View explaining that DevTools could not capture coverage.\n */\n activationNoCapture: 'Could not capture coverage info because the page was prerendered in the background.',\n /**\n *@description Message in the Coverage View prompting the user to reload the page.\n *@example {reload button icon} PH1\n */\n reloadPrompt: 'Click the reload button {PH1} to reload and get coverage.',\n\n /**\n *@description Footer message in Coverage View of the Coverage tab\n *@example {300k used, 600k unused} PH1\n *@example {500k used, 800k unused} PH2\n */\n filteredSTotalS: 'Filtered: {PH1} Total: {PH2}',\n /**\n *@description Footer message in Coverage View of the Coverage tab\n *@example {1.5 MB} PH1\n *@example {2.1 MB} PH2\n *@example {71%} PH3\n *@example {29%} PH4\n */\n sOfSSUsedSoFarSUnused: '{PH1} of {PH2} ({PH3}%) used so far, {PH4} unused.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/coverage/CoverageView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nlet coverageViewInstance: CoverageView|undefined;\n\nexport class CoverageView extends UI.Widget.VBox {\n private model: CoverageModel|null;\n private decorationManager: CoverageDecorationManager|null;\n private readonly coverageTypeComboBox: UI.Toolbar.ToolbarComboBox;\n private readonly coverageTypeComboBoxSetting: Common.Settings.Setting;\n private toggleRecordAction: UI.ActionRegistration.Action;\n private readonly toggleRecordButton: UI.Toolbar.ToolbarButton;\n private inlineReloadButton: Element|null;\n private readonly startWithReloadButton: UI.Toolbar.ToolbarButton|undefined;\n private readonly clearAction: UI.ActionRegistration.Action;\n private readonly exportAction: UI.ActionRegistration.Action;\n private textFilterRegExp: RegExp|null;\n private readonly filterInput: UI.Toolbar.ToolbarInput;\n private typeFilterValue: number|null;\n private readonly filterByTypeComboBox: UI.Toolbar.ToolbarComboBox;\n private showContentScriptsSetting: Common.Settings.Setting;\n private readonly contentScriptsCheckbox: UI.Toolbar.ToolbarSettingCheckbox;\n private readonly coverageResultsElement: HTMLElement;\n private readonly landingPage: UI.Widget.VBox;\n private readonly bfcacheReloadPromptPage: UI.Widget.VBox;\n private readonly activationReloadPromptPage: UI.Widget.VBox;\n private listView: CoverageListView;\n private readonly statusToolbarElement: HTMLElement;\n private statusMessageElement: HTMLElement;\n\n constructor() {\n super(true);\n\n this.element.setAttribute('jslog', `${VisualLogging.panel('coverage').track({resize: true})}`);\n\n this.model = null;\n this.decorationManager = null;\n\n const toolbarContainer = this.contentElement.createChild('div', 'coverage-toolbar-container');\n toolbarContainer.setAttribute('jslog', `${VisualLogging.toolbar()}`);\n const toolbar = new UI.Toolbar.Toolbar('coverage-toolbar', toolbarContainer);\n toolbar.makeWrappable(true);\n\n this.coverageTypeComboBox = new UI.Toolbar.ToolbarComboBox(\n this.onCoverageTypeComboBoxSelectionChanged.bind(this), i18nString(UIStrings.chooseCoverageGranularityPer),\n undefined, 'coverage-type');\n const coverageTypes = [\n {\n label: i18nString(UIStrings.perFunction),\n value: CoverageType.JAVA_SCRIPT | CoverageType.JAVA_SCRIPT_PER_FUNCTION,\n },\n {\n label: i18nString(UIStrings.perBlock),\n value: CoverageType.JAVA_SCRIPT,\n },\n ];\n for (const type of coverageTypes) {\n this.coverageTypeComboBox.addOption(this.coverageTypeComboBox.createOption(type.label, `${type.value}`));\n }\n this.coverageTypeComboBoxSetting =\n Common.Settings.Settings.instance().createSetting('coverage-view-coverage-type', 0);\n this.coverageTypeComboBox.setSelectedIndex(this.coverageTypeComboBoxSetting.get());\n this.coverageTypeComboBox.setEnabled(true);\n toolbar.appendToolbarItem(this.coverageTypeComboBox);\n this.toggleRecordAction = UI.ActionRegistry.ActionRegistry.instance().getAction('coverage.toggle-recording');\n this.toggleRecordButton = UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction);\n toolbar.appendToolbarItem(this.toggleRecordButton);\n\n const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const mainTargetSupportsRecordOnReload = mainTarget && mainTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);\n this.inlineReloadButton = null;\n if (mainTargetSupportsRecordOnReload) {\n this.startWithReloadButton = UI.Toolbar.Toolbar.createActionButtonForId('coverage.start-with-reload');\n toolbar.appendToolbarItem(this.startWithReloadButton);\n this.toggleRecordButton.setEnabled(false);\n this.toggleRecordButton.setVisible(false);\n }\n this.clearAction = UI.ActionRegistry.ActionRegistry.instance().getAction('coverage.clear');\n this.clearAction.setEnabled(false);\n toolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.clearAction));\n\n toolbar.appendSeparator();\n this.exportAction = UI.ActionRegistry.ActionRegistry.instance().getAction('coverage.export');\n this.exportAction.setEnabled(false);\n toolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.exportAction));\n\n this.textFilterRegExp = null;\n toolbar.appendSeparator();\n this.filterInput = new UI.Toolbar.ToolbarFilter(i18nString(UIStrings.filterByUrl), 0.4, 1);\n this.filterInput.setEnabled(false);\n this.filterInput.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.onFilterChanged, this);\n toolbar.appendToolbarItem(this.filterInput);\n\n toolbar.appendSeparator();\n\n this.typeFilterValue = null;\n this.filterByTypeComboBox = new UI.Toolbar.ToolbarComboBox(\n this.onFilterByTypeChanged.bind(this), i18nString(UIStrings.filterCoverageByType), undefined,\n 'coverage-by-type');\n const options = [\n {\n label: i18nString(UIStrings.all),\n value: '',\n },\n {\n label: i18nString(UIStrings.css),\n value: CoverageType.CSS,\n },\n {\n label: i18nString(UIStrings.javascript),\n value: CoverageType.JAVA_SCRIPT | CoverageType.JAVA_SCRIPT_PER_FUNCTION,\n },\n ];\n for (const option of options) {\n this.filterByTypeComboBox.addOption(this.filterByTypeComboBox.createOption(option.label, `${option.value}`));\n }\n\n this.filterByTypeComboBox.setSelectedIndex(0);\n this.filterByTypeComboBox.setEnabled(false);\n toolbar.appendToolbarItem(this.filterByTypeComboBox);\n\n toolbar.appendSeparator();\n this.showContentScriptsSetting = Common.Settings.Settings.instance().createSetting('show-content-scripts', false);\n this.showContentScriptsSetting.addChangeListener(this.onFilterChanged, this);\n this.contentScriptsCheckbox = new UI.Toolbar.ToolbarSettingCheckbox(\n this.showContentScriptsSetting, i18nString(UIStrings.includeExtensionContentScripts),\n i18nString(UIStrings.contentScripts));\n this.contentScriptsCheckbox.setEnabled(false);\n toolbar.appendToolbarItem(this.contentScriptsCheckbox);\n\n this.coverageResultsElement = this.contentElement.createChild('div', 'coverage-results');\n this.landingPage = this.buildLandingPage();\n this.bfcacheReloadPromptPage = this.buildReloadPromptPage(i18nString(UIStrings.bfcacheNoCapture), 'bfcache-page');\n this.activationReloadPromptPage =\n this.buildReloadPromptPage(i18nString(UIStrings.activationNoCapture), 'prerender-page');\n this.listView = new CoverageListView(this.isVisible.bind(this, false));\n\n this.statusToolbarElement = this.contentElement.createChild('div', 'coverage-toolbar-summary');\n this.statusMessageElement = this.statusToolbarElement.createChild('div', 'coverage-message');\n this.landingPage.show(this.coverageResultsElement);\n }\n\n static instance(): CoverageView {\n if (!coverageViewInstance) {\n coverageViewInstance = new CoverageView();\n }\n return coverageViewInstance;\n }\n\n static removeInstance(): void {\n coverageViewInstance = undefined;\n }\n\n private buildLandingPage(): UI.Widget.VBox {\n const widget = new UI.Widget.VBox();\n let message;\n if (this.startWithReloadButton) {\n this.inlineReloadButton =\n UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButtonForId('coverage.start-with-reload'));\n message = i18n.i18n.getFormatLocalizedString(\n str_, UIStrings.clickTheReloadButtonSToReloadAnd, {PH1: this.inlineReloadButton});\n } else {\n const recordButton =\n UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction));\n message = i18n.i18n.getFormatLocalizedString(str_, UIStrings.clickTheRecordButtonSToStart, {PH1: recordButton});\n }\n message.classList.add('message');\n widget.contentElement.appendChild(message);\n widget.element.classList.add('landing-page');\n return widget;\n }\n\n private buildReloadPromptPage(message: Common.UIString.LocalizedString, className: string): UI.Widget.VBox {\n const widget = new UI.Widget.VBox();\n const reasonDiv = document.createElement('div');\n reasonDiv.classList.add('message');\n reasonDiv.textContent = message;\n widget.contentElement.appendChild(reasonDiv);\n this.inlineReloadButton =\n UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButtonForId('inspector-main.reload'));\n const messageElement =\n i18n.i18n.getFormatLocalizedString(str_, UIStrings.reloadPrompt, {PH1: this.inlineReloadButton});\n messageElement.classList.add('message');\n widget.contentElement.appendChild(messageElement);\n widget.element.classList.add(className);\n return widget;\n }\n\n clear(): void {\n if (this.model) {\n this.model.reset();\n }\n this.reset();\n }\n\n private reset(): void {\n if (this.decorationManager) {\n this.decorationManager.dispose();\n this.decorationManager = null;\n }\n this.listView.reset();\n this.listView.detach();\n this.landingPage.show(this.coverageResultsElement);\n this.statusMessageElement.textContent = '';\n this.filterInput.setEnabled(false);\n this.filterByTypeComboBox.setEnabled(false);\n this.contentScriptsCheckbox.setEnabled(false);\n this.exportAction.setEnabled(false);\n }\n\n toggleRecording(): void {\n const enable = !this.toggleRecordAction.toggled();\n\n if (enable) {\n void this.startRecording({reload: false, jsCoveragePerBlock: this.isBlockCoverageSelected()});\n } else {\n void this.stopRecording();\n }\n }\n\n isBlockCoverageSelected(): boolean {\n const option = this.coverageTypeComboBox.selectedOption();\n const coverageType = Number(option ? option.value : Number.NaN);\n // Check that Coverage.CoverageType.JavaScriptPerFunction is not present.\n return coverageType === CoverageType.JAVA_SCRIPT;\n }\n\n private selectCoverageType(jsCoveragePerBlock: boolean): void {\n const selectedIndex = jsCoveragePerBlock ? 1 : 0;\n this.coverageTypeComboBox.setSelectedIndex(selectedIndex);\n }\n\n private onCoverageTypeComboBoxSelectionChanged(): void {\n this.coverageTypeComboBoxSetting.set(this.coverageTypeComboBox.selectedIndex());\n }\n\n async ensureRecordingStarted(): Promise {\n const enabled = this.toggleRecordAction.toggled();\n\n if (enabled) {\n await this.stopRecording();\n }\n await this.startRecording({reload: false, jsCoveragePerBlock: false});\n }\n\n async startRecording(options: {reload: (boolean|undefined), jsCoveragePerBlock: (boolean|undefined)}|\n null): Promise {\n let hadFocus, reloadButtonFocused;\n if ((this.startWithReloadButton && this.startWithReloadButton.element.hasFocus()) ||\n (this.inlineReloadButton && this.inlineReloadButton.hasFocus())) {\n reloadButtonFocused = true;\n } else if (this.hasFocus()) {\n hadFocus = true;\n }\n\n this.reset();\n const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!mainTarget) {\n return;\n }\n\n const {reload, jsCoveragePerBlock} = {reload: false, jsCoveragePerBlock: false, ...options};\n\n if (!this.model || reload) {\n this.model = mainTarget.model(CoverageModel);\n }\n if (!this.model) {\n return;\n }\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageStarted);\n if (jsCoveragePerBlock) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageStartedPerBlock);\n }\n const success = await this.model.start(Boolean(jsCoveragePerBlock));\n if (!success) {\n return;\n }\n this.selectCoverageType(Boolean(jsCoveragePerBlock));\n this.model.addEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n this.model.addEventListener(Events.SourceMapResolved, this.updateListView, this);\n const resourceTreeModel =\n mainTarget.model(SDK.ResourceTreeModel.ResourceTreeModel) as SDK.ResourceTreeModel.ResourceTreeModel | null;\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,\n this.onPrimaryPageChanged, this);\n this.decorationManager = new CoverageDecorationManager(\n this.model, Workspace.Workspace.WorkspaceImpl.instance(),\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(),\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance());\n this.toggleRecordAction.setToggled(true);\n this.clearAction.setEnabled(false);\n if (this.startWithReloadButton) {\n this.startWithReloadButton.setEnabled(false);\n this.startWithReloadButton.setVisible(false);\n this.toggleRecordButton.setEnabled(true);\n this.toggleRecordButton.setVisible(true);\n if (reloadButtonFocused) {\n this.toggleRecordButton.focus();\n }\n }\n this.coverageTypeComboBox.setEnabled(false);\n this.filterInput.setEnabled(true);\n this.filterByTypeComboBox.setEnabled(true);\n this.contentScriptsCheckbox.setEnabled(true);\n if (this.landingPage.isShowing()) {\n this.landingPage.detach();\n }\n this.listView.show(this.coverageResultsElement);\n if (hadFocus && !reloadButtonFocused) {\n this.listView.focus();\n }\n if (reload && resourceTreeModel) {\n resourceTreeModel.reloadPage();\n } else {\n void this.model.startPolling();\n }\n }\n\n private onCoverageDataReceived(event: Common.EventTarget.EventTargetEvent): void {\n const data = event.data;\n this.updateViews(data);\n }\n\n private updateListView(): void {\n this.listView.update(this.model && this.model.entries() || []);\n }\n\n async stopRecording(): Promise {\n SDK.TargetManager.TargetManager.instance().removeModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,\n this.onPrimaryPageChanged, this);\n if (this.hasFocus()) {\n this.listView.focus();\n }\n // Stopping the model triggers one last poll to get the final data.\n if (this.model) {\n await this.model.stop();\n this.model.removeEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n }\n this.toggleRecordAction.setToggled(false);\n this.coverageTypeComboBox.setEnabled(true);\n if (this.startWithReloadButton) {\n this.startWithReloadButton.setEnabled(true);\n this.startWithReloadButton.setVisible(true);\n this.toggleRecordButton.setEnabled(false);\n this.toggleRecordButton.setVisible(false);\n }\n this.clearAction.setEnabled(true);\n }\n\n processBacklog(): void {\n this.model && void this.model.processJSBacklog();\n }\n\n private async onPrimaryPageChanged(\n event: Common.EventTarget.EventTargetEvent<\n {frame: SDK.ResourceTreeModel.ResourceTreeFrame, type: SDK.ResourceTreeModel.PrimaryPageChangeType}>):\n Promise {\n const frame = event.data.frame;\n const coverageModel = frame.resourceTreeModel().target().model(CoverageModel);\n if (!coverageModel) {\n return;\n }\n // If the primary page target has changed (due to MPArch activation), switch to new CoverageModel.\n if (this.model !== coverageModel) {\n if (this.model) {\n await this.model.stop();\n this.model.removeEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n }\n this.model = coverageModel;\n const success = await this.model.start(this.isBlockCoverageSelected());\n if (!success) {\n return;\n }\n\n this.model.addEventListener(Events.CoverageUpdated, this.onCoverageDataReceived, this);\n this.decorationManager = new CoverageDecorationManager(\n this.model, Workspace.Workspace.WorkspaceImpl.instance(),\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(),\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance());\n }\n\n if (this.bfcacheReloadPromptPage.isShowing()) {\n this.bfcacheReloadPromptPage.detach();\n this.listView.show(this.coverageResultsElement);\n }\n if (this.activationReloadPromptPage.isShowing()) {\n this.activationReloadPromptPage.detach();\n this.listView.show(this.coverageResultsElement);\n }\n if (frame.backForwardCacheDetails.restoredFromCache) {\n this.listView.detach();\n this.bfcacheReloadPromptPage.show(this.coverageResultsElement);\n }\n if (event.data.type === SDK.ResourceTreeModel.PrimaryPageChangeType.ACTIVATION) {\n this.listView.detach();\n this.activationReloadPromptPage.show(this.coverageResultsElement);\n }\n\n this.model.reset();\n this.decorationManager && this.decorationManager.reset();\n this.listView.reset();\n void this.model.startPolling();\n }\n\n private updateViews(updatedEntries: CoverageInfo[]): void {\n this.updateStats();\n this.listView.update(this.model && this.model.entries() || []);\n this.exportAction.setEnabled(this.model !== null && this.model.entries().length > 0);\n this.decorationManager && this.decorationManager.update(updatedEntries);\n }\n\n private updateStats(): void {\n const all = {total: 0, unused: 0};\n const filtered = {total: 0, unused: 0};\n const filterApplied = this.textFilterRegExp !== null;\n if (this.model) {\n for (const info of this.model.entries()) {\n all.total += info.size();\n all.unused += info.unusedSize();\n if (this.isVisible(false, info)) {\n if (this.textFilterRegExp?.test(info.url())) {\n filtered.total += info.size();\n filtered.unused += info.unusedSize();\n } else {\n // If it doesn't match the filter, calculate the stats from visible children if there are any\n for (const childInfo of info.sourcesURLCoverageInfo.values()) {\n if (this.isVisible(false, childInfo)) {\n filtered.total += childInfo.size();\n filtered.unused += childInfo.unusedSize();\n }\n }\n }\n }\n }\n }\n this.statusMessageElement.textContent = filterApplied ?\n i18nString(UIStrings.filteredSTotalS, {PH1: formatStat(filtered), PH2: formatStat(all)}) :\n formatStat(all);\n\n function formatStat({total, unused}: {total: number, unused: number}): string {\n const used = total - unused;\n const percentUsed = total ? Math.round(100 * used / total) : 0;\n return i18nString(UIStrings.sOfSSUsedSoFarSUnused, {\n PH1: i18n.ByteUtilities.bytesToString(used),\n PH2: i18n.ByteUtilities.bytesToString(total),\n PH3: percentUsed,\n PH4: i18n.ByteUtilities.bytesToString(unused),\n });\n }\n }\n\n private onFilterChanged(): void {\n if (!this.listView) {\n return;\n }\n const text = this.filterInput.value();\n this.textFilterRegExp = text ? Platform.StringUtilities.createPlainTextSearchRegex(text, 'i') : null;\n this.listView.updateFilterAndHighlight(this.textFilterRegExp);\n this.updateStats();\n }\n\n private onFilterByTypeChanged(): void {\n if (!this.listView) {\n return;\n }\n\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageReportFiltered);\n\n const option = this.filterByTypeComboBox.selectedOption();\n const type = option && option.value;\n this.typeFilterValue = parseInt(type || '', 10) || null;\n this.listView.updateFilterAndHighlight(this.textFilterRegExp);\n this.updateStats();\n }\n\n private isVisible(ignoreTextFilter: boolean, coverageInfo: URLCoverageInfo): boolean {\n const url = coverageInfo.url();\n if (url.startsWith(CoverageView.EXTENSION_BINDINGS_URL_PREFIX)) {\n return false;\n }\n if (coverageInfo.isContentScript() && !this.showContentScriptsSetting.get()) {\n return false;\n }\n if (this.typeFilterValue && !(coverageInfo.type() & this.typeFilterValue)) {\n return false;\n }\n // If it's a parent, check if any children are visible\n if (coverageInfo.sourcesURLCoverageInfo.size > 0) {\n for (const sourceURLCoverageInfo of coverageInfo.sourcesURLCoverageInfo.values()) {\n if (this.isVisible(ignoreTextFilter, sourceURLCoverageInfo)) {\n return true;\n }\n }\n }\n\n return ignoreTextFilter || !this.textFilterRegExp || this.textFilterRegExp.test(url);\n }\n\n async exportReport(): Promise {\n const fos = new Bindings.FileUtils.FileOutputStream();\n const fileName =\n `Coverage-${Platform.DateUtilities.toISO8601Compact(new Date())}.json` as Platform.DevToolsPath.RawPathString;\n const accepted = await fos.open(fileName);\n if (!accepted) {\n return;\n }\n this.model && await this.model.exportReport(fos);\n }\n\n selectCoverageItemByUrl(url: string): void {\n this.listView.selectByUrl(url);\n }\n\n static readonly EXTENSION_BINDINGS_URL_PREFIX = 'extensions::';\n\n override wasShown(): void {\n UI.Context.Context.instance().setFlavor(CoverageView, this);\n super.wasShown();\n this.registerCSSFiles([coverageViewStyles]);\n }\n\n override willHide(): void {\n super.willHide();\n UI.Context.Context.instance().setFlavor(CoverageView, null);\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(_context: UI.Context.Context, actionId: string): boolean {\n const coverageViewId = 'coverage';\n void UI.ViewManager.ViewManager.instance()\n .showView(coverageViewId, /** userGesture= */ false, /** omitFocus= */ true)\n .then(() => {\n const view = UI.ViewManager.ViewManager.instance().view(coverageViewId);\n return view && view.widget();\n })\n .then(widget => this.innerHandleAction(widget as CoverageView, actionId));\n\n return true;\n }\n\n private innerHandleAction(coverageView: CoverageView, actionId: string): void {\n switch (actionId) {\n case 'coverage.toggle-recording':\n coverageView.toggleRecording();\n break;\n case 'coverage.start-with-reload':\n void coverageView.startRecording({reload: true, jsCoveragePerBlock: coverageView.isBlockCoverageSelected()});\n break;\n case 'coverage.clear':\n coverageView.clear();\n break;\n case 'coverage.export':\n void coverageView.exportReport();\n break;\n default:\n console.assert(false, `Unknown action: ${actionId}`);\n }\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/elements/ComputedStyleModel.d.ts b/public/panels/elements/ComputedStyleModel.d.ts index 5d17536c..59f62da3 100644 --- a/public/panels/elements/ComputedStyleModel.d.ts +++ b/public/panels/elements/ComputedStyleModel.d.ts @@ -20,7 +20,7 @@ export declare class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapp export declare const enum Events { COMPUTED_STYLE_CHANGED = "ComputedStyleChanged" } -export type ComputedStyleChangedEvent = SDK.CSSStyleSheetHeader.CSSStyleSheetHeader | SDK.CSSModel.StyleSheetChangedEvent | void | SDK.CSSModel.PseudoStateForcedEvent | null; +export type ComputedStyleChangedEvent = SDK.CSSStyleSheetHeader.CSSStyleSheetHeader | SDK.CSSModel.StyleSheetChangedEvent | SDK.CSSModel.PseudoStateForcedEvent | SDK.CSSModel.ComputedStyleUpdatedEvent | null | void; export type EventTypes = { [Events.COMPUTED_STYLE_CHANGED]: ComputedStyleChangedEvent; }; diff --git a/public/panels/elements/ComputedStyleModel.js b/public/panels/elements/ComputedStyleModel.js index 263b0bb5..0f3910e6 100644 --- a/public/panels/elements/ComputedStyleModel.js +++ b/public/panels/elements/ComputedStyleModel.js @@ -45,6 +45,7 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper { cssModel.addEventListener(SDK.CSSModel.Events.MediaQueryResultChanged, this.onComputedStyleChanged, this), cssModel.addEventListener(SDK.CSSModel.Events.PseudoStateForced, this.onComputedStyleChanged, this), cssModel.addEventListener(SDK.CSSModel.Events.ModelWasEnabled, this.onComputedStyleChanged, this), + cssModel.addEventListener(SDK.CSSModel.Events.ComputedStyleUpdated, this.onComputedStyleChanged, this), domModel.addEventListener(SDK.DOMModel.Events.DOMMutated, this.onDOMModelChanged, this), resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameResized, this.onFrameResized, this), ]; @@ -52,6 +53,11 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper { } onComputedStyleChanged(event) { delete this.computedStylePromise; + // If the event contains `nodeId` and that's not the same as this node's id + // we don't emit the COMPUTED_STYLE_CHANGED event. + if (event?.data && 'nodeId' in event.data && event.data.nodeId !== this.nodeInternal?.id) { + return; + } this.dispatchEventToListeners("ComputedStyleChanged" /* Events.COMPUTED_STYLE_CHANGED */, event?.data ?? null); } onDOMModelChanged(event) { diff --git a/public/panels/elements/ComputedStyleModel.js.map b/public/panels/elements/ComputedStyleModel.js.map index aad900ee..c04b2da0 100644 --- a/public/panels/elements/ComputedStyleModel.js.map +++ b/public/panels/elements/ComputedStyleModel.js.map @@ -1 +1 @@ -{"version":3,"file":"ComputedStyleModel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ComputedStyleModel.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAEhD,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,aAAa,CAAC,aAAyB;IAC5E,YAAY,CAA4B;IACxC,gBAAgB,CAA6B;IAC7C,cAAc,CAAuC;IACrD,iBAAiB,CAAU;IAC3B,oBAAoB,CAA+B;IAC3D;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/E,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QACzB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACxG,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;IACnG,CAAC;IAEO,aAAa,CAAC,KAAqE;QACzF,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC;QAC/B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrF,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEO,WAAW,CAAC,QAAoC;QACtD,IAAI,IAAI,CAAC,gBAAgB,KAAK,QAAQ,EAAE,CAAC;YACvC,OAAO;QACT,CAAC;QACD,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7G,IAAI,QAAQ,IAAI,QAAQ,IAAI,iBAAiB,EAAE,CAAC;YAC9C,IAAI,CAAC,cAAc,GAAG;gBACpB,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACjG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACnG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACnG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBAC9F,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,uBAAuB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACzG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACnG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACjG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC;gBACvF,iBAAiB,CAAC,gBAAgB,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC;aACzG,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,KAA0E;QACvG,OAAO,IAAI,CAAC,oBAAoB,CAAC;QACjC,IAAI,CAAC,wBAAwB,6DAAgC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC;IACpF,CAAC;IAEO,iBAAiB,CAAC,KAAgE;QACxF,kFAAkF;QAClF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,YAAY;YAClB,IAAI,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,YAAY,CAAC,UAAU;gBAC1E,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEO,cAAc;QACpB,SAAS,eAAe;YACtB,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC,iBAAiB,CAAC;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9E,CAAC;IAEO,WAAW;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,sBAAsB,EAAE,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC/B,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;QAC7G,CAAC;QAED,OAAO,IAAI,CAAC,oBAAoB,CAAC;QAEjC,SAAS,cAAc,CACO,WAAiC,EAAE,KAA+B;YAE9F,OAAO,WAAW,KAAK,IAAI,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;gBACvC,IAA4B,CAAC;QACpF,CAAC;IACH,CAAC;CACF;AAcD,MAAM,OAAO,aAAa;IACxB,IAAI,CAAuB;IAC3B,aAAa,CAAsB;IACnC,YAAY,IAA0B,EAAE,aAAkC;QACxE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF","sourcesContent":["// Copyright (c) 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 SDK from '../../core/sdk/sdk.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nexport class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper {\n private nodeInternal: SDK.DOMModel.DOMNode|null;\n private cssModelInternal: SDK.CSSModel.CSSModel|null;\n private eventListeners: Common.EventTarget.EventDescriptor[];\n private frameResizedTimer?: number;\n private computedStylePromise?: Promise;\n constructor() {\n super();\n this.nodeInternal = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n this.cssModelInternal = null;\n this.eventListeners = [];\n UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.onNodeChanged, this);\n }\n\n node(): SDK.DOMModel.DOMNode|null {\n return this.nodeInternal;\n }\n\n cssModel(): SDK.CSSModel.CSSModel|null {\n return this.cssModelInternal && this.cssModelInternal.isEnabled() ? this.cssModelInternal : null;\n }\n\n private onNodeChanged(event: Common.EventTarget.EventTargetEvent): void {\n this.nodeInternal = event.data;\n this.updateModel(this.nodeInternal ? this.nodeInternal.domModel().cssModel() : null);\n this.onComputedStyleChanged(null);\n }\n\n private updateModel(cssModel: SDK.CSSModel.CSSModel|null): void {\n if (this.cssModelInternal === cssModel) {\n return;\n }\n Common.EventTarget.removeEventListeners(this.eventListeners);\n this.cssModelInternal = cssModel;\n const domModel = cssModel ? cssModel.domModel() : null;\n const resourceTreeModel = cssModel ? cssModel.target().model(SDK.ResourceTreeModel.ResourceTreeModel) : null;\n if (cssModel && domModel && resourceTreeModel) {\n this.eventListeners = [\n cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetChanged, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.FontsUpdated, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.MediaQueryResultChanged, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.PseudoStateForced, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.ModelWasEnabled, this.onComputedStyleChanged, this),\n domModel.addEventListener(SDK.DOMModel.Events.DOMMutated, this.onDOMModelChanged, this),\n resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameResized, this.onFrameResized, this),\n ];\n }\n }\n\n private onComputedStyleChanged(event: Common.EventTarget.EventTargetEvent|null): void {\n delete this.computedStylePromise;\n this.dispatchEventToListeners(Events.COMPUTED_STYLE_CHANGED, event?.data ?? null);\n }\n\n private onDOMModelChanged(event: Common.EventTarget.EventTargetEvent): void {\n // Any attribute removal or modification can affect the styles of \"related\" nodes.\n const node = event.data;\n if (!this.nodeInternal ||\n this.nodeInternal !== node && node.parentNode !== this.nodeInternal.parentNode &&\n !node.isAncestor(this.nodeInternal)) {\n return;\n }\n this.onComputedStyleChanged(null);\n }\n\n private onFrameResized(): void {\n function refreshContents(this: ComputedStyleModel): void {\n this.onComputedStyleChanged(null);\n delete this.frameResizedTimer;\n }\n\n if (this.frameResizedTimer) {\n clearTimeout(this.frameResizedTimer);\n }\n\n this.frameResizedTimer = window.setTimeout(refreshContents.bind(this), 100);\n }\n\n private elementNode(): SDK.DOMModel.DOMNode|null {\n const node = this.node();\n if (!node) {\n return null;\n }\n return node.enclosingElementOrSelf();\n }\n\n async fetchComputedStyle(): Promise {\n const elementNode = this.elementNode();\n const cssModel = this.cssModel();\n if (!elementNode || !cssModel) {\n return null;\n }\n const nodeId = elementNode.id;\n if (!nodeId) {\n return null;\n }\n\n if (!this.computedStylePromise) {\n this.computedStylePromise = cssModel.getComputedStyle(nodeId).then(verifyOutdated.bind(this, elementNode));\n }\n\n return this.computedStylePromise;\n\n function verifyOutdated(\n this: ComputedStyleModel, elementNode: SDK.DOMModel.DOMNode, style: Map|null): ComputedStyle|\n null {\n return elementNode === this.elementNode() && style ? new ComputedStyle(elementNode, style) :\n null as ComputedStyle | null;\n }\n }\n}\n\nexport const enum Events {\n COMPUTED_STYLE_CHANGED = 'ComputedStyleChanged',\n}\n\nexport type ComputedStyleChangedEvent = SDK.CSSStyleSheetHeader.CSSStyleSheetHeader|\n SDK.CSSModel.StyleSheetChangedEvent|void|SDK.CSSModel.PseudoStateForcedEvent|\n null;\n\nexport type EventTypes = {\n [Events.COMPUTED_STYLE_CHANGED]: ComputedStyleChangedEvent,\n};\n\nexport class ComputedStyle {\n node: SDK.DOMModel.DOMNode;\n computedStyle: Map;\n constructor(node: SDK.DOMModel.DOMNode, computedStyle: Map) {\n this.node = node;\n this.computedStyle = computedStyle;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ComputedStyleModel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ComputedStyleModel.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAEhD,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,aAAa,CAAC,aAAyB;IAC5E,YAAY,CAA4B;IACxC,gBAAgB,CAA6B;IAC7C,cAAc,CAAuC;IACrD,iBAAiB,CAAU;IAC3B,oBAAoB,CAA+B;IAC3D;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/E,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QACzB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACxG,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;IACnG,CAAC;IAEO,aAAa,CAAC,KAAqE;QACzF,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC;QAC/B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrF,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEO,WAAW,CAAC,QAAoC;QACtD,IAAI,IAAI,CAAC,gBAAgB,KAAK,QAAQ,EAAE,CAAC;YACvC,OAAO;QACT,CAAC;QACD,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7G,IAAI,QAAQ,IAAI,QAAQ,IAAI,iBAAiB,EAAE,CAAC;YAC9C,IAAI,CAAC,cAAc,GAAG;gBACpB,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACjG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACnG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACnG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBAC9F,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,uBAAuB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACzG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACnG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACjG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC;gBACtG,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC;gBACvF,iBAAiB,CAAC,gBAAgB,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC;aACzG,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,KAA0E;QACvG,OAAO,IAAI,CAAC,oBAAoB,CAAC;QACjC,2EAA2E;QAC3E,kDAAkD;QAClD,IAAI,KAAK,EAAE,IAAI,IAAI,QAAQ,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,CAAC;YACzF,OAAO;QACT,CAAC;QAED,IAAI,CAAC,wBAAwB,6DAAgC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC;IACpF,CAAC;IAEO,iBAAiB,CAAC,KAAgE;QACxF,kFAAkF;QAClF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,YAAY;YAClB,IAAI,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,YAAY,CAAC,UAAU;gBAC1E,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEO,cAAc;QACpB,SAAS,eAAe;YACtB,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC,iBAAiB,CAAC;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9E,CAAC;IAEO,WAAW;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,sBAAsB,EAAE,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC/B,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;QAC7G,CAAC;QAED,OAAO,IAAI,CAAC,oBAAoB,CAAC;QAEjC,SAAS,cAAc,CACO,WAAiC,EAAE,KAA+B;YAE9F,OAAO,WAAW,KAAK,IAAI,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;gBACvC,IAA4B,CAAC;QACpF,CAAC;IACH,CAAC;CACF;AAcD,MAAM,OAAO,aAAa;IACxB,IAAI,CAAuB;IAC3B,aAAa,CAAsB;IACnC,YAAY,IAA0B,EAAE,aAAkC;QACxE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF","sourcesContent":["// Copyright (c) 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 SDK from '../../core/sdk/sdk.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nexport class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper {\n private nodeInternal: SDK.DOMModel.DOMNode|null;\n private cssModelInternal: SDK.CSSModel.CSSModel|null;\n private eventListeners: Common.EventTarget.EventDescriptor[];\n private frameResizedTimer?: number;\n private computedStylePromise?: Promise;\n constructor() {\n super();\n this.nodeInternal = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n this.cssModelInternal = null;\n this.eventListeners = [];\n UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.onNodeChanged, this);\n }\n\n node(): SDK.DOMModel.DOMNode|null {\n return this.nodeInternal;\n }\n\n cssModel(): SDK.CSSModel.CSSModel|null {\n return this.cssModelInternal && this.cssModelInternal.isEnabled() ? this.cssModelInternal : null;\n }\n\n private onNodeChanged(event: Common.EventTarget.EventTargetEvent): void {\n this.nodeInternal = event.data;\n this.updateModel(this.nodeInternal ? this.nodeInternal.domModel().cssModel() : null);\n this.onComputedStyleChanged(null);\n }\n\n private updateModel(cssModel: SDK.CSSModel.CSSModel|null): void {\n if (this.cssModelInternal === cssModel) {\n return;\n }\n Common.EventTarget.removeEventListeners(this.eventListeners);\n this.cssModelInternal = cssModel;\n const domModel = cssModel ? cssModel.domModel() : null;\n const resourceTreeModel = cssModel ? cssModel.target().model(SDK.ResourceTreeModel.ResourceTreeModel) : null;\n if (cssModel && domModel && resourceTreeModel) {\n this.eventListeners = [\n cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetChanged, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.FontsUpdated, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.MediaQueryResultChanged, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.PseudoStateForced, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.ModelWasEnabled, this.onComputedStyleChanged, this),\n cssModel.addEventListener(SDK.CSSModel.Events.ComputedStyleUpdated, this.onComputedStyleChanged, this),\n domModel.addEventListener(SDK.DOMModel.Events.DOMMutated, this.onDOMModelChanged, this),\n resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameResized, this.onFrameResized, this),\n ];\n }\n }\n\n private onComputedStyleChanged(event: Common.EventTarget.EventTargetEvent|null): void {\n delete this.computedStylePromise;\n // If the event contains `nodeId` and that's not the same as this node's id\n // we don't emit the COMPUTED_STYLE_CHANGED event.\n if (event?.data && 'nodeId' in event.data && event.data.nodeId !== this.nodeInternal?.id) {\n return;\n }\n\n this.dispatchEventToListeners(Events.COMPUTED_STYLE_CHANGED, event?.data ?? null);\n }\n\n private onDOMModelChanged(event: Common.EventTarget.EventTargetEvent): void {\n // Any attribute removal or modification can affect the styles of \"related\" nodes.\n const node = event.data;\n if (!this.nodeInternal ||\n this.nodeInternal !== node && node.parentNode !== this.nodeInternal.parentNode &&\n !node.isAncestor(this.nodeInternal)) {\n return;\n }\n this.onComputedStyleChanged(null);\n }\n\n private onFrameResized(): void {\n function refreshContents(this: ComputedStyleModel): void {\n this.onComputedStyleChanged(null);\n delete this.frameResizedTimer;\n }\n\n if (this.frameResizedTimer) {\n clearTimeout(this.frameResizedTimer);\n }\n\n this.frameResizedTimer = window.setTimeout(refreshContents.bind(this), 100);\n }\n\n private elementNode(): SDK.DOMModel.DOMNode|null {\n const node = this.node();\n if (!node) {\n return null;\n }\n return node.enclosingElementOrSelf();\n }\n\n async fetchComputedStyle(): Promise {\n const elementNode = this.elementNode();\n const cssModel = this.cssModel();\n if (!elementNode || !cssModel) {\n return null;\n }\n const nodeId = elementNode.id;\n if (!nodeId) {\n return null;\n }\n\n if (!this.computedStylePromise) {\n this.computedStylePromise = cssModel.getComputedStyle(nodeId).then(verifyOutdated.bind(this, elementNode));\n }\n\n return this.computedStylePromise;\n\n function verifyOutdated(\n this: ComputedStyleModel, elementNode: SDK.DOMModel.DOMNode, style: Map|null): ComputedStyle|\n null {\n return elementNode === this.elementNode() && style ? new ComputedStyle(elementNode, style) :\n null as ComputedStyle | null;\n }\n }\n}\n\nexport const enum Events {\n COMPUTED_STYLE_CHANGED = 'ComputedStyleChanged',\n}\n\nexport type ComputedStyleChangedEvent = SDK.CSSStyleSheetHeader.CSSStyleSheetHeader|\n SDK.CSSModel.StyleSheetChangedEvent|SDK.CSSModel.PseudoStateForcedEvent|\n SDK.CSSModel.ComputedStyleUpdatedEvent|null|void;\n\nexport type EventTypes = {\n [Events.COMPUTED_STYLE_CHANGED]: ComputedStyleChangedEvent,\n};\n\nexport class ComputedStyle {\n node: SDK.DOMModel.DOMNode;\n computedStyle: Map;\n constructor(node: SDK.DOMModel.DOMNode, computedStyle: Map) {\n this.node = node;\n this.computedStyle = computedStyle;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/elements/ComputedStyleWidget.d.ts b/public/panels/elements/ComputedStyleWidget.d.ts index db2fb594..0514cc0d 100644 --- a/public/panels/elements/ComputedStyleWidget.d.ts +++ b/public/panels/elements/ComputedStyleWidget.d.ts @@ -12,6 +12,7 @@ export declare class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWid constructor(); onResize(): void; wasShown(): void; + willHide(): void; doUpdate(): Promise; private fetchMatchedCascade; private rebuildAlphabeticalList; diff --git a/public/panels/elements/ComputedStyleWidget.js b/public/panels/elements/ComputedStyleWidget.js index ef626738..6129fc7b 100644 --- a/public/panels/elements/ComputedStyleWidget.js +++ b/public/panels/elements/ComputedStyleWidget.js @@ -231,6 +231,9 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget { const fontsWidget = new PlatformFontsWidget(this.computedStyleModel); fontsWidget.show(this.contentElement); } + #handleNodeChange(event) { + void this.computedStyleModel.cssModel()?.trackComputedStyleUpdatesForNode(event.data?.id); + } onResize() { const isNarrow = this.contentElement.offsetWidth < 260; this.#computedStylesTree.classList.toggle('computed-narrow', isNarrow); @@ -238,6 +241,12 @@ export class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget { wasShown() { super.wasShown(); this.registerCSSFiles([computedStyleSidebarPaneStyles]); + void this.computedStyleModel.cssModel()?.trackComputedStyleUpdatesForNode(this.computedStyleModel.node()?.id); + UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.#handleNodeChange, this); + } + willHide() { + void this.computedStyleModel.cssModel()?.trackComputedStyleUpdatesForNode(undefined); + UI.Context.Context.instance().removeFlavorChangeListener(SDK.DOMModel.DOMNode, this.#handleNodeChange, this); } async doUpdate() { const [nodeStyles, matchedStyles] = await Promise.all([this.computedStyleModel.fetchComputedStyle(), this.fetchMatchedCascade()]); diff --git a/public/panels/elements/ComputedStyleWidget.js.map b/public/panels/elements/ComputedStyleWidget.js.map index 3600c341..b9273b7f 100644 --- a/public/panels/elements/ComputedStyleWidget.js.map +++ b/public/panels/elements/ComputedStyleWidget.js.map @@ -1 +1 @@ -{"version":3,"file":"ComputedStyleWidget.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ComputedStyleWidget.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,kDAAkD,CAAC;AAChF,OAAO,KAAK,YAAY,MAAM,2DAA2D,CAAC;AAC1F,OAAO,KAAK,UAAU,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,OAAO,MAAM,+BAA+B,CAAC;AAEzD,OAAO,KAAK,kBAAkB,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAqB,kBAAkB,EAAS,MAAM,yBAAyB,CAAC;AACvF,OAAO,8BAA8B,MAAM,mCAAmC,CAAC;AAC/E,OAAO,EAAC,mBAAmB,EAAC,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAC,mBAAmB,EAAC,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAkB,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAC,sBAAsB,EAAiB,oBAAoB,EAAC,MAAM,6BAA6B,CAAC;AACxG,OAAO,EAAqB,QAAQ,EAAyB,cAAc,EAAE,WAAW,EAAC,MAAM,uBAAuB,CAAC;AACvH,OAAO,EAAC,sBAAsB,EAAC,MAAM,6BAA6B,CAAC;AAEnE,MAAM,EAAC,IAAI,EAAC,GAAG,OAAO,CAAC;AAEvB,MAAM,SAAS,GAAG;IAChB;;;;OAIG;IACH,OAAO,EAAE,UAAU;IACnB;;;OAGG;IACH,KAAK,EAAE,OAAO;IACd;;;OAGG;IACH,kBAAkB,EAAE,sBAAsB;IAC1C;;;OAGG;IACH,wBAAwB,EAAE,6BAA6B;IACvD;;;OAGG;IACH,eAAe,EAAE,mBAAmB;CACrC,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,wCAAwC,EAAE,SAAS,CAAC,CAAC;AAC9F,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE;;;;;;;;;;;;GAYG;AACH,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAA2C,CAAC;AAEjF,SAAS,sBAAsB,CAC3B,IAA0B,EAAE,YAAoB,EAAE,aAAqB;IACzE,MAAM,QAAQ,GAAG,YAAY,GAAG,GAAG,GAAG,aAAa,CAAC;IACpD,MAAM,cAAc,GAAG,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;IACtD,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;IACnB,MAAM,KAAK,GAAG,QAAQ,CAAC,kBAAkB,CACrC,YAAY,EAAE,aAAa,EAAE,CAAC,IAAI,aAAa,EAAE,EAAE,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,cAAc,EAAE,CAAC,CAAC,CAAC;IAC3G,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC;IACrB,qBAAqB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAC,IAAI,EAAE,KAAK,EAAC,CAAC,CAAC;IACnD,OAAO,EAAC,IAAI,EAAE,KAAK,EAAC,CAAC;AACvB,CAAC;AAED;;;IAGI;AACJ,MAAM,qBAAqB,GACvB,CAAC,IAA0B,EAAE,YAAoB,EAAE,aAAqB,EAAE,SAAkB,EAAE,SAAkB,EAC/G,cAAqD,EACrD,aAAuC,EAA0B,EAAE;IAClE,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,sBAAsB,CAAC,IAAI,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IAChF,mBAAmB;IACnB,OAAO,IAAI,CAAA;qBACI,SAAS;qBACT,SAAS;yBACL,aAAa;8BACR,CAAC,KAAqE,EAAO,EAAE;QACnG,IAAI,cAAc,EAAE,CAAC;YACnB,gBAAgB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;YACG,IAAI;YACJ,KAAK;0CACyB,CAAC;IACrC,kBAAkB;AACpB,CAAC,CAAC;AAEN,MAAM,kBAAkB,GACpB,CAAC,IAA0B,EAAE,QAAqC,EAAE,oBAA6B,EAChG,aAAoD,EACpD,SAAyC,EAA4D,EAAE;IACtG,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;IAE7E,MAAM,YAAY,GAAG,QAAQ,CAAC,kBAAkB,CAC5C,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,aAAa,EAAE,EAAE,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,cAAc,EAAE,CAAC,CAAC,CAAC;IAC7G,YAAY,CAAC,IAAI,GAAG,aAAa,CAAC;IAClC,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAEhC,MAAM,IAAI,GAAI,QAAQ,CAAC,UAAU,CAAC,UAA8C,CAAC;IACjF,IAAI,cAAc,CAAC;IACnB,IAAI,IAAI,EAAE,CAAC;QACT,cAAc,GAAG,sBAAsB,CAAC,oBAAoB,CAAC,aAAa,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/F,CAAC;IACD,KAAK,CAAC,IAAI,GAAG;QACX,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,eAAe;QACtD,MAAM,EAAE,CAAC,oBAAoB;QAC7B,kBAAkB,EAAE,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;QACzD,cAAc;KACf,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEN,MAAM,aAAa;IACjB,MAAM,CAAC,KAAiB,EAAE,OAAyB;QACjD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC1D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACpD,YAAY,CAAC,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAE5B,MAAM,CAAC,gBAAgB,CACnB,YAAY,CAAC,WAAW,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC,KAAiD,EAAE,EAAE;YAC1G,MAAM,EAAC,IAAI,EAAE,EAAC,KAAK,EAAC,EAAC,GAAG,KAAK,CAAC;YAC9B,YAAY,CAAC,WAAW,GAAG,KAAK,CAAC,eAAe,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACzE,CAAC,CAAC,CAAC;QAEP,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,YAAY,EAAE,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,gBAAgB,GAAG,CAAC,WAAwC,EAAE,KAAa,EAAQ,EAAE;IACzF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACzC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAa,EAAE,KAAa,EAAU,EAAE;IAC9D,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChE,OAAO,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC9E,OAAO,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAClE,CAAC,CAAC;AAgBF,MAAM,OAAO,mBAAoB,SAAQ,EAAE,CAAC,eAAe,CAAC,eAAe;IACjE,kBAAkB,CAAqB;IAC9B,2CAA2C,CAAmC;IAC9E,0BAA0B,CAAmC;IAC9E,KAAK,CAA0B;IACvB,WAAW,CAAc;IAChB,gBAAgB,CAAc;IAC9B,SAAS,CAAiC;IAC1C,mBAAmB,CAAsB;IAE1D,mBAAmB,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,WAAW,EAAqB,CAAC;IACnF,SAAS,CAA8D;IAEvE;QACE,KAAK,CAAC,IAAI,CAAC,CAAC;QAEZ,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QAE1E,IAAI,CAAC,kBAAkB,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACnD,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,6DAAgC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAE3F,IAAI,CAAC,2CAA2C;YAC5C,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;QACzG,IAAI,CAAC,2CAA2C,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE3F,IAAI,CAAC,0BAA0B,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QACpH,IAAI,CAAC,0BAA0B,CAAC,iBAAiB,CAAC,GAAG,EAAE;YACrD,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,KAAK,EAAE,kCAAkC,CAAC,CAAC;QACxF,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;QACpE,MAAM,WAAW,GAAG,IAAI,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC/F,WAAW,CAAC,gBAAgB,iEAA6C,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QACrG,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAExB,OAAO,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,sBAAsB,CAC3D,IAAI,CAAC,2CAA2C,EAAE,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACjG,OAAO,CAAC,iBAAiB,CACrB,IAAI,EAAE,CAAC,OAAO,CAAC,sBAAsB,CAAC,IAAI,CAAC,0BAA0B,EAAE,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAEpH,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;QACpF,IAAI,CAAC,gBAAgB,CAAC,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QAE7E,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAE1D,IAAI,CAAC,SAAS,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAEnE,IAAI,CAAC,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,EAAE;YAC9E,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,IAAI,YAAY,OAAO,EAAE,CAAC;gBAC5B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;QAEzC,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACrE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IAEQ,QAAQ;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,GAAG,GAAG,CAAC;QACvD,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,MAAM,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IACzE,CAAC;IAEQ,QAAQ;QACf,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,IAAI,CAAC,gBAAgB,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC;IAC1D,CAAC;IAEQ,KAAK,CAAC,QAAQ;QACrB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAC7B,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC,UAAU,IAAI,CAAC,aAAa,EAAE,CAAC;YAClC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjD,OAAO;QACT,CAAC;QACD,MAAM,yBAAyB,GAAG,IAAI,CAAC,0BAA0B,CAAC,GAAG,EAAE,CAAC;QACxE,IAAI,yBAAyB,EAAE,CAAC;YAC9B,MAAM,IAAI,CAAC,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,uBAAuB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,mBAAmB;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC;QACpD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,QAAQ,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAElF,SAAS,cAAc,CAA4B,aAAyD;YAE1G,OAAO,aAAa,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;QACzG,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,SAAwB,EAAE,aAAoD;QAElH,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC;QACpD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QAED,MAAM,gBAAgB,GAAG,CAAC,GAAG,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7D,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAEtC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;QAC5B,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,sBAAsB,GAAG,IAAI,CAAC,6BAA6B,CAAC,aAAa,CAAC,CAAC;QACjF,MAAM,aAAa,GAAG,IAAI,CAAC,2CAA2C,CAAC,GAAG,EAAE,CAAC;QAC7E,MAAM,IAAI,GAA+D,EAAE,CAAC;QAC5E,KAAK,MAAM,YAAY,IAAI,gBAAgB,EAAE,CAAC;YAC5C,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YACtE,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;YACxF,MAAM,WAAW,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC/D,IAAI,CAAC,aAAa,IAAI,WAAW,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBACtF,SAAS;YACX,CAAC;YACD,IAAI,CAAC,aAAa,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpD,SAAS;YACX,CAAC;YACD,IAAI,YAAY,KAAK,aAAa,IAAI,aAAa,KAAK,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;gBACnG,SAAS;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;QAC1F,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,sBAAsB,CAAC,cAAc,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACzF,IAAI,CAAC,SAAS,GAAG;YACf,IAAI;YACJ,OAAO,EAAE,IAAI;YACb,eAAe;SAChB,CAAC;QACF,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAC5B,SAA6B,EAAE,aAAyD;QAC1F,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC;QACpD,IAAI,CAAC,SAAS,IAAI,CAAC,aAAa,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;QAC5B,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,sBAAsB,GAAG,IAAI,CAAC,6BAA6B,CAAC,aAAa,CAAC,CAAC;QACjF,MAAM,aAAa,GAAG,IAAI,CAAC,2CAA2C,CAAC,GAAG,EAAE,CAAC;QAE7E,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAsB,CAAC;QAE3D,MAAM,IAAI,GAA+D,EAAE,CAAC;QAC5E,KAAK,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,IAAI,SAAS,CAAC,aAAa,EAAE,CAAC;YACpE,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;YACxF,MAAM,WAAW,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC/D,IAAI,CAAC,aAAa,IAAI,WAAW,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBACtF,SAAS;YACX,CAAC;YACD,IAAI,CAAC,aAAa,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpD,SAAS;YACX,CAAC;YACD,IAAI,YAAY,KAAK,aAAa,IAAI,aAAa,KAAK,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;gBACnG,SAAS;YACX,CAAC;YAED,MAAM,UAAU,GAAG,sBAAsB,CAAC,YAAY,CAAC,CAAC;YACxD,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;gBAClC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACzC,CAAC;gBACD,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,mBAAmB,CAAC,cAAc,EAAE,CAAC;QAC1C,KAAK,MAAM,QAAQ,IAAI,oBAAoB,EAAE,CAAC;YAC5C,MAAM,UAAU,GAAG,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACtD,IAAI,UAAU,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxC,MAAM,aAAa,GAA+D,EAAE,CAAC;gBACrF,KAAK,MAAM,YAAY,IAAI,UAAU,EAAE,CAAC;oBACtC,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;oBACtE,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;oBACxF,MAAM,WAAW,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBAC/D,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;gBACnG,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAC,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,aAAa,EAAC,CAAC,CAAC;YAClH,CAAC;QACH,CAAC;QACD,MAAM,eAAe,GAAG,IAAI,CAAC,sBAAsB,CAAC,cAAc,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACzF,IAAI,CAAC,SAAS,GAAG;YACf,IAAI;YACJ,OAAO,EAAE,IAAI;YACb,eAAe;SAChB,CAAC;QACF,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACjC,CAAC;IAEO,cAAc,CAAC,QAAqC;QAE1D,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;QAC5C,OAAO;YACL,YAAY,EAAE;gBACZ,GAAG,EAAE,cAAc;gBACnB,QAAQ;gBACR,IAAI;aACL;YACD,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,YAAY,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC;SACvG,CAAC;IACJ,CAAC;IAEO,sBAAsB,CAC1B,cAA0D,EAC1D,OAA6B,EAC7B,aAAoD;QAItD,OAAO,IAAI,CAAC,EAAE;YACZ,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/B,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBACpD,MAAM,cAAc,GAAG,KAAK,EAAE,IAAI,CAC9B,QAAQ,CAAC,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,CAAC,6DAA8C,CAAC,CAAC;gBACrG,MAAM,eAAe,GAAG,qBAAqB,CACzC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,SAAS,EACrG,cAAc,EAAE,KAAK,CAAC,EAAE;oBACtB,IAAI,cAAc,EAAE,CAAC;wBACnB,IAAI,CAAC,sBAAsB,CAAC,aAAa,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;oBACpE,CAAC;gBACH,CAAC,CAAC,CAAC;gBACP,OAAO,eAAe,CAAC;YACzB,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,KAAK,cAAc,EAAE,CAAC;gBAChC,MAAM,oBAAoB,GACtB,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,qEAAkD,CAAC;gBACjG,MAAM,YAAY,GACd,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,oBAAoB,EAAE,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBACpG,YAAY,CAAC,gBAAgB,CACzB,aAAa,EAAE,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACzF,OAAO,IAAI,CAAA,GAAG,YAAY,EAAE,CAAC;YAC/B,CAAC;YACD,OAAO,IAAI,CAAA,qEAAqE,IAAI,CAAC,IAAI,SAAS,CAAC;QACrG,CAAC,CAAC;IACJ,CAAC;IAEO,aAAa,CACjB,cAA0D,EAAE,YAAoB,EAAE,aAAqB,EACvG,WAAoB;QACtB,MAAM,YAAY,GAAsB;YACtC,GAAG,EAAE,UAAU;YACf,YAAY;YACZ,aAAa;YACb,SAAS,EAAE,WAAW;SACvB,CAAC;QACF,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,YAAY;gBACZ,YAAY,EAAE,YAAY;gBAC1B,EAAE,EAAE,YAAY;aACjB,CAAC;QACJ,CAAC;QACD,OAAO;YACL,YAAY;YACZ,YAAY,EAAE,YAAY;YAC1B,EAAE,EAAE,YAAY;YAChB,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC;SACrD,CAAC;IACJ,CAAC;IAEO,sBAAsB,CAC1B,aAAoD,EAAE,QAAqC,EAAE,KAAY;QAC3G,MAAM,WAAW,GAAG,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;QAE5C,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5G,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,2BAA2B,EAAE,EAAE,CAAC;gBACpD,WAAW,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,wBAAwB,CAAC,EAAE,GAAG,EAAE;oBAC3F,sBAAsB,CAAC,yBAAyB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;gBACxE,CAAC,EAAE,EAAC,YAAY,EAAE,6BAA6B,EAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,WAAW,CAAC,cAAc,EAAE,CAAC,UAAU,CACnC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAC7E,EAAC,YAAY,EAAE,mBAAmB,EAAC,CAAC,CAAC;QACzC,KAAK,WAAW,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAEO,qBAAqB,CAAC,aAAoD;QAEhF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyC,CAAC;QAChE,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,UAAU,EAAE,EAAE,CAAC;YAC/C,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;YAC5C,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;gBACrC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxE,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAChC,CAAC;gBACD,mEAAmE;gBACnE,mBAAmB;gBACnB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,6BAA6B,CAAC,aAAoD;QACxF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,UAAU,EAAE,EAAE,CAAC;YAC/C,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,aAAa,EAAE,EAAE,CAAC;gBAC7C,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC3C,SAAS;gBACX,CAAC;gBACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,eAAe,CAAC,KAAkD;QACxE,KAAK,IAAI,CAAC,oBAAoB,CAC1B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACjG,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,KAAkB;QAC3C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,IAAI,CAAC,0BAA0B,CAAC,GAAG,EAAE,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACjC,CAAC;QACD,OAAO,IAAI,CAAC,sBAAsB,EAAE,CAAC;IACvC,CAAC;IAEO,UAAU,CAAC,IAA8D;QAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;QAC/B,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1F,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,sBAAsB;QAC5B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC,mBAAmB,CAAC,IAAI,GAAG;YAC9B,IAAI;YACJ,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe;YAC/C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO;SAChC,CAAC;QACF,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC5B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAA+D,EAAE,CAAC;QAC5E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAC;YAChC,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC/C,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC1C,MAAM,gBAAgB,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACvE,IAAI,gBAAgB,CAAC,MAAM,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,CACL,EAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,EAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAC,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,gBAAgB,EAAC,CAAC,CAAC;YACjH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,mBAAmB,CAAC,IAAI,GAAG;YAC9B,IAAI;YACJ,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe;YAC/C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO;SAChC,CAAC;QACF,MAAM,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,CAAC;CACF;AAED,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,6BAA6B,GAAG,IAAI,GAAG,CAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,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\n/*\n * Copyright (C) 2007 Apple Inc. All rights reserved.\n * Copyright (C) 2009 Joseph Pecoraro\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 i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as TreeOutline from '../../ui/components/tree_outline/tree_outline.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as Components 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';\n\nimport * as ElementsComponents from './components/components.js';\nimport {type ComputedStyle, ComputedStyleModel, Events} from './ComputedStyleModel.js';\nimport computedStyleSidebarPaneStyles from './computedStyleSidebarPane.css.js';\nimport {ImagePreviewPopover} from './ImagePreviewPopover.js';\nimport {PlatformFontsWidget} from './PlatformFontsWidget.js';\nimport {type ColorMatch, ColorMatcher} from './PropertyMatchers.js';\nimport {categorizePropertyName, type Category, DefaultCategoryOrder} from './PropertyNameCategories.js';\nimport {type MatchRenderer, Renderer, type RenderingContext, StringRenderer, URLRenderer} from './PropertyRenderer.js';\nimport {StylePropertiesSection} from './StylePropertiesSection.js';\n\nconst {html} = LitHtml;\n\nconst UIStrings = {\n /**\n * @description Text for a checkbox setting that controls whether the user-supplied filter text\n * excludes all CSS propreties which are filtered out, or just greys them out. In Computed Style\n * Widget of the Elements panel\n */\n showAll: 'Show all',\n /**\n * @description Text for a checkbox setting that controls whether similar CSS properties should be\n * grouped together or not. In Computed Style Widget of the Elements panel.\n */\n group: 'Group',\n /** [\n * @description Text shown to the user when a filter is applied to the computed CSS properties, but\n * no properties matched the filter and thus no results were returned.\n */\n noMatchingProperty: 'No matching property',\n /**\n * @description Context menu item in Elements panel to navigate to the source code location of the\n * CSS selector that was clicked on.\n */\n navigateToSelectorSource: 'Navigate to selector source',\n /**\n * @description Context menu item in Elements panel to navigate to the corresponding CSS style rule\n * for this computed property.\n */\n navigateToStyle: 'Navigate to style',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/ComputedStyleWidget.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * Rendering a property's name and value is expensive, and each time we do it\n * it generates a new HTML element. If we call this directly from our Lit\n * components, we will generate a brand new DOM element on each single render.\n * This is very expensive and unneccessary - for the majority of re-renders a\n * property's name and value does not change. So we cache the rest of rendering\n * the name and value in a map, where the key used is a combination of the\n * property's name and value. This ensures that we only re-generate this element\n * if the node itself changes.\n * The resulting Element nodes are inserted into the ComputedStyleProperty\n * component via s, ensuring that Lit doesn't directly render/re-render\n * the element.\n */\nconst propertyContentsCache = new Map();\n\nfunction renderPropertyContents(\n node: SDK.DOMModel.DOMNode, propertyName: string, propertyValue: string): {name: Element, value: Element} {\n const cacheKey = propertyName + ':' + propertyValue;\n const valueFromCache = propertyContentsCache.get(cacheKey);\n if (valueFromCache) {\n return valueFromCache;\n }\n const name = Renderer.renderNameElement(propertyName);\n name.slot = 'name';\n const value = Renderer.renderValueElement(\n propertyName, propertyValue, [new ColorRenderer(), new URLRenderer(null, node), new StringRenderer()]);\n value.slot = 'value';\n propertyContentsCache.set(cacheKey, {name, value});\n return {name, value};\n}\n\n/**\n * Note: this function is called for each tree node on each render, so we need\n * to ensure nothing expensive runs here, or if it does it is safely cached.\n **/\nconst createPropertyElement =\n (node: SDK.DOMModel.DOMNode, propertyName: string, propertyValue: string, traceable: boolean, inherited: boolean,\n activeProperty: SDK.CSSProperty.CSSProperty|undefined,\n onContextMenu: ((event: Event) => void)): LitHtml.TemplateResult => {\n const {name, value} = renderPropertyContents(node, propertyName, propertyValue);\n // clang-format off\n return html` {\n if (activeProperty) {\n navigateToSource(activeProperty, event);\n }\n }}>\n ${name}\n ${value}\n `;\n // clang-format on\n };\n\nconst createTraceElement =\n (node: SDK.DOMModel.DOMNode, property: SDK.CSSProperty.CSSProperty, isPropertyOverloaded: boolean,\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,\n linkifier: Components.Linkifier.Linkifier): ElementsComponents.ComputedStyleTrace.ComputedStyleTrace => {\n const trace = new ElementsComponents.ComputedStyleTrace.ComputedStyleTrace();\n\n const valueElement = Renderer.renderValueElement(\n property.name, property.value, [new ColorRenderer(), new URLRenderer(null, node), new StringRenderer()]);\n valueElement.slot = 'trace-value';\n trace.appendChild(valueElement);\n\n const rule = (property.ownerStyle.parentRule as SDK.CSSRule.CSSStyleRule | null);\n let ruleOriginNode;\n if (rule) {\n ruleOriginNode = StylePropertiesSection.createRuleOriginNode(matchedStyles, linkifier, rule);\n }\n trace.data = {\n selector: rule ? rule.selectorText() : 'element.style',\n active: !isPropertyOverloaded,\n onNavigateToSource: navigateToSource.bind(null, property),\n ruleOriginNode,\n };\n\n return trace;\n };\n\nclass ColorRenderer implements MatchRenderer {\n render(match: ColorMatch, context: RenderingContext): Node[] {\n const color = Common.Color.parse(match.text);\n if (!color) {\n return [document.createTextNode(match.text)];\n }\n\n const swatch = new InlineEditor.ColorSwatch.ColorSwatch();\n swatch.setReadonly(true);\n swatch.renderColor(color);\n const valueElement = document.createElement('span');\n valueElement.textContent = match.text;\n swatch.append(valueElement);\n\n swatch.addEventListener(\n InlineEditor.ColorSwatch.ColorChangedEvent.eventName, (event: InlineEditor.ColorSwatch.ColorChangedEvent) => {\n const {data: {color}} = event;\n valueElement.textContent = color.getAuthoredText() ?? color.asString();\n });\n\n context.addControl('color', swatch);\n return [swatch];\n }\n\n matcher(): ColorMatcher {\n return new ColorMatcher();\n }\n}\n\nconst navigateToSource = (cssProperty: SDK.CSSProperty.CSSProperty, event?: Event): void => {\n if (!event) {\n return;\n }\n void Common.Revealer.reveal(cssProperty);\n event.consume(true);\n};\n\nconst propertySorter = (propA: string, propB: string): number => {\n if (propA.startsWith('--') !== propB.startsWith('--')) {\n return propA.startsWith('--') ? 1 : -1;\n }\n if (propA.startsWith('-webkit') !== propB.startsWith('-webkit')) {\n return propA.startsWith('-webkit') ? 1 : -1;\n }\n const canonicalA = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propA);\n const canonicalB = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propB);\n return Platform.StringUtilities.compare(canonicalA, canonicalB);\n};\n\ntype ComputedStyleData = {\n tag: 'property',\n propertyName: string,\n propertyValue: string,\n inherited: boolean,\n}|{\n tag: 'traceElement',\n property: SDK.CSSProperty.CSSProperty,\n rule: SDK.CSSRule.CSSRule | null,\n}|{\n tag: 'category',\n name: string,\n};\n\nexport class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {\n private computedStyleModel: ComputedStyleModel;\n private readonly showInheritedComputedStylePropertiesSetting: Common.Settings.Setting;\n private readonly groupComputedStylesSetting: Common.Settings.Setting;\n input: UI.Toolbar.ToolbarInput;\n private filterRegex: RegExp|null;\n private readonly noMatchesElement: HTMLElement;\n private readonly linkifier: Components.Linkifier.Linkifier;\n private readonly imagePreviewPopover: ImagePreviewPopover;\n\n #computedStylesTree = new TreeOutline.TreeOutline.TreeOutline();\n #treeData?: TreeOutline.TreeOutline.TreeOutlineData;\n\n constructor() {\n super(true);\n\n this.contentElement.classList.add('styles-sidebar-computed-style-widget');\n\n this.computedStyleModel = new ComputedStyleModel();\n this.computedStyleModel.addEventListener(Events.COMPUTED_STYLE_CHANGED, this.update, this);\n\n this.showInheritedComputedStylePropertiesSetting =\n Common.Settings.Settings.instance().createSetting('show-inherited-computed-style-properties', false);\n this.showInheritedComputedStylePropertiesSetting.addChangeListener(this.update.bind(this));\n\n this.groupComputedStylesSetting = Common.Settings.Settings.instance().createSetting('group-computed-styles', false);\n this.groupComputedStylesSetting.addChangeListener(() => {\n this.update();\n });\n\n const hbox = this.contentElement.createChild('div', 'hbox styles-sidebar-pane-toolbar');\n const toolbar = new UI.Toolbar.Toolbar('styles-pane-toolbar', hbox);\n const filterInput = new UI.Toolbar.ToolbarFilter(undefined, 1, 1, undefined, undefined, false);\n filterInput.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.onFilterChanged, this);\n toolbar.appendToolbarItem(filterInput);\n this.input = filterInput;\n this.filterRegex = null;\n\n toolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.showInheritedComputedStylePropertiesSetting, undefined, i18nString(UIStrings.showAll)));\n toolbar.appendToolbarItem(\n new UI.Toolbar.ToolbarSettingCheckbox(this.groupComputedStylesSetting, undefined, i18nString(UIStrings.group)));\n\n this.noMatchesElement = this.contentElement.createChild('div', 'gray-info-message');\n this.noMatchesElement.textContent = i18nString(UIStrings.noMatchingProperty);\n\n this.contentElement.appendChild(this.#computedStylesTree);\n\n this.linkifier = new Components.Linkifier.Linkifier(maxLinkLength);\n\n this.imagePreviewPopover = new ImagePreviewPopover(this.contentElement, event => {\n const link = event.composedPath()[0];\n if (link instanceof Element) {\n return link;\n }\n return null;\n }, () => this.computedStyleModel.node());\n\n const fontsWidget = new PlatformFontsWidget(this.computedStyleModel);\n fontsWidget.show(this.contentElement);\n }\n\n override onResize(): void {\n const isNarrow = this.contentElement.offsetWidth < 260;\n this.#computedStylesTree.classList.toggle('computed-narrow', isNarrow);\n }\n\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([computedStyleSidebarPaneStyles]);\n }\n\n override async doUpdate(): Promise {\n const [nodeStyles, matchedStyles] =\n await Promise.all([this.computedStyleModel.fetchComputedStyle(), this.fetchMatchedCascade()]);\n if (!nodeStyles || !matchedStyles) {\n this.noMatchesElement.classList.remove('hidden');\n return;\n }\n const shouldGroupComputedStyles = this.groupComputedStylesSetting.get();\n if (shouldGroupComputedStyles) {\n await this.rebuildGroupedList(nodeStyles, matchedStyles);\n } else {\n await this.rebuildAlphabeticalList(nodeStyles, matchedStyles);\n }\n }\n\n private async fetchMatchedCascade(): Promise {\n const node = this.computedStyleModel.node();\n if (!node || !this.computedStyleModel.cssModel()) {\n return null;\n }\n\n const cssModel = this.computedStyleModel.cssModel();\n if (!cssModel) {\n return null;\n }\n\n return cssModel.cachedMatchedCascadeForNode(node).then(validateStyles.bind(this));\n\n function validateStyles(this: ComputedStyleWidget, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null):\n SDK.CSSMatchedStyles.CSSMatchedStyles|null {\n return matchedStyles && matchedStyles.node() === this.computedStyleModel.node() ? matchedStyles : null;\n }\n }\n\n private async rebuildAlphabeticalList(nodeStyle: ComputedStyle, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):\n Promise {\n this.imagePreviewPopover.hide();\n this.linkifier.reset();\n const cssModel = this.computedStyleModel.cssModel();\n if (!cssModel) {\n return;\n }\n\n const uniqueProperties = [...nodeStyle.computedStyle.keys()];\n uniqueProperties.sort(propertySorter);\n\n const node = nodeStyle.node;\n const propertyTraces = this.computePropertyTraces(matchedStyles);\n const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);\n const showInherited = this.showInheritedComputedStylePropertiesSetting.get();\n const tree: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const propertyName of uniqueProperties) {\n const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';\n const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);\n const isInherited = !nonInheritedProperties.has(canonicalName);\n if (!showInherited && isInherited && !alwaysShownComputedProperties.has(propertyName)) {\n continue;\n }\n if (!showInherited && propertyName.startsWith('--')) {\n continue;\n }\n if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) {\n continue;\n }\n tree.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));\n }\n\n const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);\n this.#treeData = {\n tree,\n compact: true,\n defaultRenderer,\n };\n this.filterAlphabeticalList();\n }\n\n private async rebuildGroupedList(\n nodeStyle: ComputedStyle|null, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null): Promise {\n this.imagePreviewPopover.hide();\n this.linkifier.reset();\n const cssModel = this.computedStyleModel.cssModel();\n if (!nodeStyle || !matchedStyles || !cssModel) {\n this.noMatchesElement.classList.remove('hidden');\n return;\n }\n\n const node = nodeStyle.node;\n const propertyTraces = this.computePropertyTraces(matchedStyles);\n const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);\n const showInherited = this.showInheritedComputedStylePropertiesSetting.get();\n\n const propertiesByCategory = new Map();\n\n const tree: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const [propertyName, propertyValue] of nodeStyle.computedStyle) {\n const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);\n const isInherited = !nonInheritedProperties.has(canonicalName);\n if (!showInherited && isInherited && !alwaysShownComputedProperties.has(propertyName)) {\n continue;\n }\n if (!showInherited && propertyName.startsWith('--')) {\n continue;\n }\n if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) {\n continue;\n }\n\n const categories = categorizePropertyName(propertyName);\n for (const category of categories) {\n if (!propertiesByCategory.has(category)) {\n propertiesByCategory.set(category, []);\n }\n propertiesByCategory.get(category)?.push(propertyName);\n }\n }\n\n this.#computedStylesTree.removeChildren();\n for (const category of DefaultCategoryOrder) {\n const properties = propertiesByCategory.get(category);\n if (properties && properties.length > 0) {\n const propertyNodes: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const propertyName of properties) {\n const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';\n const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);\n const isInherited = !nonInheritedProperties.has(canonicalName);\n propertyNodes.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));\n }\n tree.push({id: category, treeNodeData: {tag: 'category', name: category}, children: async () => propertyNodes});\n }\n }\n const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);\n this.#treeData = {\n tree,\n compact: true,\n defaultRenderer,\n };\n return this.filterGroupLists();\n }\n\n private buildTraceNode(property: SDK.CSSProperty.CSSProperty):\n TreeOutline.TreeOutlineUtils.TreeNode {\n const rule = property.ownerStyle.parentRule;\n return {\n treeNodeData: {\n tag: 'traceElement',\n property,\n rule,\n },\n id: (rule?.origin || '') + ': ' + property.ownerStyle.styleSheetId + (property.range || property.name),\n };\n }\n\n private createTreeNodeRenderer(\n propertyTraces: Map,\n domNode: SDK.DOMModel.DOMNode,\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,\n ):\n (node: TreeOutline.TreeOutlineUtils.TreeNode,\n state: {isExpanded: boolean}) => LitHtml.TemplateResult {\n return node => {\n const data = node.treeNodeData;\n if (data.tag === 'property') {\n const trace = propertyTraces.get(data.propertyName);\n const activeProperty = trace?.find(\n property => matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.ACTIVE);\n const propertyElement = createPropertyElement(\n domNode, data.propertyName, data.propertyValue, propertyTraces.has(data.propertyName), data.inherited,\n activeProperty, event => {\n if (activeProperty) {\n this.handleContextMenuEvent(matchedStyles, activeProperty, event);\n }\n });\n return propertyElement;\n }\n if (data.tag === 'traceElement') {\n const isPropertyOverloaded =\n matchedStyles.propertyState(data.property) === SDK.CSSMatchedStyles.PropertyState.OVERLOADED;\n const traceElement =\n createTraceElement(domNode, data.property, isPropertyOverloaded, matchedStyles, this.linkifier);\n traceElement.addEventListener(\n 'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, data.property));\n return html`${traceElement}`;\n }\n return html`${data.name}`;\n };\n }\n\n private buildTreeNode(\n propertyTraces: Map, propertyName: string, propertyValue: string,\n isInherited: boolean): TreeOutline.TreeOutlineUtils.TreeNode {\n const treeNodeData: ComputedStyleData = {\n tag: 'property',\n propertyName,\n propertyValue,\n inherited: isInherited,\n };\n const trace = propertyTraces.get(propertyName);\n if (!trace) {\n return {\n treeNodeData,\n jslogContext: propertyName,\n id: propertyName,\n };\n }\n return {\n treeNodeData,\n jslogContext: propertyName,\n id: propertyName,\n children: async () => trace.map(this.buildTraceNode),\n };\n }\n\n private handleContextMenuEvent(\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, property: SDK.CSSProperty.CSSProperty, event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n const rule = property.ownerStyle.parentRule;\n\n if (rule) {\n const header = rule.styleSheetId ? matchedStyles.cssModel().styleSheetHeaderForId(rule.styleSheetId) : null;\n if (header && !header.isAnonymousInlineStyleSheet()) {\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.navigateToSelectorSource), () => {\n StylePropertiesSection.tryNavigateToRuleLocation(matchedStyles, rule);\n }, {jslogContext: 'navigate-to-selector-source'});\n }\n }\n\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.navigateToStyle), () => Common.Revealer.reveal(property),\n {jslogContext: 'navigate-to-style'});\n void contextMenu.show();\n }\n\n private computePropertyTraces(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):\n Map {\n const result = new Map();\n for (const style of matchedStyles.nodeStyles()) {\n const allProperties = style.allProperties();\n for (const property of allProperties) {\n if (!property.activeInStyle() || !matchedStyles.propertyState(property)) {\n continue;\n }\n if (!result.has(property.name)) {\n result.set(property.name, []);\n }\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n result.get(property.name).push(property);\n }\n }\n return result;\n }\n\n private computeNonInheritedProperties(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles): Set {\n const result = new Set();\n for (const style of matchedStyles.nodeStyles()) {\n for (const property of style.allProperties()) {\n if (!matchedStyles.propertyState(property)) {\n continue;\n }\n result.add(SDK.CSSMetadata.cssMetadata().canonicalPropertyName(property.name));\n }\n }\n return result;\n }\n\n private onFilterChanged(event: Common.EventTarget.EventTargetEvent): void {\n void this.filterComputedStyles(\n event.data ? new RegExp(Platform.StringUtilities.escapeForRegExp(event.data), 'i') : null);\n }\n\n async filterComputedStyles(regex: RegExp|null): Promise {\n this.filterRegex = regex;\n if (this.groupComputedStylesSetting.get()) {\n return this.filterGroupLists();\n }\n return this.filterAlphabeticalList();\n }\n\n private nodeFilter(node: TreeOutline.TreeOutlineUtils.TreeNode): boolean {\n const regex = this.filterRegex;\n const data = node.treeNodeData;\n if (data.tag === 'property') {\n const matched = !regex || regex.test(data.propertyName) || regex.test(data.propertyValue);\n return matched;\n }\n return true;\n }\n\n private filterAlphabeticalList(): void {\n if (!this.#treeData) {\n return;\n }\n const tree = this.#treeData.tree.filter(this.nodeFilter.bind(this));\n this.#computedStylesTree.data = {\n tree,\n defaultRenderer: this.#treeData.defaultRenderer,\n compact: this.#treeData.compact,\n };\n this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));\n }\n\n private async filterGroupLists(): Promise {\n if (!this.#treeData) {\n return;\n }\n const tree: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const group of this.#treeData.tree) {\n const data = group.treeNodeData;\n if (data.tag !== 'category' || !group.children) {\n continue;\n }\n const properties = await group.children();\n const filteredChildren = properties.filter(this.nodeFilter.bind(this));\n if (filteredChildren.length) {\n tree.push(\n {id: data.name, treeNodeData: {tag: 'category', name: data.name}, children: async () => filteredChildren});\n }\n }\n\n this.#computedStylesTree.data = {\n tree,\n defaultRenderer: this.#treeData.defaultRenderer,\n compact: this.#treeData.compact,\n };\n await this.#computedStylesTree.expandRecursively(0);\n this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));\n }\n}\n\nconst maxLinkLength = 30;\nconst alwaysShownComputedProperties = new Set(['display', 'height', 'width']);\n"]} \ No newline at end of file +{"version":3,"file":"ComputedStyleWidget.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ComputedStyleWidget.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 Apple Inc. All rights reserved.\n * Copyright (C) 2009 Joseph Pecoraro\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 i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as TreeOutline from '../../ui/components/tree_outline/tree_outline.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as Components 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';\n\nimport * as ElementsComponents from './components/components.js';\nimport {type ComputedStyle, ComputedStyleModel, Events} from './ComputedStyleModel.js';\nimport computedStyleSidebarPaneStyles from './computedStyleSidebarPane.css.js';\nimport {ImagePreviewPopover} from './ImagePreviewPopover.js';\nimport {PlatformFontsWidget} from './PlatformFontsWidget.js';\nimport {type ColorMatch, ColorMatcher} from './PropertyMatchers.js';\nimport {categorizePropertyName, type Category, DefaultCategoryOrder} from './PropertyNameCategories.js';\nimport {type MatchRenderer, Renderer, type RenderingContext, StringRenderer, URLRenderer} from './PropertyRenderer.js';\nimport {StylePropertiesSection} from './StylePropertiesSection.js';\n\nconst {html} = LitHtml;\n\nconst UIStrings = {\n /**\n * @description Text for a checkbox setting that controls whether the user-supplied filter text\n * excludes all CSS propreties which are filtered out, or just greys them out. In Computed Style\n * Widget of the Elements panel\n */\n showAll: 'Show all',\n /**\n * @description Text for a checkbox setting that controls whether similar CSS properties should be\n * grouped together or not. In Computed Style Widget of the Elements panel.\n */\n group: 'Group',\n /** [\n * @description Text shown to the user when a filter is applied to the computed CSS properties, but\n * no properties matched the filter and thus no results were returned.\n */\n noMatchingProperty: 'No matching property',\n /**\n * @description Context menu item in Elements panel to navigate to the source code location of the\n * CSS selector that was clicked on.\n */\n navigateToSelectorSource: 'Navigate to selector source',\n /**\n * @description Context menu item in Elements panel to navigate to the corresponding CSS style rule\n * for this computed property.\n */\n navigateToStyle: 'Navigate to style',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/ComputedStyleWidget.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * Rendering a property's name and value is expensive, and each time we do it\n * it generates a new HTML element. If we call this directly from our Lit\n * components, we will generate a brand new DOM element on each single render.\n * This is very expensive and unneccessary - for the majority of re-renders a\n * property's name and value does not change. So we cache the rest of rendering\n * the name and value in a map, where the key used is a combination of the\n * property's name and value. This ensures that we only re-generate this element\n * if the node itself changes.\n * The resulting Element nodes are inserted into the ComputedStyleProperty\n * component via s, ensuring that Lit doesn't directly render/re-render\n * the element.\n */\nconst propertyContentsCache = new Map();\n\nfunction renderPropertyContents(\n node: SDK.DOMModel.DOMNode, propertyName: string, propertyValue: string): {name: Element, value: Element} {\n const cacheKey = propertyName + ':' + propertyValue;\n const valueFromCache = propertyContentsCache.get(cacheKey);\n if (valueFromCache) {\n return valueFromCache;\n }\n const name = Renderer.renderNameElement(propertyName);\n name.slot = 'name';\n const value = Renderer.renderValueElement(\n propertyName, propertyValue, [new ColorRenderer(), new URLRenderer(null, node), new StringRenderer()]);\n value.slot = 'value';\n propertyContentsCache.set(cacheKey, {name, value});\n return {name, value};\n}\n\n/**\n * Note: this function is called for each tree node on each render, so we need\n * to ensure nothing expensive runs here, or if it does it is safely cached.\n **/\nconst createPropertyElement =\n (node: SDK.DOMModel.DOMNode, propertyName: string, propertyValue: string, traceable: boolean, inherited: boolean,\n activeProperty: SDK.CSSProperty.CSSProperty|undefined,\n onContextMenu: ((event: Event) => void)): LitHtml.TemplateResult => {\n const {name, value} = renderPropertyContents(node, propertyName, propertyValue);\n // clang-format off\n return html` {\n if (activeProperty) {\n navigateToSource(activeProperty, event);\n }\n }}>\n ${name}\n ${value}\n `;\n // clang-format on\n };\n\nconst createTraceElement =\n (node: SDK.DOMModel.DOMNode, property: SDK.CSSProperty.CSSProperty, isPropertyOverloaded: boolean,\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,\n linkifier: Components.Linkifier.Linkifier): ElementsComponents.ComputedStyleTrace.ComputedStyleTrace => {\n const trace = new ElementsComponents.ComputedStyleTrace.ComputedStyleTrace();\n\n const valueElement = Renderer.renderValueElement(\n property.name, property.value, [new ColorRenderer(), new URLRenderer(null, node), new StringRenderer()]);\n valueElement.slot = 'trace-value';\n trace.appendChild(valueElement);\n\n const rule = (property.ownerStyle.parentRule as SDK.CSSRule.CSSStyleRule | null);\n let ruleOriginNode;\n if (rule) {\n ruleOriginNode = StylePropertiesSection.createRuleOriginNode(matchedStyles, linkifier, rule);\n }\n trace.data = {\n selector: rule ? rule.selectorText() : 'element.style',\n active: !isPropertyOverloaded,\n onNavigateToSource: navigateToSource.bind(null, property),\n ruleOriginNode,\n };\n\n return trace;\n };\n\nclass ColorRenderer implements MatchRenderer {\n render(match: ColorMatch, context: RenderingContext): Node[] {\n const color = Common.Color.parse(match.text);\n if (!color) {\n return [document.createTextNode(match.text)];\n }\n\n const swatch = new InlineEditor.ColorSwatch.ColorSwatch();\n swatch.setReadonly(true);\n swatch.renderColor(color);\n const valueElement = document.createElement('span');\n valueElement.textContent = match.text;\n swatch.append(valueElement);\n\n swatch.addEventListener(\n InlineEditor.ColorSwatch.ColorChangedEvent.eventName, (event: InlineEditor.ColorSwatch.ColorChangedEvent) => {\n const {data: {color}} = event;\n valueElement.textContent = color.getAuthoredText() ?? color.asString();\n });\n\n context.addControl('color', swatch);\n return [swatch];\n }\n\n matcher(): ColorMatcher {\n return new ColorMatcher();\n }\n}\n\nconst navigateToSource = (cssProperty: SDK.CSSProperty.CSSProperty, event?: Event): void => {\n if (!event) {\n return;\n }\n void Common.Revealer.reveal(cssProperty);\n event.consume(true);\n};\n\nconst propertySorter = (propA: string, propB: string): number => {\n if (propA.startsWith('--') !== propB.startsWith('--')) {\n return propA.startsWith('--') ? 1 : -1;\n }\n if (propA.startsWith('-webkit') !== propB.startsWith('-webkit')) {\n return propA.startsWith('-webkit') ? 1 : -1;\n }\n const canonicalA = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propA);\n const canonicalB = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propB);\n return Platform.StringUtilities.compare(canonicalA, canonicalB);\n};\n\ntype ComputedStyleData = {\n tag: 'property',\n propertyName: string,\n propertyValue: string,\n inherited: boolean,\n}|{\n tag: 'traceElement',\n property: SDK.CSSProperty.CSSProperty,\n rule: SDK.CSSRule.CSSRule | null,\n}|{\n tag: 'category',\n name: string,\n};\n\nexport class ComputedStyleWidget extends UI.ThrottledWidget.ThrottledWidget {\n private computedStyleModel: ComputedStyleModel;\n private readonly showInheritedComputedStylePropertiesSetting: Common.Settings.Setting;\n private readonly groupComputedStylesSetting: Common.Settings.Setting;\n input: UI.Toolbar.ToolbarInput;\n private filterRegex: RegExp|null;\n private readonly noMatchesElement: HTMLElement;\n private readonly linkifier: Components.Linkifier.Linkifier;\n private readonly imagePreviewPopover: ImagePreviewPopover;\n\n #computedStylesTree = new TreeOutline.TreeOutline.TreeOutline();\n #treeData?: TreeOutline.TreeOutline.TreeOutlineData;\n\n constructor() {\n super(true);\n\n this.contentElement.classList.add('styles-sidebar-computed-style-widget');\n\n this.computedStyleModel = new ComputedStyleModel();\n this.computedStyleModel.addEventListener(Events.COMPUTED_STYLE_CHANGED, this.update, this);\n\n this.showInheritedComputedStylePropertiesSetting =\n Common.Settings.Settings.instance().createSetting('show-inherited-computed-style-properties', false);\n this.showInheritedComputedStylePropertiesSetting.addChangeListener(this.update.bind(this));\n\n this.groupComputedStylesSetting = Common.Settings.Settings.instance().createSetting('group-computed-styles', false);\n this.groupComputedStylesSetting.addChangeListener(() => {\n this.update();\n });\n\n const hbox = this.contentElement.createChild('div', 'hbox styles-sidebar-pane-toolbar');\n const toolbar = new UI.Toolbar.Toolbar('styles-pane-toolbar', hbox);\n const filterInput = new UI.Toolbar.ToolbarFilter(undefined, 1, 1, undefined, undefined, false);\n filterInput.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.onFilterChanged, this);\n toolbar.appendToolbarItem(filterInput);\n this.input = filterInput;\n this.filterRegex = null;\n\n toolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.showInheritedComputedStylePropertiesSetting, undefined, i18nString(UIStrings.showAll)));\n toolbar.appendToolbarItem(\n new UI.Toolbar.ToolbarSettingCheckbox(this.groupComputedStylesSetting, undefined, i18nString(UIStrings.group)));\n\n this.noMatchesElement = this.contentElement.createChild('div', 'gray-info-message');\n this.noMatchesElement.textContent = i18nString(UIStrings.noMatchingProperty);\n\n this.contentElement.appendChild(this.#computedStylesTree);\n\n this.linkifier = new Components.Linkifier.Linkifier(maxLinkLength);\n\n this.imagePreviewPopover = new ImagePreviewPopover(this.contentElement, event => {\n const link = event.composedPath()[0];\n if (link instanceof Element) {\n return link;\n }\n return null;\n }, () => this.computedStyleModel.node());\n\n const fontsWidget = new PlatformFontsWidget(this.computedStyleModel);\n fontsWidget.show(this.contentElement);\n }\n\n #handleNodeChange(event: Common.EventTarget.EventTargetEvent): void {\n void this.computedStyleModel.cssModel()?.trackComputedStyleUpdatesForNode(event.data?.id);\n }\n\n override onResize(): void {\n const isNarrow = this.contentElement.offsetWidth < 260;\n this.#computedStylesTree.classList.toggle('computed-narrow', isNarrow);\n }\n\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([computedStyleSidebarPaneStyles]);\n\n void this.computedStyleModel.cssModel()?.trackComputedStyleUpdatesForNode(this.computedStyleModel.node()?.id);\n UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.#handleNodeChange, this);\n }\n\n override willHide(): void {\n void this.computedStyleModel.cssModel()?.trackComputedStyleUpdatesForNode(undefined);\n UI.Context.Context.instance().removeFlavorChangeListener(SDK.DOMModel.DOMNode, this.#handleNodeChange, this);\n }\n\n override async doUpdate(): Promise {\n const [nodeStyles, matchedStyles] =\n await Promise.all([this.computedStyleModel.fetchComputedStyle(), this.fetchMatchedCascade()]);\n if (!nodeStyles || !matchedStyles) {\n this.noMatchesElement.classList.remove('hidden');\n return;\n }\n const shouldGroupComputedStyles = this.groupComputedStylesSetting.get();\n if (shouldGroupComputedStyles) {\n await this.rebuildGroupedList(nodeStyles, matchedStyles);\n } else {\n await this.rebuildAlphabeticalList(nodeStyles, matchedStyles);\n }\n }\n\n private async fetchMatchedCascade(): Promise {\n const node = this.computedStyleModel.node();\n if (!node || !this.computedStyleModel.cssModel()) {\n return null;\n }\n\n const cssModel = this.computedStyleModel.cssModel();\n if (!cssModel) {\n return null;\n }\n\n return cssModel.cachedMatchedCascadeForNode(node).then(validateStyles.bind(this));\n\n function validateStyles(this: ComputedStyleWidget, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null):\n SDK.CSSMatchedStyles.CSSMatchedStyles|null {\n return matchedStyles && matchedStyles.node() === this.computedStyleModel.node() ? matchedStyles : null;\n }\n }\n\n private async rebuildAlphabeticalList(nodeStyle: ComputedStyle, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):\n Promise {\n this.imagePreviewPopover.hide();\n this.linkifier.reset();\n const cssModel = this.computedStyleModel.cssModel();\n if (!cssModel) {\n return;\n }\n\n const uniqueProperties = [...nodeStyle.computedStyle.keys()];\n uniqueProperties.sort(propertySorter);\n\n const node = nodeStyle.node;\n const propertyTraces = this.computePropertyTraces(matchedStyles);\n const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);\n const showInherited = this.showInheritedComputedStylePropertiesSetting.get();\n const tree: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const propertyName of uniqueProperties) {\n const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';\n const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);\n const isInherited = !nonInheritedProperties.has(canonicalName);\n if (!showInherited && isInherited && !alwaysShownComputedProperties.has(propertyName)) {\n continue;\n }\n if (!showInherited && propertyName.startsWith('--')) {\n continue;\n }\n if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) {\n continue;\n }\n tree.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));\n }\n\n const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);\n this.#treeData = {\n tree,\n compact: true,\n defaultRenderer,\n };\n this.filterAlphabeticalList();\n }\n\n private async rebuildGroupedList(\n nodeStyle: ComputedStyle|null, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null): Promise {\n this.imagePreviewPopover.hide();\n this.linkifier.reset();\n const cssModel = this.computedStyleModel.cssModel();\n if (!nodeStyle || !matchedStyles || !cssModel) {\n this.noMatchesElement.classList.remove('hidden');\n return;\n }\n\n const node = nodeStyle.node;\n const propertyTraces = this.computePropertyTraces(matchedStyles);\n const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);\n const showInherited = this.showInheritedComputedStylePropertiesSetting.get();\n\n const propertiesByCategory = new Map();\n\n const tree: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const [propertyName, propertyValue] of nodeStyle.computedStyle) {\n const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);\n const isInherited = !nonInheritedProperties.has(canonicalName);\n if (!showInherited && isInherited && !alwaysShownComputedProperties.has(propertyName)) {\n continue;\n }\n if (!showInherited && propertyName.startsWith('--')) {\n continue;\n }\n if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) {\n continue;\n }\n\n const categories = categorizePropertyName(propertyName);\n for (const category of categories) {\n if (!propertiesByCategory.has(category)) {\n propertiesByCategory.set(category, []);\n }\n propertiesByCategory.get(category)?.push(propertyName);\n }\n }\n\n this.#computedStylesTree.removeChildren();\n for (const category of DefaultCategoryOrder) {\n const properties = propertiesByCategory.get(category);\n if (properties && properties.length > 0) {\n const propertyNodes: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const propertyName of properties) {\n const propertyValue = nodeStyle.computedStyle.get(propertyName) || '';\n const canonicalName = SDK.CSSMetadata.cssMetadata().canonicalPropertyName(propertyName);\n const isInherited = !nonInheritedProperties.has(canonicalName);\n propertyNodes.push(this.buildTreeNode(propertyTraces, propertyName, propertyValue, isInherited));\n }\n tree.push({id: category, treeNodeData: {tag: 'category', name: category}, children: async () => propertyNodes});\n }\n }\n const defaultRenderer = this.createTreeNodeRenderer(propertyTraces, node, matchedStyles);\n this.#treeData = {\n tree,\n compact: true,\n defaultRenderer,\n };\n return this.filterGroupLists();\n }\n\n private buildTraceNode(property: SDK.CSSProperty.CSSProperty):\n TreeOutline.TreeOutlineUtils.TreeNode {\n const rule = property.ownerStyle.parentRule;\n return {\n treeNodeData: {\n tag: 'traceElement',\n property,\n rule,\n },\n id: (rule?.origin || '') + ': ' + property.ownerStyle.styleSheetId + (property.range || property.name),\n };\n }\n\n private createTreeNodeRenderer(\n propertyTraces: Map,\n domNode: SDK.DOMModel.DOMNode,\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,\n ):\n (node: TreeOutline.TreeOutlineUtils.TreeNode,\n state: {isExpanded: boolean}) => LitHtml.TemplateResult {\n return node => {\n const data = node.treeNodeData;\n if (data.tag === 'property') {\n const trace = propertyTraces.get(data.propertyName);\n const activeProperty = trace?.find(\n property => matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.ACTIVE);\n const propertyElement = createPropertyElement(\n domNode, data.propertyName, data.propertyValue, propertyTraces.has(data.propertyName), data.inherited,\n activeProperty, event => {\n if (activeProperty) {\n this.handleContextMenuEvent(matchedStyles, activeProperty, event);\n }\n });\n return propertyElement;\n }\n if (data.tag === 'traceElement') {\n const isPropertyOverloaded =\n matchedStyles.propertyState(data.property) === SDK.CSSMatchedStyles.PropertyState.OVERLOADED;\n const traceElement =\n createTraceElement(domNode, data.property, isPropertyOverloaded, matchedStyles, this.linkifier);\n traceElement.addEventListener(\n 'contextmenu', this.handleContextMenuEvent.bind(this, matchedStyles, data.property));\n return html`${traceElement}`;\n }\n return html`${data.name}`;\n };\n }\n\n private buildTreeNode(\n propertyTraces: Map, propertyName: string, propertyValue: string,\n isInherited: boolean): TreeOutline.TreeOutlineUtils.TreeNode {\n const treeNodeData: ComputedStyleData = {\n tag: 'property',\n propertyName,\n propertyValue,\n inherited: isInherited,\n };\n const trace = propertyTraces.get(propertyName);\n if (!trace) {\n return {\n treeNodeData,\n jslogContext: propertyName,\n id: propertyName,\n };\n }\n return {\n treeNodeData,\n jslogContext: propertyName,\n id: propertyName,\n children: async () => trace.map(this.buildTraceNode),\n };\n }\n\n private handleContextMenuEvent(\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, property: SDK.CSSProperty.CSSProperty, event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n const rule = property.ownerStyle.parentRule;\n\n if (rule) {\n const header = rule.styleSheetId ? matchedStyles.cssModel().styleSheetHeaderForId(rule.styleSheetId) : null;\n if (header && !header.isAnonymousInlineStyleSheet()) {\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.navigateToSelectorSource), () => {\n StylePropertiesSection.tryNavigateToRuleLocation(matchedStyles, rule);\n }, {jslogContext: 'navigate-to-selector-source'});\n }\n }\n\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.navigateToStyle), () => Common.Revealer.reveal(property),\n {jslogContext: 'navigate-to-style'});\n void contextMenu.show();\n }\n\n private computePropertyTraces(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):\n Map {\n const result = new Map();\n for (const style of matchedStyles.nodeStyles()) {\n const allProperties = style.allProperties();\n for (const property of allProperties) {\n if (!property.activeInStyle() || !matchedStyles.propertyState(property)) {\n continue;\n }\n if (!result.has(property.name)) {\n result.set(property.name, []);\n }\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n result.get(property.name).push(property);\n }\n }\n return result;\n }\n\n private computeNonInheritedProperties(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles): Set {\n const result = new Set();\n for (const style of matchedStyles.nodeStyles()) {\n for (const property of style.allProperties()) {\n if (!matchedStyles.propertyState(property)) {\n continue;\n }\n result.add(SDK.CSSMetadata.cssMetadata().canonicalPropertyName(property.name));\n }\n }\n return result;\n }\n\n private onFilterChanged(event: Common.EventTarget.EventTargetEvent): void {\n void this.filterComputedStyles(\n event.data ? new RegExp(Platform.StringUtilities.escapeForRegExp(event.data), 'i') : null);\n }\n\n async filterComputedStyles(regex: RegExp|null): Promise {\n this.filterRegex = regex;\n if (this.groupComputedStylesSetting.get()) {\n return this.filterGroupLists();\n }\n return this.filterAlphabeticalList();\n }\n\n private nodeFilter(node: TreeOutline.TreeOutlineUtils.TreeNode): boolean {\n const regex = this.filterRegex;\n const data = node.treeNodeData;\n if (data.tag === 'property') {\n const matched = !regex || regex.test(data.propertyName) || regex.test(data.propertyValue);\n return matched;\n }\n return true;\n }\n\n private filterAlphabeticalList(): void {\n if (!this.#treeData) {\n return;\n }\n const tree = this.#treeData.tree.filter(this.nodeFilter.bind(this));\n this.#computedStylesTree.data = {\n tree,\n defaultRenderer: this.#treeData.defaultRenderer,\n compact: this.#treeData.compact,\n };\n this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));\n }\n\n private async filterGroupLists(): Promise {\n if (!this.#treeData) {\n return;\n }\n const tree: TreeOutline.TreeOutlineUtils.TreeNode[] = [];\n for (const group of this.#treeData.tree) {\n const data = group.treeNodeData;\n if (data.tag !== 'category' || !group.children) {\n continue;\n }\n const properties = await group.children();\n const filteredChildren = properties.filter(this.nodeFilter.bind(this));\n if (filteredChildren.length) {\n tree.push(\n {id: data.name, treeNodeData: {tag: 'category', name: data.name}, children: async () => filteredChildren});\n }\n }\n\n this.#computedStylesTree.data = {\n tree,\n defaultRenderer: this.#treeData.defaultRenderer,\n compact: this.#treeData.compact,\n };\n await this.#computedStylesTree.expandRecursively(0);\n this.noMatchesElement.classList.toggle('hidden', Boolean(tree.length));\n }\n}\n\nconst maxLinkLength = 30;\nconst alwaysShownComputedProperties = new Set(['display', 'height', 'width']);\n"]} \ No newline at end of file diff --git a/public/panels/elements/ComputedStyleWidget.test.d.ts b/public/panels/elements/ComputedStyleWidget.test.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/public/panels/elements/ComputedStyleWidget.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/public/panels/elements/ComputedStyleWidget.test.js b/public/panels/elements/ComputedStyleWidget.test.js new file mode 100644 index 00000000..e8c3dfed --- /dev/null +++ b/public/panels/elements/ComputedStyleWidget.test.js @@ -0,0 +1,60 @@ +// 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 SDK from '../../core/sdk/sdk.js'; +import { createTarget, stubNoopSettings } from '../../testing/EnvironmentHelpers.js'; +import { describeWithMockConnection } from '../../testing/MockConnection.js'; +import * as UI from '../../ui/legacy/legacy.js'; +import * as Elements from './elements.js'; +describeWithMockConnection('ComputedStyleWidget', () => { + let target; + let view; + let trackComputedStyleUpdatesForNodeSpy; + beforeEach(() => { + stubNoopSettings(); + target = createTarget(); + UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, null); + trackComputedStyleUpdatesForNodeSpy = + sinon.spy(SDK.CSSModel.CSSModel.prototype, 'trackComputedStyleUpdatesForNode'); + const cssModel = target.model(SDK.CSSModel.CSSModel); + sinon.stub(Elements.ComputedStyleModel.ComputedStyleModel.prototype, 'cssModel').returns(cssModel); + }); + afterEach(() => { + view.detach(); + }); + it('tracks computed style updates for the node when the widget is shown', () => { + const model = target.model(SDK.DOMModel.DOMModel); + assert.exists(model); + const node = new SDK.DOMModel.DOMNode(model); + UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node); + view = new Elements.ComputedStyleWidget.ComputedStyleWidget(); + view.markAsRoot(); + view.show(document.body); + sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, node.id); + }); + it('tracks computed style updates for the node when the selected node is changed', () => { + const model = target.model(SDK.DOMModel.DOMModel); + assert.exists(model); + const node = new SDK.DOMModel.DOMNode(model); + UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node); + view = new Elements.ComputedStyleWidget.ComputedStyleWidget(); + view.markAsRoot(); + view.show(document.body); + sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, node.id); + const newNode = new SDK.DOMModel.DOMNode(model); + UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, newNode); + sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, newNode.id); + }); + it('removes tracking computed style updates for the node when the widget is hidden', () => { + const model = target.model(SDK.DOMModel.DOMModel); + assert.exists(model); + const node = new SDK.DOMModel.DOMNode(model); + UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node); + view = new Elements.ComputedStyleWidget.ComputedStyleWidget(); + view.markAsRoot(); + view.show(document.body); + view.hideWidget(); + sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, undefined); + }); +}); +//# sourceMappingURL=ComputedStyleWidget.test.js.map \ No newline at end of file diff --git a/public/panels/elements/ComputedStyleWidget.test.js.map b/public/panels/elements/ComputedStyleWidget.test.js.map new file mode 100644 index 00000000..3bbe2cd3 --- /dev/null +++ b/public/panels/elements/ComputedStyleWidget.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ComputedStyleWidget.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ComputedStyleWidget.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 {createTarget, stubNoopSettings} from '../../testing/EnvironmentHelpers.js';\nimport {describeWithMockConnection} from '../../testing/MockConnection.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Elements from './elements.js';\n\ndescribeWithMockConnection('ComputedStyleWidget', () => {\n let target: SDK.Target.Target;\n let view: Elements.ComputedStyleWidget.ComputedStyleWidget;\n let trackComputedStyleUpdatesForNodeSpy: sinon.SinonSpy;\n\n beforeEach(() => {\n stubNoopSettings();\n target = createTarget();\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, null);\n trackComputedStyleUpdatesForNodeSpy =\n sinon.spy(SDK.CSSModel.CSSModel.prototype, 'trackComputedStyleUpdatesForNode');\n\n const cssModel = target.model(SDK.CSSModel.CSSModel);\n sinon.stub(Elements.ComputedStyleModel.ComputedStyleModel.prototype, 'cssModel').returns(cssModel);\n });\n\n afterEach(() => {\n view.detach();\n });\n\n it('tracks computed style updates for the node when the widget is shown', () => {\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n const node = new SDK.DOMModel.DOMNode(model);\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n view = new Elements.ComputedStyleWidget.ComputedStyleWidget();\n view.markAsRoot();\n view.show(document.body);\n\n sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, node.id);\n });\n\n it('tracks computed style updates for the node when the selected node is changed', () => {\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n const node = new SDK.DOMModel.DOMNode(model);\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n view = new Elements.ComputedStyleWidget.ComputedStyleWidget();\n view.markAsRoot();\n view.show(document.body);\n\n sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, node.id);\n const newNode = new SDK.DOMModel.DOMNode(model);\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, newNode);\n\n sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, newNode.id);\n });\n\n it('removes tracking computed style updates for the node when the widget is hidden', () => {\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n const node = new SDK.DOMModel.DOMNode(model);\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n view = new Elements.ComputedStyleWidget.ComputedStyleWidget();\n view.markAsRoot();\n view.show(document.body);\n view.hideWidget();\n\n sinon.assert.calledWith(trackComputedStyleUpdatesForNodeSpy, undefined);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/elements/ElementStatePaneWidget.d.ts b/public/panels/elements/ElementStatePaneWidget.d.ts index c72aa430..aabaa90c 100644 --- a/public/panels/elements/ElementStatePaneWidget.d.ts +++ b/public/panels/elements/ElementStatePaneWidget.d.ts @@ -2,6 +2,7 @@ import * as UI from '../../ui/legacy/legacy.js'; export declare class ElementStatePaneWidget extends UI.Widget.Widget { private readonly inputs; private readonly inputStates; + private readonly duals; private cssModel?; private specificPseudoStateDivs; private specificHeader; diff --git a/public/panels/elements/ElementStatePaneWidget.js b/public/panels/elements/ElementStatePaneWidget.js index c9e2f444..1993a39f 100644 --- a/public/panels/elements/ElementStatePaneWidget.js +++ b/public/panels/elements/ElementStatePaneWidget.js @@ -65,6 +65,7 @@ var SpecificPseudoStates; export class ElementStatePaneWidget extends UI.Widget.Widget { inputs; inputStates; + duals; cssModel; specificPseudoStateDivs; specificHeader; @@ -76,6 +77,7 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { const inputs = []; this.inputs = inputs; this.inputStates = new WeakMap(); + this.duals = new Map(); const createSectionHeader = (title) => { const sectionHeaderContainer = document.createElement('div'); sectionHeaderContainer.classList.add('section-header'); @@ -91,7 +93,12 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { if (!state) { return; } - node.domModel().cssModel().forcePseudoState(node, state, event.target.checked); + const checked = event.target.checked; + const dual = this.duals.get(state); + if (checked && dual) { + node.domModel().cssModel().forcePseudoState(node, dual, false); + } + node.domModel().cssModel().forcePseudoState(node, state, checked); }; const createElementStateCheckbox = (state) => { const div = document.createElement('div'); @@ -105,6 +112,10 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { div.appendChild(label); return div; }; + const setDualStateCheckboxes = (first, second) => { + this.duals.set(first, second); + this.duals.set(second, first); + }; const createEmulateFocusedPageCheckbox = () => { const div = document.createElement('div'); div.classList.add('page-state-checkbox'); @@ -170,6 +181,11 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { this.specificPseudoStateDivs.forEach(div => { elementSpecificContainer.appendChild(div); }); + setDualStateCheckboxes(SpecificPseudoStates.VALID, SpecificPseudoStates.INVALID); + setDualStateCheckboxes(SpecificPseudoStates.USER_VALID, SpecificPseudoStates.USER_INVALID); + setDualStateCheckboxes(SpecificPseudoStates.READ_ONLY, SpecificPseudoStates.READ_WRITE); + setDualStateCheckboxes(SpecificPseudoStates.IN_RANGE, SpecificPseudoStates.OUT_OF_RANGE); + setDualStateCheckboxes(SpecificPseudoStates.ENABLED, SpecificPseudoStates.DISABLED); this.specificHeader = document.createElement('details'); this.specificHeader.classList.add('specific-details'); const sectionHeaderContainer = document.createElement('summary'); @@ -243,6 +259,19 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { return isElementOfTypes(node, ['input']) && (node.getAttribute('type') === 'checkbox' || node.getAttribute('type') === 'radio'); }; + const isContentEditable = (node) => { + return node.getAttribute('contenteditable') !== undefined || + Boolean(node.parentNode && isContentEditable(node.parentNode)); + }; + const isDisabled = (node) => { + return node.getAttribute('disabled') !== undefined; + }; + const isMutable = (node) => { + if (isElementOfTypes(node, ['input', 'textarea'])) { + return node.getAttribute('readonly') === undefined && !isDisabled(node); + } + return isContentEditable(node); + }; // An autonomous custom element is called a form-associated custom element if the element is associated with a custom element definition whose form-associated field is set to true. // https://html.spec.whatwg.org/multipage/custom-elements.html#form-associated-custom-element const isFormAssociatedCustomElement = async (node) => { @@ -255,8 +284,8 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { const isFormAssociated = await isFormAssociatedCustomElement(node); if (isElementOfTypes(node, ['button', 'input', 'select', 'textarea', 'optgroup', 'option', 'fieldset']) || isFormAssociated) { - hideSpecificCheckbox(SpecificPseudoStates.ENABLED, false); - hideSpecificCheckbox(SpecificPseudoStates.DISABLED, false); + hideSpecificCheckbox(SpecificPseudoStates.ENABLED, !isDisabled(node)); + hideSpecificCheckbox(SpecificPseudoStates.DISABLED, isDisabled(node)); } else { hideSpecificCheckbox(SpecificPseudoStates.ENABLED, true); @@ -274,8 +303,14 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { if (isElementOfTypes(node, ['input', 'select', 'textarea'])) { hideSpecificCheckbox(SpecificPseudoStates.USER_VALID, false); hideSpecificCheckbox(SpecificPseudoStates.USER_INVALID, false); - hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, false); - hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, false); + if (node.getAttribute('required') === undefined) { + hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, false); + hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, true); + } + else { + hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, true); + hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, false); + } } else { hideSpecificCheckbox(SpecificPseudoStates.USER_VALID, true); @@ -283,28 +318,12 @@ export class ElementStatePaneWidget extends UI.Widget.Widget { hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, true); hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, true); } - if (isElementOfTypes(node, ['input', 'textarea'])) { - hideSpecificCheckbox(SpecificPseudoStates.READ_WRITE, false); - } - else { + if (isMutable(node)) { hideSpecificCheckbox(SpecificPseudoStates.READ_WRITE, true); - } - if (isElementOfTypes(node, [ - 'button', - 'datalist', - 'fieldset', - 'label', - 'legend', - 'meter', - 'optgroup', - 'option', - 'output', - 'progress', - 'select', - ])) { hideSpecificCheckbox(SpecificPseudoStates.READ_ONLY, false); } else { + hideSpecificCheckbox(SpecificPseudoStates.READ_WRITE, false); hideSpecificCheckbox(SpecificPseudoStates.READ_ONLY, true); } if (isElementOfTypes(node, ['input']) && diff --git a/public/panels/elements/ElementStatePaneWidget.js.map b/public/panels/elements/ElementStatePaneWidget.js.map index 52d4c16b..e5962aef 100644 --- a/public/panels/elements/ElementStatePaneWidget.js.map +++ b/public/panels/elements/ElementStatePaneWidget.js.map @@ -1 +1 @@ -{"version":3,"file":"ElementStatePaneWidget.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ElementStatePaneWidget.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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.\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 SDK from '../../core/sdk/sdk.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {ElementsPanel} from './ElementsPanel.js';\nimport elementStatePaneWidgetStyles from './elementStatePaneWidget.css.js';\n\nconst UIStrings = {\n /**\n * @description Title of a section in the Element State Pane Widget of the Elements panel. The\n * controls in this section allow users to force a particular state on the selected element, e.g. a\n * focused state via :focus or a hover state via :hover.\n */\n forceElementState: 'Force element state',\n /**\n * @description Tooltip text in Element State Pane Widget of the Elements panel. For a button that\n * opens a tool that toggles the various states of the selected element on/off.\n */\n toggleElementState: 'Toggle Element State',\n /**\n * @description The name of a checkbox setting in the Element & Page State Pane Widget of the Elements panel.. This setting\n * emulates/pretends that the webpage is focused.\n */\n emulateFocusedPage: 'Emulate a focused page',\n /**\n * @description Explanation text for the 'Emulate a focused page' setting in the Rendering tool.\n */\n emulatesAFocusedPage: 'Keep page focused. Commonly used for debugging disappearing elements.',\n /**\n * @description Similar with forceElementState but allows users to force specific state of the selected element.\n */\n forceElementSpecificStates: 'Force specific element state',\n /**\n *@description Text that is usually a hyperlink to more documentation\n */\n learnMore: 'Learn more',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/ElementStatePaneWidget.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nenum SpecificPseudoStates {\n ENABLED = 'enabled',\n DISABLED = 'disabled',\n VALID = 'valid',\n INVALID = 'invalid',\n USER_VALID = 'user-valid',\n USER_INVALID = 'user-invalid',\n REQUIRED = 'required',\n OPTIONAL = 'optional',\n READ_ONLY = 'read-only',\n READ_WRITE = 'read-write',\n IN_RANGE = 'in-range',\n OUT_OF_RANGE = 'out-of-range',\n VISITED = 'visited',\n CHECKED = 'checked',\n INDETERMINATE = 'indeterminate',\n PLACEHOLDER_SHOWN = 'placeholder-shown',\n AUTOFILL = 'autofill',\n} // TODO(crbug.com/332914922): Also add :link and tests for :visited when the bug is fixed.\n\nexport class ElementStatePaneWidget extends UI.Widget.Widget {\n private readonly inputs: HTMLInputElement[];\n private readonly inputStates: WeakMap;\n private cssModel?: SDK.CSSModel.CSSModel|null;\n private specificPseudoStateDivs: Map;\n private specificHeader: HTMLDetailsElement;\n private readonly throttler: Common.Throttler.Throttler;\n\n constructor() {\n super(true);\n this.contentElement.className = 'styles-element-state-pane';\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('element-states')}`);\n const inputs: HTMLInputElement[] = [];\n this.inputs = inputs;\n this.inputStates = new WeakMap();\n const createSectionHeader = (title: string): HTMLDivElement => {\n const sectionHeaderContainer = document.createElement('div');\n sectionHeaderContainer.classList.add('section-header');\n UI.UIUtils.createTextChild(sectionHeaderContainer.createChild('span'), title);\n\n return sectionHeaderContainer;\n };\n const clickListener = (event: MouseEvent): void => {\n const node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n if (!node || !(event.target instanceof HTMLInputElement)) {\n return;\n }\n const state = this.inputStates.get(event.target);\n if (!state) {\n return;\n }\n node.domModel().cssModel().forcePseudoState(node, state, event.target.checked);\n };\n const createElementStateCheckbox = (state: string): HTMLDivElement => {\n const div = document.createElement('div');\n div.id = state;\n const label = UI.UIUtils.CheckboxLabel.create(':' + state, undefined, undefined, undefined, true);\n const input = label.checkboxElement;\n this.inputStates.set(input, state);\n input.addEventListener('click', (clickListener as EventListener), false);\n input.setAttribute('jslog', `${VisualLogging.toggle().track({change: true}).context(state)}`);\n inputs.push(input);\n div.appendChild(label);\n return div;\n };\n\n const createEmulateFocusedPageCheckbox = (): Element => {\n const div = document.createElement('div');\n div.classList.add('page-state-checkbox');\n const label = UI.UIUtils.CheckboxLabel.create(\n i18nString(UIStrings.emulateFocusedPage), undefined, undefined, 'emulate-page-focus', true);\n UI.SettingsUI.bindCheckbox(\n label.checkboxElement, Common.Settings.Settings.instance().moduleSetting('emulate-page-focus'), {\n enable: Host.UserMetrics.Action.ToggleEmulateFocusedPageFromStylesPaneOn,\n disable: Host.UserMetrics.Action.ToggleEmulateFocusedPageFromStylesPaneOff,\n });\n UI.Tooltip.Tooltip.install(label.textElement, i18nString(UIStrings.emulatesAFocusedPage));\n\n const learnMoreButton = new Buttons.Button.Button();\n learnMoreButton.data = {\n variant: Buttons.Button.Variant.ICON,\n iconName: 'help',\n size: Buttons.Button.Size.SMALL,\n jslogContext: 'learn-more',\n title: i18nString(UIStrings.learnMore),\n };\n learnMoreButton.addEventListener(\n 'click',\n () => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(\n 'https://goo.gle/devtools-emulate-focused-page' as Platform.DevToolsPath.UrlString));\n\n div.appendChild(label);\n div.appendChild(learnMoreButton);\n return div;\n };\n\n this.contentElement.className = 'styles-element-state-pane';\n\n // Populate page states\n const keepPageFocusedCheckbox = createEmulateFocusedPageCheckbox();\n\n this.contentElement.appendChild(keepPageFocusedCheckbox);\n\n // Populate element states\n this.contentElement.appendChild(createSectionHeader(i18nString(UIStrings.forceElementState)));\n\n const persistentContainer = document.createElement('div');\n persistentContainer.classList.add('source-code');\n persistentContainer.classList.add('pseudo-states-container');\n UI.ARIAUtils.markAsPresentation(persistentContainer);\n\n persistentContainer.appendChild(createElementStateCheckbox('active'));\n persistentContainer.appendChild(createElementStateCheckbox('hover'));\n persistentContainer.appendChild(createElementStateCheckbox('focus'));\n persistentContainer.appendChild(createElementStateCheckbox('focus-within'));\n persistentContainer.appendChild(createElementStateCheckbox('focus-visible'));\n persistentContainer.appendChild(createElementStateCheckbox('target'));\n this.contentElement.appendChild(persistentContainer);\n\n const elementSpecificContainer = document.createElement('div');\n elementSpecificContainer.classList.add('source-code');\n elementSpecificContainer.classList.add('pseudo-states-container');\n elementSpecificContainer.classList.add('specific-pseudo-states');\n UI.ARIAUtils.markAsPresentation(elementSpecificContainer);\n\n this.specificPseudoStateDivs = new Map();\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.ENABLED, createElementStateCheckbox(SpecificPseudoStates.ENABLED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.DISABLED, createElementStateCheckbox(SpecificPseudoStates.DISABLED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.VALID, createElementStateCheckbox(SpecificPseudoStates.VALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.INVALID, createElementStateCheckbox(SpecificPseudoStates.INVALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.USER_VALID, createElementStateCheckbox(SpecificPseudoStates.USER_VALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.USER_INVALID, createElementStateCheckbox(SpecificPseudoStates.USER_INVALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.REQUIRED, createElementStateCheckbox(SpecificPseudoStates.REQUIRED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.OPTIONAL, createElementStateCheckbox(SpecificPseudoStates.OPTIONAL));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.READ_ONLY, createElementStateCheckbox(SpecificPseudoStates.READ_ONLY));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.READ_WRITE, createElementStateCheckbox(SpecificPseudoStates.READ_WRITE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.IN_RANGE, createElementStateCheckbox(SpecificPseudoStates.IN_RANGE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.OUT_OF_RANGE, createElementStateCheckbox(SpecificPseudoStates.OUT_OF_RANGE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.VISITED, createElementStateCheckbox(SpecificPseudoStates.VISITED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.CHECKED, createElementStateCheckbox(SpecificPseudoStates.CHECKED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.INDETERMINATE, createElementStateCheckbox(SpecificPseudoStates.INDETERMINATE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.PLACEHOLDER_SHOWN, createElementStateCheckbox(SpecificPseudoStates.PLACEHOLDER_SHOWN));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.AUTOFILL, createElementStateCheckbox(SpecificPseudoStates.AUTOFILL));\n\n this.specificPseudoStateDivs.forEach(div => {\n elementSpecificContainer.appendChild(div);\n });\n\n this.specificHeader = document.createElement('details');\n this.specificHeader.classList.add('specific-details');\n\n const sectionHeaderContainer = document.createElement('summary');\n sectionHeaderContainer.classList.add('force-specific-element-header');\n sectionHeaderContainer.classList.add('section-header');\n UI.UIUtils.createTextChild(\n sectionHeaderContainer.createChild('span'), i18nString(UIStrings.forceElementSpecificStates));\n\n this.specificHeader.appendChild(sectionHeaderContainer);\n this.specificHeader.appendChild(elementSpecificContainer);\n this.contentElement.appendChild(this.specificHeader);\n\n this.throttler = new Common.Throttler.Throttler(100);\n UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.update, this);\n }\n private updateModel(cssModel: SDK.CSSModel.CSSModel|null): void {\n if (this.cssModel === cssModel) {\n return;\n }\n if (this.cssModel) {\n this.cssModel.removeEventListener(SDK.CSSModel.Events.PseudoStateForced, this.update, this);\n }\n this.cssModel = cssModel;\n if (this.cssModel) {\n this.cssModel.addEventListener(SDK.CSSModel.Events.PseudoStateForced, this.update, this);\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([elementStatePaneWidgetStyles]);\n this.update();\n }\n private update(): void {\n let node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n if (node) {\n node = node.enclosingElementOrSelf();\n }\n this.updateModel(node ? node.domModel().cssModel() : null);\n if (node) {\n const nodePseudoState = node.domModel().cssModel().pseudoState(node);\n for (const input of this.inputs) {\n input.disabled = Boolean(node.pseudoType());\n const state = this.inputStates.get(input);\n input.checked = nodePseudoState && state !== undefined ? nodePseudoState.indexOf(state) >= 0 : false;\n }\n } else {\n for (const input of this.inputs) {\n input.disabled = true;\n input.checked = false;\n }\n }\n void this.throttler.schedule(this.updateElementSpecificStatesTable.bind(this, node));\n ButtonProvider.instance().item().setToggled(this.inputs.some(input => input.checked));\n }\n\n private async updateElementSpecificStatesTable(node: SDK.DOMModel.DOMNode|null = null): Promise {\n if (!node || node.nodeType() !== Node.ELEMENT_NODE) {\n this.specificHeader.hidden = true;\n this.updateElementSpecificStatesTableForTest();\n return;\n }\n let showedACheckbox = false;\n const hideSpecificCheckbox = (pseudoClass: SpecificPseudoStates, hide: boolean): void => {\n const checkbox = this.specificPseudoStateDivs.get(pseudoClass);\n if (checkbox) {\n checkbox.hidden = hide;\n }\n showedACheckbox = showedACheckbox || !hide;\n };\n const isElementOfTypes = (node: SDK.DOMModel.DOMNode, types: string[]): boolean => {\n return types.includes(node.nodeName()?.toLowerCase());\n };\n const isInputWithTypeRadioOrCheckbox = (node: SDK.DOMModel.DOMNode): boolean => {\n return isElementOfTypes(node, ['input']) &&\n (node.getAttribute('type') === 'checkbox' || node.getAttribute('type') === 'radio');\n };\n // An autonomous custom element is called a form-associated custom element if the element is associated with a custom element definition whose form-associated field is set to true.\n // https://html.spec.whatwg.org/multipage/custom-elements.html#form-associated-custom-element\n const isFormAssociatedCustomElement = async(node: SDK.DOMModel.DOMNode): Promise => {\n function getFormAssociatedField(this: HTMLElement): boolean {\n return ('formAssociated' in this.constructor && this.constructor.formAssociated === true);\n }\n const response = await node.callFunction(getFormAssociatedField);\n return response ? response.value : false;\n };\n const isFormAssociated = await isFormAssociatedCustomElement(node);\n\n if (isElementOfTypes(node, ['button', 'input', 'select', 'textarea', 'optgroup', 'option', 'fieldset']) ||\n isFormAssociated) {\n hideSpecificCheckbox(SpecificPseudoStates.ENABLED, false);\n hideSpecificCheckbox(SpecificPseudoStates.DISABLED, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.ENABLED, true);\n hideSpecificCheckbox(SpecificPseudoStates.DISABLED, true);\n }\n\n if (isElementOfTypes(node, ['button', 'fieldset', 'input', 'object', 'output', 'select', 'textarea', 'img']) ||\n isFormAssociated) {\n hideSpecificCheckbox(SpecificPseudoStates.VALID, false);\n hideSpecificCheckbox(SpecificPseudoStates.INVALID, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.VALID, true);\n hideSpecificCheckbox(SpecificPseudoStates.INVALID, true);\n }\n\n if (isElementOfTypes(node, ['input', 'select', 'textarea'])) {\n hideSpecificCheckbox(SpecificPseudoStates.USER_VALID, false);\n hideSpecificCheckbox(SpecificPseudoStates.USER_INVALID, false);\n hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, false);\n hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.USER_VALID, true);\n hideSpecificCheckbox(SpecificPseudoStates.USER_INVALID, true);\n hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, true);\n hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, true);\n }\n\n if (isElementOfTypes(node, ['input', 'textarea'])) {\n hideSpecificCheckbox(SpecificPseudoStates.READ_WRITE, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.READ_WRITE, true);\n }\n\n if (isElementOfTypes(node, [\n 'button',\n 'datalist',\n 'fieldset',\n 'label',\n 'legend',\n 'meter',\n 'optgroup',\n 'option',\n 'output',\n 'progress',\n 'select',\n ])) {\n hideSpecificCheckbox(SpecificPseudoStates.READ_ONLY, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.READ_ONLY, true);\n }\n\n if (isElementOfTypes(node, ['input']) &&\n (node.getAttribute('min') !== undefined || node.getAttribute('max') !== undefined)) {\n hideSpecificCheckbox(SpecificPseudoStates.IN_RANGE, false);\n hideSpecificCheckbox(SpecificPseudoStates.OUT_OF_RANGE, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.IN_RANGE, true);\n hideSpecificCheckbox(SpecificPseudoStates.OUT_OF_RANGE, true);\n }\n\n if (isElementOfTypes(node, ['a', 'area']) && node.getAttribute('href') !== undefined) {\n hideSpecificCheckbox(SpecificPseudoStates.VISITED, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.VISITED, true);\n }\n\n if (isInputWithTypeRadioOrCheckbox(node) || isElementOfTypes(node, ['option'])) {\n hideSpecificCheckbox(SpecificPseudoStates.CHECKED, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.CHECKED, true);\n }\n\n if (isInputWithTypeRadioOrCheckbox(node) || isElementOfTypes(node, ['progress'])) {\n hideSpecificCheckbox(SpecificPseudoStates.INDETERMINATE, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.INDETERMINATE, true);\n }\n\n if (isElementOfTypes(node, ['input', 'textarea'])) {\n hideSpecificCheckbox(SpecificPseudoStates.PLACEHOLDER_SHOWN, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.PLACEHOLDER_SHOWN, true);\n }\n\n if (isElementOfTypes(node, ['input'])) {\n hideSpecificCheckbox(SpecificPseudoStates.AUTOFILL, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.AUTOFILL, true);\n }\n\n this.specificHeader.hidden = showedACheckbox ? false : true;\n this.updateElementSpecificStatesTableForTest();\n }\n\n updateElementSpecificStatesTableForTest(): void {\n }\n}\n\nlet buttonProviderInstance: ButtonProvider;\nexport class ButtonProvider implements UI.Toolbar.Provider {\n private readonly button: UI.Toolbar.ToolbarToggle;\n private view: ElementStatePaneWidget;\n private constructor() {\n this.button = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.toggleElementState), 'hover');\n this.button.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, this.clicked, this);\n this.button.element.classList.add('element-state');\n this.button.element.setAttribute('jslog', `${VisualLogging.toggleSubpane('element-states').track({click: true})}`);\n this.button.element.style.setProperty('--dot-toggle-top', '12px');\n this.button.element.style.setProperty('--dot-toggle-left', '18px');\n this.view = new ElementStatePaneWidget();\n }\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): ButtonProvider {\n const {forceNew} = opts;\n if (!buttonProviderInstance || forceNew) {\n buttonProviderInstance = new ButtonProvider();\n }\n return buttonProviderInstance;\n }\n private clicked(): void {\n ElementsPanel.instance().showToolbarPane(!this.view.isShowing() ? this.view : null, this.button);\n }\n item(): UI.Toolbar.ToolbarToggle {\n return this.button;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ElementStatePaneWidget.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ElementStatePaneWidget.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 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.\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 SDK from '../../core/sdk/sdk.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {ElementsPanel} from './ElementsPanel.js';\nimport elementStatePaneWidgetStyles from './elementStatePaneWidget.css.js';\n\nconst UIStrings = {\n /**\n * @description Title of a section in the Element State Pane Widget of the Elements panel. The\n * controls in this section allow users to force a particular state on the selected element, e.g. a\n * focused state via :focus or a hover state via :hover.\n */\n forceElementState: 'Force element state',\n /**\n * @description Tooltip text in Element State Pane Widget of the Elements panel. For a button that\n * opens a tool that toggles the various states of the selected element on/off.\n */\n toggleElementState: 'Toggle Element State',\n /**\n * @description The name of a checkbox setting in the Element & Page State Pane Widget of the Elements panel.. This setting\n * emulates/pretends that the webpage is focused.\n */\n emulateFocusedPage: 'Emulate a focused page',\n /**\n * @description Explanation text for the 'Emulate a focused page' setting in the Rendering tool.\n */\n emulatesAFocusedPage: 'Keep page focused. Commonly used for debugging disappearing elements.',\n /**\n * @description Similar with forceElementState but allows users to force specific state of the selected element.\n */\n forceElementSpecificStates: 'Force specific element state',\n /**\n *@description Text that is usually a hyperlink to more documentation\n */\n learnMore: 'Learn more',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/ElementStatePaneWidget.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nenum SpecificPseudoStates {\n ENABLED = 'enabled',\n DISABLED = 'disabled',\n VALID = 'valid',\n INVALID = 'invalid',\n USER_VALID = 'user-valid',\n USER_INVALID = 'user-invalid',\n REQUIRED = 'required',\n OPTIONAL = 'optional',\n READ_ONLY = 'read-only',\n READ_WRITE = 'read-write',\n IN_RANGE = 'in-range',\n OUT_OF_RANGE = 'out-of-range',\n VISITED = 'visited',\n CHECKED = 'checked',\n INDETERMINATE = 'indeterminate',\n PLACEHOLDER_SHOWN = 'placeholder-shown',\n AUTOFILL = 'autofill',\n} // TODO(crbug.com/332914922): Also add :link and tests for :visited when the bug is fixed.\n\nexport class ElementStatePaneWidget extends UI.Widget.Widget {\n private readonly inputs: HTMLInputElement[];\n private readonly inputStates: WeakMap;\n private readonly duals: Map;\n private cssModel?: SDK.CSSModel.CSSModel|null;\n private specificPseudoStateDivs: Map;\n private specificHeader: HTMLDetailsElement;\n private readonly throttler: Common.Throttler.Throttler;\n\n constructor() {\n super(true);\n this.contentElement.className = 'styles-element-state-pane';\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('element-states')}`);\n const inputs: HTMLInputElement[] = [];\n this.inputs = inputs;\n this.inputStates = new WeakMap();\n this.duals = new Map();\n const createSectionHeader = (title: string): HTMLDivElement => {\n const sectionHeaderContainer = document.createElement('div');\n sectionHeaderContainer.classList.add('section-header');\n UI.UIUtils.createTextChild(sectionHeaderContainer.createChild('span'), title);\n\n return sectionHeaderContainer;\n };\n const clickListener = (event: MouseEvent): void => {\n const node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n if (!node || !(event.target instanceof HTMLInputElement)) {\n return;\n }\n const state = this.inputStates.get(event.target);\n if (!state) {\n return;\n }\n const checked = event.target.checked;\n const dual = this.duals.get(state as SpecificPseudoStates);\n if (checked && dual) {\n node.domModel().cssModel().forcePseudoState(node, dual, false);\n }\n node.domModel().cssModel().forcePseudoState(node, state, checked);\n };\n const createElementStateCheckbox = (state: string): HTMLDivElement => {\n const div = document.createElement('div');\n div.id = state;\n const label = UI.UIUtils.CheckboxLabel.create(':' + state, undefined, undefined, undefined, true);\n const input = label.checkboxElement;\n this.inputStates.set(input, state);\n input.addEventListener('click', (clickListener as EventListener), false);\n input.setAttribute('jslog', `${VisualLogging.toggle().track({change: true}).context(state)}`);\n inputs.push(input);\n div.appendChild(label);\n return div;\n };\n const setDualStateCheckboxes = (first: SpecificPseudoStates, second: SpecificPseudoStates): void => {\n this.duals.set(first, second);\n this.duals.set(second, first);\n };\n const createEmulateFocusedPageCheckbox = (): Element => {\n const div = document.createElement('div');\n div.classList.add('page-state-checkbox');\n const label = UI.UIUtils.CheckboxLabel.create(\n i18nString(UIStrings.emulateFocusedPage), undefined, undefined, 'emulate-page-focus', true);\n UI.SettingsUI.bindCheckbox(\n label.checkboxElement, Common.Settings.Settings.instance().moduleSetting('emulate-page-focus'), {\n enable: Host.UserMetrics.Action.ToggleEmulateFocusedPageFromStylesPaneOn,\n disable: Host.UserMetrics.Action.ToggleEmulateFocusedPageFromStylesPaneOff,\n });\n UI.Tooltip.Tooltip.install(label.textElement, i18nString(UIStrings.emulatesAFocusedPage));\n\n const learnMoreButton = new Buttons.Button.Button();\n learnMoreButton.data = {\n variant: Buttons.Button.Variant.ICON,\n iconName: 'help',\n size: Buttons.Button.Size.SMALL,\n jslogContext: 'learn-more',\n title: i18nString(UIStrings.learnMore),\n };\n learnMoreButton.addEventListener(\n 'click',\n () => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(\n 'https://goo.gle/devtools-emulate-focused-page' as Platform.DevToolsPath.UrlString));\n\n div.appendChild(label);\n div.appendChild(learnMoreButton);\n return div;\n };\n\n this.contentElement.className = 'styles-element-state-pane';\n\n // Populate page states\n const keepPageFocusedCheckbox = createEmulateFocusedPageCheckbox();\n\n this.contentElement.appendChild(keepPageFocusedCheckbox);\n\n // Populate element states\n this.contentElement.appendChild(createSectionHeader(i18nString(UIStrings.forceElementState)));\n\n const persistentContainer = document.createElement('div');\n persistentContainer.classList.add('source-code');\n persistentContainer.classList.add('pseudo-states-container');\n UI.ARIAUtils.markAsPresentation(persistentContainer);\n\n persistentContainer.appendChild(createElementStateCheckbox('active'));\n persistentContainer.appendChild(createElementStateCheckbox('hover'));\n persistentContainer.appendChild(createElementStateCheckbox('focus'));\n persistentContainer.appendChild(createElementStateCheckbox('focus-within'));\n persistentContainer.appendChild(createElementStateCheckbox('focus-visible'));\n persistentContainer.appendChild(createElementStateCheckbox('target'));\n this.contentElement.appendChild(persistentContainer);\n\n const elementSpecificContainer = document.createElement('div');\n elementSpecificContainer.classList.add('source-code');\n elementSpecificContainer.classList.add('pseudo-states-container');\n elementSpecificContainer.classList.add('specific-pseudo-states');\n UI.ARIAUtils.markAsPresentation(elementSpecificContainer);\n\n this.specificPseudoStateDivs = new Map();\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.ENABLED, createElementStateCheckbox(SpecificPseudoStates.ENABLED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.DISABLED, createElementStateCheckbox(SpecificPseudoStates.DISABLED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.VALID, createElementStateCheckbox(SpecificPseudoStates.VALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.INVALID, createElementStateCheckbox(SpecificPseudoStates.INVALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.USER_VALID, createElementStateCheckbox(SpecificPseudoStates.USER_VALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.USER_INVALID, createElementStateCheckbox(SpecificPseudoStates.USER_INVALID));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.REQUIRED, createElementStateCheckbox(SpecificPseudoStates.REQUIRED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.OPTIONAL, createElementStateCheckbox(SpecificPseudoStates.OPTIONAL));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.READ_ONLY, createElementStateCheckbox(SpecificPseudoStates.READ_ONLY));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.READ_WRITE, createElementStateCheckbox(SpecificPseudoStates.READ_WRITE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.IN_RANGE, createElementStateCheckbox(SpecificPseudoStates.IN_RANGE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.OUT_OF_RANGE, createElementStateCheckbox(SpecificPseudoStates.OUT_OF_RANGE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.VISITED, createElementStateCheckbox(SpecificPseudoStates.VISITED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.CHECKED, createElementStateCheckbox(SpecificPseudoStates.CHECKED));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.INDETERMINATE, createElementStateCheckbox(SpecificPseudoStates.INDETERMINATE));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.PLACEHOLDER_SHOWN, createElementStateCheckbox(SpecificPseudoStates.PLACEHOLDER_SHOWN));\n this.specificPseudoStateDivs.set(\n SpecificPseudoStates.AUTOFILL, createElementStateCheckbox(SpecificPseudoStates.AUTOFILL));\n\n this.specificPseudoStateDivs.forEach(div => {\n elementSpecificContainer.appendChild(div);\n });\n\n setDualStateCheckboxes(SpecificPseudoStates.VALID, SpecificPseudoStates.INVALID);\n setDualStateCheckboxes(SpecificPseudoStates.USER_VALID, SpecificPseudoStates.USER_INVALID);\n setDualStateCheckboxes(SpecificPseudoStates.READ_ONLY, SpecificPseudoStates.READ_WRITE);\n setDualStateCheckboxes(SpecificPseudoStates.IN_RANGE, SpecificPseudoStates.OUT_OF_RANGE);\n setDualStateCheckboxes(SpecificPseudoStates.ENABLED, SpecificPseudoStates.DISABLED);\n\n this.specificHeader = document.createElement('details');\n this.specificHeader.classList.add('specific-details');\n\n const sectionHeaderContainer = document.createElement('summary');\n sectionHeaderContainer.classList.add('force-specific-element-header');\n sectionHeaderContainer.classList.add('section-header');\n UI.UIUtils.createTextChild(\n sectionHeaderContainer.createChild('span'), i18nString(UIStrings.forceElementSpecificStates));\n\n this.specificHeader.appendChild(sectionHeaderContainer);\n this.specificHeader.appendChild(elementSpecificContainer);\n this.contentElement.appendChild(this.specificHeader);\n\n this.throttler = new Common.Throttler.Throttler(100);\n UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.update, this);\n }\n private updateModel(cssModel: SDK.CSSModel.CSSModel|null): void {\n if (this.cssModel === cssModel) {\n return;\n }\n if (this.cssModel) {\n this.cssModel.removeEventListener(SDK.CSSModel.Events.PseudoStateForced, this.update, this);\n }\n this.cssModel = cssModel;\n if (this.cssModel) {\n this.cssModel.addEventListener(SDK.CSSModel.Events.PseudoStateForced, this.update, this);\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([elementStatePaneWidgetStyles]);\n this.update();\n }\n private update(): void {\n let node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n if (node) {\n node = node.enclosingElementOrSelf();\n }\n this.updateModel(node ? node.domModel().cssModel() : null);\n if (node) {\n const nodePseudoState = node.domModel().cssModel().pseudoState(node);\n for (const input of this.inputs) {\n input.disabled = Boolean(node.pseudoType());\n const state = this.inputStates.get(input);\n input.checked = nodePseudoState && state !== undefined ? nodePseudoState.indexOf(state) >= 0 : false;\n }\n } else {\n for (const input of this.inputs) {\n input.disabled = true;\n input.checked = false;\n }\n }\n void this.throttler.schedule(this.updateElementSpecificStatesTable.bind(this, node));\n ButtonProvider.instance().item().setToggled(this.inputs.some(input => input.checked));\n }\n\n private async updateElementSpecificStatesTable(node: SDK.DOMModel.DOMNode|null = null): Promise {\n if (!node || node.nodeType() !== Node.ELEMENT_NODE) {\n this.specificHeader.hidden = true;\n this.updateElementSpecificStatesTableForTest();\n return;\n }\n let showedACheckbox = false;\n const hideSpecificCheckbox = (pseudoClass: SpecificPseudoStates, hide: boolean): void => {\n const checkbox = this.specificPseudoStateDivs.get(pseudoClass);\n if (checkbox) {\n checkbox.hidden = hide;\n }\n showedACheckbox = showedACheckbox || !hide;\n };\n const isElementOfTypes = (node: SDK.DOMModel.DOMNode, types: string[]): boolean => {\n return types.includes(node.nodeName()?.toLowerCase());\n };\n const isInputWithTypeRadioOrCheckbox = (node: SDK.DOMModel.DOMNode): boolean => {\n return isElementOfTypes(node, ['input']) &&\n (node.getAttribute('type') === 'checkbox' || node.getAttribute('type') === 'radio');\n };\n const isContentEditable = (node: SDK.DOMModel.DOMNode): boolean => {\n return node.getAttribute('contenteditable') !== undefined ||\n Boolean(node.parentNode && isContentEditable(node.parentNode));\n };\n const isDisabled = (node: SDK.DOMModel.DOMNode): boolean => {\n return node.getAttribute('disabled') !== undefined;\n };\n const isMutable = (node: SDK.DOMModel.DOMNode): boolean => {\n if (isElementOfTypes(node, ['input', 'textarea'])) {\n return node.getAttribute('readonly') === undefined && !isDisabled(node);\n }\n return isContentEditable(node);\n };\n // An autonomous custom element is called a form-associated custom element if the element is associated with a custom element definition whose form-associated field is set to true.\n // https://html.spec.whatwg.org/multipage/custom-elements.html#form-associated-custom-element\n const isFormAssociatedCustomElement = async(node: SDK.DOMModel.DOMNode): Promise => {\n function getFormAssociatedField(this: HTMLElement): boolean {\n return ('formAssociated' in this.constructor && this.constructor.formAssociated === true);\n }\n const response = await node.callFunction(getFormAssociatedField);\n return response ? response.value : false;\n };\n const isFormAssociated = await isFormAssociatedCustomElement(node);\n\n if (isElementOfTypes(node, ['button', 'input', 'select', 'textarea', 'optgroup', 'option', 'fieldset']) ||\n isFormAssociated) {\n hideSpecificCheckbox(SpecificPseudoStates.ENABLED, !isDisabled(node));\n hideSpecificCheckbox(SpecificPseudoStates.DISABLED, isDisabled(node));\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.ENABLED, true);\n hideSpecificCheckbox(SpecificPseudoStates.DISABLED, true);\n }\n\n if (isElementOfTypes(node, ['button', 'fieldset', 'input', 'object', 'output', 'select', 'textarea', 'img']) ||\n isFormAssociated) {\n hideSpecificCheckbox(SpecificPseudoStates.VALID, false);\n hideSpecificCheckbox(SpecificPseudoStates.INVALID, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.VALID, true);\n hideSpecificCheckbox(SpecificPseudoStates.INVALID, true);\n }\n\n if (isElementOfTypes(node, ['input', 'select', 'textarea'])) {\n hideSpecificCheckbox(SpecificPseudoStates.USER_VALID, false);\n hideSpecificCheckbox(SpecificPseudoStates.USER_INVALID, false);\n if (node.getAttribute('required') === undefined) {\n hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, false);\n hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, true);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, true);\n hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, false);\n }\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.USER_VALID, true);\n hideSpecificCheckbox(SpecificPseudoStates.USER_INVALID, true);\n hideSpecificCheckbox(SpecificPseudoStates.REQUIRED, true);\n hideSpecificCheckbox(SpecificPseudoStates.OPTIONAL, true);\n }\n\n if (isMutable(node)) {\n hideSpecificCheckbox(SpecificPseudoStates.READ_WRITE, true);\n hideSpecificCheckbox(SpecificPseudoStates.READ_ONLY, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.READ_WRITE, false);\n hideSpecificCheckbox(SpecificPseudoStates.READ_ONLY, true);\n }\n\n if (isElementOfTypes(node, ['input']) &&\n (node.getAttribute('min') !== undefined || node.getAttribute('max') !== undefined)) {\n hideSpecificCheckbox(SpecificPseudoStates.IN_RANGE, false);\n hideSpecificCheckbox(SpecificPseudoStates.OUT_OF_RANGE, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.IN_RANGE, true);\n hideSpecificCheckbox(SpecificPseudoStates.OUT_OF_RANGE, true);\n }\n\n if (isElementOfTypes(node, ['a', 'area']) && node.getAttribute('href') !== undefined) {\n hideSpecificCheckbox(SpecificPseudoStates.VISITED, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.VISITED, true);\n }\n\n if (isInputWithTypeRadioOrCheckbox(node) || isElementOfTypes(node, ['option'])) {\n hideSpecificCheckbox(SpecificPseudoStates.CHECKED, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.CHECKED, true);\n }\n\n if (isInputWithTypeRadioOrCheckbox(node) || isElementOfTypes(node, ['progress'])) {\n hideSpecificCheckbox(SpecificPseudoStates.INDETERMINATE, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.INDETERMINATE, true);\n }\n\n if (isElementOfTypes(node, ['input', 'textarea'])) {\n hideSpecificCheckbox(SpecificPseudoStates.PLACEHOLDER_SHOWN, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.PLACEHOLDER_SHOWN, true);\n }\n\n if (isElementOfTypes(node, ['input'])) {\n hideSpecificCheckbox(SpecificPseudoStates.AUTOFILL, false);\n } else {\n hideSpecificCheckbox(SpecificPseudoStates.AUTOFILL, true);\n }\n\n this.specificHeader.hidden = showedACheckbox ? false : true;\n this.updateElementSpecificStatesTableForTest();\n }\n\n updateElementSpecificStatesTableForTest(): void {\n }\n}\n\nlet buttonProviderInstance: ButtonProvider;\nexport class ButtonProvider implements UI.Toolbar.Provider {\n private readonly button: UI.Toolbar.ToolbarToggle;\n private view: ElementStatePaneWidget;\n private constructor() {\n this.button = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.toggleElementState), 'hover');\n this.button.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, this.clicked, this);\n this.button.element.classList.add('element-state');\n this.button.element.setAttribute('jslog', `${VisualLogging.toggleSubpane('element-states').track({click: true})}`);\n this.button.element.style.setProperty('--dot-toggle-top', '12px');\n this.button.element.style.setProperty('--dot-toggle-left', '18px');\n this.view = new ElementStatePaneWidget();\n }\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): ButtonProvider {\n const {forceNew} = opts;\n if (!buttonProviderInstance || forceNew) {\n buttonProviderInstance = new ButtonProvider();\n }\n return buttonProviderInstance;\n }\n private clicked(): void {\n ElementsPanel.instance().showToolbarPane(!this.view.isShowing() ? this.view : null, this.button);\n }\n item(): UI.Toolbar.ToolbarToggle {\n return this.button;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/elements/ElementStatePaneWidget.test.js b/public/panels/elements/ElementStatePaneWidget.test.js index 667843bc..6097fc9b 100644 --- a/public/panels/elements/ElementStatePaneWidget.test.js +++ b/public/panels/elements/ElementStatePaneWidget.test.js @@ -53,7 +53,8 @@ describeWithMockConnection('ElementStatePaneWidget', () => { for (const pseudoClass of pseudoClasses) { const div = view.contentElement.querySelector(`#${pseudoClass}`); assert.instanceOf(div, HTMLDivElement); - assert.strictEqual(!div.hidden, expectedPseudoClasses.includes(div.id), `Wrong state for ${div.id}`); + const shouldShow = expectedPseudoClasses.includes(pseudoClass); + assert.strictEqual(!div.hidden, shouldShow, `Checkbox for ${pseudoClass} should be ${shouldShow ? 'shown' : 'hidden'}`); } }; it('Calls the right backend functions', async () => { @@ -112,89 +113,118 @@ describeWithMockConnection('ElementStatePaneWidget', () => { }); it('Shows the specific pseudo-classes for input', async () => { await assertExpectedPseudoClasses('input', [ - 'enabled', 'disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', - 'optional', - 'read-write', + 'read-only', 'placeholder-shown', 'autofill', ]); }); it('Shows the specific pseudo-classes for button', async () => { - await assertExpectedPseudoClasses('button', ['enabled', 'disabled', 'valid', 'invalid', 'read-only']); + await assertExpectedPseudoClasses('button', ['disabled', 'valid', 'invalid', 'read-write']); }); it('Shows the specific pseudo-classes for fieldset', async () => { - await assertExpectedPseudoClasses('fieldset', ['enabled', 'disabled', 'valid', 'invalid', 'read-only']); + await assertExpectedPseudoClasses('fieldset', ['disabled', 'valid', 'invalid', 'read-write']); }); it('Shows the specific pseudo-classes for textarea', async () => { await assertExpectedPseudoClasses('textarea', [ - 'enabled', 'disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', - 'optional', - 'read-write', + 'read-only', 'placeholder-shown', ]); + await assertExpectedPseudoClasses('textarea', [ + 'disabled', + 'valid', + 'invalid', + 'user-valid', + 'user-invalid', + 'required', + 'read-write', + 'placeholder-shown', + ], false, ['readonly', '']); + await assertExpectedPseudoClasses('textarea', [ + 'enabled', + 'valid', + 'invalid', + 'user-valid', + 'user-invalid', + 'required', + 'read-write', + 'placeholder-shown', + ], false, ['disabled', '']); + await assertExpectedPseudoClasses('textarea', [ + 'disabled', + 'valid', + 'invalid', + 'user-valid', + 'user-invalid', + 'optional', + 'read-only', + 'placeholder-shown', + ], false, ['required', '']); }); it('Shows the specific pseudo-classes for select', async () => { - await assertExpectedPseudoClasses('select', ['enabled', 'disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', 'optional', 'read-only']); + await assertExpectedPseudoClasses('select', ['disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', 'read-write']); }); it('Shows the specific pseudo-classes for option', async () => { - await assertExpectedPseudoClasses('option', ['enabled', 'disabled', 'checked', 'read-only']); + await assertExpectedPseudoClasses('option', ['disabled', 'checked', 'read-write']); }); it('Shows the specific pseudo-classes for optgroup', async () => { - await assertExpectedPseudoClasses('optgroup', ['enabled', 'disabled', 'read-only']); + await assertExpectedPseudoClasses('optgroup', ['disabled', 'read-write']); }); it('Shows the specific pseudo-classes for FormAssociated', async () => { - await assertExpectedPseudoClasses('CustomFormAssociatedElement', ['enabled', 'disabled', 'valid', 'invalid'], true); + await assertExpectedPseudoClasses('CustomFormAssociatedElement', ['disabled', 'valid', 'invalid', 'read-write'], true); }); it('Shows the specific pseudo-classes for object, output and img', async () => { - await assertExpectedPseudoClasses('object', ['valid', 'invalid']); - await assertExpectedPseudoClasses('output', ['valid', 'invalid', 'read-only']); - await assertExpectedPseudoClasses('img', ['valid', 'invalid']); + await assertExpectedPseudoClasses('object', ['valid', 'invalid', 'read-write']); + await assertExpectedPseudoClasses('output', ['valid', 'invalid', 'read-write']); + await assertExpectedPseudoClasses('img', ['valid', 'invalid', 'read-write']); }); it('Shows the specific pseudo-classes for progress', async () => { - await assertExpectedPseudoClasses('progress', ['read-only', 'indeterminate']); + await assertExpectedPseudoClasses('progress', ['read-write', 'indeterminate']); }); it('Shows the specific pseudo-classes for a and area with href', async () => { - await assertExpectedPseudoClasses('a', ['visited'], false, ['href', 'www.google.com']); - await assertExpectedPseudoClasses('a', ['visited'], false, ['href', 'www.google.com']); + await assertExpectedPseudoClasses('a', ['visited', 'read-write'], false, ['href', 'www.google.com']); + await assertExpectedPseudoClasses('area', ['visited', 'read-write'], false, ['href', 'www.google.com']); + }); + it('Shows the specific pseudo-classes for a and area without href', async () => { + await assertExpectedPseudoClasses('a', ['read-write']); + await assertExpectedPseudoClasses('area', ['read-write']); + }); + it('Shows the specific pseudo-classes for contenteditable div', async () => { + await assertExpectedPseudoClasses('div', ['read-only'], false, ['contenteditable', '']); }); it('Shows the specific pseudo-classes for radio or checkbox inputs', async () => { await assertExpectedPseudoClasses('input', [ - 'enabled', 'disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', - 'optional', - 'read-write', + 'read-only', 'placeholder-shown', 'autofill', 'checked', 'indeterminate', ], false, ['type', 'checkbox']); await assertExpectedPseudoClasses('input', [ - 'enabled', 'disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', - 'optional', - 'read-write', + 'read-only', 'placeholder-shown', 'autofill', 'checked', @@ -202,10 +232,10 @@ describeWithMockConnection('ElementStatePaneWidget', () => { ], false, ['type', 'radio']); }); it('Shows the specific pseudo-classes for datalist, label, legend and meter', async () => { - await assertExpectedPseudoClasses('datalist', ['read-only']); - await assertExpectedPseudoClasses('label', ['read-only']); - await assertExpectedPseudoClasses('legend', ['read-only']); - await assertExpectedPseudoClasses('meter', ['read-only']); + await assertExpectedPseudoClasses('datalist', ['read-write']); + await assertExpectedPseudoClasses('label', ['read-write']); + await assertExpectedPseudoClasses('legend', ['read-write']); + await assertExpectedPseudoClasses('meter', ['read-write']); }); }); //# sourceMappingURL=ElementStatePaneWidget.test.js.map \ No newline at end of file diff --git a/public/panels/elements/ElementStatePaneWidget.test.js.map b/public/panels/elements/ElementStatePaneWidget.test.js.map index 2fab80e1..5f0a9a10 100644 --- a/public/panels/elements/ElementStatePaneWidget.test.js.map +++ b/public/panels/elements/ElementStatePaneWidget.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ElementStatePaneWidget.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ElementStatePaneWidget.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 SDK from '../../core/sdk/sdk.js';\nimport {createTarget, stubNoopSettings} from '../../testing/EnvironmentHelpers.js';\nimport {\n describeWithMockConnection,\n} from '../../testing/MockConnection.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Elements from './elements.js';\n\ndescribeWithMockConnection('ElementStatePaneWidget', () => {\n let target: SDK.Target.Target;\n let view: Elements.ElementStatePaneWidget.ElementStatePaneWidget;\n\n const pseudoClasses = [\n 'enabled',\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'optional',\n 'read-only',\n 'read-write',\n 'in-range',\n 'out-of-range',\n 'visited',\n 'checked',\n 'indeterminate',\n 'placeholder-shown',\n 'autofill',\n ];\n\n beforeEach(() => {\n stubNoopSettings();\n target = createTarget();\n });\n\n const assertExpectedPseudoClasses = async (\n nodeName: string, expectedPseudoClasses: string[], formAssociated: boolean = false,\n attribute?: [string, string]) => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n const tableUpdatedPromise = new Promise(\n resolve => sinon.stub(view, 'updateElementSpecificStatesTableForTest').callsFake(resolve),\n );\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n\n const node = new SDK.DOMModel.DOMNode(model);\n\n sinon.stub(node, 'nodeType').returns(Node.ELEMENT_NODE);\n sinon.stub(node, 'nodeName').returns(nodeName);\n sinon.stub(node, 'enclosingElementOrSelf').returns(node);\n sinon.stub(node, 'callFunction').resolves({value: formAssociated});\n if (attribute) {\n sinon.stub(node, 'getAttribute').withArgs(attribute[0]).returns(attribute[1]);\n }\n\n const header = view.contentElement.querySelector('.force-specific-element-header');\n assert.instanceOf(header, HTMLElement);\n header.click();\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n\n await tableUpdatedPromise;\n\n for (const pseudoClass of pseudoClasses) {\n const div = view.contentElement.querySelector(`#${pseudoClass}`);\n assert.instanceOf(div, HTMLDivElement);\n assert.strictEqual(!div.hidden, expectedPseudoClasses.includes(div.id), `Wrong state for ${div.id}`);\n }\n };\n\n it('Calls the right backend functions', async () => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n\n const node = new SDK.DOMModel.DOMNode(model);\n\n sinon.stub(node, 'nodeType').returns(Node.ELEMENT_NODE);\n sinon.stub(node, 'nodeName').returns('input');\n sinon.stub(node, 'enclosingElementOrSelf').returns(node);\n const checkboxes = sinon.spy(node.domModel().cssModel(), 'forcePseudoState');\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n\n for (const pseudoClass of pseudoClasses) {\n const div = view.contentElement.querySelector(`#${pseudoClass}`);\n assert.exists(div);\n const span = div.children[0];\n const shadowRoot = span.shadowRoot;\n const input = shadowRoot?.querySelector('input');\n assert.exists(input, 'The span element doesn\\'t have an input element');\n input.click();\n\n const args = checkboxes.lastCall.args;\n assert.strictEqual(args[0], node, 'Called forcePseudoState with wrong node');\n assert.strictEqual(args[1], pseudoClass, 'Called forcePseudoState with wrong pseudo-state');\n assert.strictEqual(args[2], true, 'Called forcePseudoState with wrong enable state');\n }\n });\n\n it('Hidden state for not ELEMENT_NODE type', async () => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n const tableUpdatedPromise = new Promise(\n resolve => sinon.stub(view, 'updateElementSpecificStatesTableForTest').callsFake(resolve),\n );\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n const node = new SDK.DOMModel.DOMNode(model);\n sinon.stub(node, 'nodeType').returns(Node.TEXT_NODE);\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n await tableUpdatedPromise;\n\n const details = view.contentElement.querySelector('.specific-details');\n assert.exists(details, 'The details element doesn\\'t exist');\n assert.instanceOf(details, HTMLDetailsElement, 'The details element is not an instance of HTMLDetailsElement');\n assert.isTrue(details.hidden, 'The details element is not hidden');\n });\n\n it('Hidden state for not supported element type', async () => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n const tableUpdatedPromise = new Promise(\n resolve => sinon.stub(view, 'updateElementSpecificStatesTableForTest').callsFake(resolve),\n );\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n const node = new SDK.DOMModel.DOMNode(model);\n sinon.stub(node, 'nodeName').returns('not supported');\n sinon.stub(node, 'enclosingElementOrSelf').returns(node);\n sinon.stub(node, 'callFunction').resolves({value: false});\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n await tableUpdatedPromise;\n\n const details = view.contentElement.querySelector('.specific-details');\n assert.exists(details, 'The details element doesn\\'t exist');\n assert.instanceOf(details, HTMLDetailsElement, 'The details element is not an instance of HTMLDetailsElement');\n assert.isTrue(details.hidden, 'The details element is not hidden');\n });\n\n it('Shows the specific pseudo-classes for input', async () => {\n await assertExpectedPseudoClasses(\n 'input',\n [\n 'enabled',\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'optional',\n 'read-write',\n 'placeholder-shown',\n 'autofill',\n ],\n );\n });\n\n it('Shows the specific pseudo-classes for button', async () => {\n await assertExpectedPseudoClasses(\n 'button',\n ['enabled', 'disabled', 'valid', 'invalid', 'read-only'],\n );\n });\n\n it('Shows the specific pseudo-classes for fieldset', async () => {\n await assertExpectedPseudoClasses(\n 'fieldset',\n ['enabled', 'disabled', 'valid', 'invalid', 'read-only'],\n );\n });\n\n it('Shows the specific pseudo-classes for textarea', async () => {\n await assertExpectedPseudoClasses(\n 'textarea',\n [\n 'enabled',\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'optional',\n 'read-write',\n 'placeholder-shown',\n ],\n );\n });\n\n it('Shows the specific pseudo-classes for select', async () => {\n await assertExpectedPseudoClasses(\n 'select',\n ['enabled', 'disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', 'optional', 'read-only'],\n );\n });\n\n it('Shows the specific pseudo-classes for option', async () => {\n await assertExpectedPseudoClasses(\n 'option',\n ['enabled', 'disabled', 'checked', 'read-only'],\n );\n });\n\n it('Shows the specific pseudo-classes for optgroup', async () => {\n await assertExpectedPseudoClasses(\n 'optgroup',\n ['enabled', 'disabled', 'read-only'],\n );\n });\n\n it('Shows the specific pseudo-classes for FormAssociated', async () => {\n await assertExpectedPseudoClasses(\n 'CustomFormAssociatedElement',\n ['enabled', 'disabled', 'valid', 'invalid'],\n true,\n );\n });\n\n it('Shows the specific pseudo-classes for object, output and img', async () => {\n await assertExpectedPseudoClasses(\n 'object',\n ['valid', 'invalid'],\n );\n\n await assertExpectedPseudoClasses(\n 'output',\n ['valid', 'invalid', 'read-only'],\n );\n\n await assertExpectedPseudoClasses(\n 'img',\n ['valid', 'invalid'],\n );\n });\n it('Shows the specific pseudo-classes for progress', async () => {\n await assertExpectedPseudoClasses(\n 'progress',\n ['read-only', 'indeterminate'],\n );\n });\n\n it('Shows the specific pseudo-classes for a and area with href', async () => {\n await assertExpectedPseudoClasses(\n 'a',\n ['visited'],\n false,\n ['href', 'www.google.com'],\n );\n\n await assertExpectedPseudoClasses(\n 'a',\n ['visited'],\n false,\n ['href', 'www.google.com'],\n );\n });\n\n it('Shows the specific pseudo-classes for radio or checkbox inputs', async () => {\n await assertExpectedPseudoClasses(\n 'input',\n [\n 'enabled',\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'optional',\n 'read-write',\n 'placeholder-shown',\n 'autofill',\n 'checked',\n 'indeterminate',\n ],\n false,\n ['type', 'checkbox'],\n );\n await assertExpectedPseudoClasses(\n 'input',\n [\n 'enabled',\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'optional',\n 'read-write',\n 'placeholder-shown',\n 'autofill',\n 'checked',\n 'indeterminate',\n ],\n false,\n ['type', 'radio'],\n );\n });\n\n it('Shows the specific pseudo-classes for datalist, label, legend and meter', async () => {\n await assertExpectedPseudoClasses(\n 'datalist',\n ['read-only'],\n );\n await assertExpectedPseudoClasses(\n 'label',\n ['read-only'],\n );\n await assertExpectedPseudoClasses(\n 'legend',\n ['read-only'],\n );\n await assertExpectedPseudoClasses(\n 'meter',\n ['read-only'],\n );\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ElementStatePaneWidget.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ElementStatePaneWidget.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 SDK from '../../core/sdk/sdk.js';\nimport {createTarget, stubNoopSettings} from '../../testing/EnvironmentHelpers.js';\nimport {\n describeWithMockConnection,\n} from '../../testing/MockConnection.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Elements from './elements.js';\n\ndescribeWithMockConnection('ElementStatePaneWidget', () => {\n let target: SDK.Target.Target;\n let view: Elements.ElementStatePaneWidget.ElementStatePaneWidget;\n\n const pseudoClasses = [\n 'enabled',\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'optional',\n 'read-only',\n 'read-write',\n 'in-range',\n 'out-of-range',\n 'visited',\n 'checked',\n 'indeterminate',\n 'placeholder-shown',\n 'autofill',\n ];\n\n beforeEach(() => {\n stubNoopSettings();\n target = createTarget();\n });\n\n const assertExpectedPseudoClasses = async (\n nodeName: string, expectedPseudoClasses: string[], formAssociated: boolean = false,\n attribute?: [string, string]) => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n const tableUpdatedPromise = new Promise(\n resolve => sinon.stub(view, 'updateElementSpecificStatesTableForTest').callsFake(resolve),\n );\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n\n const node = new SDK.DOMModel.DOMNode(model);\n\n sinon.stub(node, 'nodeType').returns(Node.ELEMENT_NODE);\n sinon.stub(node, 'nodeName').returns(nodeName);\n sinon.stub(node, 'enclosingElementOrSelf').returns(node);\n sinon.stub(node, 'callFunction').resolves({value: formAssociated});\n if (attribute) {\n sinon.stub(node, 'getAttribute').withArgs(attribute[0]).returns(attribute[1]);\n }\n\n const header = view.contentElement.querySelector('.force-specific-element-header');\n assert.instanceOf(header, HTMLElement);\n header.click();\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n\n await tableUpdatedPromise;\n\n for (const pseudoClass of pseudoClasses) {\n const div = view.contentElement.querySelector(`#${pseudoClass}`);\n assert.instanceOf(div, HTMLDivElement);\n const shouldShow = expectedPseudoClasses.includes(pseudoClass);\n assert.strictEqual(\n !div.hidden, shouldShow, `Checkbox for ${pseudoClass} should be ${shouldShow ? 'shown' : 'hidden'}`);\n }\n };\n\n it('Calls the right backend functions', async () => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n\n const node = new SDK.DOMModel.DOMNode(model);\n\n sinon.stub(node, 'nodeType').returns(Node.ELEMENT_NODE);\n sinon.stub(node, 'nodeName').returns('input');\n sinon.stub(node, 'enclosingElementOrSelf').returns(node);\n const checkboxes = sinon.spy(node.domModel().cssModel(), 'forcePseudoState');\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n\n for (const pseudoClass of pseudoClasses) {\n const div = view.contentElement.querySelector(`#${pseudoClass}`);\n assert.exists(div);\n const span = div.children[0];\n const shadowRoot = span.shadowRoot;\n const input = shadowRoot?.querySelector('input');\n assert.exists(input, 'The span element doesn\\'t have an input element');\n input.click();\n\n const args = checkboxes.lastCall.args;\n assert.strictEqual(args[0], node, 'Called forcePseudoState with wrong node');\n assert.strictEqual(args[1], pseudoClass, 'Called forcePseudoState with wrong pseudo-state');\n assert.strictEqual(args[2], true, 'Called forcePseudoState with wrong enable state');\n }\n });\n\n it('Hidden state for not ELEMENT_NODE type', async () => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n const tableUpdatedPromise = new Promise(\n resolve => sinon.stub(view, 'updateElementSpecificStatesTableForTest').callsFake(resolve),\n );\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n const node = new SDK.DOMModel.DOMNode(model);\n sinon.stub(node, 'nodeType').returns(Node.TEXT_NODE);\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n await tableUpdatedPromise;\n\n const details = view.contentElement.querySelector('.specific-details');\n assert.exists(details, 'The details element doesn\\'t exist');\n assert.instanceOf(details, HTMLDetailsElement, 'The details element is not an instance of HTMLDetailsElement');\n assert.isTrue(details.hidden, 'The details element is not hidden');\n });\n\n it('Hidden state for not supported element type', async () => {\n view = new Elements.ElementStatePaneWidget.ElementStatePaneWidget();\n const tableUpdatedPromise = new Promise(\n resolve => sinon.stub(view, 'updateElementSpecificStatesTableForTest').callsFake(resolve),\n );\n\n const model = target.model(SDK.DOMModel.DOMModel);\n assert.exists(model);\n const node = new SDK.DOMModel.DOMNode(model);\n sinon.stub(node, 'nodeName').returns('not supported');\n sinon.stub(node, 'enclosingElementOrSelf').returns(node);\n sinon.stub(node, 'callFunction').resolves({value: false});\n\n UI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, node);\n await tableUpdatedPromise;\n\n const details = view.contentElement.querySelector('.specific-details');\n assert.exists(details, 'The details element doesn\\'t exist');\n assert.instanceOf(details, HTMLDetailsElement, 'The details element is not an instance of HTMLDetailsElement');\n assert.isTrue(details.hidden, 'The details element is not hidden');\n });\n\n it('Shows the specific pseudo-classes for input', async () => {\n await assertExpectedPseudoClasses(\n 'input',\n [\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'read-only',\n 'placeholder-shown',\n 'autofill',\n ],\n );\n });\n\n it('Shows the specific pseudo-classes for button', async () => {\n await assertExpectedPseudoClasses(\n 'button',\n ['disabled', 'valid', 'invalid', 'read-write'],\n );\n });\n\n it('Shows the specific pseudo-classes for fieldset', async () => {\n await assertExpectedPseudoClasses(\n 'fieldset',\n ['disabled', 'valid', 'invalid', 'read-write'],\n );\n });\n\n it('Shows the specific pseudo-classes for textarea', async () => {\n await assertExpectedPseudoClasses(\n 'textarea',\n [\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'read-only',\n 'placeholder-shown',\n ],\n );\n await assertExpectedPseudoClasses(\n 'textarea',\n [\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'read-write',\n 'placeholder-shown',\n ],\n false, ['readonly', '']);\n await assertExpectedPseudoClasses(\n 'textarea',\n [\n 'enabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'read-write',\n 'placeholder-shown',\n ],\n false, ['disabled', '']);\n await assertExpectedPseudoClasses(\n 'textarea',\n [\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'optional',\n 'read-only',\n 'placeholder-shown',\n ],\n false, ['required', '']);\n });\n\n it('Shows the specific pseudo-classes for select', async () => {\n await assertExpectedPseudoClasses(\n 'select',\n ['disabled', 'valid', 'invalid', 'user-valid', 'user-invalid', 'required', 'read-write'],\n );\n });\n\n it('Shows the specific pseudo-classes for option', async () => {\n await assertExpectedPseudoClasses(\n 'option',\n ['disabled', 'checked', 'read-write'],\n );\n });\n\n it('Shows the specific pseudo-classes for optgroup', async () => {\n await assertExpectedPseudoClasses(\n 'optgroup',\n ['disabled', 'read-write'],\n );\n });\n\n it('Shows the specific pseudo-classes for FormAssociated', async () => {\n await assertExpectedPseudoClasses(\n 'CustomFormAssociatedElement',\n ['disabled', 'valid', 'invalid', 'read-write'],\n true,\n );\n });\n\n it('Shows the specific pseudo-classes for object, output and img', async () => {\n await assertExpectedPseudoClasses(\n 'object',\n ['valid', 'invalid', 'read-write'],\n );\n\n await assertExpectedPseudoClasses(\n 'output',\n ['valid', 'invalid', 'read-write'],\n );\n\n await assertExpectedPseudoClasses(\n 'img',\n ['valid', 'invalid', 'read-write'],\n );\n });\n it('Shows the specific pseudo-classes for progress', async () => {\n await assertExpectedPseudoClasses(\n 'progress',\n ['read-write', 'indeterminate'],\n );\n });\n\n it('Shows the specific pseudo-classes for a and area with href', async () => {\n await assertExpectedPseudoClasses(\n 'a',\n ['visited', 'read-write'],\n false,\n ['href', 'www.google.com'],\n );\n\n await assertExpectedPseudoClasses(\n 'area',\n ['visited', 'read-write'],\n false,\n ['href', 'www.google.com'],\n );\n });\n\n it('Shows the specific pseudo-classes for a and area without href', async () => {\n await assertExpectedPseudoClasses(\n 'a',\n ['read-write'],\n );\n\n await assertExpectedPseudoClasses(\n 'area',\n ['read-write'],\n );\n });\n\n it('Shows the specific pseudo-classes for contenteditable div', async () => {\n await assertExpectedPseudoClasses(\n 'div',\n ['read-only'],\n false,\n ['contenteditable', ''],\n );\n });\n\n it('Shows the specific pseudo-classes for radio or checkbox inputs', async () => {\n await assertExpectedPseudoClasses(\n 'input',\n [\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'read-only',\n 'placeholder-shown',\n 'autofill',\n 'checked',\n 'indeterminate',\n ],\n false,\n ['type', 'checkbox'],\n );\n await assertExpectedPseudoClasses(\n 'input',\n [\n 'disabled',\n 'valid',\n 'invalid',\n 'user-valid',\n 'user-invalid',\n 'required',\n 'read-only',\n 'placeholder-shown',\n 'autofill',\n 'checked',\n 'indeterminate',\n ],\n false,\n ['type', 'radio'],\n );\n });\n\n it('Shows the specific pseudo-classes for datalist, label, legend and meter', async () => {\n await assertExpectedPseudoClasses(\n 'datalist',\n ['read-write'],\n );\n await assertExpectedPseudoClasses(\n 'label',\n ['read-write'],\n );\n await assertExpectedPseudoClasses(\n 'legend',\n ['read-write'],\n );\n await assertExpectedPseudoClasses(\n 'meter',\n ['read-write'],\n );\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/elements/ElementsTreeElement.js b/public/panels/elements/ElementsTreeElement.js index 36d4f0cc..ba7a124d 100644 --- a/public/panels/elements/ElementsTreeElement.js +++ b/public/panels/elements/ElementsTreeElement.js @@ -817,7 +817,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement { } // Remove zero-width spaces that were added by nodeTitleInfo. removeZeroWidthSpaceRecursive(attribute); - const config = new UI.InplaceEditor.Config(this.attributeEditingCommitted.bind(this), this.editingCancelled.bind(this), attributeName || undefined); + const config = new UI.InplaceEditor.Config(this.attributeEditingCommitted.bind(this), this.editingCancelled.bind(this), attributeName); function postKeyDownFinishHandler(event) { UI.UIUtils.handleElementValueModifications(event, attribute); return ''; @@ -844,7 +844,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement { if (container) { container.textContent = textNode.nodeValue(); } // Strip the CSS or JS highlighting if present. - const config = new UI.InplaceEditor.Config(this.textNodeEditingCommitted.bind(this, textNode), this.editingCancelled.bind(this)); + const config = new UI.InplaceEditor.Config(this.textNodeEditingCommitted.bind(this, textNode), this.editingCancelled.bind(this), null); this.updateEditorHandles(textNodeElement, config); const componentSelection = this.listItemElement.getComponentSelection(); componentSelection && componentSelection.selectAllChildren(textNodeElement); @@ -1086,7 +1086,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement { } } } - if ((attributeName.trim() || newText.trim()) && oldText !== newText) { + if (attributeName !== null && (attributeName.trim() || newText.trim()) && oldText !== newText) { this.nodeInternal.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this)); return; } @@ -1912,8 +1912,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement { styles.get('grid-template-rows')?.startsWith('subgrid'))) ?? false; const containerType = styles.get('container-type'); - const contain = styles.get('contain'); - const isContainer = SDK.CSSContainerQuery.getQueryAxis(`${containerType} ${contain}`) !== "" /* SDK.CSSContainerQuery.QueryAxis.NONE */; + const isContainer = containerType && containerType !== '' && containerType !== 'normal'; if (isGrid) { this.pushGridAdorner(this.tagTypeContext, isSubgrid); } diff --git a/public/panels/elements/ElementsTreeElement.js.map b/public/panels/elements/ElementsTreeElement.js.map index 6b8391bd..21d71d4e 100644 --- a/public/panels/elements/ElementsTreeElement.js.map +++ b/public/panels/elements/ElementsTreeElement.js.map @@ -1 +1 @@ -{"version":3,"file":"ElementsTreeElement.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ElementsTreeElement.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 Matt Lilek \n * Copyright (C) 2009 Joseph Pecoraro\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 type * as IssuesManager from '../../models/issues_manager/issues_manager.js';\nimport * as TextUtils from '../../models/text_utils/text_utils.js';\nimport * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as Adorners from '../../ui/components/adorners/adorners.js';\nimport * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js';\nimport * as FloatingButton from '../../ui/components/floating_button/floating_button.js';\nimport * as Highlighting from '../../ui/components/highlighting/highlighting.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as TextEditor from '../../ui/components/text_editor/text_editor.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';\nimport * as Emulation from '../emulation/emulation.js';\n\nimport * as ElementsComponents from './components/components.js';\nimport {canGetJSPath, cssPath, jsPath, xPath} from './DOMPath.js';\nimport {ElementsPanel} from './ElementsPanel.js';\nimport {type ElementsTreeOutline, MappedCharToEntity, type UpdateRecord} from './ElementsTreeOutline.js';\nimport {ImagePreviewPopover} from './ImagePreviewPopover.js';\nimport {getRegisteredDecorators, type MarkerDecorator, type MarkerDecoratorRegistration} from './MarkerDecorator.js';\n\nconst UIStrings = {\n /**\n *@description Title for Ad adorner. This iframe is marked as advertisement frame.\n */\n thisFrameWasIdentifiedAsAnAd: 'This frame was identified as an ad frame',\n /**\n *@description A context menu item in the Elements panel. Force is used as a verb, indicating intention to make the state change.\n */\n forceState: 'Force state',\n /**\n *@description Hint element title in Elements Tree Element of the Elements panel\n *@example {0} PH1\n */\n useSInTheConsoleToReferToThis: 'Use {PH1} in the console to refer to this element.',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n addAttribute: 'Add attribute',\n /**\n *@description Text to modify the attribute of an item\n */\n editAttribute: 'Edit attribute',\n /**\n *@description Text to focus on something\n */\n focus: 'Focus',\n /**\n *@description Text to scroll the displayed content into view\n */\n scrollIntoView: 'Scroll into view',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n editText: 'Edit text',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n editAsHtml: 'Edit as HTML',\n /**\n *@description Text to cut an element, cut should be used as a verb\n */\n cut: 'Cut',\n /**\n *@description Text for copying, copy should be used as a verb\n */\n copy: 'Copy',\n /**\n *@description Text to paste an element, paste should be used as a verb\n */\n paste: 'Paste',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyOuterhtml: 'Copy outerHTML',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copySelector: 'Copy `selector`',\n /**\n *@description Text in Elements Tree Element of the Elements panel\n */\n copyJsPath: 'Copy JS path',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyStyles: 'Copy styles',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyXpath: 'Copy XPath',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyFullXpath: 'Copy full XPath',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyElement: 'Copy element',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n duplicateElement: 'Duplicate element',\n /**\n *@description Text to hide an element\n */\n hideElement: 'Hide element',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n deleteElement: 'Delete element',\n /**\n *@description Text to expand something recursively\n */\n expandRecursively: 'Expand recursively',\n /**\n *@description Text to collapse children of a parent group\n */\n collapseChildren: 'Collapse children',\n /**\n *@description Title of an action in the emulation tool to capture node screenshot\n */\n captureNodeScreenshot: 'Capture node screenshot',\n /**\n *@description Title of a context menu item. When clicked DevTools goes to the Application panel and shows this specific iframe's details\n */\n showFrameDetails: 'Show `iframe` details',\n /**\n *@description Text in Elements Tree Element of the Elements panel\n */\n valueIsTooLargeToEdit: '',\n /**\n *@description Element text content in Elements Tree Element of the Elements panel\n */\n children: 'Children:',\n /**\n *@description ARIA label for Elements Tree adorners\n */\n enableGridMode: 'Enable grid mode',\n /**\n *@description ARIA label for Elements Tree adorners\n */\n disableGridMode: 'Disable grid mode',\n /**\n *@description Label of the adorner for flex elements in the Elements panel\n */\n enableFlexMode: 'Enable flex mode',\n /**\n *@description Label of the adorner for flex elements in the Elements panel\n */\n disableFlexMode: 'Disable flex mode',\n /**\n *@description Label of an adorner in the Elements panel. When clicked, it enables\n * the overlay showing CSS scroll snapping for the current element.\n */\n enableScrollSnap: 'Enable scroll-snap overlay',\n /**\n *@description Label of an adorner in the Elements panel. When clicked, it disables\n * the overlay showing CSS scroll snapping for the current element.\n */\n disableScrollSnap: 'Disable scroll-snap overlay',\n /**\n *@description Label of an adorner in the Elements panel. When clicked, it redirects\n * to the Media Panel.\n */\n openMediaPanel: 'Jump to Media panel',\n /**\n *@description Text of a tooltip to redirect to another element in the Elements panel\n */\n showPopoverTarget: 'Show popover target',\n /**\n *@description Text of the tooltip for scroll adorner.\n */\n elementHasScrollableOverflow: 'This element has a scrollable overflow',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/ElementsTreeElement.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst enum TagType {\n OPENING = 'OPENING_TAG',\n CLOSING = 'CLOSING_TAG',\n}\n\ntype OpeningTagContext = {\n tagType: TagType.OPENING,\n readonly adornerContainer: HTMLElement,\n adorners: Adorners.Adorner.Adorner[],\n styleAdorners: Adorners.Adorner.Adorner[],\n readonly adornersThrottler: Common.Throttler.Throttler,\n canAddAttributes: boolean,\n slot?: Adorners.Adorner.Adorner,\n};\n\ntype ClosingTagContext = {\n tagType: TagType.CLOSING,\n};\n\nexport type TagTypeContext = OpeningTagContext|ClosingTagContext;\n\nexport function isOpeningTag(context: TagTypeContext): context is OpeningTagContext {\n return context.tagType === TagType.OPENING;\n}\n\nexport class ElementsTreeElement extends UI.TreeOutline.TreeElement {\n nodeInternal: SDK.DOMModel.DOMNode;\n override treeOutline: ElementsTreeOutline|null;\n private gutterContainer: HTMLElement;\n private readonly decorationsElement: HTMLElement;\n private searchQuery: string|null;\n private expandedChildrenLimitInternal: number;\n private readonly decorationsThrottler: Common.Throttler.Throttler;\n private inClipboard: boolean;\n private hoveredInternal: boolean;\n private editing: EditorHandles|null;\n private htmlEditElement?: HTMLElement;\n expandAllButtonElement: UI.TreeOutline.TreeElement|null;\n selectionElement?: HTMLDivElement;\n private hintElement?: HTMLElement;\n private aiButtonContainer?: HTMLElement;\n private contentElement: HTMLElement;\n #elementIssues: Map = new Map();\n #nodeElementToIssue: Map = new Map();\n #highlights: Range[] = [];\n\n readonly tagTypeContext: TagTypeContext;\n\n constructor(node: SDK.DOMModel.DOMNode, isClosingTag?: boolean) {\n // The title will be updated in onattach.\n super();\n this.nodeInternal = node;\n this.treeOutline = null;\n this.listItemElement.setAttribute(\n 'jslog', `${VisualLogging.treeItem().parent('elementsTreeOutline').track({\n keydown: 'ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Backspace|Delete|Enter|Space|Home|End',\n drag: true,\n click: true,\n })}`);\n this.contentElement = this.listItemElement.createChild('div');\n this.gutterContainer = this.contentElement.createChild('div', 'gutter-container');\n this.gutterContainer.addEventListener('click', this.showContextMenu.bind(this));\n const gutterMenuIcon = new IconButton.Icon.Icon();\n gutterMenuIcon.data = {\n color: 'var(--icon-default)',\n iconName: 'dots-horizontal',\n height: '16px',\n width: '16px',\n };\n this.gutterContainer.append(gutterMenuIcon);\n this.decorationsElement = this.gutterContainer.createChild('div', 'hidden');\n\n this.searchQuery = null;\n this.expandedChildrenLimitInternal = InitialChildrenLimit;\n this.decorationsThrottler = new Common.Throttler.Throttler(100);\n\n this.inClipboard = false;\n this.hoveredInternal = false;\n\n this.editing = null;\n\n if (isClosingTag) {\n this.tagTypeContext = {tagType: TagType.CLOSING};\n } else {\n this.tagTypeContext = {\n tagType: TagType.OPENING,\n adornerContainer: this.contentElement.createChild('div', 'adorner-container hidden'),\n adorners: [],\n styleAdorners: [],\n adornersThrottler: new Common.Throttler.Throttler(100),\n canAddAttributes: this.nodeInternal.nodeType() === Node.ELEMENT_NODE,\n };\n void this.updateStyleAdorners();\n\n if (node.isAdFrameNode()) {\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.AD);\n const adorner = this.adorn(config);\n UI.Tooltip.Tooltip.install(adorner, i18nString(UIStrings.thisFrameWasIdentifiedAsAnAd));\n }\n\n void this.updateScrollAdorner();\n }\n this.expandAllButtonElement = null;\n }\n\n static animateOnDOMUpdate(treeElement: ElementsTreeElement): void {\n const tagName = treeElement.listItemElement.querySelector('.webkit-html-tag-name');\n UI.UIUtils.runCSSAnimationOnce(tagName || treeElement.listItemElement, 'dom-update-highlight');\n }\n\n static visibleShadowRoots(node: SDK.DOMModel.DOMNode): SDK.DOMModel.DOMNode[] {\n let roots = node.shadowRoots();\n if (roots.length && !Common.Settings.Settings.instance().moduleSetting('show-ua-shadow-dom').get()) {\n roots = roots.filter(filter);\n }\n\n function filter(root: SDK.DOMModel.DOMNode): boolean {\n return root.shadowRootType() !== SDK.DOMModel.DOMNode.ShadowRootTypes.UserAgent;\n }\n return roots;\n }\n\n static canShowInlineText(node: SDK.DOMModel.DOMNode): boolean {\n if (node.contentDocument() || node.templateContent() || ElementsTreeElement.visibleShadowRoots(node).length ||\n node.hasPseudoElements()) {\n return false;\n }\n if (node.nodeType() !== Node.ELEMENT_NODE) {\n return false;\n }\n if (!node.firstChild || node.firstChild !== node.lastChild || node.firstChild.nodeType() !== Node.TEXT_NODE) {\n return false;\n }\n const textChild = node.firstChild;\n const maxInlineTextChildLength = 80;\n if (textChild.nodeValue().length < maxInlineTextChildLength) {\n return true;\n }\n return false;\n }\n\n static populateForcedPseudoStateItems(contextMenu: UI.ContextMenu.ContextMenu, node: SDK.DOMModel.DOMNode): void {\n const pseudoClasses = ['active', 'hover', 'focus', 'visited', 'focus-within', 'focus-visible'];\n const forcedPseudoState = node.domModel().cssModel().pseudoState(node);\n const stateMenu =\n contextMenu.debugSection().appendSubMenuItem(i18nString(UIStrings.forceState), false, 'force-state');\n for (const pseudoClass of pseudoClasses) {\n const pseudoClassForced = forcedPseudoState ? forcedPseudoState.indexOf(pseudoClass) >= 0 : false;\n stateMenu.defaultSection().appendCheckboxItem(\n ':' + pseudoClass, setPseudoStateCallback.bind(null, pseudoClass, !pseudoClassForced),\n {checked: pseudoClassForced, jslogContext: pseudoClass});\n }\n\n function setPseudoStateCallback(pseudoState: string, enabled: boolean): void {\n node.domModel().cssModel().forcePseudoState(node, pseudoState, enabled);\n }\n }\n\n isClosingTag(): boolean {\n return !isOpeningTag(this.tagTypeContext);\n }\n\n node(): SDK.DOMModel.DOMNode {\n return this.nodeInternal;\n }\n\n isEditing(): boolean {\n return Boolean(this.editing);\n }\n\n highlightSearchResults(searchQuery: string): void {\n this.searchQuery = searchQuery;\n if (!this.editing) {\n this.highlightSearchResultsInternal();\n }\n }\n\n hideSearchHighlights(): void {\n Highlighting.HighlightManager.HighlightManager.instance().removeHighlights(this.#highlights);\n this.#highlights = [];\n }\n\n setInClipboard(inClipboard: boolean): void {\n if (this.inClipboard === inClipboard) {\n return;\n }\n this.inClipboard = inClipboard;\n this.listItemElement.classList.toggle('in-clipboard', inClipboard);\n }\n\n get hovered(): boolean {\n return this.hoveredInternal;\n }\n\n set hovered(isHovered: boolean) {\n if (this.hoveredInternal === isHovered) {\n return;\n }\n\n if (isHovered && !this.aiButtonContainer) {\n this.createAiButton();\n } else if (!isHovered && this.aiButtonContainer) {\n this.aiButtonContainer.remove();\n delete this.aiButtonContainer;\n }\n\n this.hoveredInternal = isHovered;\n\n if (this.listItemElement) {\n if (isHovered) {\n this.createSelection();\n this.listItemElement.classList.add('hovered');\n } else {\n this.listItemElement.classList.remove('hovered');\n }\n }\n }\n\n addIssue(newIssue: IssuesManager.GenericIssue.GenericIssue): void {\n if (this.#elementIssues.has(newIssue.primaryKey())) {\n return;\n }\n\n this.#elementIssues.set(newIssue.primaryKey(), newIssue);\n this.#applyIssueStyleAndTooltip(newIssue);\n }\n\n #applyIssueStyleAndTooltip(issue: IssuesManager.GenericIssue.GenericIssue): void {\n const issueDetails = issue.details();\n\n if (issueDetails.violatingNodeAttribute) {\n this.#highlightViolatingAttr(issueDetails.violatingNodeAttribute, issue);\n } else {\n this.#highlightTagAsViolating(issue);\n }\n }\n\n get issuesByNodeElement(): Map {\n return this.#nodeElementToIssue;\n }\n\n #highlightViolatingAttr(name: string, issue: IssuesManager.GenericIssue.GenericIssue): void {\n const tag = this.listItemElement.getElementsByClassName('webkit-html-tag')[0];\n const attributes = tag.getElementsByClassName('webkit-html-attribute');\n for (const attribute of attributes) {\n if (attribute.getElementsByClassName('webkit-html-attribute-name')[0].textContent === name) {\n const attributeElement = attribute.getElementsByClassName('webkit-html-attribute-name')[0];\n attributeElement.classList.add('violating-element');\n this.#nodeElementToIssue.set(attributeElement, issue);\n }\n }\n }\n\n #highlightTagAsViolating(issue: IssuesManager.GenericIssue.GenericIssue): void {\n const tagElement = this.listItemElement.getElementsByClassName('webkit-html-tag-name')[0];\n tagElement.classList.add('violating-element');\n this.#nodeElementToIssue.set(tagElement, issue);\n }\n\n expandedChildrenLimit(): number {\n return this.expandedChildrenLimitInternal;\n }\n\n setExpandedChildrenLimit(expandedChildrenLimit: number): void {\n this.expandedChildrenLimitInternal = expandedChildrenLimit;\n }\n\n createSlotLink(nodeShortcut: SDK.DOMModel.DOMNodeShortcut|null): void {\n if (!isOpeningTag(this.tagTypeContext)) {\n return;\n }\n if (nodeShortcut) {\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.SLOT);\n this.tagTypeContext.slot = this.adornSlot(config, this.tagTypeContext);\n const deferredNode = nodeShortcut.deferredNode;\n this.tagTypeContext.slot.addEventListener('click', () => {\n deferredNode.resolve(node => {\n void Common.Revealer.reveal(node);\n });\n });\n this.tagTypeContext.slot.addEventListener('mousedown', e => e.consume(), false);\n }\n }\n\n private createSelection(): void {\n const contentElement = this.contentElement;\n if (!contentElement) {\n return;\n }\n\n if (!this.selectionElement) {\n this.selectionElement = document.createElement('div');\n this.selectionElement.className = 'selection fill';\n this.selectionElement.style.setProperty('margin-left', (-this.computeLeftIndent()) + 'px');\n contentElement.prepend(this.selectionElement);\n }\n }\n\n private createHint(): void {\n if (this.contentElement && !this.hintElement) {\n this.hintElement = this.contentElement.createChild('span', 'selected-hint');\n const selectedElementCommand = '$0';\n UI.Tooltip.Tooltip.install(\n this.hintElement, i18nString(UIStrings.useSInTheConsoleToReferToThis, {PH1: selectedElementCommand}));\n UI.ARIAUtils.markAsHidden(this.hintElement);\n }\n }\n\n private createAiButton(): void {\n const isElementNode = this.node().nodeType() === Node.ELEMENT_NODE;\n if (!isElementNode ||\n !UI.ActionRegistry.ActionRegistry.instance().hasAction('freestyler.elements-floating-button')) {\n return;\n }\n\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('freestyler.elements-floating-button');\n if (this.contentElement && !this.aiButtonContainer) {\n this.aiButtonContainer = this.contentElement.createChild('span', 'ai-button-container');\n const floatingButton = new FloatingButton.FloatingButton.FloatingButton({\n iconName: 'smart-assistant',\n });\n floatingButton.addEventListener('click', ev => {\n ev.stopPropagation();\n this.select(true, false);\n void action.execute();\n }, {capture: true});\n floatingButton.addEventListener('mousedown', ev => {\n ev.stopPropagation();\n }, {capture: true});\n this.aiButtonContainer.appendChild(floatingButton);\n }\n }\n\n override onbind(): void {\n if (this.treeOutline && !this.isClosingTag()) {\n this.treeOutline.treeElementByNode.set(this.nodeInternal, this);\n }\n }\n\n override onunbind(): void {\n if (this.editing) {\n this.editing.cancel();\n }\n if (this.treeOutline && this.treeOutline.treeElementByNode.get(this.nodeInternal) === this) {\n this.treeOutline.treeElementByNode.delete(this.nodeInternal);\n }\n }\n\n override onattach(): void {\n if (this.hoveredInternal) {\n this.createSelection();\n this.listItemElement.classList.add('hovered');\n }\n\n this.updateTitle();\n this.listItemElement.draggable = true;\n }\n\n override async onpopulate(): Promise {\n if (this.treeOutline) {\n return this.treeOutline.populateTreeElement(this);\n }\n }\n\n override async expandRecursively(): Promise {\n await this.nodeInternal.getSubtree(-1, true);\n await super.expandRecursively(Number.MAX_VALUE);\n }\n\n override onexpand(): void {\n if (this.isClosingTag()) {\n return;\n }\n\n this.updateTitle();\n }\n\n override oncollapse(): void {\n if (this.isClosingTag()) {\n return;\n }\n\n this.updateTitle();\n }\n\n override select(omitFocus?: boolean, selectedByUser?: boolean): boolean {\n if (this.editing) {\n return false;\n }\n return super.select(omitFocus, selectedByUser);\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n if (!this.treeOutline) {\n return false;\n }\n this.treeOutline.suppressRevealAndSelect = true;\n this.treeOutline.selectDOMNode(this.nodeInternal, selectedByUser);\n if (selectedByUser) {\n this.nodeInternal.highlight();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.ChangeInspectedNodeInElementsPanel);\n }\n this.createSelection();\n this.createHint();\n this.treeOutline.suppressRevealAndSelect = false;\n return true;\n }\n\n override ondelete(): boolean {\n if (!this.treeOutline) {\n return false;\n }\n const startTagTreeElement = this.treeOutline.findTreeElement(this.nodeInternal);\n startTagTreeElement ? startTagTreeElement.remove() : this.remove();\n return true;\n }\n\n override onenter(): boolean {\n // On Enter or Return start editing the first attribute\n // or create a new attribute on the selected element.\n if (this.editing) {\n return false;\n }\n\n this.startEditing();\n\n // prevent a newline from being immediately inserted\n return true;\n }\n\n override selectOnMouseDown(event: MouseEvent): void {\n super.selectOnMouseDown(event);\n\n if (this.editing) {\n return;\n }\n\n // Prevent selecting the nearest word on double click.\n if (event.detail >= 2) {\n event.preventDefault();\n }\n }\n\n override ondblclick(event: Event): boolean {\n if (this.editing || this.isClosingTag()) {\n return false;\n }\n if (this.startEditingTarget((event.target as Element))) {\n return false;\n }\n\n if (this.isExpandable() && !this.expanded) {\n this.expand();\n }\n return false;\n }\n\n hasEditableNode(): boolean {\n return !this.nodeInternal.isShadowRoot() && !this.nodeInternal.ancestorUserAgentShadowRoot();\n }\n\n private insertInLastAttributePosition(tag: Element, node: Element): void {\n if (tag.getElementsByClassName('webkit-html-attribute').length > 0) {\n tag.insertBefore(node, tag.lastChild);\n } else if (tag.textContent !== null) {\n const matchResult = tag.textContent.match(/^<(.*?)>$/);\n if (!matchResult) {\n return;\n }\n const nodeName = matchResult[1];\n tag.textContent = '';\n UI.UIUtils.createTextChild(tag, '<' + nodeName);\n tag.appendChild(node);\n UI.UIUtils.createTextChild(tag, '>');\n }\n }\n\n private startEditingTarget(eventTarget: Element): boolean {\n if (!this.treeOutline || this.treeOutline.selectedDOMNode() !== this.nodeInternal) {\n return false;\n }\n\n if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE && this.nodeInternal.nodeType() !== Node.TEXT_NODE) {\n return false;\n }\n\n const textNode = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-text-node');\n if (textNode) {\n return this.startEditingTextNode(textNode);\n }\n\n const attribute = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-attribute');\n if (attribute) {\n return this.startEditingAttribute(attribute, eventTarget);\n }\n\n const tagName = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-tag-name');\n if (tagName) {\n return this.startEditingTagName(tagName);\n }\n\n const newAttribute = eventTarget.enclosingNodeOrSelfWithClass('add-attribute');\n if (newAttribute) {\n return this.addNewAttribute();\n }\n\n return false;\n }\n\n private showContextMenu(event: Event): void {\n this.treeOutline && this.treeOutline.showContextMenu(this, event);\n }\n\n populateTagContextMenu(contextMenu: UI.ContextMenu.ContextMenu, event: Event): void {\n // Add attribute-related actions.\n const treeElement =\n this.isClosingTag() && this.treeOutline ? this.treeOutline.findTreeElement(this.nodeInternal) : this;\n if (!treeElement) {\n return;\n }\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.addAttribute), treeElement.addNewAttribute.bind(treeElement),\n {jslogContext: 'add-attribute'});\n\n const target = (event.target as Element);\n const attribute = target.enclosingNodeOrSelfWithClass('webkit-html-attribute');\n const newAttribute = target.enclosingNodeOrSelfWithClass('add-attribute');\n if (attribute && !newAttribute) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.editAttribute), this.startEditingAttribute.bind(this, attribute, target),\n {jslogContext: 'edit-attribute'});\n }\n this.populateNodeContextMenu(contextMenu);\n ElementsTreeElement.populateForcedPseudoStateItems(contextMenu, treeElement.node());\n this.populateScrollIntoView(contextMenu);\n contextMenu.viewSection().appendItem(i18nString(UIStrings.focus), async () => {\n await this.nodeInternal.focus();\n }, {jslogContext: 'focus'});\n }\n\n populatePseudoElementContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n if (this.childCount() !== 0) {\n this.populateExpandRecursively(contextMenu);\n }\n\n this.populateScrollIntoView(contextMenu);\n }\n\n private populateExpandRecursively(contextMenu: UI.ContextMenu.ContextMenu): void {\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.expandRecursively), this.expandRecursively.bind(this),\n {jslogContext: 'expand-recursively'});\n }\n\n private populateScrollIntoView(contextMenu: UI.ContextMenu.ContextMenu): void {\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.scrollIntoView), () => this.nodeInternal.scrollIntoView(),\n {jslogContext: 'scroll-into-view'});\n }\n\n populateTextContextMenu(contextMenu: UI.ContextMenu.ContextMenu, textNode: Element): void {\n if (!this.editing) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.editText), this.startEditingTextNode.bind(this, textNode), {jslogContext: 'edit-text'});\n }\n this.populateNodeContextMenu(contextMenu);\n }\n\n populateNodeContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n // Add free-form node-related actions.\n const isEditable = this.hasEditableNode();\n // clang-format off\n if (isEditable && !this.editing) {\n contextMenu.editSection().appendItem(i18nString(UIStrings.editAsHtml), this.editAsHTML.bind(this), {jslogContext: 'elements.edit-as-html'});\n }\n // clang-format on\n const isShadowRoot = this.nodeInternal.isShadowRoot();\n\n const createShortcut = UI.KeyboardShortcut.KeyboardShortcut.shortcutToString.bind(null);\n const modifier = UI.KeyboardShortcut.Modifiers.CtrlOrMeta.value;\n const treeOutline = this.treeOutline;\n if (!treeOutline) {\n return;\n }\n let menuItem;\n\n if (UI.ActionRegistry.ActionRegistry.instance().hasAction('freestyler.element-panel-context')) {\n contextMenu.headerSection().appendAction(\n 'freestyler.element-panel-context',\n );\n }\n\n menuItem = contextMenu.clipboardSection().appendItem(\n i18nString(UIStrings.cut), treeOutline.performCopyOrCut.bind(treeOutline, true, this.nodeInternal),\n {disabled: !this.hasEditableNode(), jslogContext: 'cut'});\n menuItem.setShortcut(createShortcut('X', modifier));\n\n // Place it here so that all \"Copy\"-ing items stick together.\n const copyMenu = contextMenu.clipboardSection().appendSubMenuItem(i18nString(UIStrings.copy), false, 'copy');\n const section = copyMenu.section();\n if (!isShadowRoot) {\n menuItem = section.appendItem(\n i18nString(UIStrings.copyOuterhtml), treeOutline.performCopyOrCut.bind(treeOutline, false, this.nodeInternal),\n {jslogContext: 'copy-outer-html'});\n menuItem.setShortcut(createShortcut('V', modifier));\n }\n if (this.nodeInternal.nodeType() === Node.ELEMENT_NODE) {\n section.appendItem(\n i18nString(UIStrings.copySelector), this.copyCSSPath.bind(this), {jslogContext: 'copy-selector'});\n section.appendItem(\n i18nString(UIStrings.copyJsPath), this.copyJSPath.bind(this),\n {disabled: !canGetJSPath(this.nodeInternal), jslogContext: 'copy-js-path'});\n section.appendItem(\n i18nString(UIStrings.copyStyles), this.copyStyles.bind(this), {jslogContext: 'elements.copy-styles'});\n }\n if (!isShadowRoot) {\n section.appendItem(i18nString(UIStrings.copyXpath), this.copyXPath.bind(this), {jslogContext: 'copy-xpath'});\n section.appendItem(\n i18nString(UIStrings.copyFullXpath), this.copyFullXPath.bind(this), {jslogContext: 'copy-full-xpath'});\n }\n\n if (!isShadowRoot) {\n menuItem = copyMenu.clipboardSection().appendItem(\n i18nString(UIStrings.copyElement), treeOutline.performCopyOrCut.bind(treeOutline, false, this.nodeInternal),\n {jslogContext: 'copy-element'});\n menuItem.setShortcut(createShortcut('C', modifier));\n\n // Duplicate element, disabled on root element and ShadowDOM.\n const isRootElement = !this.nodeInternal.parentNode || this.nodeInternal.parentNode.nodeName() === '#document';\n menuItem = contextMenu.editSection().appendItem(\n i18nString(UIStrings.duplicateElement), treeOutline.duplicateNode.bind(treeOutline, this.nodeInternal), {\n disabled: (this.nodeInternal.isInShadowTree() || isRootElement),\n jslogContext: 'elements.duplicate-element',\n });\n }\n\n menuItem = contextMenu.clipboardSection().appendItem(\n i18nString(UIStrings.paste), treeOutline.pasteNode.bind(treeOutline, this.nodeInternal),\n {disabled: !treeOutline.canPaste(this.nodeInternal), jslogContext: 'paste'});\n menuItem.setShortcut(createShortcut('V', modifier));\n\n menuItem = contextMenu.debugSection().appendCheckboxItem(\n i18nString(UIStrings.hideElement), treeOutline.toggleHideElement.bind(treeOutline, this.nodeInternal),\n {checked: treeOutline.isToggledToHidden(this.nodeInternal), jslogContext: 'elements.hide-element'});\n menuItem.setShortcut(\n UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutTitleForAction('elements.hide-element') || '');\n\n if (isEditable) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.deleteElement), this.remove.bind(this), {jslogContext: 'delete-element'});\n }\n\n this.populateExpandRecursively(contextMenu);\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.collapseChildren), this.collapseChildren.bind(this), {jslogContext: 'collapse-children'});\n const deviceModeWrapperAction = new Emulation.DeviceModeWrapper.ActionDelegate();\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.captureNodeScreenshot),\n deviceModeWrapperAction.handleAction.bind(\n null, UI.Context.Context.instance(), 'emulation.capture-node-screenshot'),\n {jslogContext: 'emulation.capture-node-screenshot'});\n if (this.nodeInternal.frameOwnerFrameId()) {\n contextMenu.viewSection().appendItem(i18nString(UIStrings.showFrameDetails), () => {\n const frameOwnerFrameId = this.nodeInternal.frameOwnerFrameId();\n if (frameOwnerFrameId) {\n const frame = SDK.FrameManager.FrameManager.instance().getFrame(frameOwnerFrameId);\n void Common.Revealer.reveal(frame);\n }\n }, {jslogContext: 'show-frame-details'});\n }\n }\n\n private startEditing(): boolean|undefined {\n if (!this.treeOutline || this.treeOutline.selectedDOMNode() !== this.nodeInternal) {\n return;\n }\n\n const listItem = this.listItemElement;\n\n if (isOpeningTag(this.tagTypeContext) && this.tagTypeContext.canAddAttributes) {\n const attribute = listItem.getElementsByClassName('webkit-html-attribute')[0];\n if (attribute) {\n return this.startEditingAttribute(\n attribute, attribute.getElementsByClassName('webkit-html-attribute-value')[0]);\n }\n\n return this.addNewAttribute();\n }\n\n if (this.nodeInternal.nodeType() === Node.TEXT_NODE) {\n const textNode = listItem.getElementsByClassName('webkit-html-text-node')[0];\n if (textNode) {\n return this.startEditingTextNode(textNode);\n }\n }\n\n return;\n }\n\n private addNewAttribute(): boolean {\n // Cannot just convert the textual html into an element without\n // a parent node. Use a temporary span container for the HTML.\n const container = document.createElement('span');\n const attr = this.buildAttributeDOM(container, ' ', '', null);\n attr.style.marginLeft = '2px'; // overrides the .editing margin rule\n attr.style.marginRight = '2px'; // overrides the .editing margin rule\n attr.setAttribute('jslog', `${VisualLogging.value('new-attribute').track({change: true, resize: true})}`);\n\n const tag = this.listItemElement.getElementsByClassName('webkit-html-tag')[0];\n this.insertInLastAttributePosition(tag, attr);\n attr.scrollIntoViewIfNeeded(true);\n return this.startEditingAttribute(attr, attr);\n }\n\n private triggerEditAttribute(attributeName: string): boolean|undefined {\n const attributeElements = this.listItemElement.getElementsByClassName('webkit-html-attribute-name');\n for (let i = 0, len = attributeElements.length; i < len; ++i) {\n if (attributeElements[i].textContent === attributeName) {\n for (let elem: (ChildNode|null) = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {\n if (elem.nodeType !== Node.ELEMENT_NODE) {\n continue;\n }\n if ((elem as Element).classList.contains('webkit-html-attribute-value')) {\n return this.startEditingAttribute((elem.parentElement as HTMLElement), (elem as Element));\n }\n }\n }\n }\n\n return;\n }\n\n private startEditingAttribute(attribute: Element, elementForSelection: Element): boolean {\n console.assert(this.listItemElement.isAncestor(attribute));\n\n if (UI.UIUtils.isBeingEdited(attribute)) {\n return true;\n }\n\n const attributeNameElement = attribute.getElementsByClassName('webkit-html-attribute-name')[0];\n if (!attributeNameElement) {\n return false;\n }\n\n const attributeName = attributeNameElement.textContent;\n const attributeValueElement = attribute.getElementsByClassName('webkit-html-attribute-value')[0];\n\n // Make sure elementForSelection is not a child of attributeValueElement.\n elementForSelection =\n attributeValueElement.isAncestor(elementForSelection) ? attributeValueElement : elementForSelection;\n\n function removeZeroWidthSpaceRecursive(node: Node): void {\n if (node.nodeType === Node.TEXT_NODE) {\n node.nodeValue = node.nodeValue ? node.nodeValue.replace(/\\u200B/g, '') : '';\n return;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return;\n }\n\n for (let child: (ChildNode|null) = node.firstChild; child; child = child.nextSibling) {\n removeZeroWidthSpaceRecursive(child);\n }\n }\n\n const attributeValue = attributeName && attributeValueElement ?\n this.nodeInternal.getAttribute(attributeName)?.replaceAll('\"', '"') :\n undefined;\n if (attributeValue !== undefined) {\n attributeValueElement.setTextContentTruncatedIfNeeded(\n attributeValue, i18nString(UIStrings.valueIsTooLargeToEdit));\n }\n\n // Remove zero-width spaces that were added by nodeTitleInfo.\n removeZeroWidthSpaceRecursive(attribute);\n\n const config = new UI.InplaceEditor.Config(\n this.attributeEditingCommitted.bind(this), this.editingCancelled.bind(this), attributeName || undefined);\n\n function postKeyDownFinishHandler(event: Event): string {\n UI.UIUtils.handleElementValueModifications(event, attribute);\n return '';\n }\n\n if (!Common.ParsedURL.ParsedURL.fromString(attributeValueElement.textContent || '')) {\n config.setPostKeydownFinishHandler(postKeyDownFinishHandler);\n }\n\n this.updateEditorHandles(attribute, config);\n\n const componentSelection = this.listItemElement.getComponentSelection();\n componentSelection && componentSelection.selectAllChildren(elementForSelection);\n\n return true;\n }\n\n private startEditingTextNode(textNodeElement: Element): boolean {\n if (UI.UIUtils.isBeingEdited(textNodeElement)) {\n return true;\n }\n\n let textNode: SDK.DOMModel.DOMNode = this.nodeInternal;\n // We only show text nodes inline in elements if the element only\n // has a single child, and that child is a text node.\n if (textNode.nodeType() === Node.ELEMENT_NODE && textNode.firstChild) {\n textNode = textNode.firstChild;\n }\n\n const container = textNodeElement.enclosingNodeOrSelfWithClass('webkit-html-text-node');\n if (container) {\n container.textContent = textNode.nodeValue();\n } // Strip the CSS or JS highlighting if present.\n const config = new UI.InplaceEditor.Config(\n this.textNodeEditingCommitted.bind(this, textNode), this.editingCancelled.bind(this));\n this.updateEditorHandles(textNodeElement, config);\n const componentSelection = this.listItemElement.getComponentSelection();\n componentSelection && componentSelection.selectAllChildren(textNodeElement);\n\n return true;\n }\n\n private startEditingTagName(tagNameElement?: Element): boolean {\n if (!tagNameElement) {\n tagNameElement = this.listItemElement.getElementsByClassName('webkit-html-tag-name')[0];\n if (!tagNameElement) {\n return false;\n }\n }\n\n const tagName = tagNameElement.textContent;\n if (tagName !== null && EditTagBlocklist.has(tagName.toLowerCase())) {\n return false;\n }\n\n if (UI.UIUtils.isBeingEdited(tagNameElement)) {\n return true;\n }\n\n const closingTagElement = this.distinctClosingTagElement();\n\n function keyupListener(): void {\n if (closingTagElement && tagNameElement) {\n closingTagElement.textContent = '';\n }\n }\n\n const keydownListener = (event: Event): void => {\n if ((event as KeyboardEvent).key !== ' ') {\n return;\n }\n this.editing && this.editing.commit();\n event.consume(true);\n };\n\n function editingCommitted(\n this: ElementsTreeElement, element: Element, newTagName: string, oldText: string, tagName: string|null,\n moveDirection: string): void {\n if (!tagNameElement) {\n return;\n }\n tagNameElement.removeEventListener('keyup', keyupListener, false);\n tagNameElement.removeEventListener('keydown', keydownListener, false);\n this.tagNameEditingCommitted(element, newTagName, oldText, tagName, moveDirection);\n }\n\n function editingCancelled(this: ElementsTreeElement, element: Element, tagName: string|null): void {\n if (!tagNameElement) {\n return;\n }\n tagNameElement.removeEventListener('keyup', keyupListener, false);\n tagNameElement.removeEventListener('keydown', keydownListener, false);\n this.editingCancelled(element, tagName);\n }\n\n tagNameElement.addEventListener('keyup', keyupListener, false);\n tagNameElement.addEventListener('keydown', keydownListener, false);\n\n const config =\n new UI.InplaceEditor.Config(editingCommitted.bind(this), editingCancelled.bind(this), tagName);\n this.updateEditorHandles(tagNameElement, config);\n const componentSelection = this.listItemElement.getComponentSelection();\n componentSelection && componentSelection.selectAllChildren(tagNameElement);\n return true;\n }\n\n private updateEditorHandles(element: Element, config?: UI.InplaceEditor.Config): void {\n const editorHandles = UI.InplaceEditor.InplaceEditor.startEditing(element, config);\n if (!editorHandles) {\n this.editing = null;\n } else {\n this.editing = {\n commit: editorHandles.commit,\n cancel: editorHandles.cancel,\n editor: undefined,\n resize: () => {},\n };\n }\n }\n\n private async startEditingAsHTML(\n commitCallback: (arg0: string, arg1: string) => void, disposeCallback: () => void,\n maybeInitialValue: string|null): Promise {\n if (maybeInitialValue === null) {\n return;\n }\n if (this.editing) {\n return;\n }\n\n const initialValue = this.convertWhitespaceToEntities(maybeInitialValue).text;\n this.htmlEditElement = document.createElement('div');\n this.htmlEditElement.className = 'source-code elements-tree-editor';\n\n // Hide header items.\n let child: (ChildNode|null) = this.listItemElement.firstChild;\n while (child) {\n (child as HTMLElement).style.display = 'none';\n child = child.nextSibling;\n }\n // Hide children item.\n if (this.childrenListElement) {\n this.childrenListElement.style.display = 'none';\n }\n // Append editor.\n this.listItemElement.append(this.htmlEditElement);\n this.htmlEditElement.addEventListener('keydown', event => {\n if (event.key === 'Escape') {\n event.consume(true);\n }\n });\n\n const editor = new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({\n doc: initialValue,\n extensions: [\n CodeMirror.keymap.of([\n {\n key: 'Mod-Enter',\n run: () => {\n this.editing?.commit();\n return true;\n },\n },\n {\n key: 'Escape',\n run: () => {\n this.editing?.cancel();\n return true;\n },\n },\n ]),\n TextEditor.Config.baseConfiguration(initialValue),\n TextEditor.Config.closeBrackets.instance(),\n TextEditor.Config.autocompletion.instance(),\n CodeMirror.html.html({autoCloseTags: false, selfClosingTags: true}),\n TextEditor.Config.domWordWrap.instance(),\n CodeMirror.EditorView.theme({\n '&.cm-editor': {maxHeight: '300px'},\n '.cm-scroller': {overflowY: 'auto'},\n }),\n CodeMirror.EditorView.domEventHandlers({\n focusout: event => {\n // The relatedTarget is null when no element gains focus, e.g. switching windows.\n const relatedTarget = (event.relatedTarget as Node | null);\n if (relatedTarget && !relatedTarget.isSelfOrDescendant(editor)) {\n this.editing && this.editing.commit();\n }\n },\n }),\n ],\n }));\n this.editing = {commit: commit.bind(this), cancel: dispose.bind(this), editor, resize: resize.bind(this)};\n resize.call(this);\n this.htmlEditElement.appendChild(editor);\n editor.editor.focus();\n\n this.treeOutline && this.treeOutline.setMultilineEditing(this.editing);\n\n function resize(this: ElementsTreeElement): void {\n if (this.treeOutline && this.htmlEditElement) {\n this.htmlEditElement.style.width = this.treeOutline.visibleWidth() - this.computeLeftIndent() - 30 + 'px';\n }\n }\n\n function commit(this: ElementsTreeElement): void {\n if (this.editing && this.editing.editor) {\n commitCallback(initialValue, this.editing.editor.state.doc.toString());\n }\n dispose.call(this);\n }\n\n function dispose(this: ElementsTreeElement): void {\n if (!this.editing || !this.editing.editor) {\n return;\n }\n this.editing = null;\n\n // Remove editor.\n if (this.htmlEditElement) {\n this.listItemElement.removeChild(this.htmlEditElement);\n }\n this.htmlEditElement = undefined;\n // Unhide children item.\n if (this.childrenListElement) {\n this.childrenListElement.style.removeProperty('display');\n }\n // Unhide header items.\n let child: (ChildNode|null) = this.listItemElement.firstChild;\n while (child) {\n (child as HTMLElement).style.removeProperty('display');\n child = child.nextSibling;\n }\n\n if (this.treeOutline) {\n this.treeOutline.setMultilineEditing(null);\n this.treeOutline.focus();\n }\n\n disposeCallback();\n }\n }\n\n private attributeEditingCommitted(\n element: Element, newText: string, oldText: string, attributeName: string, moveDirection: string): void {\n this.editing = null;\n\n const treeOutline = this.treeOutline;\n\n function moveToNextAttributeIfNeeded(this: ElementsTreeElement, error?: string|null): void {\n if (error) {\n this.editingCancelled(element, attributeName);\n }\n\n if (!moveDirection) {\n return;\n }\n\n if (treeOutline) {\n treeOutline.runPendingUpdates();\n treeOutline.focus();\n }\n\n // Search for the attribute's position, and then decide where to move to.\n const attributes = this.nodeInternal.attributes();\n for (let i = 0; i < attributes.length; ++i) {\n if (attributes[i].name !== attributeName) {\n continue;\n }\n\n if (moveDirection === 'backward') {\n if (i === 0) {\n this.startEditingTagName();\n } else {\n this.triggerEditAttribute(attributes[i - 1].name);\n }\n } else {\n if (i === attributes.length - 1) {\n this.addNewAttribute();\n } else {\n this.triggerEditAttribute(attributes[i + 1].name);\n }\n }\n return;\n }\n\n // Moving From the \"New Attribute\" position.\n if (moveDirection === 'backward') {\n if (newText === ' ') {\n // Moving from \"New Attribute\" that was not edited\n if (attributes.length > 0) {\n this.triggerEditAttribute(attributes[attributes.length - 1].name);\n }\n } else {\n // Moving from \"New Attribute\" that holds new value\n if (attributes.length > 1) {\n this.triggerEditAttribute(attributes[attributes.length - 2].name);\n }\n }\n } else if (moveDirection === 'forward') {\n if (!Platform.StringUtilities.isWhitespace(newText)) {\n this.addNewAttribute();\n } else {\n this.startEditingTagName();\n }\n }\n }\n\n if ((attributeName.trim() || newText.trim()) && oldText !== newText) {\n this.nodeInternal.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));\n return;\n }\n\n this.updateTitle();\n moveToNextAttributeIfNeeded.call(this);\n }\n\n private tagNameEditingCommitted(\n element: Element, newText: string, oldText: string, tagName: string|null, moveDirection: string): void {\n this.editing = null;\n const self = this;\n\n function cancel(): void {\n const closingTagElement = self.distinctClosingTagElement();\n if (closingTagElement) {\n closingTagElement.textContent = '';\n }\n\n self.editingCancelled(element, tagName);\n moveToNextAttributeIfNeeded.call(self);\n }\n\n function moveToNextAttributeIfNeeded(this: ElementsTreeElement): void {\n if (moveDirection !== 'forward') {\n this.addNewAttribute();\n return;\n }\n\n const attributes = this.nodeInternal.attributes();\n if (attributes.length > 0) {\n this.triggerEditAttribute(attributes[0].name);\n } else {\n this.addNewAttribute();\n }\n }\n\n newText = newText.trim();\n if (newText === oldText) {\n cancel();\n return;\n }\n\n const treeOutline = this.treeOutline;\n const wasExpanded = this.expanded;\n\n this.nodeInternal.setNodeName(newText, (error, newNode) => {\n if (error || !newNode) {\n cancel();\n return;\n }\n if (!treeOutline) {\n return;\n }\n const newTreeItem = treeOutline.selectNodeAfterEdit(wasExpanded, error, newNode);\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n moveToNextAttributeIfNeeded.call(newTreeItem);\n });\n }\n\n private textNodeEditingCommitted(textNode: SDK.DOMModel.DOMNode, element: Element, newText: string): void {\n this.editing = null;\n\n function callback(this: ElementsTreeElement): void {\n this.updateTitle();\n }\n textNode.setNodeValue(newText, callback.bind(this));\n }\n\n private editingCancelled(_element: Element, _tagName: string|null): void {\n this.editing = null;\n\n // Need to restore attributes structure.\n this.updateTitle();\n }\n\n private distinctClosingTagElement(): Element|null {\n // FIXME: Improve the Tree Element / Outline Abstraction to prevent crawling the DOM\n\n // For an expanded element, it will be the last element with class \"close\"\n // in the child element list.\n if (this.expanded) {\n const closers = this.childrenListElement.querySelectorAll('.close');\n return closers[closers.length - 1];\n }\n\n // Remaining cases are single line non-expanded elements with a closing\n // tag, or HTML elements without a closing tag (such as
). Return\n // null in the case where there isn't a closing tag.\n const tags = this.listItemElement.getElementsByClassName('webkit-html-tag');\n return tags.length === 1 ? null : tags[tags.length - 1];\n }\n\n updateTitle(updateRecord?: UpdateRecord|null): void {\n // If we are editing, return early to prevent canceling the edit.\n // After editing is committed updateTitle will be called.\n if (this.editing) {\n return;\n }\n\n const nodeInfo = this.nodeTitleInfo(updateRecord || null);\n if (this.nodeInternal.nodeType() === Node.DOCUMENT_FRAGMENT_NODE && this.nodeInternal.isInShadowTree() &&\n this.nodeInternal.shadowRootType()) {\n this.childrenListElement.classList.add('shadow-root');\n let depth = 4;\n for (let node: (SDK.DOMModel.DOMNode|null) = (this.nodeInternal as SDK.DOMModel.DOMNode | null); depth && node;\n node = node.parentNode) {\n if (node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE) {\n depth--;\n }\n }\n if (!depth) {\n this.childrenListElement.classList.add('shadow-root-deep');\n } else {\n this.childrenListElement.classList.add('shadow-root-depth-' + depth);\n }\n }\n this.contentElement.removeChildren();\n const highlightElement = this.contentElement.createChild('span', 'highlight');\n highlightElement.append(nodeInfo);\n // fixme: make it clear that `this.title = x` is a setter with significant side effects\n this.title = this.contentElement;\n this.updateDecorations();\n this.contentElement.prepend(this.gutterContainer);\n if (isOpeningTag(this.tagTypeContext)) {\n this.contentElement.append(this.tagTypeContext.adornerContainer);\n if (this.tagTypeContext.slot) {\n this.contentElement.append(this.tagTypeContext.slot);\n }\n }\n delete this.selectionElement;\n delete this.hintElement;\n delete this.aiButtonContainer;\n if (this.selected) {\n this.createSelection();\n this.createHint();\n }\n\n // If there is an issue with this node, make sure to update it.\n for (const issue of this.#elementIssues.values()) {\n this.#applyIssueStyleAndTooltip(issue);\n }\n\n this.highlightSearchResultsInternal();\n }\n\n private computeLeftIndent(): number {\n let treeElement: (UI.TreeOutline.TreeElement|null) = this.parent;\n let depth = 0;\n while (treeElement !== null) {\n depth++;\n treeElement = treeElement.parent;\n }\n\n /** Keep it in sync with elementsTreeOutline.css **/\n return 12 * (depth - 2) + (this.isExpandable() && this.isCollapsible() ? 1 : 12);\n }\n\n updateDecorations(): void {\n const indent = this.computeLeftIndent();\n this.gutterContainer.style.left = (-indent) + 'px';\n this.listItemElement.style.setProperty('--indent', indent + 'px');\n\n if (this.isClosingTag()) {\n return;\n }\n\n if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE) {\n return;\n }\n\n void this.decorationsThrottler.schedule(this.updateDecorationsInternal.bind(this));\n }\n\n private updateDecorationsInternal(): Promise {\n if (!this.treeOutline) {\n return Promise.resolve();\n }\n\n const node = this.nodeInternal;\n\n if (!this.treeOutline.decoratorExtensions) {\n this.treeOutline.decoratorExtensions = getRegisteredDecorators();\n }\n\n const markerToExtension = new Map();\n for (const decoratorExtension of this.treeOutline.decoratorExtensions) {\n markerToExtension.set(decoratorExtension.marker, decoratorExtension);\n }\n\n const promises: Promise[] = [];\n const decorations: {\n title: string,\n color: string,\n }[] = [];\n const descendantDecorations: {\n title: string,\n color: string,\n }[] = [];\n node.traverseMarkers(visitor);\n\n function visitor(n: SDK.DOMModel.DOMNode, marker: string): void {\n const extension = markerToExtension.get(marker);\n if (!extension) {\n return;\n }\n promises.push(Promise.resolve(extension.decorator()).then(collectDecoration.bind(null, n)));\n }\n\n function collectDecoration(n: SDK.DOMModel.DOMNode, decorator: MarkerDecorator): void {\n const decoration = decorator.decorate(n);\n if (!decoration) {\n return;\n }\n (n === node ? decorations : descendantDecorations).push(decoration);\n }\n\n return Promise.all(promises).then(updateDecorationsUI.bind(this));\n\n function updateDecorationsUI(this: ElementsTreeElement): void {\n this.decorationsElement.removeChildren();\n this.decorationsElement.classList.add('hidden');\n this.gutterContainer.classList.toggle(\n 'has-decorations', Boolean(decorations.length || descendantDecorations.length));\n UI.ARIAUtils.setLabel(this.decorationsElement, '');\n\n if (!decorations.length && !descendantDecorations.length) {\n return;\n }\n\n const colors = new Set();\n const titles = document.createElement('div');\n\n for (const decoration of decorations) {\n const titleElement = titles.createChild('div');\n titleElement.textContent = decoration.title;\n colors.add(decoration.color);\n }\n if (this.expanded && !decorations.length) {\n return;\n }\n\n const descendantColors = new Set();\n if (descendantDecorations.length) {\n let element = titles.createChild('div');\n element.textContent = i18nString(UIStrings.children);\n for (const decoration of descendantDecorations) {\n element = titles.createChild('div');\n element.style.marginLeft = '15px';\n element.textContent = decoration.title;\n descendantColors.add(decoration.color);\n }\n }\n\n let offset = 0;\n processColors.call(this, colors, 'elements-gutter-decoration');\n if (!this.expanded) {\n processColors.call(this, descendantColors, 'elements-gutter-decoration elements-has-decorated-children');\n }\n UI.Tooltip.Tooltip.install(this.decorationsElement, titles.textContent);\n UI.ARIAUtils.setLabel(this.decorationsElement, titles.textContent || '');\n\n function processColors(this: ElementsTreeElement, colors: Set, className: string): void {\n for (const color of colors) {\n const child = this.decorationsElement.createChild('div', className);\n this.decorationsElement.classList.remove('hidden');\n child.style.backgroundColor = color;\n child.style.borderColor = color;\n if (offset) {\n child.style.marginLeft = offset + 'px';\n }\n offset += 3;\n }\n }\n }\n }\n\n private buildAttributeDOM(\n parentElement: Element|DocumentFragment, name: string, value: string, updateRecord: UpdateRecord|null,\n forceValue?: boolean, node?: SDK.DOMModel.DOMNode): HTMLElement {\n const closingPunctuationRegex = /[\\/;:\\)\\]\\}]/g;\n let highlightIndex = 0;\n let highlightCount = 0;\n let additionalHighlightOffset = 0;\n\n function setValueWithEntities(this: ElementsTreeElement, element: Element, value: string): void {\n const result = this.convertWhitespaceToEntities(value);\n highlightCount = result.entityRanges.length;\n value = result.text.replace(closingPunctuationRegex, (match, replaceOffset) => {\n while (highlightIndex < highlightCount && result.entityRanges[highlightIndex].offset < replaceOffset) {\n result.entityRanges[highlightIndex].offset += additionalHighlightOffset;\n ++highlightIndex;\n }\n additionalHighlightOffset += 1;\n return match + '\\u200B';\n });\n\n while (highlightIndex < highlightCount) {\n result.entityRanges[highlightIndex].offset += additionalHighlightOffset;\n ++highlightIndex;\n }\n element.setTextContentTruncatedIfNeeded(value);\n UI.UIUtils.highlightRangesWithStyleClass(element, result.entityRanges, 'webkit-html-entity-value');\n }\n\n const hasText = (forceValue || value.length > 0);\n const attrSpanElement = (parentElement.createChild('span', 'webkit-html-attribute') as HTMLElement);\n attrSpanElement.setAttribute(\n 'jslog', `${VisualLogging.value(name === 'style' ? 'style-attribute' : 'attribute').track({\n change: true,\n dblclick: true,\n })}`);\n\n const attrNameElement = attrSpanElement.createChild('span', 'webkit-html-attribute-name');\n attrNameElement.textContent = name;\n\n if (hasText) {\n UI.UIUtils.createTextChild(attrSpanElement, '=\\u200B\"');\n }\n\n const attrValueElement = attrSpanElement.createChild('span', 'webkit-html-attribute-value');\n\n if (updateRecord && updateRecord.isAttributeModified(name)) {\n UI.UIUtils.runCSSAnimationOnce(hasText ? attrValueElement : attrNameElement, 'dom-update-highlight');\n }\n\n function linkifyValue(this: ElementsTreeElement, value: string): Element {\n const rewrittenHref = node ? node.resolveURL(value) : null;\n if (rewrittenHref === null) {\n const span = document.createElement('span');\n setValueWithEntities.call(this, span, value);\n return span;\n }\n value = value.replace(closingPunctuationRegex, '$&\\u200B');\n if (value.startsWith('data:')) {\n value = Platform.StringUtilities.trimMiddle(value, 60);\n }\n const link = node && node.nodeName().toLowerCase() === 'a' ?\n UI.XLink.XLink.create(rewrittenHref, value, '', true /* preventClick */, 'image-url') :\n Components.Linkifier.Linkifier.linkifyURL(rewrittenHref, {\n text: value,\n preventClick: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n });\n return ImagePreviewPopover.setImageUrl(link, rewrittenHref);\n }\n\n const nodeName = node ? node.nodeName().toLowerCase() : '';\n // If the href/src attribute has a value, attempt to link it.\n // There's no point trying to link it if the value is empty (e.g. ).\n if (nodeName && (name === 'src' || name === 'href') && value) {\n attrValueElement.appendChild(linkifyValue.call(this, value));\n } else if ((nodeName === 'img' || nodeName === 'source') && name === 'srcset') {\n attrValueElement.appendChild(linkifySrcset.call(this, value));\n } else if (nodeName === 'image' && (name === 'xlink:href' || name === 'href')) {\n attrValueElement.appendChild(linkifySrcset.call(this, value));\n } else {\n setValueWithEntities.call(this, attrValueElement, value);\n }\n\n if (name === 'popovertarget') {\n const linkedPart = value ? attrValueElement : attrNameElement;\n void this.linkifyElementByRelation(\n linkedPart, Protocol.DOM.GetElementByRelationRequestRelation.PopoverTarget,\n i18nString(UIStrings.showPopoverTarget));\n }\n\n if (hasText) {\n UI.UIUtils.createTextChild(attrSpanElement, '\"');\n }\n\n function linkifySrcset(this: ElementsTreeElement, value: string): DocumentFragment {\n // Splitting normally on commas or spaces will break on valid srcsets \"foo 1x,bar 2x\" and \"data:,foo 1x\".\n // 1) Let the index of the next space be `indexOfSpace`.\n // 2a) If the character at `indexOfSpace - 1` is a comma, collect the preceding characters up to\n // `indexOfSpace - 1` as a URL and repeat step 1).\n // 2b) Else, collect the preceding characters as a URL.\n // 3) Collect the characters from `indexOfSpace` up to the next comma as the size descriptor and repeat step 1).\n // https://html.spec.whatwg.org/C/#parse-a-srcset-attribute\n const fragment = document.createDocumentFragment();\n let i = 0;\n while (value.length) {\n if (i++ > 0) {\n UI.UIUtils.createTextChild(fragment, ' ');\n }\n value = value.trim();\n // The url and descriptor may end with a separating comma.\n let url = '';\n let descriptor = '';\n const indexOfSpace = value.search(/\\s/);\n if (indexOfSpace === -1) {\n url = value;\n } else if (indexOfSpace > 0 && value[indexOfSpace - 1] === ',') {\n url = value.substring(0, indexOfSpace);\n } else {\n url = value.substring(0, indexOfSpace);\n const indexOfComma = value.indexOf(',', indexOfSpace);\n if (indexOfComma !== -1) {\n descriptor = value.substring(indexOfSpace, indexOfComma + 1);\n } else {\n descriptor = value.substring(indexOfSpace);\n }\n }\n\n if (url) {\n // Up to one trailing comma should be removed from `url`.\n if (url.endsWith(',')) {\n fragment.appendChild(linkifyValue.call(this, url.substring(0, url.length - 1)));\n UI.UIUtils.createTextChild(fragment, ',');\n } else {\n fragment.appendChild(linkifyValue.call(this, url));\n }\n }\n if (descriptor) {\n UI.UIUtils.createTextChild(fragment, descriptor);\n }\n value = value.substring(url.length + descriptor.length);\n }\n return fragment;\n }\n\n return attrSpanElement;\n }\n\n private async linkifyElementByRelation(\n linkContainer: Element, relation: Protocol.DOM.GetElementByRelationRequestRelation,\n tooltip: string): Promise {\n const relatedElementId = await this.nodeInternal.domModel().getElementByRelation(this.nodeInternal.id, relation);\n const relatedElement = this.nodeInternal.domModel().nodeForId(relatedElementId);\n if (!relatedElement) {\n return;\n }\n const link = await Common.Linkifier.Linkifier.linkify(relatedElement, {\n preventKeyboardFocus: true,\n tooltip,\n textContent: linkContainer.textContent || undefined,\n isDynamicLink: true,\n });\n linkContainer.removeChildren();\n linkContainer.append(link);\n }\n\n private buildPseudoElementDOM(parentElement: DocumentFragment, pseudoElementName: string): void {\n const pseudoElement = parentElement.createChild('span', 'webkit-html-pseudo-element');\n pseudoElement.textContent = '::' + pseudoElementName;\n UI.UIUtils.createTextChild(parentElement, '\\u200B');\n }\n\n private buildTagDOM(\n parentElement: DocumentFragment, tagName: string, isClosingTag: boolean, isDistinctTreeElement: boolean,\n updateRecord: UpdateRecord|null): void {\n const node = this.nodeInternal;\n const classes = ['webkit-html-tag'];\n if (isClosingTag && isDistinctTreeElement) {\n classes.push('close');\n }\n const tagElement = parentElement.createChild('span', classes.join(' '));\n UI.UIUtils.createTextChild(tagElement, '<');\n const tagNameElement =\n tagElement.createChild('span', isClosingTag ? 'webkit-html-close-tag-name' : 'webkit-html-tag-name');\n if (!isClosingTag) {\n tagNameElement.setAttribute('jslog', `${VisualLogging.value('tag-name').track({change: true, dblclick: true})}`);\n }\n tagNameElement.textContent = (isClosingTag ? '/' : '') + tagName;\n if (!isClosingTag) {\n if (node.hasAttributes()) {\n const attributes = node.attributes();\n for (let i = 0; i < attributes.length; ++i) {\n const attr = attributes[i];\n UI.UIUtils.createTextChild(tagElement, ' ');\n this.buildAttributeDOM(tagElement, attr.name, attr.value, updateRecord, false, node);\n }\n }\n if (updateRecord) {\n let hasUpdates: boolean = updateRecord.hasRemovedAttributes() || updateRecord.hasRemovedChildren();\n hasUpdates = hasUpdates || (!this.expanded && updateRecord.hasChangedChildren());\n if (hasUpdates) {\n UI.UIUtils.runCSSAnimationOnce(tagNameElement, 'dom-update-highlight');\n }\n }\n }\n\n UI.UIUtils.createTextChild(tagElement, '>');\n UI.UIUtils.createTextChild(parentElement, '\\u200B');\n if (tagElement.textContent) {\n UI.ARIAUtils.setLabel(tagElement, tagElement.textContent);\n }\n }\n\n private convertWhitespaceToEntities(text: string): {\n text: string,\n entityRanges: Array,\n } {\n let result = '';\n let lastIndexAfterEntity = 0;\n const entityRanges = [];\n const charToEntity = MappedCharToEntity;\n for (let i = 0, size = text.length; i < size; ++i) {\n const char = text.charAt(i);\n if (charToEntity.has(char)) {\n result += text.substring(lastIndexAfterEntity, i);\n const entityValue = '&' + charToEntity.get(char) + ';';\n entityRanges.push(new TextUtils.TextRange.SourceRange(result.length, entityValue.length));\n result += entityValue;\n lastIndexAfterEntity = i + 1;\n }\n }\n if (result) {\n result += text.substring(lastIndexAfterEntity);\n }\n return {text: result || text, entityRanges};\n }\n\n private nodeTitleInfo(updateRecord: UpdateRecord|null): DocumentFragment {\n const node = this.nodeInternal;\n const titleDOM = document.createDocumentFragment();\n const updateSearchHighlight = (): void => {\n this.highlightSearchResultsInternal();\n };\n\n switch (node.nodeType()) {\n case Node.ATTRIBUTE_NODE:\n this.buildAttributeDOM(titleDOM, (node.name as string), (node.value as string), updateRecord, true);\n break;\n\n case Node.ELEMENT_NODE: {\n let pseudoElementName = node.pseudoType();\n if (pseudoElementName) {\n const pseudoIdentifier = node.pseudoIdentifier();\n if (pseudoIdentifier) {\n pseudoElementName += `(${pseudoIdentifier})`;\n }\n this.buildPseudoElementDOM(titleDOM, pseudoElementName);\n break;\n }\n\n const tagName = node.nodeNameInCorrectCase();\n if (this.isClosingTag()) {\n this.buildTagDOM(titleDOM, tagName, true, true, updateRecord);\n break;\n }\n\n this.buildTagDOM(titleDOM, tagName, false, false, updateRecord);\n\n if (this.isExpandable()) {\n if (!this.expanded) {\n const expandButton = new ElementsComponents.ElementsTreeExpandButton.ElementsTreeExpandButton();\n expandButton.data = {\n clickHandler: () => this.expand(),\n };\n titleDOM.appendChild(expandButton);\n\n // This hidden span with … is for blink layout tests.\n // The method dumpElementsTree(front_end/legacy_test_runner/elements_test_runner/ElementsTestRunner.js)\n // dumps … to identify expandable element.\n const hidden = document.createElement('span');\n hidden.textContent = '…';\n hidden.style.fontSize = '0';\n titleDOM.appendChild(hidden);\n\n UI.UIUtils.createTextChild(titleDOM, '\\u200B');\n this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);\n }\n break;\n }\n\n if (ElementsTreeElement.canShowInlineText(node)) {\n const textNodeElement = titleDOM.createChild('span', 'webkit-html-text-node');\n textNodeElement.setAttribute(\n 'jslog', `${VisualLogging.value('text-node').track({change: true, dblclick: true})}`);\n const firstChild = node.firstChild;\n if (!firstChild) {\n throw new Error('ElementsTreeElement._nodeTitleInfo expects node.firstChild to be defined.');\n }\n const result = this.convertWhitespaceToEntities(firstChild.nodeValue());\n textNodeElement.textContent = Platform.StringUtilities.collapseWhitespace(result.text);\n UI.UIUtils.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, 'webkit-html-entity-value');\n UI.UIUtils.createTextChild(titleDOM, '\\u200B');\n this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);\n if (updateRecord && updateRecord.hasChangedChildren()) {\n UI.UIUtils.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');\n }\n if (updateRecord && updateRecord.isCharDataModified()) {\n UI.UIUtils.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');\n }\n break;\n }\n\n if (this.treeOutline && this.treeOutline.isXMLMimeType || !ForbiddenClosingTagElements.has(tagName)) {\n this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);\n }\n break;\n }\n\n case Node.TEXT_NODE:\n if (node.parentNode && node.parentNode.nodeName().toLowerCase() === 'script') {\n const newNode = titleDOM.createChild('span', 'webkit-html-text-node webkit-html-js-node');\n newNode.setAttribute(\n 'jslog', `${VisualLogging.value('script-text-node').track({change: true, dblclick: true})}`);\n const text = node.nodeValue();\n newNode.textContent = text.replace(/^[\\n\\r]+|\\s+$/g, '');\n void CodeHighlighter.CodeHighlighter.highlightNode(newNode, 'text/javascript').then(updateSearchHighlight);\n } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === 'style') {\n const newNode = titleDOM.createChild('span', 'webkit-html-text-node webkit-html-css-node');\n newNode.setAttribute(\n 'jslog', `${VisualLogging.value('css-text-node').track({change: true, dblclick: true})}`);\n const text = node.nodeValue();\n newNode.textContent = text.replace(/^[\\n\\r]+|\\s+$/g, '');\n void CodeHighlighter.CodeHighlighter.highlightNode(newNode, 'text/css').then(updateSearchHighlight);\n } else {\n UI.UIUtils.createTextChild(titleDOM, '\"');\n const textNodeElement = titleDOM.createChild('span', 'webkit-html-text-node');\n textNodeElement.setAttribute(\n 'jslog', `${VisualLogging.value('text-node').track({change: true, dblclick: true})}`);\n const result = this.convertWhitespaceToEntities(node.nodeValue());\n textNodeElement.textContent = Platform.StringUtilities.collapseWhitespace(result.text);\n UI.UIUtils.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, 'webkit-html-entity-value');\n UI.UIUtils.createTextChild(titleDOM, '\"');\n if (updateRecord && updateRecord.isCharDataModified()) {\n UI.UIUtils.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');\n }\n }\n break;\n\n case Node.COMMENT_NODE: {\n const commentElement = titleDOM.createChild('span', 'webkit-html-comment');\n UI.UIUtils.createTextChild(commentElement, '');\n break;\n }\n\n case Node.DOCUMENT_TYPE_NODE: {\n const docTypeElement = titleDOM.createChild('span', 'webkit-html-doctype');\n UI.UIUtils.createTextChild(docTypeElement, '');\n break;\n }\n\n case Node.CDATA_SECTION_NODE: {\n const cdataElement = titleDOM.createChild('span', 'webkit-html-text-node');\n UI.UIUtils.createTextChild(cdataElement, '');\n break;\n }\n\n case Node.DOCUMENT_NODE: {\n const documentElement = titleDOM.createChild('span');\n UI.UIUtils.createTextChild(documentElement, '#document (');\n const text = (node as SDK.DOMModel.DOMDocument).documentURL;\n documentElement.appendChild(Components.Linkifier.Linkifier.linkifyURL(text, {\n text,\n preventClick: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n }));\n UI.UIUtils.createTextChild(documentElement, ')');\n break;\n }\n\n case Node.DOCUMENT_FRAGMENT_NODE: {\n const fragmentElement = titleDOM.createChild('span', 'webkit-html-fragment');\n fragmentElement.textContent = Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase());\n break;\n }\n\n default: {\n const nameWithSpaceCollapsed = Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase());\n UI.UIUtils.createTextChild(titleDOM, nameWithSpaceCollapsed);\n }\n }\n\n return titleDOM;\n }\n\n remove(): void {\n if (this.nodeInternal.pseudoType()) {\n return;\n }\n const parentElement = this.parent;\n if (!parentElement) {\n return;\n }\n\n if (!this.nodeInternal.parentNode || this.nodeInternal.parentNode.nodeType() === Node.DOCUMENT_NODE) {\n return;\n }\n void this.nodeInternal.removeNode();\n }\n\n toggleEditAsHTML(callback?: ((arg0: boolean) => void), startEditing?: boolean): void {\n if (this.editing && this.htmlEditElement) {\n this.editing.commit();\n return;\n }\n\n if (startEditing === false) {\n return;\n }\n\n function selectNode(error: string|null): void {\n if (callback) {\n callback(!error);\n }\n }\n\n function commitChange(initialValue: string, value: string): void {\n if (initialValue !== value) {\n node.setOuterHTML(value, selectNode);\n }\n }\n\n function disposeCallback(): void {\n if (callback) {\n callback(false);\n }\n }\n\n const node = this.nodeInternal;\n void node.getOuterHTML().then(this.startEditingAsHTML.bind(this, commitChange, disposeCallback));\n }\n\n private copyCSSPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(cssPath(this.nodeInternal, true));\n }\n\n private copyJSPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(jsPath(this.nodeInternal, true));\n }\n\n private copyXPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(xPath(this.nodeInternal, true));\n }\n\n private copyFullXPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(xPath(this.nodeInternal, false));\n }\n\n async copyStyles(): Promise {\n const node = this.nodeInternal;\n const cssModel = node.domModel().cssModel();\n const cascade = await cssModel.cachedMatchedCascadeForNode(node);\n if (!cascade) {\n return;\n }\n\n const indent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n const lines: string[] = [];\n for (const style of cascade.nodeStyles().reverse()) {\n for (const property of style.leadingProperties()) {\n if (!property.parsedOk || property.disabled || !property.activeInStyle() || property.implicit) {\n continue;\n }\n if (cascade.isInherited(style) && !SDK.CSSMetadata.cssMetadata().isPropertyInherited(property.name)) {\n continue;\n }\n if (style.parentRule && style.parentRule.isUserAgent()) {\n continue;\n }\n if (cascade.propertyState(property) !== SDK.CSSMatchedStyles.PropertyState.ACTIVE) {\n continue;\n }\n lines.push(`${indent}${property.name}: ${property.value};`);\n }\n }\n\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(lines.join('\\n'));\n }\n\n private highlightSearchResultsInternal(): void {\n this.hideSearchHighlights();\n\n if (!this.searchQuery) {\n return;\n }\n\n const text = this.listItemElement.textContent || '';\n const regexObject = Platform.StringUtilities.createPlainTextSearchRegex(this.searchQuery, 'gi');\n\n const matchRanges = [];\n let match = regexObject.exec(text);\n while (match) {\n matchRanges.push(new TextUtils.TextRange.SourceRange(match.index, match[0].length));\n match = regexObject.exec(text);\n }\n\n // Fall back for XPath, etc. matches.\n if (!matchRanges.length) {\n matchRanges.push(new TextUtils.TextRange.SourceRange(0, text.length));\n }\n\n this.#highlights = Highlighting.HighlightManager.HighlightManager.instance().highlightOrderedTextRanges(\n this.listItemElement, matchRanges);\n }\n\n private editAsHTML(): void {\n const promise = Common.Revealer.reveal(this.node());\n void promise.then(() => {\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('elements.edit-as-html');\n return action.execute();\n });\n }\n\n // TODO: add unit tests for adorner-related methods after component and TypeScript works are done\n adorn({name}: {name: string}, content?: HTMLElement): Adorners.Adorner.Adorner {\n let adornerContent = content;\n if (!adornerContent) {\n adornerContent = document.createElement('span');\n adornerContent.textContent = name;\n }\n const adorner = new Adorners.Adorner.Adorner();\n adorner.data = {\n name,\n content: adornerContent,\n jslogContext: name,\n };\n if (isOpeningTag(this.tagTypeContext)) {\n this.tagTypeContext.adorners.push(adorner);\n ElementsPanel.instance().registerAdorner(adorner);\n this.updateAdorners(this.tagTypeContext);\n }\n return adorner;\n }\n\n adornSlot({name}: {name: string}, context: OpeningTagContext): Adorners.Adorner.Adorner {\n const linkIcon = new IconButton.Icon.Icon();\n linkIcon.name = 'select-element';\n const slotText = document.createElement('span');\n slotText.textContent = name;\n const adornerContent = document.createElement('span');\n adornerContent.append(linkIcon);\n adornerContent.append(slotText);\n adornerContent.classList.add('adorner-with-icon');\n const adorner = new Adorners.Adorner.Adorner();\n adorner.data = {\n name,\n content: adornerContent,\n jslogContext: 'slot',\n };\n context.adorners.push(adorner);\n ElementsPanel.instance().registerAdorner(adorner);\n this.updateAdorners(context);\n return adorner;\n }\n\n adornMedia({name}: {name: string}): Adorners.Adorner.Adorner {\n const adornerContent = document.createElement('span');\n\n adornerContent.textContent = name;\n adornerContent.classList.add('adorner-with-icon');\n\n const linkIcon = new IconButton.Icon.Icon();\n linkIcon.name = 'select-element';\n adornerContent.append(linkIcon);\n\n const adorner = new Adorners.Adorner.Adorner();\n adorner.data = {\n name,\n content: adornerContent,\n jslogContext: 'media',\n };\n if (isOpeningTag(this.tagTypeContext)) {\n this.tagTypeContext.adorners.push(adorner);\n ElementsPanel.instance().registerAdorner(adorner);\n this.updateAdorners(this.tagTypeContext);\n }\n return adorner;\n }\n\n removeAdorner(adornerToRemove: Adorners.Adorner.Adorner, context: OpeningTagContext): void {\n const adorners = context.adorners;\n ElementsPanel.instance().deregisterAdorner(adornerToRemove);\n adornerToRemove.remove();\n for (let i = 0; i < adorners.length; ++i) {\n if (adorners[i] === adornerToRemove) {\n adorners.splice(i, 1);\n this.updateAdorners(context);\n return;\n }\n }\n }\n\n removeAllAdorners(): void {\n if (isOpeningTag(this.tagTypeContext)) {\n for (const adorner of this.tagTypeContext.adorners) {\n ElementsPanel.instance().deregisterAdorner(adorner);\n adorner.remove();\n }\n\n this.tagTypeContext.adorners = [];\n this.updateAdorners(this.tagTypeContext);\n }\n }\n\n private updateAdorners(context: OpeningTagContext): void {\n void context.adornersThrottler.schedule(this.updateAdornersInternal.bind(null, context));\n }\n\n private updateAdornersInternal(context: OpeningTagContext): Promise {\n const adornerContainer = context.adornerContainer;\n if (!adornerContainer) {\n return Promise.resolve();\n }\n const adorners = context.adorners;\n if (adorners.length === 0) {\n adornerContainer.classList.add('hidden');\n return Promise.resolve();\n }\n\n adorners.sort(adornerComparator);\n\n adornerContainer.removeChildren();\n for (const adorner of adorners) {\n adornerContainer.appendChild(adorner);\n }\n adornerContainer.classList.remove('hidden');\n return Promise.resolve();\n }\n\n async updateStyleAdorners(): Promise {\n if (!isOpeningTag(this.tagTypeContext)) {\n return;\n }\n\n const node = this.node();\n const nodeId = node.id;\n if (node.nodeType() === Node.COMMENT_NODE || node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE ||\n node.nodeType() === Node.TEXT_NODE || nodeId === undefined) {\n return;\n }\n\n const styles = await node.domModel().cssModel().getComputedStyle(nodeId);\n for (const styleAdorner of this.tagTypeContext.styleAdorners) {\n this.removeAdorner(styleAdorner, this.tagTypeContext);\n }\n this.tagTypeContext.styleAdorners = [];\n if (!styles) {\n return;\n }\n\n const display = styles.get('display');\n const isGrid = display === 'grid' || display === 'inline-grid';\n const isFlex = display === 'flex' || display === 'inline-flex';\n const isSubgrid = (isGrid &&\n (styles.get('grid-template-columns')?.startsWith('subgrid') ||\n styles.get('grid-template-rows')?.startsWith('subgrid'))) ??\n false;\n\n const containerType = styles.get('container-type');\n const contain = styles.get('contain');\n const isContainer =\n SDK.CSSContainerQuery.getQueryAxis(`${containerType} ${contain}`) !== SDK.CSSContainerQuery.QueryAxis.NONE;\n\n if (isGrid) {\n this.pushGridAdorner(this.tagTypeContext, isSubgrid);\n }\n if (isFlex) {\n this.pushFlexAdorner(this.tagTypeContext);\n }\n if (styles.get('scroll-snap-type') && styles.get('scroll-snap-type') !== 'none') {\n this.pushScrollSnapAdorner(this.tagTypeContext);\n }\n if (isContainer) {\n this.pushContainerAdorner(this.tagTypeContext);\n }\n\n if (node.isMediaNode()) {\n this.pushMediaAdorner(this.tagTypeContext);\n }\n }\n\n pushGridAdorner(context: OpeningTagContext, isSubgrid: boolean): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n isSubgrid ? ElementsComponents.AdornerManager.RegisteredAdorners.SUBGRID :\n ElementsComponents.AdornerManager.RegisteredAdorners.GRID);\n const adorner = this.adorn(config);\n adorner.classList.add('grid');\n\n const onClick = ((() => {\n if (adorner.isActive()) {\n node.domModel().overlayModel().highlightGridInPersistentOverlay(nodeId);\n } else {\n node.domModel().overlayModel().hideGridInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableGridMode),\n ariaLabelActive: i18nString(UIStrings.disableGridMode),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_GRID_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n if (node.domModel().overlayModel().isHighlightedGridInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushScrollSnapAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL_SNAP);\n const adorner = this.adorn(config);\n adorner.classList.add('scroll-snap');\n\n const onClick = ((() => {\n const model = node.domModel().overlayModel();\n if (adorner.isActive()) {\n model.highlightScrollSnapInPersistentOverlay(nodeId);\n } else {\n model.hideScrollSnapInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableScrollSnap),\n ariaLabelActive: i18nString(UIStrings.disableScrollSnap),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_SCROLL_SNAP_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n\n if (node.domModel().overlayModel().isHighlightedScrollSnapInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushFlexAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.FLEX);\n const adorner = this.adorn(config);\n adorner.classList.add('flex');\n\n const onClick = ((() => {\n const model = node.domModel().overlayModel();\n if (adorner.isActive()) {\n model.highlightFlexContainerInPersistentOverlay(nodeId);\n } else {\n model.hideFlexContainerInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableFlexMode),\n ariaLabelActive: i18nString(UIStrings.disableFlexMode),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_FLEX_CONTAINER_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n\n if (node.domModel().overlayModel().isHighlightedFlexContainerInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushContainerAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.CONTAINER);\n const adorner = this.adorn(config);\n adorner.classList.add('container');\n\n const onClick = ((() => {\n const model = node.domModel().overlayModel();\n if (adorner.isActive()) {\n model.highlightContainerQueryInPersistentOverlay(nodeId);\n } else {\n model.hideContainerQueryInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableScrollSnap),\n ariaLabelActive: i18nString(UIStrings.disableScrollSnap),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_CONTAINER_QUERY_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n if (node.domModel().overlayModel().isHighlightedContainerQueryInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushMediaAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.MEDIA);\n const adorner = this.adornMedia(config);\n adorner.classList.add('media');\n\n const onClick = ((() => {\n void UI.ViewManager.ViewManager.instance().showView('medias');\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: false,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.openMediaPanel),\n ariaLabelActive: i18nString(UIStrings.openMediaPanel),\n });\n\n context.styleAdorners.push(adorner);\n }\n\n updateScrollAdorner(): void {\n if (!isOpeningTag(this.tagTypeContext)) {\n return;\n }\n const scrollAdorner = this.tagTypeContext.adorners.find(x => x.name === 'scroll');\n // Check if the node is scrollable, or if it's the element and the document is scrollable because the top-level document (#document) doesn't have a corresponding tree element.\n const needsAScrollAdorner = (this.node().nodeName() === 'HTML' && this.node().ownerDocument?.isScrollable()) ||\n (this.node().nodeName() !== '#document' && this.node().isScrollable());\n if (needsAScrollAdorner && !scrollAdorner) {\n this.pushScrollAdorner();\n } else if (!needsAScrollAdorner && scrollAdorner) {\n this.removeAdorner(scrollAdorner, this.tagTypeContext);\n }\n }\n\n pushScrollAdorner(): void {\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL);\n const adorner = this.adorn(config);\n UI.Tooltip.Tooltip.install(adorner, i18nString(UIStrings.elementHasScrollableOverflow));\n adorner.classList.add('scroll');\n }\n}\n\nexport const InitialChildrenLimit = 500;\n\n// A union of HTML4 and HTML5-Draft elements that explicitly\n// or implicitly (for HTML5) forbid the closing tag.\nexport const ForbiddenClosingTagElements = new Set([\n 'area', 'base', 'basefont', 'br', 'canvas', 'col', 'command', 'embed', 'frame', 'hr',\n 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr',\n]);\n\n// These tags we do not allow editing their tag name.\nexport const EditTagBlocklist = new Set(['html', 'head', 'body']);\n\nexport function adornerComparator(adornerA: Adorners.Adorner.Adorner, adornerB: Adorners.Adorner.Adorner): number {\n const compareCategories =\n ElementsComponents.AdornerManager.compareAdornerNamesByCategory(adornerB.name, adornerB.name);\n if (compareCategories === 0) {\n return adornerA.name.localeCompare(adornerB.name);\n }\n return compareCategories;\n}\nexport interface EditorHandles {\n commit: () => void;\n cancel: () => void;\n editor?: TextEditor.TextEditor.TextEditor;\n resize: () => void;\n}\n\n// As a privacy measure we are logging elements tree outline as a flat list where every tree item is a\n// child of a tree outline.\nfunction loggingParentProvider(e: Element): Element|undefined {\n const treeElement = UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(e);\n return treeElement?.treeOutline?.contentElement;\n}\n\nVisualLogging.registerParentProvider('elementsTreeOutline', loggingParentProvider);\n"]} \ No newline at end of file +{"version":3,"file":"ElementsTreeElement.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/ElementsTreeElement.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 Matt Lilek \n * Copyright (C) 2009 Joseph Pecoraro\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 type * as IssuesManager from '../../models/issues_manager/issues_manager.js';\nimport * as TextUtils from '../../models/text_utils/text_utils.js';\nimport * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as Adorners from '../../ui/components/adorners/adorners.js';\nimport * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js';\nimport * as FloatingButton from '../../ui/components/floating_button/floating_button.js';\nimport * as Highlighting from '../../ui/components/highlighting/highlighting.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as TextEditor from '../../ui/components/text_editor/text_editor.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';\nimport * as Emulation from '../emulation/emulation.js';\n\nimport * as ElementsComponents from './components/components.js';\nimport {canGetJSPath, cssPath, jsPath, xPath} from './DOMPath.js';\nimport {ElementsPanel} from './ElementsPanel.js';\nimport {type ElementsTreeOutline, MappedCharToEntity, type UpdateRecord} from './ElementsTreeOutline.js';\nimport {ImagePreviewPopover} from './ImagePreviewPopover.js';\nimport {getRegisteredDecorators, type MarkerDecorator, type MarkerDecoratorRegistration} from './MarkerDecorator.js';\n\nconst UIStrings = {\n /**\n *@description Title for Ad adorner. This iframe is marked as advertisement frame.\n */\n thisFrameWasIdentifiedAsAnAd: 'This frame was identified as an ad frame',\n /**\n *@description A context menu item in the Elements panel. Force is used as a verb, indicating intention to make the state change.\n */\n forceState: 'Force state',\n /**\n *@description Hint element title in Elements Tree Element of the Elements panel\n *@example {0} PH1\n */\n useSInTheConsoleToReferToThis: 'Use {PH1} in the console to refer to this element.',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n addAttribute: 'Add attribute',\n /**\n *@description Text to modify the attribute of an item\n */\n editAttribute: 'Edit attribute',\n /**\n *@description Text to focus on something\n */\n focus: 'Focus',\n /**\n *@description Text to scroll the displayed content into view\n */\n scrollIntoView: 'Scroll into view',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n editText: 'Edit text',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n editAsHtml: 'Edit as HTML',\n /**\n *@description Text to cut an element, cut should be used as a verb\n */\n cut: 'Cut',\n /**\n *@description Text for copying, copy should be used as a verb\n */\n copy: 'Copy',\n /**\n *@description Text to paste an element, paste should be used as a verb\n */\n paste: 'Paste',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyOuterhtml: 'Copy outerHTML',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copySelector: 'Copy `selector`',\n /**\n *@description Text in Elements Tree Element of the Elements panel\n */\n copyJsPath: 'Copy JS path',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyStyles: 'Copy styles',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyXpath: 'Copy XPath',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyFullXpath: 'Copy full XPath',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copyElement: 'Copy element',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n duplicateElement: 'Duplicate element',\n /**\n *@description Text to hide an element\n */\n hideElement: 'Hide element',\n /**\n *@description A context menu item in the Elements Tree Element of the Elements panel\n */\n deleteElement: 'Delete element',\n /**\n *@description Text to expand something recursively\n */\n expandRecursively: 'Expand recursively',\n /**\n *@description Text to collapse children of a parent group\n */\n collapseChildren: 'Collapse children',\n /**\n *@description Title of an action in the emulation tool to capture node screenshot\n */\n captureNodeScreenshot: 'Capture node screenshot',\n /**\n *@description Title of a context menu item. When clicked DevTools goes to the Application panel and shows this specific iframe's details\n */\n showFrameDetails: 'Show `iframe` details',\n /**\n *@description Text in Elements Tree Element of the Elements panel\n */\n valueIsTooLargeToEdit: '',\n /**\n *@description Element text content in Elements Tree Element of the Elements panel\n */\n children: 'Children:',\n /**\n *@description ARIA label for Elements Tree adorners\n */\n enableGridMode: 'Enable grid mode',\n /**\n *@description ARIA label for Elements Tree adorners\n */\n disableGridMode: 'Disable grid mode',\n /**\n *@description Label of the adorner for flex elements in the Elements panel\n */\n enableFlexMode: 'Enable flex mode',\n /**\n *@description Label of the adorner for flex elements in the Elements panel\n */\n disableFlexMode: 'Disable flex mode',\n /**\n *@description Label of an adorner in the Elements panel. When clicked, it enables\n * the overlay showing CSS scroll snapping for the current element.\n */\n enableScrollSnap: 'Enable scroll-snap overlay',\n /**\n *@description Label of an adorner in the Elements panel. When clicked, it disables\n * the overlay showing CSS scroll snapping for the current element.\n */\n disableScrollSnap: 'Disable scroll-snap overlay',\n /**\n *@description Label of an adorner in the Elements panel. When clicked, it redirects\n * to the Media Panel.\n */\n openMediaPanel: 'Jump to Media panel',\n /**\n *@description Text of a tooltip to redirect to another element in the Elements panel\n */\n showPopoverTarget: 'Show popover target',\n /**\n *@description Text of the tooltip for scroll adorner.\n */\n elementHasScrollableOverflow: 'This element has a scrollable overflow',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/ElementsTreeElement.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst enum TagType {\n OPENING = 'OPENING_TAG',\n CLOSING = 'CLOSING_TAG',\n}\n\ntype OpeningTagContext = {\n tagType: TagType.OPENING,\n readonly adornerContainer: HTMLElement,\n adorners: Adorners.Adorner.Adorner[],\n styleAdorners: Adorners.Adorner.Adorner[],\n readonly adornersThrottler: Common.Throttler.Throttler,\n canAddAttributes: boolean,\n slot?: Adorners.Adorner.Adorner,\n};\n\ntype ClosingTagContext = {\n tagType: TagType.CLOSING,\n};\n\nexport type TagTypeContext = OpeningTagContext|ClosingTagContext;\n\nexport function isOpeningTag(context: TagTypeContext): context is OpeningTagContext {\n return context.tagType === TagType.OPENING;\n}\n\nexport class ElementsTreeElement extends UI.TreeOutline.TreeElement {\n nodeInternal: SDK.DOMModel.DOMNode;\n override treeOutline: ElementsTreeOutline|null;\n private gutterContainer: HTMLElement;\n private readonly decorationsElement: HTMLElement;\n private searchQuery: string|null;\n private expandedChildrenLimitInternal: number;\n private readonly decorationsThrottler: Common.Throttler.Throttler;\n private inClipboard: boolean;\n private hoveredInternal: boolean;\n private editing: EditorHandles|null;\n private htmlEditElement?: HTMLElement;\n expandAllButtonElement: UI.TreeOutline.TreeElement|null;\n selectionElement?: HTMLDivElement;\n private hintElement?: HTMLElement;\n private aiButtonContainer?: HTMLElement;\n private contentElement: HTMLElement;\n #elementIssues: Map = new Map();\n #nodeElementToIssue: Map = new Map();\n #highlights: Range[] = [];\n\n readonly tagTypeContext: TagTypeContext;\n\n constructor(node: SDK.DOMModel.DOMNode, isClosingTag?: boolean) {\n // The title will be updated in onattach.\n super();\n this.nodeInternal = node;\n this.treeOutline = null;\n this.listItemElement.setAttribute(\n 'jslog', `${VisualLogging.treeItem().parent('elementsTreeOutline').track({\n keydown: 'ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Backspace|Delete|Enter|Space|Home|End',\n drag: true,\n click: true,\n })}`);\n this.contentElement = this.listItemElement.createChild('div');\n this.gutterContainer = this.contentElement.createChild('div', 'gutter-container');\n this.gutterContainer.addEventListener('click', this.showContextMenu.bind(this));\n const gutterMenuIcon = new IconButton.Icon.Icon();\n gutterMenuIcon.data = {\n color: 'var(--icon-default)',\n iconName: 'dots-horizontal',\n height: '16px',\n width: '16px',\n };\n this.gutterContainer.append(gutterMenuIcon);\n this.decorationsElement = this.gutterContainer.createChild('div', 'hidden');\n\n this.searchQuery = null;\n this.expandedChildrenLimitInternal = InitialChildrenLimit;\n this.decorationsThrottler = new Common.Throttler.Throttler(100);\n\n this.inClipboard = false;\n this.hoveredInternal = false;\n\n this.editing = null;\n\n if (isClosingTag) {\n this.tagTypeContext = {tagType: TagType.CLOSING};\n } else {\n this.tagTypeContext = {\n tagType: TagType.OPENING,\n adornerContainer: this.contentElement.createChild('div', 'adorner-container hidden'),\n adorners: [],\n styleAdorners: [],\n adornersThrottler: new Common.Throttler.Throttler(100),\n canAddAttributes: this.nodeInternal.nodeType() === Node.ELEMENT_NODE,\n };\n void this.updateStyleAdorners();\n\n if (node.isAdFrameNode()) {\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.AD);\n const adorner = this.adorn(config);\n UI.Tooltip.Tooltip.install(adorner, i18nString(UIStrings.thisFrameWasIdentifiedAsAnAd));\n }\n\n void this.updateScrollAdorner();\n }\n this.expandAllButtonElement = null;\n }\n\n static animateOnDOMUpdate(treeElement: ElementsTreeElement): void {\n const tagName = treeElement.listItemElement.querySelector('.webkit-html-tag-name');\n UI.UIUtils.runCSSAnimationOnce(tagName || treeElement.listItemElement, 'dom-update-highlight');\n }\n\n static visibleShadowRoots(node: SDK.DOMModel.DOMNode): SDK.DOMModel.DOMNode[] {\n let roots = node.shadowRoots();\n if (roots.length && !Common.Settings.Settings.instance().moduleSetting('show-ua-shadow-dom').get()) {\n roots = roots.filter(filter);\n }\n\n function filter(root: SDK.DOMModel.DOMNode): boolean {\n return root.shadowRootType() !== SDK.DOMModel.DOMNode.ShadowRootTypes.UserAgent;\n }\n return roots;\n }\n\n static canShowInlineText(node: SDK.DOMModel.DOMNode): boolean {\n if (node.contentDocument() || node.templateContent() || ElementsTreeElement.visibleShadowRoots(node).length ||\n node.hasPseudoElements()) {\n return false;\n }\n if (node.nodeType() !== Node.ELEMENT_NODE) {\n return false;\n }\n if (!node.firstChild || node.firstChild !== node.lastChild || node.firstChild.nodeType() !== Node.TEXT_NODE) {\n return false;\n }\n const textChild = node.firstChild;\n const maxInlineTextChildLength = 80;\n if (textChild.nodeValue().length < maxInlineTextChildLength) {\n return true;\n }\n return false;\n }\n\n static populateForcedPseudoStateItems(contextMenu: UI.ContextMenu.ContextMenu, node: SDK.DOMModel.DOMNode): void {\n const pseudoClasses = ['active', 'hover', 'focus', 'visited', 'focus-within', 'focus-visible'];\n const forcedPseudoState = node.domModel().cssModel().pseudoState(node);\n const stateMenu =\n contextMenu.debugSection().appendSubMenuItem(i18nString(UIStrings.forceState), false, 'force-state');\n for (const pseudoClass of pseudoClasses) {\n const pseudoClassForced = forcedPseudoState ? forcedPseudoState.indexOf(pseudoClass) >= 0 : false;\n stateMenu.defaultSection().appendCheckboxItem(\n ':' + pseudoClass, setPseudoStateCallback.bind(null, pseudoClass, !pseudoClassForced),\n {checked: pseudoClassForced, jslogContext: pseudoClass});\n }\n\n function setPseudoStateCallback(pseudoState: string, enabled: boolean): void {\n node.domModel().cssModel().forcePseudoState(node, pseudoState, enabled);\n }\n }\n\n isClosingTag(): boolean {\n return !isOpeningTag(this.tagTypeContext);\n }\n\n node(): SDK.DOMModel.DOMNode {\n return this.nodeInternal;\n }\n\n isEditing(): boolean {\n return Boolean(this.editing);\n }\n\n highlightSearchResults(searchQuery: string): void {\n this.searchQuery = searchQuery;\n if (!this.editing) {\n this.highlightSearchResultsInternal();\n }\n }\n\n hideSearchHighlights(): void {\n Highlighting.HighlightManager.HighlightManager.instance().removeHighlights(this.#highlights);\n this.#highlights = [];\n }\n\n setInClipboard(inClipboard: boolean): void {\n if (this.inClipboard === inClipboard) {\n return;\n }\n this.inClipboard = inClipboard;\n this.listItemElement.classList.toggle('in-clipboard', inClipboard);\n }\n\n get hovered(): boolean {\n return this.hoveredInternal;\n }\n\n set hovered(isHovered: boolean) {\n if (this.hoveredInternal === isHovered) {\n return;\n }\n\n if (isHovered && !this.aiButtonContainer) {\n this.createAiButton();\n } else if (!isHovered && this.aiButtonContainer) {\n this.aiButtonContainer.remove();\n delete this.aiButtonContainer;\n }\n\n this.hoveredInternal = isHovered;\n\n if (this.listItemElement) {\n if (isHovered) {\n this.createSelection();\n this.listItemElement.classList.add('hovered');\n } else {\n this.listItemElement.classList.remove('hovered');\n }\n }\n }\n\n addIssue(newIssue: IssuesManager.GenericIssue.GenericIssue): void {\n if (this.#elementIssues.has(newIssue.primaryKey())) {\n return;\n }\n\n this.#elementIssues.set(newIssue.primaryKey(), newIssue);\n this.#applyIssueStyleAndTooltip(newIssue);\n }\n\n #applyIssueStyleAndTooltip(issue: IssuesManager.GenericIssue.GenericIssue): void {\n const issueDetails = issue.details();\n\n if (issueDetails.violatingNodeAttribute) {\n this.#highlightViolatingAttr(issueDetails.violatingNodeAttribute, issue);\n } else {\n this.#highlightTagAsViolating(issue);\n }\n }\n\n get issuesByNodeElement(): Map {\n return this.#nodeElementToIssue;\n }\n\n #highlightViolatingAttr(name: string, issue: IssuesManager.GenericIssue.GenericIssue): void {\n const tag = this.listItemElement.getElementsByClassName('webkit-html-tag')[0];\n const attributes = tag.getElementsByClassName('webkit-html-attribute');\n for (const attribute of attributes) {\n if (attribute.getElementsByClassName('webkit-html-attribute-name')[0].textContent === name) {\n const attributeElement = attribute.getElementsByClassName('webkit-html-attribute-name')[0];\n attributeElement.classList.add('violating-element');\n this.#nodeElementToIssue.set(attributeElement, issue);\n }\n }\n }\n\n #highlightTagAsViolating(issue: IssuesManager.GenericIssue.GenericIssue): void {\n const tagElement = this.listItemElement.getElementsByClassName('webkit-html-tag-name')[0];\n tagElement.classList.add('violating-element');\n this.#nodeElementToIssue.set(tagElement, issue);\n }\n\n expandedChildrenLimit(): number {\n return this.expandedChildrenLimitInternal;\n }\n\n setExpandedChildrenLimit(expandedChildrenLimit: number): void {\n this.expandedChildrenLimitInternal = expandedChildrenLimit;\n }\n\n createSlotLink(nodeShortcut: SDK.DOMModel.DOMNodeShortcut|null): void {\n if (!isOpeningTag(this.tagTypeContext)) {\n return;\n }\n if (nodeShortcut) {\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.SLOT);\n this.tagTypeContext.slot = this.adornSlot(config, this.tagTypeContext);\n const deferredNode = nodeShortcut.deferredNode;\n this.tagTypeContext.slot.addEventListener('click', () => {\n deferredNode.resolve(node => {\n void Common.Revealer.reveal(node);\n });\n });\n this.tagTypeContext.slot.addEventListener('mousedown', e => e.consume(), false);\n }\n }\n\n private createSelection(): void {\n const contentElement = this.contentElement;\n if (!contentElement) {\n return;\n }\n\n if (!this.selectionElement) {\n this.selectionElement = document.createElement('div');\n this.selectionElement.className = 'selection fill';\n this.selectionElement.style.setProperty('margin-left', (-this.computeLeftIndent()) + 'px');\n contentElement.prepend(this.selectionElement);\n }\n }\n\n private createHint(): void {\n if (this.contentElement && !this.hintElement) {\n this.hintElement = this.contentElement.createChild('span', 'selected-hint');\n const selectedElementCommand = '$0';\n UI.Tooltip.Tooltip.install(\n this.hintElement, i18nString(UIStrings.useSInTheConsoleToReferToThis, {PH1: selectedElementCommand}));\n UI.ARIAUtils.markAsHidden(this.hintElement);\n }\n }\n\n private createAiButton(): void {\n const isElementNode = this.node().nodeType() === Node.ELEMENT_NODE;\n if (!isElementNode ||\n !UI.ActionRegistry.ActionRegistry.instance().hasAction('freestyler.elements-floating-button')) {\n return;\n }\n\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('freestyler.elements-floating-button');\n if (this.contentElement && !this.aiButtonContainer) {\n this.aiButtonContainer = this.contentElement.createChild('span', 'ai-button-container');\n const floatingButton = new FloatingButton.FloatingButton.FloatingButton({\n iconName: 'smart-assistant',\n });\n floatingButton.addEventListener('click', ev => {\n ev.stopPropagation();\n this.select(true, false);\n void action.execute();\n }, {capture: true});\n floatingButton.addEventListener('mousedown', ev => {\n ev.stopPropagation();\n }, {capture: true});\n this.aiButtonContainer.appendChild(floatingButton);\n }\n }\n\n override onbind(): void {\n if (this.treeOutline && !this.isClosingTag()) {\n this.treeOutline.treeElementByNode.set(this.nodeInternal, this);\n }\n }\n\n override onunbind(): void {\n if (this.editing) {\n this.editing.cancel();\n }\n if (this.treeOutline && this.treeOutline.treeElementByNode.get(this.nodeInternal) === this) {\n this.treeOutline.treeElementByNode.delete(this.nodeInternal);\n }\n }\n\n override onattach(): void {\n if (this.hoveredInternal) {\n this.createSelection();\n this.listItemElement.classList.add('hovered');\n }\n\n this.updateTitle();\n this.listItemElement.draggable = true;\n }\n\n override async onpopulate(): Promise {\n if (this.treeOutline) {\n return this.treeOutline.populateTreeElement(this);\n }\n }\n\n override async expandRecursively(): Promise {\n await this.nodeInternal.getSubtree(-1, true);\n await super.expandRecursively(Number.MAX_VALUE);\n }\n\n override onexpand(): void {\n if (this.isClosingTag()) {\n return;\n }\n\n this.updateTitle();\n }\n\n override oncollapse(): void {\n if (this.isClosingTag()) {\n return;\n }\n\n this.updateTitle();\n }\n\n override select(omitFocus?: boolean, selectedByUser?: boolean): boolean {\n if (this.editing) {\n return false;\n }\n return super.select(omitFocus, selectedByUser);\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n if (!this.treeOutline) {\n return false;\n }\n this.treeOutline.suppressRevealAndSelect = true;\n this.treeOutline.selectDOMNode(this.nodeInternal, selectedByUser);\n if (selectedByUser) {\n this.nodeInternal.highlight();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.ChangeInspectedNodeInElementsPanel);\n }\n this.createSelection();\n this.createHint();\n this.treeOutline.suppressRevealAndSelect = false;\n return true;\n }\n\n override ondelete(): boolean {\n if (!this.treeOutline) {\n return false;\n }\n const startTagTreeElement = this.treeOutline.findTreeElement(this.nodeInternal);\n startTagTreeElement ? startTagTreeElement.remove() : this.remove();\n return true;\n }\n\n override onenter(): boolean {\n // On Enter or Return start editing the first attribute\n // or create a new attribute on the selected element.\n if (this.editing) {\n return false;\n }\n\n this.startEditing();\n\n // prevent a newline from being immediately inserted\n return true;\n }\n\n override selectOnMouseDown(event: MouseEvent): void {\n super.selectOnMouseDown(event);\n\n if (this.editing) {\n return;\n }\n\n // Prevent selecting the nearest word on double click.\n if (event.detail >= 2) {\n event.preventDefault();\n }\n }\n\n override ondblclick(event: Event): boolean {\n if (this.editing || this.isClosingTag()) {\n return false;\n }\n if (this.startEditingTarget((event.target as Element))) {\n return false;\n }\n\n if (this.isExpandable() && !this.expanded) {\n this.expand();\n }\n return false;\n }\n\n hasEditableNode(): boolean {\n return !this.nodeInternal.isShadowRoot() && !this.nodeInternal.ancestorUserAgentShadowRoot();\n }\n\n private insertInLastAttributePosition(tag: Element, node: Element): void {\n if (tag.getElementsByClassName('webkit-html-attribute').length > 0) {\n tag.insertBefore(node, tag.lastChild);\n } else if (tag.textContent !== null) {\n const matchResult = tag.textContent.match(/^<(.*?)>$/);\n if (!matchResult) {\n return;\n }\n const nodeName = matchResult[1];\n tag.textContent = '';\n UI.UIUtils.createTextChild(tag, '<' + nodeName);\n tag.appendChild(node);\n UI.UIUtils.createTextChild(tag, '>');\n }\n }\n\n private startEditingTarget(eventTarget: Element): boolean {\n if (!this.treeOutline || this.treeOutline.selectedDOMNode() !== this.nodeInternal) {\n return false;\n }\n\n if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE && this.nodeInternal.nodeType() !== Node.TEXT_NODE) {\n return false;\n }\n\n const textNode = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-text-node');\n if (textNode) {\n return this.startEditingTextNode(textNode);\n }\n\n const attribute = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-attribute');\n if (attribute) {\n return this.startEditingAttribute(attribute, eventTarget);\n }\n\n const tagName = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-tag-name');\n if (tagName) {\n return this.startEditingTagName(tagName);\n }\n\n const newAttribute = eventTarget.enclosingNodeOrSelfWithClass('add-attribute');\n if (newAttribute) {\n return this.addNewAttribute();\n }\n\n return false;\n }\n\n private showContextMenu(event: Event): void {\n this.treeOutline && this.treeOutline.showContextMenu(this, event);\n }\n\n populateTagContextMenu(contextMenu: UI.ContextMenu.ContextMenu, event: Event): void {\n // Add attribute-related actions.\n const treeElement =\n this.isClosingTag() && this.treeOutline ? this.treeOutline.findTreeElement(this.nodeInternal) : this;\n if (!treeElement) {\n return;\n }\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.addAttribute), treeElement.addNewAttribute.bind(treeElement),\n {jslogContext: 'add-attribute'});\n\n const target = (event.target as Element);\n const attribute = target.enclosingNodeOrSelfWithClass('webkit-html-attribute');\n const newAttribute = target.enclosingNodeOrSelfWithClass('add-attribute');\n if (attribute && !newAttribute) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.editAttribute), this.startEditingAttribute.bind(this, attribute, target),\n {jslogContext: 'edit-attribute'});\n }\n this.populateNodeContextMenu(contextMenu);\n ElementsTreeElement.populateForcedPseudoStateItems(contextMenu, treeElement.node());\n this.populateScrollIntoView(contextMenu);\n contextMenu.viewSection().appendItem(i18nString(UIStrings.focus), async () => {\n await this.nodeInternal.focus();\n }, {jslogContext: 'focus'});\n }\n\n populatePseudoElementContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n if (this.childCount() !== 0) {\n this.populateExpandRecursively(contextMenu);\n }\n\n this.populateScrollIntoView(contextMenu);\n }\n\n private populateExpandRecursively(contextMenu: UI.ContextMenu.ContextMenu): void {\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.expandRecursively), this.expandRecursively.bind(this),\n {jslogContext: 'expand-recursively'});\n }\n\n private populateScrollIntoView(contextMenu: UI.ContextMenu.ContextMenu): void {\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.scrollIntoView), () => this.nodeInternal.scrollIntoView(),\n {jslogContext: 'scroll-into-view'});\n }\n\n populateTextContextMenu(contextMenu: UI.ContextMenu.ContextMenu, textNode: Element): void {\n if (!this.editing) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.editText), this.startEditingTextNode.bind(this, textNode), {jslogContext: 'edit-text'});\n }\n this.populateNodeContextMenu(contextMenu);\n }\n\n populateNodeContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n // Add free-form node-related actions.\n const isEditable = this.hasEditableNode();\n // clang-format off\n if (isEditable && !this.editing) {\n contextMenu.editSection().appendItem(i18nString(UIStrings.editAsHtml), this.editAsHTML.bind(this), {jslogContext: 'elements.edit-as-html'});\n }\n // clang-format on\n const isShadowRoot = this.nodeInternal.isShadowRoot();\n\n const createShortcut = UI.KeyboardShortcut.KeyboardShortcut.shortcutToString.bind(null);\n const modifier = UI.KeyboardShortcut.Modifiers.CtrlOrMeta.value;\n const treeOutline = this.treeOutline;\n if (!treeOutline) {\n return;\n }\n let menuItem;\n\n if (UI.ActionRegistry.ActionRegistry.instance().hasAction('freestyler.element-panel-context')) {\n contextMenu.headerSection().appendAction(\n 'freestyler.element-panel-context',\n );\n }\n\n menuItem = contextMenu.clipboardSection().appendItem(\n i18nString(UIStrings.cut), treeOutline.performCopyOrCut.bind(treeOutline, true, this.nodeInternal),\n {disabled: !this.hasEditableNode(), jslogContext: 'cut'});\n menuItem.setShortcut(createShortcut('X', modifier));\n\n // Place it here so that all \"Copy\"-ing items stick together.\n const copyMenu = contextMenu.clipboardSection().appendSubMenuItem(i18nString(UIStrings.copy), false, 'copy');\n const section = copyMenu.section();\n if (!isShadowRoot) {\n menuItem = section.appendItem(\n i18nString(UIStrings.copyOuterhtml), treeOutline.performCopyOrCut.bind(treeOutline, false, this.nodeInternal),\n {jslogContext: 'copy-outer-html'});\n menuItem.setShortcut(createShortcut('V', modifier));\n }\n if (this.nodeInternal.nodeType() === Node.ELEMENT_NODE) {\n section.appendItem(\n i18nString(UIStrings.copySelector), this.copyCSSPath.bind(this), {jslogContext: 'copy-selector'});\n section.appendItem(\n i18nString(UIStrings.copyJsPath), this.copyJSPath.bind(this),\n {disabled: !canGetJSPath(this.nodeInternal), jslogContext: 'copy-js-path'});\n section.appendItem(\n i18nString(UIStrings.copyStyles), this.copyStyles.bind(this), {jslogContext: 'elements.copy-styles'});\n }\n if (!isShadowRoot) {\n section.appendItem(i18nString(UIStrings.copyXpath), this.copyXPath.bind(this), {jslogContext: 'copy-xpath'});\n section.appendItem(\n i18nString(UIStrings.copyFullXpath), this.copyFullXPath.bind(this), {jslogContext: 'copy-full-xpath'});\n }\n\n if (!isShadowRoot) {\n menuItem = copyMenu.clipboardSection().appendItem(\n i18nString(UIStrings.copyElement), treeOutline.performCopyOrCut.bind(treeOutline, false, this.nodeInternal),\n {jslogContext: 'copy-element'});\n menuItem.setShortcut(createShortcut('C', modifier));\n\n // Duplicate element, disabled on root element and ShadowDOM.\n const isRootElement = !this.nodeInternal.parentNode || this.nodeInternal.parentNode.nodeName() === '#document';\n menuItem = contextMenu.editSection().appendItem(\n i18nString(UIStrings.duplicateElement), treeOutline.duplicateNode.bind(treeOutline, this.nodeInternal), {\n disabled: (this.nodeInternal.isInShadowTree() || isRootElement),\n jslogContext: 'elements.duplicate-element',\n });\n }\n\n menuItem = contextMenu.clipboardSection().appendItem(\n i18nString(UIStrings.paste), treeOutline.pasteNode.bind(treeOutline, this.nodeInternal),\n {disabled: !treeOutline.canPaste(this.nodeInternal), jslogContext: 'paste'});\n menuItem.setShortcut(createShortcut('V', modifier));\n\n menuItem = contextMenu.debugSection().appendCheckboxItem(\n i18nString(UIStrings.hideElement), treeOutline.toggleHideElement.bind(treeOutline, this.nodeInternal),\n {checked: treeOutline.isToggledToHidden(this.nodeInternal), jslogContext: 'elements.hide-element'});\n menuItem.setShortcut(\n UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutTitleForAction('elements.hide-element') || '');\n\n if (isEditable) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.deleteElement), this.remove.bind(this), {jslogContext: 'delete-element'});\n }\n\n this.populateExpandRecursively(contextMenu);\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.collapseChildren), this.collapseChildren.bind(this), {jslogContext: 'collapse-children'});\n const deviceModeWrapperAction = new Emulation.DeviceModeWrapper.ActionDelegate();\n contextMenu.viewSection().appendItem(\n i18nString(UIStrings.captureNodeScreenshot),\n deviceModeWrapperAction.handleAction.bind(\n null, UI.Context.Context.instance(), 'emulation.capture-node-screenshot'),\n {jslogContext: 'emulation.capture-node-screenshot'});\n if (this.nodeInternal.frameOwnerFrameId()) {\n contextMenu.viewSection().appendItem(i18nString(UIStrings.showFrameDetails), () => {\n const frameOwnerFrameId = this.nodeInternal.frameOwnerFrameId();\n if (frameOwnerFrameId) {\n const frame = SDK.FrameManager.FrameManager.instance().getFrame(frameOwnerFrameId);\n void Common.Revealer.reveal(frame);\n }\n }, {jslogContext: 'show-frame-details'});\n }\n }\n\n private startEditing(): boolean|undefined {\n if (!this.treeOutline || this.treeOutline.selectedDOMNode() !== this.nodeInternal) {\n return;\n }\n\n const listItem = this.listItemElement;\n\n if (isOpeningTag(this.tagTypeContext) && this.tagTypeContext.canAddAttributes) {\n const attribute = listItem.getElementsByClassName('webkit-html-attribute')[0];\n if (attribute) {\n return this.startEditingAttribute(\n attribute, attribute.getElementsByClassName('webkit-html-attribute-value')[0]);\n }\n\n return this.addNewAttribute();\n }\n\n if (this.nodeInternal.nodeType() === Node.TEXT_NODE) {\n const textNode = listItem.getElementsByClassName('webkit-html-text-node')[0];\n if (textNode) {\n return this.startEditingTextNode(textNode);\n }\n }\n\n return;\n }\n\n private addNewAttribute(): boolean {\n // Cannot just convert the textual html into an element without\n // a parent node. Use a temporary span container for the HTML.\n const container = document.createElement('span');\n const attr = this.buildAttributeDOM(container, ' ', '', null);\n attr.style.marginLeft = '2px'; // overrides the .editing margin rule\n attr.style.marginRight = '2px'; // overrides the .editing margin rule\n attr.setAttribute('jslog', `${VisualLogging.value('new-attribute').track({change: true, resize: true})}`);\n\n const tag = this.listItemElement.getElementsByClassName('webkit-html-tag')[0];\n this.insertInLastAttributePosition(tag, attr);\n attr.scrollIntoViewIfNeeded(true);\n return this.startEditingAttribute(attr, attr);\n }\n\n private triggerEditAttribute(attributeName: string): boolean|undefined {\n const attributeElements = this.listItemElement.getElementsByClassName('webkit-html-attribute-name');\n for (let i = 0, len = attributeElements.length; i < len; ++i) {\n if (attributeElements[i].textContent === attributeName) {\n for (let elem: (ChildNode|null) = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {\n if (elem.nodeType !== Node.ELEMENT_NODE) {\n continue;\n }\n if ((elem as Element).classList.contains('webkit-html-attribute-value')) {\n return this.startEditingAttribute((elem.parentElement as HTMLElement), (elem as Element));\n }\n }\n }\n }\n\n return;\n }\n\n private startEditingAttribute(attribute: Element, elementForSelection: Element): boolean {\n console.assert(this.listItemElement.isAncestor(attribute));\n\n if (UI.UIUtils.isBeingEdited(attribute)) {\n return true;\n }\n\n const attributeNameElement = attribute.getElementsByClassName('webkit-html-attribute-name')[0];\n if (!attributeNameElement) {\n return false;\n }\n\n const attributeName = attributeNameElement.textContent;\n const attributeValueElement = attribute.getElementsByClassName('webkit-html-attribute-value')[0];\n\n // Make sure elementForSelection is not a child of attributeValueElement.\n elementForSelection =\n attributeValueElement.isAncestor(elementForSelection) ? attributeValueElement : elementForSelection;\n\n function removeZeroWidthSpaceRecursive(node: Node): void {\n if (node.nodeType === Node.TEXT_NODE) {\n node.nodeValue = node.nodeValue ? node.nodeValue.replace(/\\u200B/g, '') : '';\n return;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return;\n }\n\n for (let child: (ChildNode|null) = node.firstChild; child; child = child.nextSibling) {\n removeZeroWidthSpaceRecursive(child);\n }\n }\n\n const attributeValue = attributeName && attributeValueElement ?\n this.nodeInternal.getAttribute(attributeName)?.replaceAll('\"', '"') :\n undefined;\n if (attributeValue !== undefined) {\n attributeValueElement.setTextContentTruncatedIfNeeded(\n attributeValue, i18nString(UIStrings.valueIsTooLargeToEdit));\n }\n\n // Remove zero-width spaces that were added by nodeTitleInfo.\n removeZeroWidthSpaceRecursive(attribute);\n\n const config = new UI.InplaceEditor.Config(\n this.attributeEditingCommitted.bind(this), this.editingCancelled.bind(this), attributeName);\n\n function postKeyDownFinishHandler(event: Event): string {\n UI.UIUtils.handleElementValueModifications(event, attribute);\n return '';\n }\n\n if (!Common.ParsedURL.ParsedURL.fromString(attributeValueElement.textContent || '')) {\n config.setPostKeydownFinishHandler(postKeyDownFinishHandler);\n }\n\n this.updateEditorHandles(attribute, config);\n\n const componentSelection = this.listItemElement.getComponentSelection();\n componentSelection && componentSelection.selectAllChildren(elementForSelection);\n\n return true;\n }\n\n private startEditingTextNode(textNodeElement: Element): boolean {\n if (UI.UIUtils.isBeingEdited(textNodeElement)) {\n return true;\n }\n\n let textNode: SDK.DOMModel.DOMNode = this.nodeInternal;\n // We only show text nodes inline in elements if the element only\n // has a single child, and that child is a text node.\n if (textNode.nodeType() === Node.ELEMENT_NODE && textNode.firstChild) {\n textNode = textNode.firstChild;\n }\n\n const container = textNodeElement.enclosingNodeOrSelfWithClass('webkit-html-text-node');\n if (container) {\n container.textContent = textNode.nodeValue();\n } // Strip the CSS or JS highlighting if present.\n const config = new UI.InplaceEditor.Config(\n this.textNodeEditingCommitted.bind(this, textNode), this.editingCancelled.bind(this), null);\n this.updateEditorHandles(textNodeElement, config);\n const componentSelection = this.listItemElement.getComponentSelection();\n componentSelection && componentSelection.selectAllChildren(textNodeElement);\n\n return true;\n }\n\n private startEditingTagName(tagNameElement?: Element): boolean {\n if (!tagNameElement) {\n tagNameElement = this.listItemElement.getElementsByClassName('webkit-html-tag-name')[0];\n if (!tagNameElement) {\n return false;\n }\n }\n\n const tagName = tagNameElement.textContent;\n if (tagName !== null && EditTagBlocklist.has(tagName.toLowerCase())) {\n return false;\n }\n\n if (UI.UIUtils.isBeingEdited(tagNameElement)) {\n return true;\n }\n\n const closingTagElement = this.distinctClosingTagElement();\n\n function keyupListener(): void {\n if (closingTagElement && tagNameElement) {\n closingTagElement.textContent = '';\n }\n }\n\n const keydownListener = (event: Event): void => {\n if ((event as KeyboardEvent).key !== ' ') {\n return;\n }\n this.editing && this.editing.commit();\n event.consume(true);\n };\n\n function editingCommitted(\n this: ElementsTreeElement,\n element: Element,\n newTagName: string,\n oldText: string|null,\n tagName: string|null,\n moveDirection: string,\n ): void {\n if (!tagNameElement) {\n return;\n }\n tagNameElement.removeEventListener('keyup', keyupListener, false);\n tagNameElement.removeEventListener('keydown', keydownListener, false);\n this.tagNameEditingCommitted(element, newTagName, oldText, tagName, moveDirection);\n }\n\n function editingCancelled(this: ElementsTreeElement, element: Element, tagName: string|null): void {\n if (!tagNameElement) {\n return;\n }\n tagNameElement.removeEventListener('keyup', keyupListener, false);\n tagNameElement.removeEventListener('keydown', keydownListener, false);\n this.editingCancelled(element, tagName);\n }\n\n tagNameElement.addEventListener('keyup', keyupListener, false);\n tagNameElement.addEventListener('keydown', keydownListener, false);\n\n const config =\n new UI.InplaceEditor.Config(editingCommitted.bind(this), editingCancelled.bind(this), tagName);\n this.updateEditorHandles(tagNameElement, config);\n const componentSelection = this.listItemElement.getComponentSelection();\n componentSelection && componentSelection.selectAllChildren(tagNameElement);\n return true;\n }\n\n private updateEditorHandles(element: Element, config: UI.InplaceEditor.Config): void {\n const editorHandles = UI.InplaceEditor.InplaceEditor.startEditing(element, config);\n if (!editorHandles) {\n this.editing = null;\n } else {\n this.editing = {\n commit: editorHandles.commit,\n cancel: editorHandles.cancel,\n editor: undefined,\n resize: () => {},\n };\n }\n }\n\n private async startEditingAsHTML(\n commitCallback: (arg0: string, arg1: string) => void, disposeCallback: () => void,\n maybeInitialValue: string|null): Promise {\n if (maybeInitialValue === null) {\n return;\n }\n if (this.editing) {\n return;\n }\n\n const initialValue = this.convertWhitespaceToEntities(maybeInitialValue).text;\n this.htmlEditElement = document.createElement('div');\n this.htmlEditElement.className = 'source-code elements-tree-editor';\n\n // Hide header items.\n let child: (ChildNode|null) = this.listItemElement.firstChild;\n while (child) {\n (child as HTMLElement).style.display = 'none';\n child = child.nextSibling;\n }\n // Hide children item.\n if (this.childrenListElement) {\n this.childrenListElement.style.display = 'none';\n }\n // Append editor.\n this.listItemElement.append(this.htmlEditElement);\n this.htmlEditElement.addEventListener('keydown', event => {\n if (event.key === 'Escape') {\n event.consume(true);\n }\n });\n\n const editor = new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({\n doc: initialValue,\n extensions: [\n CodeMirror.keymap.of([\n {\n key: 'Mod-Enter',\n run: () => {\n this.editing?.commit();\n return true;\n },\n },\n {\n key: 'Escape',\n run: () => {\n this.editing?.cancel();\n return true;\n },\n },\n ]),\n TextEditor.Config.baseConfiguration(initialValue),\n TextEditor.Config.closeBrackets.instance(),\n TextEditor.Config.autocompletion.instance(),\n CodeMirror.html.html({autoCloseTags: false, selfClosingTags: true}),\n TextEditor.Config.domWordWrap.instance(),\n CodeMirror.EditorView.theme({\n '&.cm-editor': {maxHeight: '300px'},\n '.cm-scroller': {overflowY: 'auto'},\n }),\n CodeMirror.EditorView.domEventHandlers({\n focusout: event => {\n // The relatedTarget is null when no element gains focus, e.g. switching windows.\n const relatedTarget = (event.relatedTarget as Node | null);\n if (relatedTarget && !relatedTarget.isSelfOrDescendant(editor)) {\n this.editing && this.editing.commit();\n }\n },\n }),\n ],\n }));\n this.editing = {commit: commit.bind(this), cancel: dispose.bind(this), editor, resize: resize.bind(this)};\n resize.call(this);\n this.htmlEditElement.appendChild(editor);\n editor.editor.focus();\n\n this.treeOutline && this.treeOutline.setMultilineEditing(this.editing);\n\n function resize(this: ElementsTreeElement): void {\n if (this.treeOutline && this.htmlEditElement) {\n this.htmlEditElement.style.width = this.treeOutline.visibleWidth() - this.computeLeftIndent() - 30 + 'px';\n }\n }\n\n function commit(this: ElementsTreeElement): void {\n if (this.editing && this.editing.editor) {\n commitCallback(initialValue, this.editing.editor.state.doc.toString());\n }\n dispose.call(this);\n }\n\n function dispose(this: ElementsTreeElement): void {\n if (!this.editing || !this.editing.editor) {\n return;\n }\n this.editing = null;\n\n // Remove editor.\n if (this.htmlEditElement) {\n this.listItemElement.removeChild(this.htmlEditElement);\n }\n this.htmlEditElement = undefined;\n // Unhide children item.\n if (this.childrenListElement) {\n this.childrenListElement.style.removeProperty('display');\n }\n // Unhide header items.\n let child: (ChildNode|null) = this.listItemElement.firstChild;\n while (child) {\n (child as HTMLElement).style.removeProperty('display');\n child = child.nextSibling;\n }\n\n if (this.treeOutline) {\n this.treeOutline.setMultilineEditing(null);\n this.treeOutline.focus();\n }\n\n disposeCallback();\n }\n }\n\n private attributeEditingCommitted(\n element: Element,\n newText: string,\n oldText: string|null,\n attributeName: string|null,\n moveDirection: string,\n ): void {\n this.editing = null;\n\n const treeOutline = this.treeOutline;\n\n function moveToNextAttributeIfNeeded(this: ElementsTreeElement, error?: string|null): void {\n if (error) {\n this.editingCancelled(element, attributeName);\n }\n\n if (!moveDirection) {\n return;\n }\n\n if (treeOutline) {\n treeOutline.runPendingUpdates();\n treeOutline.focus();\n }\n\n // Search for the attribute's position, and then decide where to move to.\n const attributes = this.nodeInternal.attributes();\n for (let i = 0; i < attributes.length; ++i) {\n if (attributes[i].name !== attributeName) {\n continue;\n }\n\n if (moveDirection === 'backward') {\n if (i === 0) {\n this.startEditingTagName();\n } else {\n this.triggerEditAttribute(attributes[i - 1].name);\n }\n } else {\n if (i === attributes.length - 1) {\n this.addNewAttribute();\n } else {\n this.triggerEditAttribute(attributes[i + 1].name);\n }\n }\n return;\n }\n\n // Moving From the \"New Attribute\" position.\n if (moveDirection === 'backward') {\n if (newText === ' ') {\n // Moving from \"New Attribute\" that was not edited\n if (attributes.length > 0) {\n this.triggerEditAttribute(attributes[attributes.length - 1].name);\n }\n } else {\n // Moving from \"New Attribute\" that holds new value\n if (attributes.length > 1) {\n this.triggerEditAttribute(attributes[attributes.length - 2].name);\n }\n }\n } else if (moveDirection === 'forward') {\n if (!Platform.StringUtilities.isWhitespace(newText)) {\n this.addNewAttribute();\n } else {\n this.startEditingTagName();\n }\n }\n }\n\n if (attributeName !== null && (attributeName.trim() || newText.trim()) && oldText !== newText) {\n this.nodeInternal.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));\n return;\n }\n\n this.updateTitle();\n moveToNextAttributeIfNeeded.call(this);\n }\n\n private tagNameEditingCommitted(\n element: Element,\n newText: string,\n oldText: string|null,\n tagName: string|null,\n moveDirection: string,\n ): void {\n this.editing = null;\n const self = this;\n\n function cancel(): void {\n const closingTagElement = self.distinctClosingTagElement();\n if (closingTagElement) {\n closingTagElement.textContent = '';\n }\n\n self.editingCancelled(element, tagName);\n moveToNextAttributeIfNeeded.call(self);\n }\n\n function moveToNextAttributeIfNeeded(this: ElementsTreeElement): void {\n if (moveDirection !== 'forward') {\n this.addNewAttribute();\n return;\n }\n\n const attributes = this.nodeInternal.attributes();\n if (attributes.length > 0) {\n this.triggerEditAttribute(attributes[0].name);\n } else {\n this.addNewAttribute();\n }\n }\n\n newText = newText.trim();\n if (newText === oldText) {\n cancel();\n return;\n }\n\n const treeOutline = this.treeOutline;\n const wasExpanded = this.expanded;\n\n this.nodeInternal.setNodeName(newText, (error, newNode) => {\n if (error || !newNode) {\n cancel();\n return;\n }\n if (!treeOutline) {\n return;\n }\n const newTreeItem = treeOutline.selectNodeAfterEdit(wasExpanded, error, newNode);\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n moveToNextAttributeIfNeeded.call(newTreeItem);\n });\n }\n\n private textNodeEditingCommitted(textNode: SDK.DOMModel.DOMNode, element: Element, newText: string): void {\n this.editing = null;\n\n function callback(this: ElementsTreeElement): void {\n this.updateTitle();\n }\n textNode.setNodeValue(newText, callback.bind(this));\n }\n\n private editingCancelled(_element: Element, _tagName: string|null): void {\n this.editing = null;\n\n // Need to restore attributes structure.\n this.updateTitle();\n }\n\n private distinctClosingTagElement(): Element|null {\n // FIXME: Improve the Tree Element / Outline Abstraction to prevent crawling the DOM\n\n // For an expanded element, it will be the last element with class \"close\"\n // in the child element list.\n if (this.expanded) {\n const closers = this.childrenListElement.querySelectorAll('.close');\n return closers[closers.length - 1];\n }\n\n // Remaining cases are single line non-expanded elements with a closing\n // tag, or HTML elements without a closing tag (such as
). Return\n // null in the case where there isn't a closing tag.\n const tags = this.listItemElement.getElementsByClassName('webkit-html-tag');\n return tags.length === 1 ? null : tags[tags.length - 1];\n }\n\n updateTitle(updateRecord?: UpdateRecord|null): void {\n // If we are editing, return early to prevent canceling the edit.\n // After editing is committed updateTitle will be called.\n if (this.editing) {\n return;\n }\n\n const nodeInfo = this.nodeTitleInfo(updateRecord || null);\n if (this.nodeInternal.nodeType() === Node.DOCUMENT_FRAGMENT_NODE && this.nodeInternal.isInShadowTree() &&\n this.nodeInternal.shadowRootType()) {\n this.childrenListElement.classList.add('shadow-root');\n let depth = 4;\n for (let node: (SDK.DOMModel.DOMNode|null) = (this.nodeInternal as SDK.DOMModel.DOMNode | null); depth && node;\n node = node.parentNode) {\n if (node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE) {\n depth--;\n }\n }\n if (!depth) {\n this.childrenListElement.classList.add('shadow-root-deep');\n } else {\n this.childrenListElement.classList.add('shadow-root-depth-' + depth);\n }\n }\n this.contentElement.removeChildren();\n const highlightElement = this.contentElement.createChild('span', 'highlight');\n highlightElement.append(nodeInfo);\n // fixme: make it clear that `this.title = x` is a setter with significant side effects\n this.title = this.contentElement;\n this.updateDecorations();\n this.contentElement.prepend(this.gutterContainer);\n if (isOpeningTag(this.tagTypeContext)) {\n this.contentElement.append(this.tagTypeContext.adornerContainer);\n if (this.tagTypeContext.slot) {\n this.contentElement.append(this.tagTypeContext.slot);\n }\n }\n delete this.selectionElement;\n delete this.hintElement;\n delete this.aiButtonContainer;\n if (this.selected) {\n this.createSelection();\n this.createHint();\n }\n\n // If there is an issue with this node, make sure to update it.\n for (const issue of this.#elementIssues.values()) {\n this.#applyIssueStyleAndTooltip(issue);\n }\n\n this.highlightSearchResultsInternal();\n }\n\n private computeLeftIndent(): number {\n let treeElement: (UI.TreeOutline.TreeElement|null) = this.parent;\n let depth = 0;\n while (treeElement !== null) {\n depth++;\n treeElement = treeElement.parent;\n }\n\n /** Keep it in sync with elementsTreeOutline.css **/\n return 12 * (depth - 2) + (this.isExpandable() && this.isCollapsible() ? 1 : 12);\n }\n\n updateDecorations(): void {\n const indent = this.computeLeftIndent();\n this.gutterContainer.style.left = (-indent) + 'px';\n this.listItemElement.style.setProperty('--indent', indent + 'px');\n\n if (this.isClosingTag()) {\n return;\n }\n\n if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE) {\n return;\n }\n\n void this.decorationsThrottler.schedule(this.updateDecorationsInternal.bind(this));\n }\n\n private updateDecorationsInternal(): Promise {\n if (!this.treeOutline) {\n return Promise.resolve();\n }\n\n const node = this.nodeInternal;\n\n if (!this.treeOutline.decoratorExtensions) {\n this.treeOutline.decoratorExtensions = getRegisteredDecorators();\n }\n\n const markerToExtension = new Map();\n for (const decoratorExtension of this.treeOutline.decoratorExtensions) {\n markerToExtension.set(decoratorExtension.marker, decoratorExtension);\n }\n\n const promises: Promise[] = [];\n const decorations: {\n title: string,\n color: string,\n }[] = [];\n const descendantDecorations: {\n title: string,\n color: string,\n }[] = [];\n node.traverseMarkers(visitor);\n\n function visitor(n: SDK.DOMModel.DOMNode, marker: string): void {\n const extension = markerToExtension.get(marker);\n if (!extension) {\n return;\n }\n promises.push(Promise.resolve(extension.decorator()).then(collectDecoration.bind(null, n)));\n }\n\n function collectDecoration(n: SDK.DOMModel.DOMNode, decorator: MarkerDecorator): void {\n const decoration = decorator.decorate(n);\n if (!decoration) {\n return;\n }\n (n === node ? decorations : descendantDecorations).push(decoration);\n }\n\n return Promise.all(promises).then(updateDecorationsUI.bind(this));\n\n function updateDecorationsUI(this: ElementsTreeElement): void {\n this.decorationsElement.removeChildren();\n this.decorationsElement.classList.add('hidden');\n this.gutterContainer.classList.toggle(\n 'has-decorations', Boolean(decorations.length || descendantDecorations.length));\n UI.ARIAUtils.setLabel(this.decorationsElement, '');\n\n if (!decorations.length && !descendantDecorations.length) {\n return;\n }\n\n const colors = new Set();\n const titles = document.createElement('div');\n\n for (const decoration of decorations) {\n const titleElement = titles.createChild('div');\n titleElement.textContent = decoration.title;\n colors.add(decoration.color);\n }\n if (this.expanded && !decorations.length) {\n return;\n }\n\n const descendantColors = new Set();\n if (descendantDecorations.length) {\n let element = titles.createChild('div');\n element.textContent = i18nString(UIStrings.children);\n for (const decoration of descendantDecorations) {\n element = titles.createChild('div');\n element.style.marginLeft = '15px';\n element.textContent = decoration.title;\n descendantColors.add(decoration.color);\n }\n }\n\n let offset = 0;\n processColors.call(this, colors, 'elements-gutter-decoration');\n if (!this.expanded) {\n processColors.call(this, descendantColors, 'elements-gutter-decoration elements-has-decorated-children');\n }\n UI.Tooltip.Tooltip.install(this.decorationsElement, titles.textContent);\n UI.ARIAUtils.setLabel(this.decorationsElement, titles.textContent || '');\n\n function processColors(this: ElementsTreeElement, colors: Set, className: string): void {\n for (const color of colors) {\n const child = this.decorationsElement.createChild('div', className);\n this.decorationsElement.classList.remove('hidden');\n child.style.backgroundColor = color;\n child.style.borderColor = color;\n if (offset) {\n child.style.marginLeft = offset + 'px';\n }\n offset += 3;\n }\n }\n }\n }\n\n private buildAttributeDOM(\n parentElement: Element|DocumentFragment, name: string, value: string, updateRecord: UpdateRecord|null,\n forceValue?: boolean, node?: SDK.DOMModel.DOMNode): HTMLElement {\n const closingPunctuationRegex = /[\\/;:\\)\\]\\}]/g;\n let highlightIndex = 0;\n let highlightCount = 0;\n let additionalHighlightOffset = 0;\n\n function setValueWithEntities(this: ElementsTreeElement, element: Element, value: string): void {\n const result = this.convertWhitespaceToEntities(value);\n highlightCount = result.entityRanges.length;\n value = result.text.replace(closingPunctuationRegex, (match, replaceOffset) => {\n while (highlightIndex < highlightCount && result.entityRanges[highlightIndex].offset < replaceOffset) {\n result.entityRanges[highlightIndex].offset += additionalHighlightOffset;\n ++highlightIndex;\n }\n additionalHighlightOffset += 1;\n return match + '\\u200B';\n });\n\n while (highlightIndex < highlightCount) {\n result.entityRanges[highlightIndex].offset += additionalHighlightOffset;\n ++highlightIndex;\n }\n element.setTextContentTruncatedIfNeeded(value);\n UI.UIUtils.highlightRangesWithStyleClass(element, result.entityRanges, 'webkit-html-entity-value');\n }\n\n const hasText = (forceValue || value.length > 0);\n const attrSpanElement = (parentElement.createChild('span', 'webkit-html-attribute') as HTMLElement);\n attrSpanElement.setAttribute(\n 'jslog', `${VisualLogging.value(name === 'style' ? 'style-attribute' : 'attribute').track({\n change: true,\n dblclick: true,\n })}`);\n\n const attrNameElement = attrSpanElement.createChild('span', 'webkit-html-attribute-name');\n attrNameElement.textContent = name;\n\n if (hasText) {\n UI.UIUtils.createTextChild(attrSpanElement, '=\\u200B\"');\n }\n\n const attrValueElement = attrSpanElement.createChild('span', 'webkit-html-attribute-value');\n\n if (updateRecord && updateRecord.isAttributeModified(name)) {\n UI.UIUtils.runCSSAnimationOnce(hasText ? attrValueElement : attrNameElement, 'dom-update-highlight');\n }\n\n function linkifyValue(this: ElementsTreeElement, value: string): Element {\n const rewrittenHref = node ? node.resolveURL(value) : null;\n if (rewrittenHref === null) {\n const span = document.createElement('span');\n setValueWithEntities.call(this, span, value);\n return span;\n }\n value = value.replace(closingPunctuationRegex, '$&\\u200B');\n if (value.startsWith('data:')) {\n value = Platform.StringUtilities.trimMiddle(value, 60);\n }\n const link = node && node.nodeName().toLowerCase() === 'a' ?\n UI.XLink.XLink.create(rewrittenHref, value, '', true /* preventClick */, 'image-url') :\n Components.Linkifier.Linkifier.linkifyURL(rewrittenHref, {\n text: value,\n preventClick: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n });\n return ImagePreviewPopover.setImageUrl(link, rewrittenHref);\n }\n\n const nodeName = node ? node.nodeName().toLowerCase() : '';\n // If the href/src attribute has a value, attempt to link it.\n // There's no point trying to link it if the value is empty (e.g.
).\n if (nodeName && (name === 'src' || name === 'href') && value) {\n attrValueElement.appendChild(linkifyValue.call(this, value));\n } else if ((nodeName === 'img' || nodeName === 'source') && name === 'srcset') {\n attrValueElement.appendChild(linkifySrcset.call(this, value));\n } else if (nodeName === 'image' && (name === 'xlink:href' || name === 'href')) {\n attrValueElement.appendChild(linkifySrcset.call(this, value));\n } else {\n setValueWithEntities.call(this, attrValueElement, value);\n }\n\n if (name === 'popovertarget') {\n const linkedPart = value ? attrValueElement : attrNameElement;\n void this.linkifyElementByRelation(\n linkedPart, Protocol.DOM.GetElementByRelationRequestRelation.PopoverTarget,\n i18nString(UIStrings.showPopoverTarget));\n }\n\n if (hasText) {\n UI.UIUtils.createTextChild(attrSpanElement, '\"');\n }\n\n function linkifySrcset(this: ElementsTreeElement, value: string): DocumentFragment {\n // Splitting normally on commas or spaces will break on valid srcsets \"foo 1x,bar 2x\" and \"data:,foo 1x\".\n // 1) Let the index of the next space be `indexOfSpace`.\n // 2a) If the character at `indexOfSpace - 1` is a comma, collect the preceding characters up to\n // `indexOfSpace - 1` as a URL and repeat step 1).\n // 2b) Else, collect the preceding characters as a URL.\n // 3) Collect the characters from `indexOfSpace` up to the next comma as the size descriptor and repeat step 1).\n // https://html.spec.whatwg.org/C/#parse-a-srcset-attribute\n const fragment = document.createDocumentFragment();\n let i = 0;\n while (value.length) {\n if (i++ > 0) {\n UI.UIUtils.createTextChild(fragment, ' ');\n }\n value = value.trim();\n // The url and descriptor may end with a separating comma.\n let url = '';\n let descriptor = '';\n const indexOfSpace = value.search(/\\s/);\n if (indexOfSpace === -1) {\n url = value;\n } else if (indexOfSpace > 0 && value[indexOfSpace - 1] === ',') {\n url = value.substring(0, indexOfSpace);\n } else {\n url = value.substring(0, indexOfSpace);\n const indexOfComma = value.indexOf(',', indexOfSpace);\n if (indexOfComma !== -1) {\n descriptor = value.substring(indexOfSpace, indexOfComma + 1);\n } else {\n descriptor = value.substring(indexOfSpace);\n }\n }\n\n if (url) {\n // Up to one trailing comma should be removed from `url`.\n if (url.endsWith(',')) {\n fragment.appendChild(linkifyValue.call(this, url.substring(0, url.length - 1)));\n UI.UIUtils.createTextChild(fragment, ',');\n } else {\n fragment.appendChild(linkifyValue.call(this, url));\n }\n }\n if (descriptor) {\n UI.UIUtils.createTextChild(fragment, descriptor);\n }\n value = value.substring(url.length + descriptor.length);\n }\n return fragment;\n }\n\n return attrSpanElement;\n }\n\n private async linkifyElementByRelation(\n linkContainer: Element, relation: Protocol.DOM.GetElementByRelationRequestRelation,\n tooltip: string): Promise {\n const relatedElementId = await this.nodeInternal.domModel().getElementByRelation(this.nodeInternal.id, relation);\n const relatedElement = this.nodeInternal.domModel().nodeForId(relatedElementId);\n if (!relatedElement) {\n return;\n }\n const link = await Common.Linkifier.Linkifier.linkify(relatedElement, {\n preventKeyboardFocus: true,\n tooltip,\n textContent: linkContainer.textContent || undefined,\n isDynamicLink: true,\n });\n linkContainer.removeChildren();\n linkContainer.append(link);\n }\n\n private buildPseudoElementDOM(parentElement: DocumentFragment, pseudoElementName: string): void {\n const pseudoElement = parentElement.createChild('span', 'webkit-html-pseudo-element');\n pseudoElement.textContent = '::' + pseudoElementName;\n UI.UIUtils.createTextChild(parentElement, '\\u200B');\n }\n\n private buildTagDOM(\n parentElement: DocumentFragment, tagName: string, isClosingTag: boolean, isDistinctTreeElement: boolean,\n updateRecord: UpdateRecord|null): void {\n const node = this.nodeInternal;\n const classes = ['webkit-html-tag'];\n if (isClosingTag && isDistinctTreeElement) {\n classes.push('close');\n }\n const tagElement = parentElement.createChild('span', classes.join(' '));\n UI.UIUtils.createTextChild(tagElement, '<');\n const tagNameElement =\n tagElement.createChild('span', isClosingTag ? 'webkit-html-close-tag-name' : 'webkit-html-tag-name');\n if (!isClosingTag) {\n tagNameElement.setAttribute('jslog', `${VisualLogging.value('tag-name').track({change: true, dblclick: true})}`);\n }\n tagNameElement.textContent = (isClosingTag ? '/' : '') + tagName;\n if (!isClosingTag) {\n if (node.hasAttributes()) {\n const attributes = node.attributes();\n for (let i = 0; i < attributes.length; ++i) {\n const attr = attributes[i];\n UI.UIUtils.createTextChild(tagElement, ' ');\n this.buildAttributeDOM(tagElement, attr.name, attr.value, updateRecord, false, node);\n }\n }\n if (updateRecord) {\n let hasUpdates: boolean = updateRecord.hasRemovedAttributes() || updateRecord.hasRemovedChildren();\n hasUpdates = hasUpdates || (!this.expanded && updateRecord.hasChangedChildren());\n if (hasUpdates) {\n UI.UIUtils.runCSSAnimationOnce(tagNameElement, 'dom-update-highlight');\n }\n }\n }\n\n UI.UIUtils.createTextChild(tagElement, '>');\n UI.UIUtils.createTextChild(parentElement, '\\u200B');\n if (tagElement.textContent) {\n UI.ARIAUtils.setLabel(tagElement, tagElement.textContent);\n }\n }\n\n private convertWhitespaceToEntities(text: string): {\n text: string,\n entityRanges: Array,\n } {\n let result = '';\n let lastIndexAfterEntity = 0;\n const entityRanges = [];\n const charToEntity = MappedCharToEntity;\n for (let i = 0, size = text.length; i < size; ++i) {\n const char = text.charAt(i);\n if (charToEntity.has(char)) {\n result += text.substring(lastIndexAfterEntity, i);\n const entityValue = '&' + charToEntity.get(char) + ';';\n entityRanges.push(new TextUtils.TextRange.SourceRange(result.length, entityValue.length));\n result += entityValue;\n lastIndexAfterEntity = i + 1;\n }\n }\n if (result) {\n result += text.substring(lastIndexAfterEntity);\n }\n return {text: result || text, entityRanges};\n }\n\n private nodeTitleInfo(updateRecord: UpdateRecord|null): DocumentFragment {\n const node = this.nodeInternal;\n const titleDOM = document.createDocumentFragment();\n const updateSearchHighlight = (): void => {\n this.highlightSearchResultsInternal();\n };\n\n switch (node.nodeType()) {\n case Node.ATTRIBUTE_NODE:\n this.buildAttributeDOM(titleDOM, (node.name as string), (node.value as string), updateRecord, true);\n break;\n\n case Node.ELEMENT_NODE: {\n let pseudoElementName = node.pseudoType();\n if (pseudoElementName) {\n const pseudoIdentifier = node.pseudoIdentifier();\n if (pseudoIdentifier) {\n pseudoElementName += `(${pseudoIdentifier})`;\n }\n this.buildPseudoElementDOM(titleDOM, pseudoElementName);\n break;\n }\n\n const tagName = node.nodeNameInCorrectCase();\n if (this.isClosingTag()) {\n this.buildTagDOM(titleDOM, tagName, true, true, updateRecord);\n break;\n }\n\n this.buildTagDOM(titleDOM, tagName, false, false, updateRecord);\n\n if (this.isExpandable()) {\n if (!this.expanded) {\n const expandButton = new ElementsComponents.ElementsTreeExpandButton.ElementsTreeExpandButton();\n expandButton.data = {\n clickHandler: () => this.expand(),\n };\n titleDOM.appendChild(expandButton);\n\n // This hidden span with … is for blink layout tests.\n // The method dumpElementsTree(front_end/legacy_test_runner/elements_test_runner/ElementsTestRunner.js)\n // dumps … to identify expandable element.\n const hidden = document.createElement('span');\n hidden.textContent = '…';\n hidden.style.fontSize = '0';\n titleDOM.appendChild(hidden);\n\n UI.UIUtils.createTextChild(titleDOM, '\\u200B');\n this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);\n }\n break;\n }\n\n if (ElementsTreeElement.canShowInlineText(node)) {\n const textNodeElement = titleDOM.createChild('span', 'webkit-html-text-node');\n textNodeElement.setAttribute(\n 'jslog', `${VisualLogging.value('text-node').track({change: true, dblclick: true})}`);\n const firstChild = node.firstChild;\n if (!firstChild) {\n throw new Error('ElementsTreeElement._nodeTitleInfo expects node.firstChild to be defined.');\n }\n const result = this.convertWhitespaceToEntities(firstChild.nodeValue());\n textNodeElement.textContent = Platform.StringUtilities.collapseWhitespace(result.text);\n UI.UIUtils.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, 'webkit-html-entity-value');\n UI.UIUtils.createTextChild(titleDOM, '\\u200B');\n this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);\n if (updateRecord && updateRecord.hasChangedChildren()) {\n UI.UIUtils.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');\n }\n if (updateRecord && updateRecord.isCharDataModified()) {\n UI.UIUtils.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');\n }\n break;\n }\n\n if (this.treeOutline && this.treeOutline.isXMLMimeType || !ForbiddenClosingTagElements.has(tagName)) {\n this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);\n }\n break;\n }\n\n case Node.TEXT_NODE:\n if (node.parentNode && node.parentNode.nodeName().toLowerCase() === 'script') {\n const newNode = titleDOM.createChild('span', 'webkit-html-text-node webkit-html-js-node');\n newNode.setAttribute(\n 'jslog', `${VisualLogging.value('script-text-node').track({change: true, dblclick: true})}`);\n const text = node.nodeValue();\n newNode.textContent = text.replace(/^[\\n\\r]+|\\s+$/g, '');\n void CodeHighlighter.CodeHighlighter.highlightNode(newNode, 'text/javascript').then(updateSearchHighlight);\n } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === 'style') {\n const newNode = titleDOM.createChild('span', 'webkit-html-text-node webkit-html-css-node');\n newNode.setAttribute(\n 'jslog', `${VisualLogging.value('css-text-node').track({change: true, dblclick: true})}`);\n const text = node.nodeValue();\n newNode.textContent = text.replace(/^[\\n\\r]+|\\s+$/g, '');\n void CodeHighlighter.CodeHighlighter.highlightNode(newNode, 'text/css').then(updateSearchHighlight);\n } else {\n UI.UIUtils.createTextChild(titleDOM, '\"');\n const textNodeElement = titleDOM.createChild('span', 'webkit-html-text-node');\n textNodeElement.setAttribute(\n 'jslog', `${VisualLogging.value('text-node').track({change: true, dblclick: true})}`);\n const result = this.convertWhitespaceToEntities(node.nodeValue());\n textNodeElement.textContent = Platform.StringUtilities.collapseWhitespace(result.text);\n UI.UIUtils.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, 'webkit-html-entity-value');\n UI.UIUtils.createTextChild(titleDOM, '\"');\n if (updateRecord && updateRecord.isCharDataModified()) {\n UI.UIUtils.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');\n }\n }\n break;\n\n case Node.COMMENT_NODE: {\n const commentElement = titleDOM.createChild('span', 'webkit-html-comment');\n UI.UIUtils.createTextChild(commentElement, '');\n break;\n }\n\n case Node.DOCUMENT_TYPE_NODE: {\n const docTypeElement = titleDOM.createChild('span', 'webkit-html-doctype');\n UI.UIUtils.createTextChild(docTypeElement, '');\n break;\n }\n\n case Node.CDATA_SECTION_NODE: {\n const cdataElement = titleDOM.createChild('span', 'webkit-html-text-node');\n UI.UIUtils.createTextChild(cdataElement, '');\n break;\n }\n\n case Node.DOCUMENT_NODE: {\n const documentElement = titleDOM.createChild('span');\n UI.UIUtils.createTextChild(documentElement, '#document (');\n const text = (node as SDK.DOMModel.DOMDocument).documentURL;\n documentElement.appendChild(Components.Linkifier.Linkifier.linkifyURL(text, {\n text,\n preventClick: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n }));\n UI.UIUtils.createTextChild(documentElement, ')');\n break;\n }\n\n case Node.DOCUMENT_FRAGMENT_NODE: {\n const fragmentElement = titleDOM.createChild('span', 'webkit-html-fragment');\n fragmentElement.textContent = Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase());\n break;\n }\n\n default: {\n const nameWithSpaceCollapsed = Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase());\n UI.UIUtils.createTextChild(titleDOM, nameWithSpaceCollapsed);\n }\n }\n\n return titleDOM;\n }\n\n remove(): void {\n if (this.nodeInternal.pseudoType()) {\n return;\n }\n const parentElement = this.parent;\n if (!parentElement) {\n return;\n }\n\n if (!this.nodeInternal.parentNode || this.nodeInternal.parentNode.nodeType() === Node.DOCUMENT_NODE) {\n return;\n }\n void this.nodeInternal.removeNode();\n }\n\n toggleEditAsHTML(callback?: ((arg0: boolean) => void), startEditing?: boolean): void {\n if (this.editing && this.htmlEditElement) {\n this.editing.commit();\n return;\n }\n\n if (startEditing === false) {\n return;\n }\n\n function selectNode(error: string|null): void {\n if (callback) {\n callback(!error);\n }\n }\n\n function commitChange(initialValue: string, value: string): void {\n if (initialValue !== value) {\n node.setOuterHTML(value, selectNode);\n }\n }\n\n function disposeCallback(): void {\n if (callback) {\n callback(false);\n }\n }\n\n const node = this.nodeInternal;\n void node.getOuterHTML().then(this.startEditingAsHTML.bind(this, commitChange, disposeCallback));\n }\n\n private copyCSSPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(cssPath(this.nodeInternal, true));\n }\n\n private copyJSPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(jsPath(this.nodeInternal, true));\n }\n\n private copyXPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(xPath(this.nodeInternal, true));\n }\n\n private copyFullXPath(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(xPath(this.nodeInternal, false));\n }\n\n async copyStyles(): Promise {\n const node = this.nodeInternal;\n const cssModel = node.domModel().cssModel();\n const cascade = await cssModel.cachedMatchedCascadeForNode(node);\n if (!cascade) {\n return;\n }\n\n const indent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n const lines: string[] = [];\n for (const style of cascade.nodeStyles().reverse()) {\n for (const property of style.leadingProperties()) {\n if (!property.parsedOk || property.disabled || !property.activeInStyle() || property.implicit) {\n continue;\n }\n if (cascade.isInherited(style) && !SDK.CSSMetadata.cssMetadata().isPropertyInherited(property.name)) {\n continue;\n }\n if (style.parentRule && style.parentRule.isUserAgent()) {\n continue;\n }\n if (cascade.propertyState(property) !== SDK.CSSMatchedStyles.PropertyState.ACTIVE) {\n continue;\n }\n lines.push(`${indent}${property.name}: ${property.value};`);\n }\n }\n\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(lines.join('\\n'));\n }\n\n private highlightSearchResultsInternal(): void {\n this.hideSearchHighlights();\n\n if (!this.searchQuery) {\n return;\n }\n\n const text = this.listItemElement.textContent || '';\n const regexObject = Platform.StringUtilities.createPlainTextSearchRegex(this.searchQuery, 'gi');\n\n const matchRanges = [];\n let match = regexObject.exec(text);\n while (match) {\n matchRanges.push(new TextUtils.TextRange.SourceRange(match.index, match[0].length));\n match = regexObject.exec(text);\n }\n\n // Fall back for XPath, etc. matches.\n if (!matchRanges.length) {\n matchRanges.push(new TextUtils.TextRange.SourceRange(0, text.length));\n }\n\n this.#highlights = Highlighting.HighlightManager.HighlightManager.instance().highlightOrderedTextRanges(\n this.listItemElement, matchRanges);\n }\n\n private editAsHTML(): void {\n const promise = Common.Revealer.reveal(this.node());\n void promise.then(() => {\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('elements.edit-as-html');\n return action.execute();\n });\n }\n\n // TODO: add unit tests for adorner-related methods after component and TypeScript works are done\n adorn({name}: {name: string}, content?: HTMLElement): Adorners.Adorner.Adorner {\n let adornerContent = content;\n if (!adornerContent) {\n adornerContent = document.createElement('span');\n adornerContent.textContent = name;\n }\n const adorner = new Adorners.Adorner.Adorner();\n adorner.data = {\n name,\n content: adornerContent,\n jslogContext: name,\n };\n if (isOpeningTag(this.tagTypeContext)) {\n this.tagTypeContext.adorners.push(adorner);\n ElementsPanel.instance().registerAdorner(adorner);\n this.updateAdorners(this.tagTypeContext);\n }\n return adorner;\n }\n\n adornSlot({name}: {name: string}, context: OpeningTagContext): Adorners.Adorner.Adorner {\n const linkIcon = new IconButton.Icon.Icon();\n linkIcon.name = 'select-element';\n const slotText = document.createElement('span');\n slotText.textContent = name;\n const adornerContent = document.createElement('span');\n adornerContent.append(linkIcon);\n adornerContent.append(slotText);\n adornerContent.classList.add('adorner-with-icon');\n const adorner = new Adorners.Adorner.Adorner();\n adorner.data = {\n name,\n content: adornerContent,\n jslogContext: 'slot',\n };\n context.adorners.push(adorner);\n ElementsPanel.instance().registerAdorner(adorner);\n this.updateAdorners(context);\n return adorner;\n }\n\n adornMedia({name}: {name: string}): Adorners.Adorner.Adorner {\n const adornerContent = document.createElement('span');\n\n adornerContent.textContent = name;\n adornerContent.classList.add('adorner-with-icon');\n\n const linkIcon = new IconButton.Icon.Icon();\n linkIcon.name = 'select-element';\n adornerContent.append(linkIcon);\n\n const adorner = new Adorners.Adorner.Adorner();\n adorner.data = {\n name,\n content: adornerContent,\n jslogContext: 'media',\n };\n if (isOpeningTag(this.tagTypeContext)) {\n this.tagTypeContext.adorners.push(adorner);\n ElementsPanel.instance().registerAdorner(adorner);\n this.updateAdorners(this.tagTypeContext);\n }\n return adorner;\n }\n\n removeAdorner(adornerToRemove: Adorners.Adorner.Adorner, context: OpeningTagContext): void {\n const adorners = context.adorners;\n ElementsPanel.instance().deregisterAdorner(adornerToRemove);\n adornerToRemove.remove();\n for (let i = 0; i < adorners.length; ++i) {\n if (adorners[i] === adornerToRemove) {\n adorners.splice(i, 1);\n this.updateAdorners(context);\n return;\n }\n }\n }\n\n removeAllAdorners(): void {\n if (isOpeningTag(this.tagTypeContext)) {\n for (const adorner of this.tagTypeContext.adorners) {\n ElementsPanel.instance().deregisterAdorner(adorner);\n adorner.remove();\n }\n\n this.tagTypeContext.adorners = [];\n this.updateAdorners(this.tagTypeContext);\n }\n }\n\n private updateAdorners(context: OpeningTagContext): void {\n void context.adornersThrottler.schedule(this.updateAdornersInternal.bind(null, context));\n }\n\n private updateAdornersInternal(context: OpeningTagContext): Promise {\n const adornerContainer = context.adornerContainer;\n if (!adornerContainer) {\n return Promise.resolve();\n }\n const adorners = context.adorners;\n if (adorners.length === 0) {\n adornerContainer.classList.add('hidden');\n return Promise.resolve();\n }\n\n adorners.sort(adornerComparator);\n\n adornerContainer.removeChildren();\n for (const adorner of adorners) {\n adornerContainer.appendChild(adorner);\n }\n adornerContainer.classList.remove('hidden');\n return Promise.resolve();\n }\n\n async updateStyleAdorners(): Promise {\n if (!isOpeningTag(this.tagTypeContext)) {\n return;\n }\n\n const node = this.node();\n const nodeId = node.id;\n if (node.nodeType() === Node.COMMENT_NODE || node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE ||\n node.nodeType() === Node.TEXT_NODE || nodeId === undefined) {\n return;\n }\n\n const styles = await node.domModel().cssModel().getComputedStyle(nodeId);\n for (const styleAdorner of this.tagTypeContext.styleAdorners) {\n this.removeAdorner(styleAdorner, this.tagTypeContext);\n }\n this.tagTypeContext.styleAdorners = [];\n if (!styles) {\n return;\n }\n\n const display = styles.get('display');\n const isGrid = display === 'grid' || display === 'inline-grid';\n const isFlex = display === 'flex' || display === 'inline-flex';\n const isSubgrid = (isGrid &&\n (styles.get('grid-template-columns')?.startsWith('subgrid') ||\n styles.get('grid-template-rows')?.startsWith('subgrid'))) ??\n false;\n\n const containerType = styles.get('container-type');\n const isContainer = containerType && containerType !== '' && containerType !== 'normal';\n\n if (isGrid) {\n this.pushGridAdorner(this.tagTypeContext, isSubgrid);\n }\n if (isFlex) {\n this.pushFlexAdorner(this.tagTypeContext);\n }\n if (styles.get('scroll-snap-type') && styles.get('scroll-snap-type') !== 'none') {\n this.pushScrollSnapAdorner(this.tagTypeContext);\n }\n if (isContainer) {\n this.pushContainerAdorner(this.tagTypeContext);\n }\n\n if (node.isMediaNode()) {\n this.pushMediaAdorner(this.tagTypeContext);\n }\n }\n\n pushGridAdorner(context: OpeningTagContext, isSubgrid: boolean): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n isSubgrid ? ElementsComponents.AdornerManager.RegisteredAdorners.SUBGRID :\n ElementsComponents.AdornerManager.RegisteredAdorners.GRID);\n const adorner = this.adorn(config);\n adorner.classList.add('grid');\n\n const onClick = ((() => {\n if (adorner.isActive()) {\n node.domModel().overlayModel().highlightGridInPersistentOverlay(nodeId);\n } else {\n node.domModel().overlayModel().hideGridInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableGridMode),\n ariaLabelActive: i18nString(UIStrings.disableGridMode),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_GRID_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n if (node.domModel().overlayModel().isHighlightedGridInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushScrollSnapAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL_SNAP);\n const adorner = this.adorn(config);\n adorner.classList.add('scroll-snap');\n\n const onClick = ((() => {\n const model = node.domModel().overlayModel();\n if (adorner.isActive()) {\n model.highlightScrollSnapInPersistentOverlay(nodeId);\n } else {\n model.hideScrollSnapInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableScrollSnap),\n ariaLabelActive: i18nString(UIStrings.disableScrollSnap),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_SCROLL_SNAP_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n\n if (node.domModel().overlayModel().isHighlightedScrollSnapInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushFlexAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.FLEX);\n const adorner = this.adorn(config);\n adorner.classList.add('flex');\n\n const onClick = ((() => {\n const model = node.domModel().overlayModel();\n if (adorner.isActive()) {\n model.highlightFlexContainerInPersistentOverlay(nodeId);\n } else {\n model.hideFlexContainerInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableFlexMode),\n ariaLabelActive: i18nString(UIStrings.disableFlexMode),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_FLEX_CONTAINER_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n\n if (node.domModel().overlayModel().isHighlightedFlexContainerInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushContainerAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.CONTAINER);\n const adorner = this.adorn(config);\n adorner.classList.add('container');\n\n const onClick = ((() => {\n const model = node.domModel().overlayModel();\n if (adorner.isActive()) {\n model.highlightContainerQueryInPersistentOverlay(nodeId);\n } else {\n model.hideContainerQueryInPersistentOverlay(nodeId);\n }\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: true,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.enableScrollSnap),\n ariaLabelActive: i18nString(UIStrings.disableScrollSnap),\n });\n\n node.domModel().overlayModel().addEventListener(\n SDK.OverlayModel.Events.PERSISTENT_CONTAINER_QUERY_OVERLAY_STATE_CHANGED, event => {\n const {nodeId: eventNodeId, enabled} = event.data;\n if (eventNodeId !== nodeId) {\n return;\n }\n adorner.toggle(enabled);\n });\n\n context.styleAdorners.push(adorner);\n if (node.domModel().overlayModel().isHighlightedContainerQueryInPersistentOverlay(nodeId)) {\n adorner.toggle(true);\n }\n }\n\n pushMediaAdorner(context: OpeningTagContext): void {\n const node = this.node();\n const nodeId = node.id;\n if (!nodeId) {\n return;\n }\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.MEDIA);\n const adorner = this.adornMedia(config);\n adorner.classList.add('media');\n\n const onClick = ((() => {\n void UI.ViewManager.ViewManager.instance().showView('medias');\n }) as EventListener);\n\n adorner.addInteraction(onClick, {\n isToggle: false,\n shouldPropagateOnKeydown: false,\n ariaLabelDefault: i18nString(UIStrings.openMediaPanel),\n ariaLabelActive: i18nString(UIStrings.openMediaPanel),\n });\n\n context.styleAdorners.push(adorner);\n }\n\n updateScrollAdorner(): void {\n if (!isOpeningTag(this.tagTypeContext)) {\n return;\n }\n const scrollAdorner = this.tagTypeContext.adorners.find(x => x.name === 'scroll');\n // Check if the node is scrollable, or if it's the element and the document is scrollable because the top-level document (#document) doesn't have a corresponding tree element.\n const needsAScrollAdorner = (this.node().nodeName() === 'HTML' && this.node().ownerDocument?.isScrollable()) ||\n (this.node().nodeName() !== '#document' && this.node().isScrollable());\n if (needsAScrollAdorner && !scrollAdorner) {\n this.pushScrollAdorner();\n } else if (!needsAScrollAdorner && scrollAdorner) {\n this.removeAdorner(scrollAdorner, this.tagTypeContext);\n }\n }\n\n pushScrollAdorner(): void {\n const config = ElementsComponents.AdornerManager.getRegisteredAdorner(\n ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL);\n const adorner = this.adorn(config);\n UI.Tooltip.Tooltip.install(adorner, i18nString(UIStrings.elementHasScrollableOverflow));\n adorner.classList.add('scroll');\n }\n}\n\nexport const InitialChildrenLimit = 500;\n\n// A union of HTML4 and HTML5-Draft elements that explicitly\n// or implicitly (for HTML5) forbid the closing tag.\nexport const ForbiddenClosingTagElements = new Set([\n 'area', 'base', 'basefont', 'br', 'canvas', 'col', 'command', 'embed', 'frame', 'hr',\n 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr',\n]);\n\n// These tags we do not allow editing their tag name.\nexport const EditTagBlocklist = new Set(['html', 'head', 'body']);\n\nexport function adornerComparator(adornerA: Adorners.Adorner.Adorner, adornerB: Adorners.Adorner.Adorner): number {\n const compareCategories =\n ElementsComponents.AdornerManager.compareAdornerNamesByCategory(adornerB.name, adornerB.name);\n if (compareCategories === 0) {\n return adornerA.name.localeCompare(adornerB.name);\n }\n return compareCategories;\n}\nexport interface EditorHandles {\n commit: () => void;\n cancel: () => void;\n editor?: TextEditor.TextEditor.TextEditor;\n resize: () => void;\n}\n\n// As a privacy measure we are logging elements tree outline as a flat list where every tree item is a\n// child of a tree outline.\nfunction loggingParentProvider(e: Element): Element|undefined {\n const treeElement = UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(e);\n return treeElement?.treeOutline?.contentElement;\n}\n\nVisualLogging.registerParentProvider('elementsTreeOutline', loggingParentProvider);\n"]} \ No newline at end of file diff --git a/public/panels/elements/MetricsSidebarPane.js.map b/public/panels/elements/MetricsSidebarPane.js.map index 9bd8bec9..31688d3b 100644 --- a/public/panels/elements/MetricsSidebarPane.js.map +++ b/public/panels/elements/MetricsSidebarPane.js.map @@ -1 +1 @@ -{"version":3,"file":"MetricsSidebarPane.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/MetricsSidebarPane.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 Apple 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 Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {ElementsSidebarPane} from './ElementsSidebarPane.js';\nimport metricsSidebarPaneStyles from './metricsSidebarPane.css.js';\n\nexport class MetricsSidebarPane extends ElementsSidebarPane {\n originalPropertyData: SDK.CSSProperty.CSSProperty|null;\n previousPropertyDataCandidate: SDK.CSSProperty.CSSProperty|null;\n private inlineStyle: SDK.CSSStyleDeclaration.CSSStyleDeclaration|null;\n private highlightMode: string;\n private boxElements: {\n element: HTMLElement,\n name: string,\n backgroundColor: string,\n }[];\n private isEditingMetrics?: boolean;\n\n constructor() {\n super();\n\n this.originalPropertyData = null;\n this.previousPropertyDataCandidate = null;\n this.inlineStyle = null;\n this.highlightMode = '';\n this.boxElements = [];\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('styles-metrics')}`);\n }\n\n override doUpdate(): Promise {\n // \"style\" attribute might have changed. Update metrics unless they are being edited\n // (if a CSS property is added, a StyleSheetChanged event is dispatched).\n if (this.isEditingMetrics) {\n return Promise.resolve();\n }\n\n // FIXME: avoid updates of a collapsed pane.\n const node = this.node();\n const cssModel = this.cssModel();\n if (!node || node.nodeType() !== Node.ELEMENT_NODE || !cssModel) {\n this.contentElement.removeChildren();\n this.element.classList.add('collapsed');\n return Promise.resolve();\n }\n\n function callback(this: MetricsSidebarPane, style: Map|null): void {\n if (!style || this.node() !== node) {\n return;\n }\n this.updateMetrics(style);\n }\n\n if (!node.id) {\n return Promise.resolve();\n }\n\n const promises = [\n cssModel.getComputedStyle(node.id).then(callback.bind(this)),\n cssModel.getInlineStyles(node.id).then(inlineStyleResult => {\n if (inlineStyleResult && this.node() === node) {\n this.inlineStyle = inlineStyleResult.inlineStyle;\n }\n }),\n ];\n return Promise.all(promises) as unknown as Promise;\n }\n\n override onCSSModelChanged(): void {\n this.update();\n }\n\n /**\n * Toggle the visibility of the Metrics pane. This toggle allows external\n * callers to control the visibility of this pane, but toggling this on does\n * not guarantee the pane will always show up, because the pane's visibility\n * is also controlled by the internal condition that style cannot be empty.\n */\n toggleVisibility(isVisible: boolean): void {\n this.element.classList.toggle('invisible', !isVisible);\n }\n\n private getPropertyValueAsPx(style: Map, propertyName: string): number {\n const propertyValue = style.get(propertyName);\n if (!propertyValue) {\n return 0;\n }\n return Number(propertyValue.replace(/px$/, '') || 0);\n }\n\n private getBox(computedStyle: Map, componentName: string): {\n left: number,\n top: number,\n right: number,\n bottom: number,\n } {\n const suffix = componentName === 'border' ? '-width' : '';\n const left = this.getPropertyValueAsPx(computedStyle, componentName + '-left' + suffix);\n const top = this.getPropertyValueAsPx(computedStyle, componentName + '-top' + suffix);\n const right = this.getPropertyValueAsPx(computedStyle, componentName + '-right' + suffix);\n const bottom = this.getPropertyValueAsPx(computedStyle, componentName + '-bottom' + suffix);\n return {left, top, right, bottom};\n }\n\n private highlightDOMNode(showHighlight: boolean, mode: string, event: Event): void {\n event.consume();\n const node = this.node();\n if (showHighlight && node) {\n if (this.highlightMode === mode) {\n return;\n }\n this.highlightMode = mode;\n node.highlight(mode);\n } else {\n this.highlightMode = '';\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n\n for (const {element, name, backgroundColor} of this.boxElements) {\n const shouldHighlight = !node || mode === 'all' || name === mode;\n element.style.backgroundColor = shouldHighlight ? backgroundColor : '';\n element.classList.toggle('highlighted', shouldHighlight);\n }\n }\n\n private updateMetrics(style: Map): void {\n // Updating with computed style.\n const metricsElement = document.createElement('div');\n metricsElement.className = 'metrics';\n const self = this;\n\n function createBoxPartElement(\n this: MetricsSidebarPane, style: Map, name: string, side: string,\n suffix: string): HTMLDivElement {\n const element = document.createElement('div');\n element.className = side;\n\n const propertyName = (name !== 'position' ? name + '-' : '') + side + suffix;\n let value = style.get(propertyName);\n if (value === undefined) {\n return element;\n }\n\n if (value === '' || (name !== 'position' && value === '0px')) {\n value = '\\u2012';\n } else if (name === 'position' && value === 'auto') {\n value = '\\u2012';\n }\n value = value.replace(/px$/, '');\n value = Platform.NumberUtilities.toFixedIfFloating(value);\n\n element.textContent = value;\n element.setAttribute('jslog', `${VisualLogging.value(propertyName).track({\n dblclick: true,\n keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',\n change: true,\n })}`);\n element.addEventListener('dblclick', this.startEditing.bind(this, element, name, propertyName, style), false);\n return element;\n }\n\n function getContentAreaWidthPx(style: Map): string {\n let width = style.get('width');\n if (!width) {\n return '';\n }\n width = width.replace(/px$/, '');\n const widthValue = Number(width);\n if (!isNaN(widthValue) && style.get('box-sizing') === 'border-box') {\n const borderBox = self.getBox(style, 'border');\n const paddingBox = self.getBox(style, 'padding');\n\n width = (widthValue - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right).toString();\n }\n\n return Platform.NumberUtilities.toFixedIfFloating(width);\n }\n\n function getContentAreaHeightPx(style: Map): string {\n let height = style.get('height');\n if (!height) {\n return '';\n }\n height = height.replace(/px$/, '');\n const heightValue = Number(height);\n if (!isNaN(heightValue) && style.get('box-sizing') === 'border-box') {\n const borderBox = self.getBox(style, 'border');\n const paddingBox = self.getBox(style, 'padding');\n\n height = (heightValue - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom).toString();\n }\n\n return Platform.NumberUtilities.toFixedIfFloating(height);\n }\n\n // Display types for which margin is ignored.\n const noMarginDisplayType = new Set([\n 'table-cell',\n 'table-column',\n 'table-column-group',\n 'table-footer-group',\n 'table-header-group',\n 'table-row',\n 'table-row-group',\n ]);\n\n // Display types for which padding is ignored.\n const noPaddingDisplayType = new Set([\n 'table-column',\n 'table-column-group',\n 'table-footer-group',\n 'table-header-group',\n 'table-row',\n 'table-row-group',\n ]);\n\n // Position types for which top, left, bottom and right are ignored.\n const noPositionType = new Set(['static']);\n\n const boxes = ['content', 'padding', 'border', 'margin', 'position'];\n const boxColors = [\n Common.Color.PageHighlight.Content,\n Common.Color.PageHighlight.Padding,\n Common.Color.PageHighlight.Border,\n Common.Color.PageHighlight.Margin,\n Common.Color.Legacy.fromRGBA([0, 0, 0, 0]),\n ];\n const boxLabels = ['content', 'padding', 'border', 'margin', 'position'];\n let previousBox: HTMLDivElement|null = null;\n this.boxElements = [];\n for (let i = 0; i < boxes.length; ++i) {\n const name = boxes[i];\n const display = style.get('display');\n const position = style.get('position');\n if (!display || !position) {\n continue;\n }\n if (name === 'margin' && noMarginDisplayType.has(display)) {\n continue;\n }\n if (name === 'padding' && noPaddingDisplayType.has(display)) {\n continue;\n }\n if (name === 'position' && noPositionType.has(position)) {\n continue;\n }\n\n const boxElement = document.createElement('div');\n boxElement.className = `${name} highlighted`;\n const backgroundColor = boxColors[i].asString(Common.Color.Format.RGBA) || '';\n boxElement.style.backgroundColor = backgroundColor;\n boxElement.setAttribute('jslog', `${VisualLogging.metricsBox().context(name).track({hover: true})}`);\n boxElement.addEventListener(\n 'mouseover', this.highlightDOMNode.bind(this, true, name === 'position' ? 'all' : name), false);\n this.boxElements.push({element: boxElement, name, backgroundColor});\n\n if (name === 'content') {\n const widthElement = document.createElement('span');\n widthElement.textContent = getContentAreaWidthPx(style);\n widthElement.addEventListener(\n 'dblclick', this.startEditing.bind(this, widthElement, 'width', 'width', style), false);\n widthElement.setAttribute('jslog', `${VisualLogging.value('width').track({\n dblclick: true,\n keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',\n change: true,\n })}`);\n\n const heightElement = document.createElement('span');\n heightElement.textContent = getContentAreaHeightPx(style);\n heightElement.addEventListener(\n 'dblclick', this.startEditing.bind(this, heightElement, 'height', 'height', style), false);\n heightElement.setAttribute('jslog', `${VisualLogging.value('height').track({\n dblclick: true,\n keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',\n change: true,\n })}`);\n\n const timesElement = document.createElement('span');\n timesElement.textContent = ' × ';\n\n boxElement.appendChild(widthElement);\n boxElement.appendChild(timesElement);\n boxElement.appendChild(heightElement);\n } else {\n const suffix = (name === 'border' ? '-width' : '');\n\n const labelElement = document.createElement('div');\n labelElement.className = 'label';\n labelElement.textContent = boxLabels[i];\n boxElement.appendChild(labelElement);\n\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'top', suffix));\n boxElement.appendChild(document.createElement('br'));\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'left', suffix));\n\n if (previousBox) {\n boxElement.appendChild(previousBox);\n }\n\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'right', suffix));\n boxElement.appendChild(document.createElement('br'));\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'bottom', suffix));\n }\n\n previousBox = boxElement;\n }\n metricsElement.appendChild((previousBox as HTMLDivElement));\n metricsElement.addEventListener('mouseover', this.highlightDOMNode.bind(this, false, 'all'), false);\n metricsElement.addEventListener('mouseleave', this.highlightDOMNode.bind(this, false, 'all'), false);\n this.contentElement.removeChildren();\n this.contentElement.appendChild(metricsElement);\n this.element.classList.remove('collapsed');\n }\n\n startEditing(targetElement: Element, box: string, styleProperty: string, computedStyle: Map): void {\n if (UI.UIUtils.isBeingEdited(targetElement)) {\n return;\n }\n\n const context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n } = {box, styleProperty, computedStyle, keyDownHandler: () => {}};\n const boundKeyDown = this.handleKeyDown.bind(this, context);\n context.keyDownHandler = boundKeyDown;\n targetElement.addEventListener('keydown', boundKeyDown, false);\n\n this.isEditingMetrics = true;\n\n const config =\n new UI.InplaceEditor.Config(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);\n UI.InplaceEditor.InplaceEditor.startEditing(targetElement, config);\n\n const selection = targetElement.getComponentSelection();\n selection && selection.selectAllChildren(targetElement);\n }\n\n private handleKeyDown(\n context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n },\n event: Event): void {\n const element = (event.currentTarget as Element);\n\n function finishHandler(this: MetricsSidebarPane, originalValue: string, replacementString: string): void {\n this.applyUserInput(element, replacementString, originalValue, context, false);\n }\n\n function customNumberHandler(prefix: string, number: number, suffix: string): string {\n if (context.styleProperty !== 'margin' && number < 0) {\n number = 0;\n }\n return prefix + number + suffix;\n }\n\n UI.UIUtils.handleElementValueModifications(\n event, element, finishHandler.bind(this), undefined, customNumberHandler);\n }\n\n editingEnded(element: Element, context: {\n keyDownHandler: (arg0: Event) => void,\n }): void {\n this.originalPropertyData = null;\n this.previousPropertyDataCandidate = null;\n element.removeEventListener('keydown', context.keyDownHandler, false);\n delete this.isEditingMetrics;\n }\n\n editingCancelled(element: Element, context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n }): void {\n if (this.inlineStyle) {\n if (!this.originalPropertyData) {\n // An added property, remove the last property in the style.\n const pastLastSourcePropertyIndex = this.inlineStyle.pastLastSourcePropertyIndex();\n if (pastLastSourcePropertyIndex) {\n void this.inlineStyle.allProperties()[pastLastSourcePropertyIndex - 1].setText('', false);\n }\n } else {\n void this.inlineStyle.allProperties()[this.originalPropertyData.index].setText(\n this.originalPropertyData.propertyText || '', false);\n }\n }\n this.editingEnded(element, context);\n this.update();\n }\n\n private applyUserInput(\n element: Element, userInput: string, previousContent: string, context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n },\n commitEditor: boolean): void {\n if (!this.inlineStyle) {\n // Element has no renderer.\n return this.editingCancelled(element, context); // nothing changed, so cancel\n }\n\n if (commitEditor && userInput === previousContent) {\n return this.editingCancelled(element, context);\n } // nothing changed, so cancel\n\n if (context.box !== 'position' && (!userInput || userInput === '\\u2012')) {\n userInput = '0px';\n } else if (context.box === 'position' && (!userInput || userInput === '\\u2012')) {\n userInput = 'auto';\n }\n\n userInput = userInput.toLowerCase();\n // Append a \"px\" unit if the user input was just a number.\n if (/^\\d+$/.test(userInput)) {\n userInput += 'px';\n }\n\n const styleProperty = context.styleProperty;\n const computedStyle = context.computedStyle;\n\n if (computedStyle.get('box-sizing') === 'border-box' && (styleProperty === 'width' || styleProperty === 'height')) {\n if (!userInput.match(/px$/)) {\n Common.Console.Console.instance().error(\n 'For elements with box-sizing: border-box, only absolute content area dimensions can be applied');\n return;\n }\n\n const borderBox = this.getBox(computedStyle, 'border');\n const paddingBox = this.getBox(computedStyle, 'padding');\n let userValuePx = Number(userInput.replace(/px$/, ''));\n if (isNaN(userValuePx)) {\n return;\n }\n if (styleProperty === 'width') {\n userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right;\n } else {\n userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom;\n }\n\n userInput = userValuePx + 'px';\n }\n\n this.previousPropertyDataCandidate = null;\n\n const allProperties = this.inlineStyle.allProperties();\n for (let i = 0; i < allProperties.length; ++i) {\n const property = allProperties[i];\n if (property.name !== context.styleProperty || !property.activeInStyle()) {\n continue;\n }\n\n this.previousPropertyDataCandidate = property;\n property.setValue(userInput, commitEditor, true, callback.bind(this));\n return;\n }\n\n this.inlineStyle.appendProperty(context.styleProperty, userInput, callback.bind(this));\n\n function callback(this: MetricsSidebarPane, success: boolean): void {\n if (!success) {\n return;\n }\n if (!this.originalPropertyData) {\n this.originalPropertyData = this.previousPropertyDataCandidate;\n }\n\n if (this.highlightMode) {\n const node = this.node();\n if (!node) {\n return;\n }\n node.highlight(this.highlightMode);\n }\n\n if (commitEditor) {\n this.update();\n }\n }\n }\n\n private editingCommitted(element: Element, userInput: string, previousContent: string, context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n }): void {\n this.editingEnded(element, context);\n this.applyUserInput(element, userInput, previousContent, context, true);\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([metricsSidebarPaneStyles]);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"MetricsSidebarPane.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/MetricsSidebarPane.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 Apple 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 Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {ElementsSidebarPane} from './ElementsSidebarPane.js';\nimport metricsSidebarPaneStyles from './metricsSidebarPane.css.js';\n\nexport class MetricsSidebarPane extends ElementsSidebarPane {\n originalPropertyData: SDK.CSSProperty.CSSProperty|null;\n previousPropertyDataCandidate: SDK.CSSProperty.CSSProperty|null;\n private inlineStyle: SDK.CSSStyleDeclaration.CSSStyleDeclaration|null;\n private highlightMode: string;\n private boxElements: {\n element: HTMLElement,\n name: string,\n backgroundColor: string,\n }[];\n private isEditingMetrics?: boolean;\n\n constructor() {\n super();\n\n this.originalPropertyData = null;\n this.previousPropertyDataCandidate = null;\n this.inlineStyle = null;\n this.highlightMode = '';\n this.boxElements = [];\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('styles-metrics')}`);\n }\n\n override doUpdate(): Promise {\n // \"style\" attribute might have changed. Update metrics unless they are being edited\n // (if a CSS property is added, a StyleSheetChanged event is dispatched).\n if (this.isEditingMetrics) {\n return Promise.resolve();\n }\n\n // FIXME: avoid updates of a collapsed pane.\n const node = this.node();\n const cssModel = this.cssModel();\n if (!node || node.nodeType() !== Node.ELEMENT_NODE || !cssModel) {\n this.contentElement.removeChildren();\n this.element.classList.add('collapsed');\n return Promise.resolve();\n }\n\n function callback(this: MetricsSidebarPane, style: Map|null): void {\n if (!style || this.node() !== node) {\n return;\n }\n this.updateMetrics(style);\n }\n\n if (!node.id) {\n return Promise.resolve();\n }\n\n const promises = [\n cssModel.getComputedStyle(node.id).then(callback.bind(this)),\n cssModel.getInlineStyles(node.id).then(inlineStyleResult => {\n if (inlineStyleResult && this.node() === node) {\n this.inlineStyle = inlineStyleResult.inlineStyle;\n }\n }),\n ];\n return Promise.all(promises) as unknown as Promise;\n }\n\n override onCSSModelChanged(): void {\n this.update();\n }\n\n /**\n * Toggle the visibility of the Metrics pane. This toggle allows external\n * callers to control the visibility of this pane, but toggling this on does\n * not guarantee the pane will always show up, because the pane's visibility\n * is also controlled by the internal condition that style cannot be empty.\n */\n toggleVisibility(isVisible: boolean): void {\n this.element.classList.toggle('invisible', !isVisible);\n }\n\n private getPropertyValueAsPx(style: Map, propertyName: string): number {\n const propertyValue = style.get(propertyName);\n if (!propertyValue) {\n return 0;\n }\n return Number(propertyValue.replace(/px$/, '') || 0);\n }\n\n private getBox(computedStyle: Map, componentName: string): {\n left: number,\n top: number,\n right: number,\n bottom: number,\n } {\n const suffix = componentName === 'border' ? '-width' : '';\n const left = this.getPropertyValueAsPx(computedStyle, componentName + '-left' + suffix);\n const top = this.getPropertyValueAsPx(computedStyle, componentName + '-top' + suffix);\n const right = this.getPropertyValueAsPx(computedStyle, componentName + '-right' + suffix);\n const bottom = this.getPropertyValueAsPx(computedStyle, componentName + '-bottom' + suffix);\n return {left, top, right, bottom};\n }\n\n private highlightDOMNode(showHighlight: boolean, mode: string, event: Event): void {\n event.consume();\n const node = this.node();\n if (showHighlight && node) {\n if (this.highlightMode === mode) {\n return;\n }\n this.highlightMode = mode;\n node.highlight(mode);\n } else {\n this.highlightMode = '';\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n\n for (const {element, name, backgroundColor} of this.boxElements) {\n const shouldHighlight = !node || mode === 'all' || name === mode;\n element.style.backgroundColor = shouldHighlight ? backgroundColor : '';\n element.classList.toggle('highlighted', shouldHighlight);\n }\n }\n\n private updateMetrics(style: Map): void {\n // Updating with computed style.\n const metricsElement = document.createElement('div');\n metricsElement.className = 'metrics';\n const self = this;\n\n function createBoxPartElement(\n this: MetricsSidebarPane, style: Map, name: string, side: string,\n suffix: string): HTMLDivElement {\n const element = document.createElement('div');\n element.className = side;\n\n const propertyName = (name !== 'position' ? name + '-' : '') + side + suffix;\n let value = style.get(propertyName);\n if (value === undefined) {\n return element;\n }\n\n if (value === '' || (name !== 'position' && value === '0px')) {\n value = '\\u2012';\n } else if (name === 'position' && value === 'auto') {\n value = '\\u2012';\n }\n value = value.replace(/px$/, '');\n value = Platform.NumberUtilities.toFixedIfFloating(value);\n\n element.textContent = value;\n element.setAttribute('jslog', `${VisualLogging.value(propertyName).track({\n dblclick: true,\n keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',\n change: true,\n })}`);\n element.addEventListener('dblclick', this.startEditing.bind(this, element, name, propertyName, style), false);\n return element;\n }\n\n function getContentAreaWidthPx(style: Map): string {\n let width = style.get('width');\n if (!width) {\n return '';\n }\n width = width.replace(/px$/, '');\n const widthValue = Number(width);\n if (!isNaN(widthValue) && style.get('box-sizing') === 'border-box') {\n const borderBox = self.getBox(style, 'border');\n const paddingBox = self.getBox(style, 'padding');\n\n width = (widthValue - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right).toString();\n }\n\n return Platform.NumberUtilities.toFixedIfFloating(width);\n }\n\n function getContentAreaHeightPx(style: Map): string {\n let height = style.get('height');\n if (!height) {\n return '';\n }\n height = height.replace(/px$/, '');\n const heightValue = Number(height);\n if (!isNaN(heightValue) && style.get('box-sizing') === 'border-box') {\n const borderBox = self.getBox(style, 'border');\n const paddingBox = self.getBox(style, 'padding');\n\n height = (heightValue - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom).toString();\n }\n\n return Platform.NumberUtilities.toFixedIfFloating(height);\n }\n\n // Display types for which margin is ignored.\n const noMarginDisplayType = new Set([\n 'table-cell',\n 'table-column',\n 'table-column-group',\n 'table-footer-group',\n 'table-header-group',\n 'table-row',\n 'table-row-group',\n ]);\n\n // Display types for which padding is ignored.\n const noPaddingDisplayType = new Set([\n 'table-column',\n 'table-column-group',\n 'table-footer-group',\n 'table-header-group',\n 'table-row',\n 'table-row-group',\n ]);\n\n // Position types for which top, left, bottom and right are ignored.\n const noPositionType = new Set(['static']);\n\n const boxes = ['content', 'padding', 'border', 'margin', 'position'];\n const boxColors = [\n Common.Color.PageHighlight.Content,\n Common.Color.PageHighlight.Padding,\n Common.Color.PageHighlight.Border,\n Common.Color.PageHighlight.Margin,\n Common.Color.Legacy.fromRGBA([0, 0, 0, 0]),\n ];\n const boxLabels = ['content', 'padding', 'border', 'margin', 'position'];\n let previousBox: HTMLDivElement|null = null;\n this.boxElements = [];\n for (let i = 0; i < boxes.length; ++i) {\n const name = boxes[i];\n const display = style.get('display');\n const position = style.get('position');\n if (!display || !position) {\n continue;\n }\n if (name === 'margin' && noMarginDisplayType.has(display)) {\n continue;\n }\n if (name === 'padding' && noPaddingDisplayType.has(display)) {\n continue;\n }\n if (name === 'position' && noPositionType.has(position)) {\n continue;\n }\n\n const boxElement = document.createElement('div');\n boxElement.className = `${name} highlighted`;\n const backgroundColor = boxColors[i].asString(Common.Color.Format.RGBA) || '';\n boxElement.style.backgroundColor = backgroundColor;\n boxElement.setAttribute('jslog', `${VisualLogging.metricsBox().context(name).track({hover: true})}`);\n boxElement.addEventListener(\n 'mouseover', this.highlightDOMNode.bind(this, true, name === 'position' ? 'all' : name), false);\n this.boxElements.push({element: boxElement, name, backgroundColor});\n\n if (name === 'content') {\n const widthElement = document.createElement('span');\n widthElement.textContent = getContentAreaWidthPx(style);\n widthElement.addEventListener(\n 'dblclick', this.startEditing.bind(this, widthElement, 'width', 'width', style), false);\n widthElement.setAttribute('jslog', `${VisualLogging.value('width').track({\n dblclick: true,\n keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',\n change: true,\n })}`);\n\n const heightElement = document.createElement('span');\n heightElement.textContent = getContentAreaHeightPx(style);\n heightElement.addEventListener(\n 'dblclick', this.startEditing.bind(this, heightElement, 'height', 'height', style), false);\n heightElement.setAttribute('jslog', `${VisualLogging.value('height').track({\n dblclick: true,\n keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',\n change: true,\n })}`);\n\n const timesElement = document.createElement('span');\n timesElement.textContent = ' × ';\n\n boxElement.appendChild(widthElement);\n boxElement.appendChild(timesElement);\n boxElement.appendChild(heightElement);\n } else {\n const suffix = (name === 'border' ? '-width' : '');\n\n const labelElement = document.createElement('div');\n labelElement.className = 'label';\n labelElement.textContent = boxLabels[i];\n boxElement.appendChild(labelElement);\n\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'top', suffix));\n boxElement.appendChild(document.createElement('br'));\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'left', suffix));\n\n if (previousBox) {\n boxElement.appendChild(previousBox);\n }\n\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'right', suffix));\n boxElement.appendChild(document.createElement('br'));\n boxElement.appendChild(createBoxPartElement.call(this, style, name, 'bottom', suffix));\n }\n\n previousBox = boxElement;\n }\n metricsElement.appendChild((previousBox as HTMLDivElement));\n metricsElement.addEventListener('mouseover', this.highlightDOMNode.bind(this, false, 'all'), false);\n metricsElement.addEventListener('mouseleave', this.highlightDOMNode.bind(this, false, 'all'), false);\n this.contentElement.removeChildren();\n this.contentElement.appendChild(metricsElement);\n this.element.classList.remove('collapsed');\n }\n\n startEditing(targetElement: Element, box: string, styleProperty: string, computedStyle: Map): void {\n if (UI.UIUtils.isBeingEdited(targetElement)) {\n return;\n }\n\n const context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n } = {box, styleProperty, computedStyle, keyDownHandler: () => {}};\n const boundKeyDown = this.handleKeyDown.bind(this, context);\n context.keyDownHandler = boundKeyDown;\n targetElement.addEventListener('keydown', boundKeyDown, false);\n\n this.isEditingMetrics = true;\n\n const config =\n new UI.InplaceEditor.Config(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);\n UI.InplaceEditor.InplaceEditor.startEditing(targetElement, config);\n\n const selection = targetElement.getComponentSelection();\n selection && selection.selectAllChildren(targetElement);\n }\n\n private handleKeyDown(\n context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n },\n event: Event): void {\n const element = (event.currentTarget as Element);\n\n function finishHandler(this: MetricsSidebarPane, originalValue: string, replacementString: string): void {\n this.applyUserInput(element, replacementString, originalValue, context, false);\n }\n\n function customNumberHandler(prefix: string, number: number, suffix: string): string {\n if (context.styleProperty !== 'margin' && number < 0) {\n number = 0;\n }\n return prefix + number + suffix;\n }\n\n UI.UIUtils.handleElementValueModifications(\n event, element, finishHandler.bind(this), undefined, customNumberHandler);\n }\n\n editingEnded(element: Element, context: {\n keyDownHandler: (arg0: Event) => void,\n }): void {\n this.originalPropertyData = null;\n this.previousPropertyDataCandidate = null;\n element.removeEventListener('keydown', context.keyDownHandler, false);\n delete this.isEditingMetrics;\n }\n\n editingCancelled(element: Element, context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n }): void {\n if (this.inlineStyle) {\n if (!this.originalPropertyData) {\n // An added property, remove the last property in the style.\n const pastLastSourcePropertyIndex = this.inlineStyle.pastLastSourcePropertyIndex();\n if (pastLastSourcePropertyIndex) {\n void this.inlineStyle.allProperties()[pastLastSourcePropertyIndex - 1].setText('', false);\n }\n } else {\n void this.inlineStyle.allProperties()[this.originalPropertyData.index].setText(\n this.originalPropertyData.propertyText || '', false);\n }\n }\n this.editingEnded(element, context);\n this.update();\n }\n\n private applyUserInput(\n element: Element, userInput: string, previousContent: string|null, context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n },\n commitEditor: boolean): void {\n if (!this.inlineStyle) {\n // Element has no renderer.\n return this.editingCancelled(element, context); // nothing changed, so cancel\n }\n\n if (commitEditor && userInput === previousContent) {\n return this.editingCancelled(element, context);\n } // nothing changed, so cancel\n\n if (context.box !== 'position' && (!userInput || userInput === '\\u2012')) {\n userInput = '0px';\n } else if (context.box === 'position' && (!userInput || userInput === '\\u2012')) {\n userInput = 'auto';\n }\n\n userInput = userInput.toLowerCase();\n // Append a \"px\" unit if the user input was just a number.\n if (/^\\d+$/.test(userInput)) {\n userInput += 'px';\n }\n\n const styleProperty = context.styleProperty;\n const computedStyle = context.computedStyle;\n\n if (computedStyle.get('box-sizing') === 'border-box' && (styleProperty === 'width' || styleProperty === 'height')) {\n if (!userInput.match(/px$/)) {\n Common.Console.Console.instance().error(\n 'For elements with box-sizing: border-box, only absolute content area dimensions can be applied');\n return;\n }\n\n const borderBox = this.getBox(computedStyle, 'border');\n const paddingBox = this.getBox(computedStyle, 'padding');\n let userValuePx = Number(userInput.replace(/px$/, ''));\n if (isNaN(userValuePx)) {\n return;\n }\n if (styleProperty === 'width') {\n userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right;\n } else {\n userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom;\n }\n\n userInput = userValuePx + 'px';\n }\n\n this.previousPropertyDataCandidate = null;\n\n const allProperties = this.inlineStyle.allProperties();\n for (let i = 0; i < allProperties.length; ++i) {\n const property = allProperties[i];\n if (property.name !== context.styleProperty || !property.activeInStyle()) {\n continue;\n }\n\n this.previousPropertyDataCandidate = property;\n property.setValue(userInput, commitEditor, true, callback.bind(this));\n return;\n }\n\n this.inlineStyle.appendProperty(context.styleProperty, userInput, callback.bind(this));\n\n function callback(this: MetricsSidebarPane, success: boolean): void {\n if (!success) {\n return;\n }\n if (!this.originalPropertyData) {\n this.originalPropertyData = this.previousPropertyDataCandidate;\n }\n\n if (this.highlightMode) {\n const node = this.node();\n if (!node) {\n return;\n }\n node.highlight(this.highlightMode);\n }\n\n if (commitEditor) {\n this.update();\n }\n }\n }\n\n private editingCommitted(\n element: Element,\n userInput: string,\n previousContent: string|null,\n context: {\n box: string,\n styleProperty: string,\n computedStyle: Map,\n keyDownHandler: (arg0: Event) => void,\n },\n ): void {\n this.editingEnded(element, context);\n this.applyUserInput(element, userInput, previousContent, context, true);\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([metricsSidebarPaneStyles]);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/elements/PropertyMatchers.js b/public/panels/elements/PropertyMatchers.js index 206c84cf..f54e63f1 100644 --- a/public/panels/elements/PropertyMatchers.js +++ b/public/panels/elements/PropertyMatchers.js @@ -408,6 +408,9 @@ export class ShadowMatcher extends matcherBase(ShadowMatch) { return null; } const valueNodes = ASTUtils.siblings(ASTUtils.declValue(node)); + if (valueNodes.length === 0) { + return null; + } const valueText = matching.ast.textRange(valueNodes[0], valueNodes[valueNodes.length - 1]); return new ShadowMatch(valueText, node, matching.ast.propertyName === 'text-shadow' ? "textShadow" /* ShadowType.TEXT_SHADOW */ : "boxShadow" /* ShadowType.BOX_SHADOW */); } diff --git a/public/panels/elements/PropertyMatchers.js.map b/public/panels/elements/PropertyMatchers.js.map index 9f49ff41..675de320 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":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AAEtD,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAE7C,OAAO,KAAK,YAAY,MAAM,2DAA2D,CAAC;AAC1F,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAMhD,MAAM,QAAQ,GAAG,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC;AAChD,MAAM,WAAW,GAAG,GAAG,CAAC,iBAAiB,CAAC,WAAW,CAAC;AACtD,MAAM,mBAAmB,GAAG,GAAG,CAAC,iBAAiB,CAAC,mBAAmB,CAAC;AAEtE,MAAM,OAAO,UAAU;IACA;IAAuB;IAA5C,YAAqB,IAAY,EAAW,IAA2B;QAAlD,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;IACvE,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,YAAa,SAAQ,WAAW,CAAC,UAAU,CAAC;IACvD,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC1E,CAAC;IACQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,wCAAwC;QACxC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC/E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;CACF;AAED,SAAS,eAAe,CAAC,IAA2B,EAAE,GAAe;IACnE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE5B,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,OAAO,aAAa;IAEX;IAAuB;IAAsC;IAC7D;IAA0C;IAFvD,YACa,IAAY,EAAW,IAA2B,EAAW,KAA8B,EAC3F,MAA+B,EAAW,MAA+B;QADzE,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,UAAK,GAAL,KAAK,CAAyB;QAC3F,WAAM,GAAN,MAAM,CAAyB;QAAW,WAAM,GAAN,MAAM,CAAyB;IACtF,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,eAAgB,SAAQ,WAAW,CAAC,aAAa,CAAC;IAC7D,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC1E,CAAC;IACQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;YACjG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5F,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,iBAAiB,CAAC;QAClD,sFAAsF;QACtF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI;YAC/F,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8DAA8D;QAC9D,MAAM,EAAE,GACJ,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAC9G,MAAM,EAAE,GACJ,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAC9G,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,4GAA4G;QAC5G,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;YACxE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,QAAQ;IAEN;IAA+C;IAAuB;IADnF,YACa,GAAoC,EAAW,IAAY,EAAW,IAA2B;QAAjG,QAAG,GAAH,GAAG,CAAiC;QAAW,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;IAC9G,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,UAAW,SAAQ,WAAW,CAAC,QAAQ,CAAC;IACnD,kBAAkB;IACT,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtE,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG;YACrC,CAAC,OAAO,CAAC,IAAI,KAAK,sBAAsB,IAAI,OAAO,CAAC,IAAI,KAAK,eAAe,CAAC;YAC7E,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAC1D,CAAC;QACpC,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1D,CAAC;CACF;AAED,MAAM,OAAO,mBAAmB;IACT;IAAuB;IAA5C,YAAqB,IAAY,EAAW,IAA2B;QAAlD,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;IACvE,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,qBAAsB,SAAQ,WAAW,CAAC,mBAAmB,CAAC;IACzE,kBAAkB;IACT,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,EAAE,CAAC;YACvG,OAAO,IAAI,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACQ,OAAO,CAAC,YAAoB;QACnC,OAAO,CAAC,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACzF,CAAC;CACF;AAED,MAAM,OAAO,UAAU;IAGR;IAAuB;IACf;IAHrB,YAAY,CAAkC;IAC9C,YACa,IAAY,EAAW,IAA2B,EAC1C,oBAA0C;QADlD,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAC1C,yBAAoB,GAApB,oBAAoB,CAAsB;QAC7D,IAAI,CAAC,YAAY,GAAG,oBAAoB,CAAC;IAC3C,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,YAAa,SAAQ,WAAW,CAAC,UAAU,CAAC;IAC1B;IAA7B,YAA6B,oBAAwC;QACjE,KAAK,EAAE,CAAC;QADiB,yBAAoB,GAApB,oBAAoB,CAAoB;IAErE,CAAC;IACD,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC1E,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACjC,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACpC,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,cAAc,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC;gBAC3C,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,iDAAiD,CAAC,EAAE,CAAC;gBACjG,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,MAAM,OAAO,mBAAmB;IAEjB;IAAuB;IAAsC;IAC7D;IAFb,YACa,IAAY,EAAW,IAA2B,EAAW,KAA8B,EAC3F,IAA6B;QAD7B,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,UAAK,GAAL,KAAK,CAAyB;QAC3F,SAAI,GAAJ,IAAI,CAAyB;IAC1C,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,qBAAsB,SAAQ,WAAW,CAAC,mBAAmB,CAAC;IACzE,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC1E,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,KAAK,YAAY,EAAE,CAAC;YAClG,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,mBAAmB,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC;CACF;AAkBD,MAAM,OAAO,iBAAiB;IAEf;IAAuB;IAAsC;IAD1E,YACa,IAAY,EAAW,IAA2B,EAAW,YAAoC;QAAjG,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,iBAAY,GAAZ,YAAY,CAAwB;IAC9G,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,mBAAoB,SAAQ,WAAW,CAAC,iBAAiB,CAAC;IACrE,kBAAkB;IACV,MAAM,CAAC,sBAAsB,CAAC,YAAoB;QACxD,MAAM,KAAK,GAAa;;;;;;SAMvB,CAAC;QACF,OAAO,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,CAAU,8BAA8B,GAAuC,IAAI,GAAG,CACxF,MAAM,CAAC,OAAO,CAAC;QACb,MAAM,mDAAiC;QACvC,SAAS,mDAAiC;QAC1C,OAAO,mDAAiC;QACxC,mBAAmB,mDAAiC;QACpD,IAAI,mDAAiC;QACrC,QAAQ,mDAAiC;QACzC,SAAS,mDAAiC;QAC1C,IAAI,mDAAiC;QACrC,OAAO,qDAAkC;QACzC,MAAM,qDAAkC;QACxC,QAAQ,+DAAuC;QAC/C,MAAM,+DAAuC;QAC7C,IAAI,+DAAuC;QAC3C,SAAS,+DAAuC;QAChD,UAAU,+DAAuC;QACjD,aAAa,+DAAuC;KACrD,CAAC,CACL,CAAC;IAEM,6BAA6B,CAAC,IAA2B,EAAE,QAA8B;QAC/F,sHAAsH;QACtH,iFAAiF;QACjF,6HAA6H;QAC7H,oFAAoF;QACpF,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,oEAAoE;QACpE,IAAI,CAAC,mBAAmB,CAAC,8BAA8B,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAClE,OAAO,IAAI,iBAAiB,CAAC,IAAI,EAAE,IAAI,qDAAmC,CAAC;QAC7E,CAAC;QACD,sEAAsE;QACtE,2EAA2E;QAC3E,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9F,MAAM,uBAAuB,GAAG,YAAY,CAAC,IAAI,CAC7C,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,oEAAoE;QACpE,yDAAyD;QACzD,6CAA6C;QAC7C,MAAM,YAAY,GAAG,QAAQ,CAAC,oBAAoB,CAAC,uBAAuB,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACrF,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,kBAAkB,GACpB,mBAAmB,CAAC,8BAA8B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAE,oCAAoC;QACvG,KAAK,IAAI,MAAM,GAA+B,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAChG,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;YACjC,2DAA2D;YAC3D,2DAA2D;YAC3D,iEAAiE;YACjE,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAChC,MAAM,aAAa,GAAG,mBAAmB,CAAC,8BAA8B,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;gBACrG,IAAI,aAAa,IAAI,aAAa,KAAK,kBAAkB,EAAE,CAAC;oBAC1D,OAAO,IAAI,iBAAiB,CAAC,IAAI,EAAE,IAAI,qDAAmC,CAAC;gBAC7E,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEQ,OAAO,CAAC,YAAoB;QACnC,OAAO,mBAAmB,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC;IAClE,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,MAAM,EAAC,YAAY,EAAC,GAAG,QAAQ,CAAC,GAAG,CAAC;QACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,oBAAoB,GAAG,UAAU,CAAC,IAAI,KAAK,aAAa,CAAC;QAC/D,MAAM,eAAe,GAAG,UAAU,CAAC,IAAI,KAAK,SAAS,IAAI,UAAU,CAAC,WAAW,EAAE,IAAI,KAAK,QAAQ;YAC9F,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,KAAK,CAAC;QACxD,MAAM,6BAA6B,GAAG,oBAAoB,IAAI,eAAe,CAAC;QAC9E,mFAAmF;QACnF,MAAM,2BAA2B,GAAG,YAAY,6DAAwC;YACpF,YAAY,iFAAkD,CAAC;QACnE,+FAA+F;QAC/F,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC;YAC5E,CAAC,6BAA6B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,2BAA2B,CAAC,EAAE,CAAC;YACjG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,6BAA6B,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5D,CAAC;QAED,8DAA8D;QAC9D,sFAAsF;QACtF,OAAO,IAAI,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,YAAsC,CAAC,CAAC;IACnF,CAAC;;AAGH,MAAM,OAAO,WAAW;IACD;IAAuB;IAA5C,YAAqB,IAAY,EAAW,IAA2B;QAAlD,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;IACvE,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,aAAc,SAAQ,WAAW,CAAC,WAAW,CAAC;IACzD,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAC3E,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAErC,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1G,MAAM,6BAA6B,GAAG,IAAI,CAAC,IAAI,KAAK,gBAAgB;YAChE,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEpF,IAAI,CAAC,oBAAoB,IAAI,CAAC,6BAA6B,EAAE,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACxE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,WAAW;IACD;IAAuB;IAA5C,YAAqB,IAAY,EAAW,IAA2B;QAAlD,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;IACvE,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,aAAc,SAAQ,WAAW,CAAC,WAAW,CAAC;IACzD,kBAAkB;IACT,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,OAAO,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/F,CAAC;CACF;AAMD,MAAM,OAAO,WAAW;IACD;IAAuB;IAAsC;IAAlF,YAAqB,IAAY,EAAW,IAA2B,EAAW,UAAsB;QAAnF,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,eAAU,GAAV,UAAU,CAAY;IACxG,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,aAAc,SAAQ,WAAW,CAAC,WAAW,CAAC;IACzD,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACtE,CAAC;IACQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3F,OAAO,IAAI,WAAW,CAClB,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,YAAY,KAAK,aAAa,CAAC,CAAC,2CAAwB,CAAC,wCAAsB,CAAC,CAAC;IACrH,CAAC;CACF;AAED,MAAM,OAAO,SAAS;IACC;IAAuB;IAA5C,YAAqB,IAAY,EAAW,IAA2B;QAAlD,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;IACvE,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,WAAY,SAAQ,WAAW,CAAC,SAAS,CAAC;IACrD,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACzE,CAAC;IACQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,KAAK,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;YAC9C,YAAY,CAAC,eAAe,CAAC,mBAAmB,CAAC;QAC7G,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7D,CAAC;CACF;AAED,MAAM,OAAO,WAAW;IACD;IAAuB;IAA5C,YAAqB,IAAY,EAAW,IAA2B;QAAlD,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;IACvE,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,aAAc,SAAQ,WAAW,CAAC,WAAW,CAAC;IACzD,kBAAkB;IACT,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,CAAC,SAAS,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;CACF;AAED,MAAM,OAAO,aAAa;IACH;IAAuB;IAAsC;IAAlF,YAAqB,IAAY,EAAW,IAA2B,EAAW,MAAe;QAA5E,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,WAAM,GAAN,MAAM,CAAS;IACjG,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,eAAgB,SAAQ,WAAW,CAAC,aAAa,CAAC;IAC7D,kBAAkB;IAClB,MAAM,CAAU,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IAC5E,MAAM,CAAU,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IACnE,OAAO,CAAC,YAAoB;QACnC,OAAO,YAAY,KAAK,SAAS,CAAC;IACpC,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC;aAC/C,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;aAClD,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;;AAGH,MAAM,OAAO,iBAAiB;IACP;IAAuB;IAAsC;IAAlF,YAAqB,IAAY,EAAW,IAA2B,EAAW,KAAgC;QAA7F,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,UAAK,GAAL,KAAK,CAA2B;IAClH,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,mBAAoB,SAAQ,WAAW,CAAC,iBAAiB,CAAC;IACrE,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,0BAA0B,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IACQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,QAAQ,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YACpE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAA8B,EAAE,CAAC;QAC5C,IAAI,OAAO,GAA4B,EAAE,CAAC;QAC1C,iFAAiF;QACjF,6CAA6C;QAC7C,sFAAsF;QACtF,mFAAmF;QACnF,sFAAsF;QACtF,sFAAsF;QACtF,qEAAqE;QACrE,IAAI,mBAAmB,GAAG,KAAK,CAAC;QAChC,4FAA4F;QAC5F,0FAA0F;QAC1F,IAAI,oBAAoB,GAAG,KAAK,CAAC;QACjC,wFAAwF;QACxF,mCAAmC;QACnC,SAAS,UAAU,CAAC,KAA8B,EAAE,cAAc,GAAG,KAAK;YACxE,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;gBAC5B,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,GAAG,CAAC,iBAAiB,CAAC,aAAa,EAAE,CAAC;oBAC9E,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;oBAC/F,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBACvB,SAAS;oBACX,CAAC;oBACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC/E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBAC1B,SAAS;oBACX,CAAC;oBACD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,mBAAmB,CAAC;wBAC9D,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;wBAChE,iGAAiG;wBACjG,mDAAmD;wBACnD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACpB,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;oBACtB,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACxB,CAAC;oBACD,kFAAkF;oBAClF,oDAAoD;oBACpD,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAC7B,CAAC;qBAAM,IAAI,OAAO,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;oBAC/C,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;gBACpD,CAAC;qBAAM,IAAI,OAAO,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;oBAC5C,IAAI,CAAC,cAAc,EAAE,CAAC;wBACpB,IAAI,mBAAmB,EAAE,CAAC;4BACxB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACxB,CAAC;6BAAM,CAAC;4BACN,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;4BACpB,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;wBACtB,CAAC;oBACH,CAAC;oBACD,oBAAoB,GAAG,IAAI,CAAC;oBAC5B,mBAAmB,GAAG,KAAK,CAAC;gBAC9B,CAAC;qBAAM,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBACxC,IAAI,CAAC,cAAc,EAAE,CAAC;wBACpB,IAAI,oBAAoB,EAAE,CAAC;4BACzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACxB,CAAC;6BAAM,CAAC;4BACN,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;4BACpB,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;wBACtB,CAAC;oBACH,CAAC;oBACD,mBAAmB,GAAG,CAAC,oBAAoB,CAAC;oBAC5C,oBAAoB,GAAG,CAAC,oBAAoB,CAAC;gBAC/C,CAAC;qBAAM,IAAI,CAAC,cAAc,EAAE,CAAC;oBAC3B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,UAAU,CAAC,UAAU,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3F,OAAO,IAAI,iBAAiB,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACvF,CAAC;CACF;AACD,MAAM,OAAO,mBAAmB;IACT;IAAuB;IAAsC;IAAlF,YAAqB,IAAY,EAAW,IAA2B,EAAW,YAAyB;QAAtF,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,iBAAY,GAAZ,YAAY,CAAa;IAC3G,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,qBAAsB,SAAQ,WAAW,CAAC,mBAAmB,CAAC;IACzE,kBAAkB;IAClB,cAAc,CAAC,IAA2B,EAAE,QAA8B;QACxE,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9D,IAAI,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;YAC5D,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACjC,oFAAoF;YACpF,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YACzB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACzC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YACvB,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACtD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,IAAI,mBAAmB,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,4EAA4E;QAC5E,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QACzD,IAAI,UAAU,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,EAAE,CAAC;YAClD,kEAAkE;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,mBAAmB,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5E,CAAC;CACF;AAED,gDAAgD;AAChD,MAAM,OAAO,mBAAmB;IACT;IAAuB;IAAyC;IAArF,YAAqB,IAAY,EAAW,QAA8B,EAAW,IAA2B;QAA3F,SAAI,GAAJ,IAAI,CAAQ;QAAW,aAAQ,GAAR,QAAQ,CAAsB;QAAW,SAAI,GAAJ,IAAI,CAAuB;IAChH,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,qBAAsB,SAAQ,WAAW,CAAC,mBAAmB,CAAC;IACzE,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,YAAY,KAAK,iBAAiB,CAAC;IAC5C,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,OAAO,IAAI,mBAAmB,CAAC,gBAAgB,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;CACF;AAED,MAAM,OAAO,mBAAmB;IAEjB;IAA+C;IAC/C;IAAgD;IAF7D,YACa,IAAoC,EAAW,IAA2B,EAC1E,QAAqC,EAAW,aAAoD;QADpG,SAAI,GAAJ,IAAI,CAAgC;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAC1E,aAAQ,GAAR,QAAQ,CAA6B;QAAW,kBAAa,GAAb,aAAa,CAAuC;IACjH,CAAC;IACD,eAAe;QACb,OAAO,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3E,CAAC;IACD,YAAY;QACV,OAAO,IAAI,CAAC,eAAe,EAAE,EAAE,KAAK,IAAI,IAAI,CAAC;IAC/C,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,qBAAsB,SAAQ,WAAW,CAAC,mBAAmB,CAAC;IAG5D;IAAgD;IAF7D,kBAAkB;IAClB,YACa,QAAqC,EAAW,aAAoD;QAC/G,KAAK,EAAE,CAAC;QADG,aAAQ,GAAR,QAAQ,CAA6B;QAAW,kBAAa,GAAb,aAAa,CAAuC;IAEjH,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,UAAU,EAAE,IAAI,KAAK,aAAa,EAAE,CAAC;YACpE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;aAChF,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAChF,CAAC;CACF;AAED,MAAM,OAAO,gBAAgB;IAEd;IAAuB;IAAsC;IAC7D;IAFb,YACa,IAAY,EAAW,IAA2B,EAAW,QAAiC,EAC9F,SAAoC;QADpC,SAAI,GAAJ,IAAI,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAuB;QAAW,aAAQ,GAAR,QAAQ,CAAyB;QAC9F,cAAS,GAAT,SAAS,CAA2B;IACjD,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,kBAAmB,SAAQ,WAAW,CAAC,gBAAgB,CAAC;IACnE,kBAAkB;IACT,OAAO,CAAC,YAAoB;QACnC,OAAO,YAAY,6DAAwC;YACvD,YAAY,iFAAkD,CAAC;IACrE,CAAC;IAEQ,OAAO,CAAC,IAA2B,EAAE,QAA8B;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,QAAQ,GAA4B,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,GAAG,CAAC,YAAY,6DAAwC,EAAE,CAAC;YACtE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC5C,MAAM,YAAY,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;gBACjD,IAAI,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC/D,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,IAAI,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,yBAAyB,CAAC,YAAY,CAAC,EAAE,CAAC;oBACxE,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;oBACzC,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3F,OAAO,IAAI,gBAAgB,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACpE,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 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 propertyName: 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 FlexGridMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly isFlex: boolean) {\n }\n}\n\n// clang-format off\nexport class FlexGridMatcher extends matcherBase(FlexGridMatch) {\n // clang-format on\n static readonly FLEX = ['flex', 'inline-flex', 'block flex', 'inline flex'];\n static readonly GRID = ['grid', 'inline-grid', 'block grid', 'inline grid'];\n override accepts(propertyName: string): boolean {\n return propertyName === 'display';\n }\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 if (valueNodes.length < 1) {\n return null;\n }\n const values = valueNodes.filter(node => node.name !== 'Important')\n .map(node => matching.getComputedText(node).trim())\n .filter(value => value);\n const text = values.join(' ');\n if (FlexGridMatcher.FLEX.includes(text)) {\n return new FlexGridMatch(matching.ast.text(node), node, true);\n }\n if (FlexGridMatcher.GRID.includes(text)) {\n return new FlexGridMatch(matching.ast.text(node), node, false);\n }\n return null;\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 // clang-format on\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\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 // clang-format on\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\nexport class CSSWideKeywordMatch implements Match {\n constructor(\n readonly text: SDK.CSSMetadata.CSSWideKeyword, readonly node: CodeMirror.SyntaxNode,\n readonly property: SDK.CSSProperty.CSSProperty, readonly matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles) {\n }\n resolveProperty(): SDK.CSSMatchedStyles.CSSValueSource|null {\n return this.matchedStyles.resolveGlobalKeyword(this.property, this.text);\n }\n computedText?(): string|null {\n return this.resolveProperty()?.value ?? null;\n }\n}\n\n// clang-format off\nexport class CSSWideKeywordMatcher extends matcherBase(CSSWideKeywordMatch) {\n // clang-format on\n constructor(\n readonly property: SDK.CSSProperty.CSSProperty, readonly matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles) {\n super();\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const parentNode = node.parent;\n if (node.name !== 'ValueName' || parentNode?.name !== 'Declaration') {\n return null;\n }\n\n if (Array.from(ASTUtils.stripComments(ASTUtils.siblings(ASTUtils.declValue(parentNode))))\n .some(child => !ASTUtils.equals(child, node))) {\n return null;\n }\n\n const text = matching.ast.text(node);\n if (!SDK.CSSMetadata.CSSMetadata.isCSSWideKeyword(text)) {\n return null;\n }\n\n return new CSSWideKeywordMatch(text, node, this.property, this.matchedStyles);\n }\n}\n\nexport class PositionTryMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly preamble: CodeMirror.SyntaxNode[],\n readonly fallbacks: CodeMirror.SyntaxNode[][]) {\n }\n}\n\n// clang-format off\nexport class PositionTryMatcher extends matcherBase(PositionTryMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return propertyName === LinkableNameProperties.POSITION_TRY ||\n propertyName === LinkableNameProperties.POSITION_TRY_FALLBACKS;\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'Declaration') {\n return null;\n }\n\n let preamble: CodeMirror.SyntaxNode[] = [];\n const valueNodes = ASTUtils.siblings(ASTUtils.declValue(node));\n const fallbacks = ASTUtils.split(valueNodes);\n if (matching.ast.propertyName === LinkableNameProperties.POSITION_TRY) {\n for (const [i, n] of fallbacks[0].entries()) {\n const computedText = matching.getComputedText(n);\n if (SDK.CSSMetadata.CSSMetadata.isCSSWideKeyword(computedText)) {\n return null;\n }\n if (SDK.CSSMetadata.CSSMetadata.isPositionTryOrderKeyword(computedText)) {\n preamble = fallbacks[0].splice(0, i + 1);\n break;\n }\n }\n }\n\n const valueText = matching.ast.textRange(valueNodes[0], valueNodes[valueNodes.length - 1]);\n return new PositionTryMatch(valueText, node, preamble, fallbacks);\n }\n}\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 propertyName: 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 if (valueNodes.length === 0) {\n return null;\n }\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 FlexGridMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly isFlex: boolean) {\n }\n}\n\n// clang-format off\nexport class FlexGridMatcher extends matcherBase(FlexGridMatch) {\n // clang-format on\n static readonly FLEX = ['flex', 'inline-flex', 'block flex', 'inline flex'];\n static readonly GRID = ['grid', 'inline-grid', 'block grid', 'inline grid'];\n override accepts(propertyName: string): boolean {\n return propertyName === 'display';\n }\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 if (valueNodes.length < 1) {\n return null;\n }\n const values = valueNodes.filter(node => node.name !== 'Important')\n .map(node => matching.getComputedText(node).trim())\n .filter(value => value);\n const text = values.join(' ');\n if (FlexGridMatcher.FLEX.includes(text)) {\n return new FlexGridMatch(matching.ast.text(node), node, true);\n }\n if (FlexGridMatcher.GRID.includes(text)) {\n return new FlexGridMatch(matching.ast.text(node), node, false);\n }\n return null;\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 // clang-format on\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\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 // clang-format on\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\nexport class CSSWideKeywordMatch implements Match {\n constructor(\n readonly text: SDK.CSSMetadata.CSSWideKeyword, readonly node: CodeMirror.SyntaxNode,\n readonly property: SDK.CSSProperty.CSSProperty, readonly matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles) {\n }\n resolveProperty(): SDK.CSSMatchedStyles.CSSValueSource|null {\n return this.matchedStyles.resolveGlobalKeyword(this.property, this.text);\n }\n computedText?(): string|null {\n return this.resolveProperty()?.value ?? null;\n }\n}\n\n// clang-format off\nexport class CSSWideKeywordMatcher extends matcherBase(CSSWideKeywordMatch) {\n // clang-format on\n constructor(\n readonly property: SDK.CSSProperty.CSSProperty, readonly matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles) {\n super();\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const parentNode = node.parent;\n if (node.name !== 'ValueName' || parentNode?.name !== 'Declaration') {\n return null;\n }\n\n if (Array.from(ASTUtils.stripComments(ASTUtils.siblings(ASTUtils.declValue(parentNode))))\n .some(child => !ASTUtils.equals(child, node))) {\n return null;\n }\n\n const text = matching.ast.text(node);\n if (!SDK.CSSMetadata.CSSMetadata.isCSSWideKeyword(text)) {\n return null;\n }\n\n return new CSSWideKeywordMatch(text, node, this.property, this.matchedStyles);\n }\n}\n\nexport class PositionTryMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly preamble: CodeMirror.SyntaxNode[],\n readonly fallbacks: CodeMirror.SyntaxNode[][]) {\n }\n}\n\n// clang-format off\nexport class PositionTryMatcher extends matcherBase(PositionTryMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return propertyName === LinkableNameProperties.POSITION_TRY ||\n propertyName === LinkableNameProperties.POSITION_TRY_FALLBACKS;\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'Declaration') {\n return null;\n }\n\n let preamble: CodeMirror.SyntaxNode[] = [];\n const valueNodes = ASTUtils.siblings(ASTUtils.declValue(node));\n const fallbacks = ASTUtils.split(valueNodes);\n if (matching.ast.propertyName === LinkableNameProperties.POSITION_TRY) {\n for (const [i, n] of fallbacks[0].entries()) {\n const computedText = matching.getComputedText(n);\n if (SDK.CSSMetadata.CSSMetadata.isCSSWideKeyword(computedText)) {\n return null;\n }\n if (SDK.CSSMetadata.CSSMetadata.isPositionTryOrderKeyword(computedText)) {\n preamble = fallbacks[0].splice(0, i + 1);\n break;\n }\n }\n }\n\n const valueText = matching.ast.textRange(valueNodes[0], valueNodes[valueNodes.length - 1]);\n return new PositionTryMatch(valueText, node, preamble, fallbacks);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/elements/StylePropertiesSection.d.ts b/public/panels/elements/StylePropertiesSection.d.ts index 15724b74..56f74c5a 100644 --- a/public/panels/elements/StylePropertiesSection.d.ts +++ b/public/panels/elements/StylePropertiesSection.d.ts @@ -112,7 +112,7 @@ export declare class StylePropertiesSection { private startEditingAtFirstPosition; startEditingSelector(): void; moveEditorFromSelector(moveDirection: string): void; - editingSelectorCommitted(element: Element, newContent: string, oldContent: string, context: Context | undefined, moveDirection: string): void; + editingSelectorCommitted(element: Element, newContent: string, oldContent: string | null, context: Context | undefined, moveDirection: string): void; setHeaderText(rule: SDK.CSSRule.CSSRule, newContent: string): Promise; protected editingSelectorCommittedForTest(): void; protected updateRuleOrigin(): void; diff --git a/public/panels/elements/StylePropertiesSection.js b/public/panels/elements/StylePropertiesSection.js index b4a9f178..5b62e562 100644 --- a/public/panels/elements/StylePropertiesSection.js +++ b/public/panels/elements/StylePropertiesSection.js @@ -1261,7 +1261,7 @@ export class StylePropertiesSection { if (textContent !== null) { element.textContent = textContent.replace(/\s+/g, ' ').trim(); } - const config = new UI.InplaceEditor.Config(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this)); + const config = new UI.InplaceEditor.Config(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), undefined); UI.InplaceEditor.InplaceEditor.startEditing(this.selectorElement, config); const selection = element.getComponentSelection(); if (selection) { diff --git a/public/panels/elements/StylePropertiesSection.js.map b/public/panels/elements/StylePropertiesSection.js.map index 2322ed1a..6a4ae3b7 100644 --- a/public/panels/elements/StylePropertiesSection.js.map +++ b/public/panels/elements/StylePropertiesSection.js.map @@ -1 +1 @@ -{"version":3,"file":"StylePropertiesSection.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/StylePropertiesSection.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 * Copyright (C) 2007 Apple Inc. All rights reserved.\n * Copyright (C) 2009 Joseph Pecoraro\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 Bindings from '../../models/bindings/bindings.js';\nimport * as TextUtils from '../../models/text_utils/text_utils.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport type * 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 {FontEditorSectionManager} from './ColorSwatchPopoverIcon.js';\nimport * as ElementsComponents from './components/components.js';\nimport {linkifyDeferredNodeReference} from './DOMLinkifier.js';\nimport {ElementsPanel} from './ElementsPanel.js';\nimport stylePropertiesTreeOutlineStyles from './stylePropertiesTreeOutline.css.js';\nimport {type Context, StylePropertyTreeElement} from './StylePropertyTreeElement.js';\nimport {StylesSidebarPane} from './StylesSidebarPane.js';\n\nconst UIStrings = {\n /**\n *@description Tooltip text that appears when hovering over the largeicon add button in the Styles Sidebar Pane of the Elements panel\n */\n insertStyleRuleBelow: 'Insert style rule below',\n /**\n *@description Text in Styles Sidebar Pane of the Elements panel\n */\n constructedStylesheet: 'constructed stylesheet',\n /**\n *@description Text in Styles Sidebar Pane of the Elements panel\n */\n userAgentStylesheet: 'user agent stylesheet',\n /**\n *@description Text in Styles Sidebar Pane of the Elements panel\n */\n injectedStylesheet: 'injected stylesheet',\n /**\n *@description Text in Styles Sidebar Pane of the Elements panel\n */\n viaInspector: 'via inspector',\n /**\n *@description Text in Styles Sidebar Pane of the Elements panel\n */\n styleAttribute: '`style` attribute',\n /**\n *@description Text in Styles Sidebar Pane of the Elements panel\n *@example {html} PH1\n */\n sattributesStyle: '{PH1}[Attributes Style]',\n /**\n *@description Show all button text content in Styles Sidebar Pane of the Elements panel\n *@example {3} PH1\n */\n showAllPropertiesSMore: 'Show all properties ({PH1} more)',\n /**\n *@description Text in Elements Tree Element of the Elements panel, copy should be used as a verb\n */\n copySelector: 'Copy `selector`',\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 Text that is announced by the screen reader when the user focuses on an input field for editing the name of a CSS selector in the Styles panel\n */\n cssSelector: '`CSS` selector',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/StylePropertiesSection.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst STYLE_TAG = '