chrome-devtools-frontend 1.0.1526630 → 1.0.1529186
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/ui_engineering.md +159 -0
- package/eslint.config.mjs +6 -1
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/i18n/i18nImpl.ts +6 -1
- package/front_end/core/protocol_client/protocol_client.ts +1 -1
- package/front_end/core/root/Runtime.ts +38 -4
- package/front_end/core/sdk/CSSMatchedStyles.ts +50 -7
- package/front_end/core/sdk/CSSRule.ts +35 -6
- package/front_end/core/sdk/Connections.ts +2 -1
- package/front_end/core/sdk/DOMModel.ts +4 -0
- package/front_end/core/sdk/DebuggerModel.ts +5 -1
- package/front_end/core/sdk/NetworkManager.ts +267 -34
- package/front_end/core/sdk/PreloadingModel.ts +82 -17
- package/front_end/core/sdk/RehydratingConnection.snapshot.txt +1 -1
- package/front_end/core/sdk/RehydratingConnection.ts +29 -4
- package/front_end/core/sdk/ScopeTreeCache.ts +8 -3
- package/front_end/core/sdk/SourceMap.ts +41 -11
- package/front_end/core/sdk/SourceMapManager.ts +13 -2
- package/front_end/core/sdk/SourceMapScopesInfo.ts +49 -2
- package/front_end/core/sdk/TargetManager.ts +0 -22
- package/front_end/core/sdk/TraceObject.ts +8 -7
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +81 -0
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +3 -1
- package/front_end/entrypoints/main/GlobalAiButton.ts +1 -0
- package/front_end/entrypoints/main/MainImpl.ts +42 -28
- package/front_end/generated/InspectorBackendCommands.js +3 -2
- package/front_end/generated/SupportedCSSProperties.js +2 -0
- package/front_end/generated/protocol.ts +17 -3
- package/front_end/models/ai_assistance/BuiltInAi.ts +111 -0
- package/front_end/models/ai_assistance/ConversationHandler.ts +15 -14
- package/front_end/models/ai_assistance/ai_assistance.ts +53 -24
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +105 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +6 -1
- package/front_end/models/extensions/ExtensionView.ts +3 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +31 -27
- package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +31 -29
- package/front_end/models/persistence/NetworkPersistenceManager.ts +3 -5
- package/front_end/models/persistence/PersistenceImpl.ts +0 -5
- package/front_end/models/persistence/persistence-meta.ts +0 -31
- package/front_end/models/persistence/persistence.ts +0 -6
- package/front_end/models/source_map_scopes/NamesResolver.ts +5 -11
- package/front_end/models/stack_trace/Trie.ts +9 -0
- package/front_end/models/trace/lantern/types/Lantern.ts +1 -1
- package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +1 -0
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +1 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +120 -113
- package/front_end/panels/ai_assistance/PatchWidget.ts +9 -8
- package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +2 -0
- package/front_end/panels/ai_assistance/components/ChatView.ts +29 -29
- package/front_end/panels/ai_assistance/components/UserActionRow.ts +1 -0
- package/front_end/panels/animation/AnimationTimeline.ts +1 -0
- package/front_end/panels/application/CookieItemsView.ts +1 -0
- package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -0
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +2 -0
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +11 -5
- package/front_end/panels/application/preloading/components/PreloadingMismatchedHeadersGrid.ts +2 -2
- package/front_end/panels/application/preloading/components/PreloadingString.ts +7 -5
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +22 -10
- package/front_end/panels/changes/CombinedDiffView.ts +1 -0
- package/front_end/{models/persistence → panels/common}/PersistenceUtils.ts +15 -17
- package/front_end/panels/common/common.ts +1 -0
- package/front_end/panels/console/ConsoleInsightTeaser.ts +369 -0
- package/front_end/panels/console/ConsolePanel.ts +2 -0
- package/front_end/panels/console/ConsolePrompt.ts +12 -2
- package/front_end/panels/console/ConsoleSidebar.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +12 -0
- package/front_end/panels/console/ConsoleViewMessage.ts +44 -0
- package/front_end/panels/{explain → console}/PromptBuilder.ts +12 -7
- package/front_end/panels/console/console-meta.ts +14 -0
- package/front_end/panels/console/console.ts +6 -0
- package/front_end/panels/console/consoleInsightTeaser.css +83 -0
- package/front_end/panels/coverage/CoverageListView.ts +29 -11
- package/front_end/panels/coverage/CoverageView.ts +292 -284
- package/front_end/panels/coverage/coverageView.css +17 -0
- package/front_end/panels/elements/ComputedStyleWidget.ts +1 -0
- package/front_end/panels/elements/LayoutPane.ts +1 -0
- package/front_end/panels/elements/NodeStackTraceWidget.ts +1 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +5 -1
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +17 -0
- package/front_end/panels/emulation/DeviceModeView.ts +2 -0
- package/front_end/panels/explain/ActionDelegate.ts +4 -2
- package/front_end/panels/explain/components/ConsoleInsight.ts +14 -12
- package/front_end/panels/explain/explain-meta.ts +7 -0
- package/front_end/panels/explain/explain.ts +0 -1
- package/front_end/panels/js_timeline/js_timeline-meta.ts +1 -1
- package/front_end/panels/layer_viewer/Layers3DView.ts +2 -0
- package/front_end/panels/lighthouse/LighthouseReportSelector.ts +1 -0
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +1 -0
- package/front_end/panels/media/MainView.ts +1 -0
- package/front_end/panels/media/TickingFlameChart.ts +2 -0
- package/front_end/panels/network/BlockedURLsPane.ts +237 -108
- package/front_end/panels/network/EventSourceMessagesView.ts +1 -0
- package/front_end/panels/network/NetworkItemView.ts +1 -0
- package/front_end/panels/network/NetworkLogView.ts +9 -7
- package/front_end/panels/network/NetworkOverview.ts +1 -0
- package/front_end/panels/network/RequestCookiesView.ts +1 -0
- package/front_end/panels/network/RequestHTMLView.ts +1 -0
- package/front_end/panels/network/RequestInitiatorView.ts +1 -0
- package/front_end/panels/network/RequestPayloadView.ts +1 -0
- package/front_end/panels/network/RequestPreviewView.ts +1 -0
- package/front_end/panels/network/RequestResponseView.ts +1 -0
- package/front_end/panels/network/RequestTimingView.ts +2 -0
- package/front_end/panels/network/ResourceDirectSocketChunkView.ts +1 -0
- package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -0
- package/front_end/panels/network/components/RequestHeadersView.ts +2 -0
- package/front_end/panels/network/components/RequestTrustTokensView.ts +2 -0
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +2 -0
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +2 -0
- package/front_end/panels/profiler/HeapSnapshotView.ts +7 -0
- package/front_end/panels/profiler/IsolateSelector.ts +1 -0
- package/front_end/panels/profiler/LiveHeapProfileView.ts +1 -0
- package/front_end/panels/profiler/ProfileView.ts +1 -0
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -0
- package/front_end/panels/recorder/RecorderPanel.ts +2 -0
- package/front_end/panels/screencast/ScreencastView.ts +1 -0
- package/front_end/panels/search/SearchView.ts +1 -0
- package/front_end/panels/settings/AISettingsTab.ts +3 -3
- package/front_end/{models/persistence → panels/settings}/EditFileSystemView.ts +3 -6
- package/front_end/panels/settings/WorkspaceSettingsTab.ts +4 -1
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -2
- package/front_end/panels/settings/settings.ts +2 -0
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +12 -0
- package/front_end/panels/sources/BreakpointsView.ts +1 -0
- package/front_end/panels/sources/DebuggerPlugin.ts +1 -0
- package/front_end/{models/persistence → panels/sources}/PersistenceActions.ts +8 -12
- package/front_end/panels/sources/TabbedEditorContainer.ts +2 -1
- package/front_end/panels/sources/UISourceCodeFrame.ts +17 -2
- package/front_end/panels/sources/sources-meta.ts +15 -0
- package/front_end/panels/sources/sources.ts +2 -0
- package/front_end/panels/timeline/README.md +2 -2
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +1 -1
- package/front_end/panels/timeline/TimelineFlameChartView.ts +4 -3
- package/front_end/panels/timeline/TimelineLayersView.ts +1 -0
- package/front_end/panels/timeline/TimelinePaintProfilerView.ts +114 -37
- package/front_end/panels/timeline/TimelinePanel.ts +43 -62
- package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
- package/front_end/panels/timeline/components/LiveMetricsView.ts +4 -8
- package/front_end/panels/timeline/components/Sidebar.ts +2 -0
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +7 -7
- package/front_end/panels/timeline/overlays/OverlaysImpl.ts +1 -1
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +4 -4
- package/front_end/panels/utils/utils.ts +2 -1
- package/front_end/panels/web_audio/WebAudioView.ts +1 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/diff/diff_match_patch.js +1 -1
- package/front_end/third_party/lighthouse/README.chromium +2 -2
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1530 -2426
- package/front_end/third_party/lighthouse/locales/ar-XB.json +107 -455
- package/front_end/third_party/lighthouse/locales/ar.json +107 -455
- package/front_end/third_party/lighthouse/locales/bg.json +96 -444
- package/front_end/third_party/lighthouse/locales/ca.json +96 -444
- package/front_end/third_party/lighthouse/locales/cs.json +96 -444
- package/front_end/third_party/lighthouse/locales/da.json +96 -444
- package/front_end/third_party/lighthouse/locales/de.json +96 -444
- package/front_end/third_party/lighthouse/locales/el.json +96 -444
- package/front_end/third_party/lighthouse/locales/en-GB.json +96 -444
- package/front_end/third_party/lighthouse/locales/en-US.json +116 -467
- package/front_end/third_party/lighthouse/locales/en-XA.json +93 -441
- package/front_end/third_party/lighthouse/locales/en-XL.json +116 -467
- package/front_end/third_party/lighthouse/locales/es-419.json +96 -444
- package/front_end/third_party/lighthouse/locales/es.json +96 -444
- package/front_end/third_party/lighthouse/locales/fi.json +96 -444
- package/front_end/third_party/lighthouse/locales/fil.json +96 -444
- package/front_end/third_party/lighthouse/locales/fr.json +96 -444
- package/front_end/third_party/lighthouse/locales/he.json +118 -466
- package/front_end/third_party/lighthouse/locales/hi.json +96 -444
- package/front_end/third_party/lighthouse/locales/hr.json +100 -448
- package/front_end/third_party/lighthouse/locales/hu.json +96 -444
- package/front_end/third_party/lighthouse/locales/id.json +96 -444
- package/front_end/third_party/lighthouse/locales/it.json +96 -444
- package/front_end/third_party/lighthouse/locales/ja.json +96 -444
- package/front_end/third_party/lighthouse/locales/ko.json +97 -445
- package/front_end/third_party/lighthouse/locales/lt.json +96 -444
- package/front_end/third_party/lighthouse/locales/lv.json +97 -445
- package/front_end/third_party/lighthouse/locales/nl.json +96 -444
- package/front_end/third_party/lighthouse/locales/no.json +96 -444
- package/front_end/third_party/lighthouse/locales/pl.json +96 -444
- package/front_end/third_party/lighthouse/locales/pt-PT.json +96 -444
- package/front_end/third_party/lighthouse/locales/pt.json +97 -445
- package/front_end/third_party/lighthouse/locales/ro.json +97 -445
- package/front_end/third_party/lighthouse/locales/ru.json +96 -444
- package/front_end/third_party/lighthouse/locales/sk.json +96 -444
- package/front_end/third_party/lighthouse/locales/sl.json +96 -444
- package/front_end/third_party/lighthouse/locales/sr-Latn.json +96 -444
- package/front_end/third_party/lighthouse/locales/sr.json +96 -444
- package/front_end/third_party/lighthouse/locales/sv.json +96 -444
- package/front_end/third_party/lighthouse/locales/ta.json +96 -444
- package/front_end/third_party/lighthouse/locales/te.json +97 -445
- package/front_end/third_party/lighthouse/locales/th.json +96 -444
- package/front_end/third_party/lighthouse/locales/tr.json +96 -444
- package/front_end/third_party/lighthouse/locales/uk.json +96 -444
- package/front_end/third_party/lighthouse/locales/vi.json +96 -444
- package/front_end/third_party/lighthouse/locales/zh-HK.json +96 -444
- package/front_end/third_party/lighthouse/locales/zh-TW.json +97 -445
- package/front_end/third_party/lighthouse/locales/zh.json +96 -444
- package/front_end/third_party/lighthouse/report/bundle.d.ts +8 -14
- package/front_end/third_party/lighthouse/report/bundle.js +10 -49
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
- package/front_end/third_party/web-vitals/README.chromium +5 -8
- package/front_end/third_party/web-vitals/package/README.md +191 -152
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/index.d.ts +0 -1
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/index.js +0 -1
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.d.ts +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.js +45 -26
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.d.ts +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.js +3 -3
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.d.ts +10 -10
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +307 -206
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.d.ts +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.js +69 -49
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.d.ts +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.js +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/index.d.ts +0 -1
- package/front_end/third_party/web-vitals/package/dist/modules/index.js +0 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.d.ts +33 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.js +111 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/LCPEntryManager.d.ts +4 -0
- package/front_end/third_party/web-vitals/package/dist/modules/{attribution/deprecated.js → lib/LCPEntryManager.js} +6 -7
- package/front_end/third_party/web-vitals/package/dist/modules/lib/LayoutShiftManager.d.ts +6 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/LayoutShiftManager.js +44 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/bindReporter.js +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/generateUniqueID.js +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getActivationStart.js +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getNavigationEntry.js +5 -7
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.js +9 -12
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.d.ts +1 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.js +52 -33
- package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.d.ts +0 -2
- package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.js +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/lib/initUnique.d.ts +6 -0
- package/front_end/third_party/web-vitals/package/dist/modules/{deprecated.js → lib/initUnique.js} +11 -4
- package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.js +3 -6
- package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/interactionCountPolyfill.js +6 -6
- package/front_end/third_party/web-vitals/package/dist/modules/lib/{whenIdle.d.ts → whenIdleOrHidden.d.ts} +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/{whenIdle.js → whenIdleOrHidden.js} +10 -8
- package/front_end/third_party/web-vitals/package/dist/modules/onCLS.js +17 -35
- package/front_end/third_party/web-vitals/package/dist/modules/onFCP.js +3 -5
- package/front_end/third_party/web-vitals/package/dist/modules/onINP.d.ts +9 -7
- package/front_end/third_party/web-vitals/package/dist/modules/onINP.js +27 -19
- package/front_end/third_party/web-vitals/package/dist/modules/onLCP.js +33 -26
- package/front_end/third_party/web-vitals/package/dist/modules/onTTFB.js +2 -4
- package/front_end/third_party/web-vitals/package/dist/modules/types/base.d.ts +6 -5
- package/front_end/third_party/web-vitals/package/dist/modules/types/cls.d.ts +5 -3
- package/front_end/third_party/web-vitals/package/dist/modules/types/inp.d.ts +80 -33
- package/front_end/third_party/web-vitals/package/dist/modules/types/lcp.d.ts +6 -2
- package/front_end/third_party/web-vitals/package/dist/modules/types.d.ts +28 -4
- package/front_end/third_party/web-vitals/package/dist/modules/types.js +0 -1
- package/front_end/third_party/web-vitals/package/package.json +4 -10
- package/front_end/third_party/web-vitals/package/src/attribution/index.ts +0 -1
- package/front_end/third_party/web-vitals/package/src/attribution/onCLS.ts +58 -33
- package/front_end/third_party/web-vitals/package/src/attribution/onFCP.ts +4 -4
- package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +382 -258
- package/front_end/third_party/web-vitals/package/src/attribution/onLCP.ts +96 -69
- package/front_end/third_party/web-vitals/package/src/attribution/onTTFB.ts +3 -3
- package/front_end/third_party/web-vitals/package/src/index.ts +0 -1
- package/front_end/third_party/web-vitals/package/src/lib/InteractionManager.ts +146 -0
- package/front_end/third_party/web-vitals/package/src/{attribution/deprecated.ts → lib/LCPEntryManager.ts} +6 -9
- package/front_end/third_party/web-vitals/package/src/lib/LayoutShiftManager.ts +50 -0
- package/front_end/third_party/web-vitals/package/src/lib/bindReporter.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/lib/generateUniqueID.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/lib/getActivationStart.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/lib/getNavigationEntry.ts +5 -8
- package/front_end/third_party/web-vitals/package/src/lib/getSelector.ts +12 -12
- package/front_end/third_party/web-vitals/package/src/lib/getVisibilityWatcher.ts +57 -35
- package/front_end/third_party/web-vitals/package/src/lib/initMetric.ts +2 -2
- package/front_end/third_party/web-vitals/package/src/{deprecated.ts → lib/initUnique.ts} +14 -8
- package/front_end/third_party/web-vitals/package/src/lib/observe.ts +3 -11
- package/front_end/third_party/web-vitals/package/src/lib/polyfills/interactionCountPolyfill.ts +12 -6
- package/front_end/third_party/web-vitals/package/src/lib/{whenIdle.ts → whenIdleOrHidden.ts} +10 -8
- package/front_end/third_party/web-vitals/package/src/onCLS.ts +17 -38
- package/front_end/third_party/web-vitals/package/src/onFCP.ts +3 -6
- package/front_end/third_party/web-vitals/package/src/onINP.ts +33 -28
- package/front_end/third_party/web-vitals/package/src/onLCP.ts +36 -29
- package/front_end/third_party/web-vitals/package/src/onTTFB.ts +2 -5
- package/front_end/third_party/web-vitals/package/src/types/base.ts +5 -5
- package/front_end/third_party/web-vitals/package/src/types/cls.ts +5 -3
- package/front_end/third_party/web-vitals/package/src/types/inp.ts +88 -33
- package/front_end/third_party/web-vitals/package/src/types/lcp.ts +6 -2
- package/front_end/third_party/web-vitals/package/src/types.ts +47 -4
- package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +75 -0
- package/front_end/third_party/web-vitals/rebuild.sh +32 -18
- package/front_end/third_party/web-vitals/web-vitals-tsconfig.json +5 -10
- package/front_end/third_party/web-vitals/web-vitals.ts +0 -2
- package/front_end/ui/components/docs/console_insight/basic.ts +3 -2
- package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +2 -0
- package/front_end/ui/components/text_editor/TextEditor.ts +0 -2
- package/front_end/ui/legacy/InspectorView.ts +2 -0
- package/front_end/ui/legacy/ListWidget.ts +2 -2
- package/front_end/ui/legacy/SplitWidget.ts +2 -0
- package/front_end/ui/legacy/TabbedPane.ts +1 -0
- package/front_end/ui/legacy/TargetCrashedScreen.ts +1 -0
- package/front_end/ui/legacy/UIUtils.ts +8 -19
- package/front_end/ui/legacy/ViewManager.ts +1 -0
- package/front_end/ui/legacy/components/color_picker/FormatPickerContextMenu.ts +7 -20
- package/front_end/ui/legacy/components/color_picker/Spectrum.ts +2 -0
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +1 -0
- package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +1 -0
- package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +1 -0
- package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/FontView.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/StreamingContentHexView.ts +2 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +25 -0
- package/mcp/README.md +7 -0
- package/mcp/mcp.ts +8 -0
- package/package.json +1 -1
- package/front_end/models/live-metrics/web-vitals-injected/OnEachInteraction.ts +0 -34
- package/front_end/third_party/web-vitals/package/attribution.d.ts +0 -16
- package/front_end/third_party/web-vitals/package/attribution.js +0 -18
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/deprecated.d.ts +0 -7
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFID.d.ts +0 -11
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFID.js +0 -46
- package/front_end/third_party/web-vitals/package/dist/modules/deprecated.d.ts +0 -5
- package/front_end/third_party/web-vitals/package/dist/modules/lib/interactions.d.ts +0 -31
- package/front_end/third_party/web-vitals/package/dist/modules/lib/interactions.js +0 -107
- package/front_end/third_party/web-vitals/package/dist/modules/lib/onHidden.d.ts +0 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/onHidden.js +0 -22
- package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/firstInputPolyfill.d.ts +0 -7
- package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/firstInputPolyfill.js +0 -147
- package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.d.ts +0 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.js +0 -25
- package/front_end/third_party/web-vitals/package/dist/modules/onFID.d.ts +0 -13
- package/front_end/third_party/web-vitals/package/dist/modules/onFID.js +0 -70
- package/front_end/third_party/web-vitals/package/dist/modules/types/fid.d.ts +0 -46
- package/front_end/third_party/web-vitals/package/dist/modules/types/fid.js +0 -16
- package/front_end/third_party/web-vitals/package/src/attribution/onFID.ts +0 -62
- package/front_end/third_party/web-vitals/package/src/lib/interactions.ts +0 -139
- package/front_end/third_party/web-vitals/package/src/lib/onHidden.ts +0 -23
- package/front_end/third_party/web-vitals/package/src/lib/polyfills/firstInputPolyfill.ts +0 -174
- package/front_end/third_party/web-vitals/package/src/onFID.ts +0 -105
- package/front_end/third_party/web-vitals/package/src/types/fid.ts +0 -65
- package/front_end/ui/components/text_editor/textEditor.css +0 -18
- package/front_end/ui/legacy/inlineButton.css +0 -22
- /package/front_end/entrypoints/{rehydrated_devtools_app/rehydrated_devtools_app.ts → trace_app/trace_app.ts} +0 -0
- /package/front_end/{models/persistence → panels/settings}/editFileSystemView.css +0 -0
|
@@ -15,55 +15,9 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { getNavigationEntry } from '../lib/getNavigationEntry.js';
|
|
17
17
|
import { getSelector } from '../lib/getSelector.js';
|
|
18
|
+
import { initUnique } from '../lib/initUnique.js';
|
|
19
|
+
import { LCPEntryManager } from '../lib/LCPEntryManager.js';
|
|
18
20
|
import { onLCP as unattributedOnLCP } from '../onLCP.js';
|
|
19
|
-
const attributeLCP = (metric) => {
|
|
20
|
-
// Use a default object if no other attribution has been set.
|
|
21
|
-
let attribution = {
|
|
22
|
-
timeToFirstByte: 0,
|
|
23
|
-
resourceLoadDelay: 0,
|
|
24
|
-
resourceLoadDuration: 0,
|
|
25
|
-
elementRenderDelay: metric.value,
|
|
26
|
-
};
|
|
27
|
-
if (metric.entries.length) {
|
|
28
|
-
const navigationEntry = getNavigationEntry();
|
|
29
|
-
if (navigationEntry) {
|
|
30
|
-
const activationStart = navigationEntry.activationStart || 0;
|
|
31
|
-
const lcpEntry = metric.entries[metric.entries.length - 1];
|
|
32
|
-
const lcpResourceEntry = lcpEntry.url &&
|
|
33
|
-
performance
|
|
34
|
-
.getEntriesByType('resource')
|
|
35
|
-
.filter((e) => e.name === lcpEntry.url)[0];
|
|
36
|
-
const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
|
|
37
|
-
const lcpRequestStart = Math.max(ttfb,
|
|
38
|
-
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
|
|
39
|
-
lcpResourceEntry
|
|
40
|
-
? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) -
|
|
41
|
-
activationStart
|
|
42
|
-
: 0);
|
|
43
|
-
const lcpResponseEnd = Math.max(lcpRequestStart, lcpResourceEntry ? lcpResourceEntry.responseEnd - activationStart : 0);
|
|
44
|
-
const lcpRenderTime = Math.max(lcpResponseEnd, lcpEntry.startTime - activationStart);
|
|
45
|
-
attribution = {
|
|
46
|
-
element: getSelector(lcpEntry.element),
|
|
47
|
-
timeToFirstByte: ttfb,
|
|
48
|
-
resourceLoadDelay: lcpRequestStart - ttfb,
|
|
49
|
-
resourceLoadDuration: lcpResponseEnd - lcpRequestStart,
|
|
50
|
-
elementRenderDelay: lcpRenderTime - lcpResponseEnd,
|
|
51
|
-
navigationEntry,
|
|
52
|
-
lcpEntry,
|
|
53
|
-
};
|
|
54
|
-
// Only attribution the URL and resource entry if they exist.
|
|
55
|
-
if (lcpEntry.url) {
|
|
56
|
-
attribution.url = lcpEntry.url;
|
|
57
|
-
}
|
|
58
|
-
if (lcpResourceEntry) {
|
|
59
|
-
attribution.lcpResourceEntry = lcpResourceEntry;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Use Object.assign to set property to keep tsc happy.
|
|
64
|
-
const metricWithAttribution = Object.assign(metric, { attribution });
|
|
65
|
-
return metricWithAttribution;
|
|
66
|
-
};
|
|
67
21
|
/**
|
|
68
22
|
* Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
|
|
69
23
|
* calls the `callback` function once the value is ready (along with the
|
|
@@ -75,7 +29,73 @@ const attributeLCP = (metric) => {
|
|
|
75
29
|
* performance entry is dispatched, or once the final value of the metric has
|
|
76
30
|
* been determined.
|
|
77
31
|
*/
|
|
78
|
-
export const onLCP = (onReport, opts) => {
|
|
32
|
+
export const onLCP = (onReport, opts = {}) => {
|
|
33
|
+
// Clone the opts object to ensure it's unique, so we can initialize a
|
|
34
|
+
// single instance of the `LCPEntryManager` class that's shared only with
|
|
35
|
+
// this function invocation and the `unattributedOnLCP()` invocation below
|
|
36
|
+
// (which is passed the same `opts` object).
|
|
37
|
+
opts = Object.assign({}, opts);
|
|
38
|
+
const lcpEntryManager = initUnique(opts, LCPEntryManager);
|
|
39
|
+
const lcpTargetMap = new WeakMap();
|
|
40
|
+
lcpEntryManager._onBeforeProcessingEntry = (entry) => {
|
|
41
|
+
const node = entry.element;
|
|
42
|
+
if (node) {
|
|
43
|
+
const customTarget = opts.generateTarget?.(node) ?? getSelector(node);
|
|
44
|
+
lcpTargetMap.set(entry, customTarget);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const attributeLCP = (metric) => {
|
|
48
|
+
// Use a default object if no other attribution has been set.
|
|
49
|
+
let attribution = {
|
|
50
|
+
timeToFirstByte: 0,
|
|
51
|
+
resourceLoadDelay: 0,
|
|
52
|
+
resourceLoadDuration: 0,
|
|
53
|
+
elementRenderDelay: metric.value,
|
|
54
|
+
};
|
|
55
|
+
if (metric.entries.length) {
|
|
56
|
+
const navigationEntry = getNavigationEntry();
|
|
57
|
+
if (navigationEntry) {
|
|
58
|
+
const activationStart = navigationEntry.activationStart || 0;
|
|
59
|
+
// The `metric.entries.length` check ensures there will be an entry.
|
|
60
|
+
const lcpEntry = metric.entries.at(-1);
|
|
61
|
+
const lcpResourceEntry = lcpEntry.url &&
|
|
62
|
+
performance
|
|
63
|
+
.getEntriesByType('resource')
|
|
64
|
+
.filter((e) => e.name === lcpEntry.url)[0];
|
|
65
|
+
const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
|
|
66
|
+
const lcpRequestStart = Math.max(ttfb,
|
|
67
|
+
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
|
|
68
|
+
lcpResourceEntry
|
|
69
|
+
? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) -
|
|
70
|
+
activationStart
|
|
71
|
+
: 0);
|
|
72
|
+
const lcpResponseEnd = Math.min(
|
|
73
|
+
// Cap at LCP time (videos continue downloading after LCP for example)
|
|
74
|
+
metric.value, Math.max(lcpRequestStart, lcpResourceEntry
|
|
75
|
+
? lcpResourceEntry.responseEnd - activationStart
|
|
76
|
+
: 0));
|
|
77
|
+
attribution = {
|
|
78
|
+
target: lcpTargetMap.get(lcpEntry),
|
|
79
|
+
timeToFirstByte: ttfb,
|
|
80
|
+
resourceLoadDelay: lcpRequestStart - ttfb,
|
|
81
|
+
resourceLoadDuration: lcpResponseEnd - lcpRequestStart,
|
|
82
|
+
elementRenderDelay: metric.value - lcpResponseEnd,
|
|
83
|
+
navigationEntry,
|
|
84
|
+
lcpEntry,
|
|
85
|
+
};
|
|
86
|
+
// Only attribute the URL and resource entry if they exist.
|
|
87
|
+
if (lcpEntry.url) {
|
|
88
|
+
attribution.url = lcpEntry.url;
|
|
89
|
+
}
|
|
90
|
+
if (lcpResourceEntry) {
|
|
91
|
+
attribution.lcpResourceEntry = lcpResourceEntry;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Use `Object.assign()` to ensure the original metric object is returned.
|
|
96
|
+
const metricWithAttribution = Object.assign(metric, { attribution });
|
|
97
|
+
return metricWithAttribution;
|
|
98
|
+
};
|
|
79
99
|
unattributedOnLCP((metric) => {
|
|
80
100
|
const metricWithAttribution = attributeLCP(metric);
|
|
81
101
|
onReport(metricWithAttribution);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TTFBMetricWithAttribution,
|
|
1
|
+
import { TTFBMetricWithAttribution, AttributionReportOpts } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Calculates the [TTFB](https://web.dev/articles/ttfb) value for the
|
|
4
4
|
* current page and calls the `callback` function once the page has loaded,
|
|
@@ -14,4 +14,4 @@ import { TTFBMetricWithAttribution, ReportOpts } from '../types.js';
|
|
|
14
14
|
* includes time spent on DNS lookup, connection negotiation, network latency,
|
|
15
15
|
* and server processing time.
|
|
16
16
|
*/
|
|
17
|
-
export declare const onTTFB: (onReport: (metric: TTFBMetricWithAttribution) => void, opts?:
|
|
17
|
+
export declare const onTTFB: (onReport: (metric: TTFBMetricWithAttribution) => void, opts?: AttributionReportOpts) => void;
|
|
@@ -49,7 +49,7 @@ const attributeTTFB = (metric) => {
|
|
|
49
49
|
navigationEntry: navigationEntry,
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
// Use Object.assign to
|
|
52
|
+
// Use `Object.assign()` to ensure the original metric object is returned.
|
|
53
53
|
const metricWithAttribution = Object.assign(metric, { attribution });
|
|
54
54
|
return metricWithAttribution;
|
|
55
55
|
};
|
|
@@ -68,7 +68,7 @@ const attributeTTFB = (metric) => {
|
|
|
68
68
|
* includes time spent on DNS lookup, connection negotiation, network latency,
|
|
69
69
|
* and server processing time.
|
|
70
70
|
*/
|
|
71
|
-
export const onTTFB = (onReport, opts) => {
|
|
71
|
+
export const onTTFB = (onReport, opts = {}) => {
|
|
72
72
|
unattributedOnTTFB((metric) => {
|
|
73
73
|
const metricWithAttribution = attributeTTFB(metric);
|
|
74
74
|
onReport(metricWithAttribution);
|
|
@@ -3,5 +3,4 @@ export { onFCP, FCPThresholds } from './onFCP.js';
|
|
|
3
3
|
export { onINP, INPThresholds } from './onINP.js';
|
|
4
4
|
export { onLCP, LCPThresholds } from './onLCP.js';
|
|
5
5
|
export { onTTFB, TTFBThresholds } from './onTTFB.js';
|
|
6
|
-
export * from './deprecated.js';
|
|
7
6
|
export * from './types.js';
|
|
@@ -18,5 +18,4 @@ export { onFCP, FCPThresholds } from './onFCP.js';
|
|
|
18
18
|
export { onINP, INPThresholds } from './onINP.js';
|
|
19
19
|
export { onLCP, LCPThresholds } from './onLCP.js';
|
|
20
20
|
export { onTTFB, TTFBThresholds } from './onTTFB.js';
|
|
21
|
-
export * from './deprecated.js';
|
|
22
21
|
export * from './types.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface Interaction {
|
|
2
|
+
_latency: number;
|
|
3
|
+
id: number;
|
|
4
|
+
entries: PerformanceEventTiming[];
|
|
5
|
+
}
|
|
6
|
+
export declare class InteractionManager {
|
|
7
|
+
/**
|
|
8
|
+
* A list of longest interactions on the page (by latency) sorted so the
|
|
9
|
+
* longest one is first. The list is at most MAX_INTERACTIONS_TO_CONSIDER
|
|
10
|
+
* long.
|
|
11
|
+
*/
|
|
12
|
+
_longestInteractionList: Interaction[];
|
|
13
|
+
/**
|
|
14
|
+
* A mapping of longest interactions by their interaction ID.
|
|
15
|
+
* This is used for faster lookup.
|
|
16
|
+
*/
|
|
17
|
+
_longestInteractionMap: Map<number, Interaction>;
|
|
18
|
+
_onBeforeProcessingEntry?: (entry: PerformanceEventTiming) => void;
|
|
19
|
+
_onAfterProcessingINPCandidate?: (interaction: Interaction) => void;
|
|
20
|
+
_resetInteractions(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Returns the estimated p98 longest interaction based on the stored
|
|
23
|
+
* interaction candidates and the interaction count for the current page.
|
|
24
|
+
*/
|
|
25
|
+
_estimateP98LongestInteraction(): Interaction;
|
|
26
|
+
/**
|
|
27
|
+
* Takes a performance entry and adds it to the list of worst interactions
|
|
28
|
+
* if its duration is long enough to make it among the worst. If the
|
|
29
|
+
* entry is part of an existing interaction, it is merged and the latency
|
|
30
|
+
* and entries list is updated as needed.
|
|
31
|
+
*/
|
|
32
|
+
_processEntry(entry: PerformanceEventTiming): void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { getInteractionCount } from './polyfills/interactionCountPolyfill.js';
|
|
17
|
+
// To prevent unnecessary memory usage on pages with lots of interactions,
|
|
18
|
+
// store at most 10 of the longest interactions to consider as INP candidates.
|
|
19
|
+
const MAX_INTERACTIONS_TO_CONSIDER = 10;
|
|
20
|
+
// Used to store the interaction count after a bfcache restore, since p98
|
|
21
|
+
// interaction latencies should only consider the current navigation.
|
|
22
|
+
let prevInteractionCount = 0;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the interaction count since the last bfcache restore (or for the
|
|
25
|
+
* full page lifecycle if there were no bfcache restores).
|
|
26
|
+
*/
|
|
27
|
+
const getInteractionCountForNavigation = () => {
|
|
28
|
+
return getInteractionCount() - prevInteractionCount;
|
|
29
|
+
};
|
|
30
|
+
export class InteractionManager {
|
|
31
|
+
/**
|
|
32
|
+
* A list of longest interactions on the page (by latency) sorted so the
|
|
33
|
+
* longest one is first. The list is at most MAX_INTERACTIONS_TO_CONSIDER
|
|
34
|
+
* long.
|
|
35
|
+
*/
|
|
36
|
+
_longestInteractionList = [];
|
|
37
|
+
/**
|
|
38
|
+
* A mapping of longest interactions by their interaction ID.
|
|
39
|
+
* This is used for faster lookup.
|
|
40
|
+
*/
|
|
41
|
+
_longestInteractionMap = new Map();
|
|
42
|
+
_onBeforeProcessingEntry;
|
|
43
|
+
_onAfterProcessingINPCandidate;
|
|
44
|
+
_resetInteractions() {
|
|
45
|
+
prevInteractionCount = getInteractionCount();
|
|
46
|
+
this._longestInteractionList.length = 0;
|
|
47
|
+
this._longestInteractionMap.clear();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns the estimated p98 longest interaction based on the stored
|
|
51
|
+
* interaction candidates and the interaction count for the current page.
|
|
52
|
+
*/
|
|
53
|
+
_estimateP98LongestInteraction() {
|
|
54
|
+
const candidateInteractionIndex = Math.min(this._longestInteractionList.length - 1, Math.floor(getInteractionCountForNavigation() / 50));
|
|
55
|
+
return this._longestInteractionList[candidateInteractionIndex];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Takes a performance entry and adds it to the list of worst interactions
|
|
59
|
+
* if its duration is long enough to make it among the worst. If the
|
|
60
|
+
* entry is part of an existing interaction, it is merged and the latency
|
|
61
|
+
* and entries list is updated as needed.
|
|
62
|
+
*/
|
|
63
|
+
_processEntry(entry) {
|
|
64
|
+
this._onBeforeProcessingEntry?.(entry);
|
|
65
|
+
// Skip further processing for entries that cannot be INP candidates.
|
|
66
|
+
if (!(entry.interactionId || entry.entryType === 'first-input'))
|
|
67
|
+
return;
|
|
68
|
+
// The least-long of the 10 longest interactions.
|
|
69
|
+
const minLongestInteraction = this._longestInteractionList.at(-1);
|
|
70
|
+
let interaction = this._longestInteractionMap.get(entry.interactionId);
|
|
71
|
+
// Only process the entry if it's possibly one of the ten longest,
|
|
72
|
+
// or if it's part of an existing interaction.
|
|
73
|
+
if (interaction ||
|
|
74
|
+
this._longestInteractionList.length < MAX_INTERACTIONS_TO_CONSIDER ||
|
|
75
|
+
// If the above conditions are false, `minLongestInteraction` will be set.
|
|
76
|
+
entry.duration > minLongestInteraction._latency) {
|
|
77
|
+
// If the interaction already exists, update it. Otherwise create one.
|
|
78
|
+
if (interaction) {
|
|
79
|
+
// If the new entry has a longer duration, replace the old entries,
|
|
80
|
+
// otherwise add to the array.
|
|
81
|
+
if (entry.duration > interaction._latency) {
|
|
82
|
+
interaction.entries = [entry];
|
|
83
|
+
interaction._latency = entry.duration;
|
|
84
|
+
}
|
|
85
|
+
else if (entry.duration === interaction._latency &&
|
|
86
|
+
entry.startTime === interaction.entries[0].startTime) {
|
|
87
|
+
interaction.entries.push(entry);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
interaction = {
|
|
92
|
+
id: entry.interactionId,
|
|
93
|
+
entries: [entry],
|
|
94
|
+
_latency: entry.duration,
|
|
95
|
+
};
|
|
96
|
+
this._longestInteractionMap.set(interaction.id, interaction);
|
|
97
|
+
this._longestInteractionList.push(interaction);
|
|
98
|
+
}
|
|
99
|
+
// Sort the entries by latency (descending) and keep only the top ten.
|
|
100
|
+
this._longestInteractionList.sort((a, b) => b._latency - a._latency);
|
|
101
|
+
if (this._longestInteractionList.length > MAX_INTERACTIONS_TO_CONSIDER) {
|
|
102
|
+
const removedInteractions = this._longestInteractionList.splice(MAX_INTERACTIONS_TO_CONSIDER);
|
|
103
|
+
for (const interaction of removedInteractions) {
|
|
104
|
+
this._longestInteractionMap.delete(interaction.id);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Call any post-processing on the interaction
|
|
108
|
+
this._onAfterProcessingINPCandidate?.(interaction);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -13,10 +13,9 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
export {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export * from '../types.js';
|
|
16
|
+
export class LCPEntryManager {
|
|
17
|
+
_onBeforeProcessingEntry;
|
|
18
|
+
_processEntry(entry) {
|
|
19
|
+
this._onBeforeProcessingEntry?.(entry);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export class LayoutShiftManager {
|
|
17
|
+
_onAfterProcessingUnexpectedShift;
|
|
18
|
+
_sessionValue = 0;
|
|
19
|
+
_sessionEntries = [];
|
|
20
|
+
_processEntry(entry) {
|
|
21
|
+
// Only count layout shifts without recent user input.
|
|
22
|
+
if (entry.hadRecentInput)
|
|
23
|
+
return;
|
|
24
|
+
const firstSessionEntry = this._sessionEntries[0];
|
|
25
|
+
const lastSessionEntry = this._sessionEntries.at(-1);
|
|
26
|
+
// If the entry occurred less than 1 second after the previous entry
|
|
27
|
+
// and less than 5 seconds after the first entry in the session,
|
|
28
|
+
// include the entry in the current session. Otherwise, start a new
|
|
29
|
+
// session.
|
|
30
|
+
if (this._sessionValue &&
|
|
31
|
+
firstSessionEntry &&
|
|
32
|
+
lastSessionEntry &&
|
|
33
|
+
entry.startTime - lastSessionEntry.startTime < 1000 &&
|
|
34
|
+
entry.startTime - firstSessionEntry.startTime < 5000) {
|
|
35
|
+
this._sessionValue += entry.value;
|
|
36
|
+
this._sessionEntries.push(entry);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this._sessionValue = entry.value;
|
|
40
|
+
this._sessionEntries = [entry];
|
|
41
|
+
}
|
|
42
|
+
this._onAfterProcessingUnexpectedShift?.(entry);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -28,7 +28,7 @@ export const bindReporter = (callback, metric, thresholds, reportAllChanges) =>
|
|
|
28
28
|
return (forceReport) => {
|
|
29
29
|
if (metric.value >= 0) {
|
|
30
30
|
if (forceReport || reportAllChanges) {
|
|
31
|
-
delta = metric.value - (prevValue
|
|
31
|
+
delta = metric.value - (prevValue ?? 0);
|
|
32
32
|
// Report the metric if there's a non-zero delta or if no previous
|
|
33
33
|
// value exists (which can happen in the case of the document becoming
|
|
34
34
|
// hidden when the metric value is 0).
|
|
@@ -14,16 +14,14 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
export const getNavigationEntry = () => {
|
|
17
|
-
const navigationEntry =
|
|
18
|
-
performance.getEntriesByType &&
|
|
19
|
-
performance.getEntriesByType('navigation')[0];
|
|
17
|
+
const navigationEntry = performance.getEntriesByType('navigation')[0];
|
|
20
18
|
// Check to ensure the `responseStart` property is present and valid.
|
|
21
|
-
// In some cases
|
|
19
|
+
// In some cases a zero value is reported by the browser (for
|
|
22
20
|
// privacy/security reasons), and in other cases (bugs) the value is
|
|
23
21
|
// negative or is larger than the current page time. Ignore these cases:
|
|
24
|
-
// https://github.com/GoogleChrome/web-vitals/issues/137
|
|
25
|
-
// https://github.com/GoogleChrome/web-vitals/issues/162
|
|
26
|
-
// https://github.com/GoogleChrome/web-vitals/issues/275
|
|
22
|
+
// - https://github.com/GoogleChrome/web-vitals/issues/137
|
|
23
|
+
// - https://github.com/GoogleChrome/web-vitals/issues/162
|
|
24
|
+
// - https://github.com/GoogleChrome/web-vitals/issues/275
|
|
27
25
|
if (navigationEntry &&
|
|
28
26
|
navigationEntry.responseStart > 0 &&
|
|
29
27
|
navigationEntry.responseStart < performance.now()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const getSelector: (node: Node | null
|
|
1
|
+
export declare const getSelector: (node: Node | null) => string;
|
|
@@ -19,29 +19,26 @@ const getName = (node) => {
|
|
|
19
19
|
? name.toLowerCase()
|
|
20
20
|
: name.toUpperCase().replace(/^#/, '');
|
|
21
21
|
};
|
|
22
|
-
|
|
22
|
+
const MAX_LEN = 100;
|
|
23
|
+
export const getSelector = (node) => {
|
|
23
24
|
let sel = '';
|
|
24
25
|
try {
|
|
25
|
-
while (node
|
|
26
|
+
while (node?.nodeType !== 9) {
|
|
26
27
|
const el = node;
|
|
27
28
|
const part = el.id
|
|
28
29
|
? '#' + el.id
|
|
29
|
-
: getName(el)
|
|
30
|
-
|
|
31
|
-
el.classList.value &&
|
|
32
|
-
el.classList.value.trim() &&
|
|
33
|
-
el.classList.value.trim().length
|
|
34
|
-
? '.' + el.classList.value.trim().replace(/\s+/g, '.')
|
|
35
|
-
: '');
|
|
36
|
-
if (sel.length + part.length > (maxLen || 100) - 1)
|
|
30
|
+
: [getName(el), ...Array.from(el.classList).sort()].join('.');
|
|
31
|
+
if (sel.length + part.length > MAX_LEN - 1) {
|
|
37
32
|
return sel || part;
|
|
33
|
+
}
|
|
38
34
|
sel = sel ? part + '>' + sel : part;
|
|
39
|
-
if (el.id)
|
|
35
|
+
if (el.id) {
|
|
40
36
|
break;
|
|
37
|
+
}
|
|
41
38
|
node = el.parentNode;
|
|
42
39
|
}
|
|
43
40
|
}
|
|
44
|
-
catch
|
|
41
|
+
catch {
|
|
45
42
|
// Do nothing...
|
|
46
43
|
}
|
|
47
44
|
return sel;
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { onBFCacheRestore } from './bfcache.js';
|
|
17
|
+
import { getActivationStart } from './getActivationStart.js';
|
|
17
18
|
let firstHiddenTime = -1;
|
|
19
|
+
const onHiddenFunctions = new Set();
|
|
18
20
|
const initHiddenTime = () => {
|
|
19
21
|
// If the document is hidden when this code runs, assume it was always
|
|
20
22
|
// hidden and the page was loaded in the background, with the one exception
|
|
@@ -26,41 +28,56 @@ const initHiddenTime = () => {
|
|
|
26
28
|
: Infinity;
|
|
27
29
|
};
|
|
28
30
|
const onVisibilityUpdate = (event) => {
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
// Handle changes to hidden state
|
|
32
|
+
if (document.visibilityState === 'hidden') {
|
|
33
|
+
if (event.type === 'visibilitychange') {
|
|
34
|
+
for (const onHiddenFunction of onHiddenFunctions) {
|
|
35
|
+
onHiddenFunction();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// If the document is 'hidden' and no previous hidden timestamp has been
|
|
39
|
+
// set (so is infinity), update it based on the current event data.
|
|
40
|
+
if (!isFinite(firstHiddenTime)) {
|
|
41
|
+
// If the event is a 'visibilitychange' event, it means the page was
|
|
42
|
+
// visible prior to this change, so the event timestamp is the first
|
|
43
|
+
// hidden time.
|
|
44
|
+
// However, if the event is not a 'visibilitychange' event, then it must
|
|
45
|
+
// be a 'prerenderingchange' event, and the fact that the document is
|
|
46
|
+
// still 'hidden' from the above check means the tab was activated
|
|
47
|
+
// in a background state and so has always been hidden.
|
|
48
|
+
firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;
|
|
49
|
+
// We no longer need the `prerenderingchange` event listener now we've
|
|
50
|
+
// set an initial init time so remove that
|
|
51
|
+
// (we'll keep the visibilitychange one for onHiddenFunction above)
|
|
52
|
+
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
|
|
53
|
+
}
|
|
42
54
|
}
|
|
43
55
|
};
|
|
44
|
-
const addChangeListeners = () => {
|
|
45
|
-
addEventListener('visibilitychange', onVisibilityUpdate, true);
|
|
46
|
-
// IMPORTANT: when a page is prerendering, its `visibilityState` is
|
|
47
|
-
// 'hidden', so in order to account for cases where this module checks for
|
|
48
|
-
// visibility during prerendering, an additional check after prerendering
|
|
49
|
-
// completes is also required.
|
|
50
|
-
addEventListener('prerenderingchange', onVisibilityUpdate, true);
|
|
51
|
-
};
|
|
52
|
-
const removeChangeListeners = () => {
|
|
53
|
-
removeEventListener('visibilitychange', onVisibilityUpdate, true);
|
|
54
|
-
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
|
|
55
|
-
};
|
|
56
56
|
export const getVisibilityWatcher = () => {
|
|
57
57
|
if (firstHiddenTime < 0) {
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
// Check if we have a previous hidden `visibility-state` performance entry.
|
|
59
|
+
const activationStart = getActivationStart();
|
|
60
|
+
/* eslint-disable indent */
|
|
61
|
+
const firstVisibilityStateHiddenTime = !document.prerendering
|
|
62
|
+
? globalThis.performance
|
|
63
|
+
.getEntriesByType('visibility-state')
|
|
64
|
+
.filter((e) => e.name === 'hidden' && e.startTime > activationStart)[0]?.startTime
|
|
65
|
+
: undefined;
|
|
66
|
+
/* eslint-enable indent */
|
|
67
|
+
// Prefer that, but if it's not available and the document is hidden when
|
|
68
|
+
// this code runs, assume it was hidden since navigation start. This isn't
|
|
69
|
+
// a perfect heuristic, but it's the best we can do until the
|
|
70
|
+
// `visibility-state` performance entry becomes available in all browsers.
|
|
71
|
+
firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();
|
|
72
|
+
// Listen for visibility changes so we can handle things like bfcache
|
|
73
|
+
// restores and/or prerender without having to examine individual
|
|
74
|
+
// timestamps in detail and also for onHidden function calls.
|
|
75
|
+
addEventListener('visibilitychange', onVisibilityUpdate, true);
|
|
76
|
+
// IMPORTANT: when a page is prerendering, its `visibilityState` is
|
|
77
|
+
// 'hidden', so in order to account for cases where this module checks for
|
|
78
|
+
// visibility during prerendering, an additional check after prerendering
|
|
79
|
+
// completes is also required.
|
|
80
|
+
addEventListener('prerenderingchange', onVisibilityUpdate, true);
|
|
64
81
|
// Reset the time on bfcache restores.
|
|
65
82
|
onBFCacheRestore(() => {
|
|
66
83
|
// Schedule a task in order to track the `visibilityState` once it's
|
|
@@ -68,13 +85,15 @@ export const getVisibilityWatcher = () => {
|
|
|
68
85
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1133363
|
|
69
86
|
setTimeout(() => {
|
|
70
87
|
firstHiddenTime = initHiddenTime();
|
|
71
|
-
|
|
72
|
-
}, 0);
|
|
88
|
+
});
|
|
73
89
|
});
|
|
74
90
|
}
|
|
75
91
|
return {
|
|
76
92
|
get firstHiddenTime() {
|
|
77
93
|
return firstHiddenTime;
|
|
78
94
|
},
|
|
95
|
+
onHidden(cb) {
|
|
96
|
+
onHiddenFunctions.add(cb);
|
|
97
|
+
},
|
|
79
98
|
};
|
|
80
99
|
};
|
|
@@ -8,8 +8,6 @@ export declare const initMetric: <MetricName extends MetricType["name"]>(name: M
|
|
|
8
8
|
name: MetricName;
|
|
9
9
|
}> | Extract<import("../types.js").FCPMetric, {
|
|
10
10
|
name: MetricName;
|
|
11
|
-
}> | Extract<import("../types.js").FIDMetric, {
|
|
12
|
-
name: MetricName;
|
|
13
11
|
}> | Extract<import("../types.js").INPMetric, {
|
|
14
12
|
name: MetricName;
|
|
15
13
|
}> | Extract<import("../types.js").LCPMetric, {
|
|
@@ -17,7 +17,7 @@ import { getBFCacheRestoreTime } from './bfcache.js';
|
|
|
17
17
|
import { generateUniqueID } from './generateUniqueID.js';
|
|
18
18
|
import { getActivationStart } from './getActivationStart.js';
|
|
19
19
|
import { getNavigationEntry } from './getNavigationEntry.js';
|
|
20
|
-
export const initMetric = (name, value) => {
|
|
20
|
+
export const initMetric = (name, value = -1) => {
|
|
21
21
|
const navEntry = getNavigationEntry();
|
|
22
22
|
let navigationType = 'navigate';
|
|
23
23
|
if (getBFCacheRestoreTime() >= 0) {
|
|
@@ -38,7 +38,7 @@ export const initMetric = (name, value) => {
|
|
|
38
38
|
const entries = [];
|
|
39
39
|
return {
|
|
40
40
|
name,
|
|
41
|
-
value
|
|
41
|
+
value,
|
|
42
42
|
rating: 'good', // If needed, will be updated when reported. `const` to keep the type from widening to `string`.
|
|
43
43
|
delta: 0,
|
|
44
44
|
entries,
|