chrome-devtools-frontend 1.0.1664496 → 1.0.1665921
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/.agents/skills/devtools-testing-guidance/SKILL.md +48 -0
- package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +3 -3
- package/.agents/skills/repro-flaky-tests/SKILL.md +2 -2
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +2 -0
- package/.agents/skills/version-control/SKILL.md +4 -3
- package/docs/ui_engineering.md +89 -0
- package/eslint.config.mjs +9 -2
- package/front_end/Images/rollup.config.mjs +1 -1
- package/front_end/Tests.js +15 -16
- package/front_end/core/common/Gzip.ts +2 -2
- package/front_end/core/common/Settings.ts +4 -20
- package/front_end/core/common/Srcset.ts +1 -1
- package/front_end/core/common/VersionController.ts +1 -1
- package/front_end/core/host/AidaClient.ts +19 -4
- package/front_end/core/host/AidaGcaTranslation.ts +2 -2
- package/front_end/core/host/GcaClient.ts +2 -2
- package/front_end/core/host/GdpClient.ts +3 -3
- package/front_end/core/host/InspectorFrontendHostStub.ts +1 -1
- package/front_end/core/host/ResourceLoader.ts +15 -15
- package/front_end/core/protocol_client/DevToolsCDPConnection.ts +2 -2
- package/front_end/core/protocol_client/InspectorBackend.ts +1 -1
- package/front_end/core/root/Runtime.ts +0 -1
- package/front_end/core/sdk/CSSMatchedStyles.ts +78 -3
- package/front_end/core/sdk/CSSMetadata.ts +17 -12
- package/front_end/core/sdk/CSSProperty.ts +1 -1
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -2
- package/front_end/core/sdk/CSSRule.ts +3 -3
- package/front_end/core/sdk/CSSStyleSheetHeader.ts +3 -3
- package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +1 -1
- package/front_end/core/sdk/Connections.ts +1 -1
- package/front_end/core/sdk/DebuggerModel.ts +13 -13
- package/front_end/core/sdk/NetworkManager.ts +19 -19
- package/front_end/core/sdk/NetworkRequest.ts +57 -57
- package/front_end/core/sdk/OverlayModel.ts +1 -1
- package/front_end/core/sdk/PageResourceLoader.ts +2 -2
- package/front_end/core/sdk/RehydratingConnection.ts +5 -5
- package/front_end/core/sdk/ScreenCaptureModel.ts +1 -1
- package/front_end/core/sdk/Script.ts +2 -2
- package/front_end/core/sdk/ServerTiming.ts +7 -7
- package/front_end/core/sdk/ServiceWorkerCacheModel.ts +1 -1
- package/front_end/core/sdk/ServiceWorkerManager.ts +11 -11
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +2 -2
- package/front_end/core/sdk/SourceMapScopesInfo.ts +1 -1
- package/front_end/core/sdk/StorageKeyManager.ts +1 -1
- package/front_end/core/sdk/sdk-meta.ts +98 -98
- package/front_end/devtools_compatibility.js +15 -13
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -8
- package/front_end/entrypoints/main/MainImpl.ts +2 -3
- package/front_end/entrypoints/main/main-meta.ts +1 -16
- package/front_end/entrypoints/shell/shell.ts +1 -0
- package/front_end/entrypoints/trace_app/trace_app.ts +1 -0
- package/front_end/foundation/README.md +1 -1
- package/front_end/foundation/Universe.test.api.ts +73 -0
- package/front_end/foundation/Universe.ts +22 -0
- package/front_end/generated/InspectorBackendCommands.ts +2 -2
- package/front_end/generated/SupportedCSSProperties.js +1 -1
- package/front_end/generated/protocol.ts +19 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +1 -1
- package/front_end/models/ai_assistance/AiConversation.ts +1 -1
- package/front_end/models/ai_assistance/BuiltInAi.ts +1 -1
- package/front_end/models/ai_assistance/ChangeManager.ts +0 -70
- package/front_end/models/ai_assistance/ExtensionScope.ts +2 -36
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +9 -9
- package/front_end/models/ai_assistance/agents/AiAgent.ts +10 -2
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +4 -4
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +21 -21
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +4 -4
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
- package/front_end/models/ai_assistance/ai_assistance.ts +0 -5
- package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +11 -4
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +8 -2
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +14 -11
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +2 -2
- package/front_end/models/ai_assistance/performance/AICallTree.ts +2 -2
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +1 -1
- package/front_end/models/ai_assistance/tools/GetNetworkRequestDetails.ts +9 -2
- package/front_end/models/ai_assistance/tools/GetStyles.ts +4 -4
- package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +2 -5
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +2 -2
- package/front_end/models/ai_code_generation/AiCodeGeneration.ts +2 -2
- package/front_end/models/badges/badges-meta.ts +27 -0
- package/front_end/models/bindings/CSSWorkspaceBinding.ts +4 -3
- package/front_end/models/bindings/ContentProviderBasedProject.ts +1 -1
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +6 -7
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +5 -4
- package/front_end/models/bindings/PresentationConsoleMessageHelper.ts +72 -29
- package/front_end/models/bindings/ResourceMapping.ts +38 -32
- package/front_end/models/bindings/ResourceScriptMapping.ts +5 -7
- package/front_end/models/breakpoints/BreakpointManager.ts +2 -1
- package/front_end/models/har/Writer.ts +2 -2
- package/front_end/models/issues_manager/ElementAccessibilityIssue.ts +1 -1
- package/front_end/models/issues_manager/GenericIssue.ts +1 -1
- package/front_end/models/issues_manager/IssuesManager.ts +14 -5
- package/front_end/models/issues_manager/PartitioningBlobURLIssue.ts +1 -1
- package/front_end/models/issues_manager/SRIMessageSignatureIssue.ts +2 -2
- package/front_end/models/issues_manager/SourceFrameIssuesManager.ts +13 -2
- package/front_end/models/issues_manager/issues_manager.ts +0 -2
- package/front_end/models/live-metrics/LiveMetrics.ts +22 -5
- package/front_end/models/live-metrics/web-vitals-injected/rollup.config.mjs +1 -1
- package/front_end/models/live-metrics/web-vitals-injected/spec/spec.ts +10 -4
- package/front_end/models/logs/logs-meta.ts +23 -16
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +2 -2
- package/front_end/models/persistence/IsolatedFileSystem.ts +1 -1
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +1 -1
- package/front_end/models/source_map_scopes/NamesResolver.ts +104 -86
- package/front_end/models/source_map_scopes/ScopeChainModel.ts +6 -2
- package/front_end/models/stack_trace/StackTraceModel.ts +1 -1
- package/front_end/models/trace/handlers/ExtensionTraceDataHandler.ts +1 -1
- package/front_end/models/trace/handlers/UserTimingsHandler.ts +17 -6
- package/front_end/models/trace/helpers/SamplesIntegrator.ts +1 -1
- package/front_end/models/trace/helpers/Timing.ts +1 -1
- package/front_end/models/trace/insights/Common.ts +1 -1
- package/front_end/models/trace/insights/DocumentLatency.ts +3 -3
- package/front_end/models/trace/insights/LCPDiscovery.ts +1 -1
- package/front_end/models/trace/insights/ModernHTTP.ts +1 -1
- package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +2 -2
- package/front_end/models/workspace_diff/WorkspaceDiff.ts +14 -9
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -15
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -2
- package/front_end/panels/ai_assistance/components/ChatInput.ts +23 -19
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +9 -18
- package/front_end/panels/ai_assistance/components/ChatView.ts +2 -35
- package/front_end/panels/ai_assistance/components/DisabledWidget.ts +1 -1
- package/front_end/panels/ai_assistance/components/ExploreWidget.ts +4 -4
- package/front_end/panels/ai_assistance/components/ImageResize.ts +74 -0
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +2 -2
- package/front_end/panels/animation/AnimationGroupPreviewUI.ts +28 -29
- package/front_end/panels/animation/AnimationTimeline.ts +3 -3
- package/front_end/panels/animation/animationTimeline.css +0 -2
- package/front_end/panels/application/AppManifestView.ts +1 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +1 -1
- package/front_end/panels/application/CookieItemsView.ts +1 -1
- package/front_end/panels/application/CrashReportContextView.ts +3 -3
- package/front_end/panels/application/DeviceBoundSessionsModel.ts +1 -1
- package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +1 -1
- package/front_end/panels/application/DeviceBoundSessionsView.ts +1 -1
- package/front_end/panels/application/IndexedDBViews.ts +1 -1
- package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -1
- package/front_end/panels/application/OriginTrialTreeView.ts +1 -1
- package/front_end/panels/application/ServiceWorkersView.ts +6 -6
- package/front_end/panels/application/StorageBucketsTreeElement.ts +1 -1
- package/front_end/panels/application/StorageItemsToolbar.ts +3 -3
- package/front_end/panels/application/WebMCPView.ts +7 -5
- package/front_end/panels/application/components/AdsView.ts +21 -6
- package/front_end/panels/application/components/BackForwardCacheView.ts +2 -2
- package/front_end/panels/application/components/ProtocolHandlersView.ts +1 -1
- package/front_end/panels/application/components/StorageMetadataView.ts +1 -1
- package/front_end/panels/application/preloading/components/MismatchedPreloadingGrid.ts +2 -2
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +2 -1
- package/front_end/panels/application/preloading/components/PreloadingString.ts +3 -3
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -1
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +1 -1
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +2 -2
- package/front_end/panels/changes/ChangesSidebar.ts +2 -2
- package/front_end/panels/changes/ChangesView.ts +4 -5
- package/front_end/panels/changes/CombinedDiffView.ts +3 -3
- package/front_end/panels/changes/changes-meta.ts +2 -2
- package/front_end/panels/common/AiCodeCompletionTeaser.ts +1 -1
- package/front_end/panels/common/AiCodeGenerationTeaser.ts +3 -3
- package/front_end/panels/common/BadgeNotification.ts +8 -8
- package/front_end/panels/common/DOMLinkifier.ts +1 -1
- package/front_end/panels/common/GdpSignUpDialog.ts +2 -2
- package/front_end/panels/common/GeminiRebrandPromoDialog.ts +1 -1
- package/front_end/panels/common/aiCodeCompletionDisclaimer.css +0 -1
- package/front_end/panels/console/ConsoleInsightTeaser.ts +1 -1
- package/front_end/panels/console/ConsolePinPane.ts +3 -3
- package/front_end/panels/console/ConsolePrompt.ts +6 -4
- package/front_end/panels/console/ConsoleSidebar.ts +8 -10
- package/front_end/panels/console_counters/WarningErrorCounter.ts +10 -11
- package/front_end/panels/coverage/CoverageView.ts +2 -2
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +3 -3
- package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +1 -1
- package/front_end/panels/developer_resources/DeveloperResourcesView.ts +1 -1
- package/front_end/panels/elements/CSSRuleValidator.ts +1 -1
- package/front_end/panels/elements/ComputedStyleWidget.ts +3 -2
- package/front_end/panels/elements/ElementsTreeElement.ts +3 -3
- package/front_end/panels/elements/EventListenersWidget.ts +1 -3
- package/front_end/panels/elements/LayoutPane.ts +23 -13
- package/front_end/panels/elements/StandaloneStylesContainer.ts +7 -7
- package/front_end/panels/elements/StylePropertiesSection.ts +33 -5
- package/front_end/panels/elements/StylePropertyTreeElement.ts +5 -5
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +6 -6
- package/front_end/panels/elements/StylesSidebarPane.ts +4 -3
- package/front_end/panels/elements/elements-meta.ts +18 -2
- package/front_end/panels/emulation/DeviceModeToolbar.ts +100 -40
- package/front_end/panels/emulation/DeviceModeView.ts +5 -4
- package/front_end/panels/emulation/MediaQueryInspector.ts +35 -19
- package/front_end/panels/event_listeners/EventListenersView.ts +4 -4
- package/front_end/panels/explain/components/ConsoleInsight.ts +8 -9
- package/front_end/panels/explain/explain-meta.ts +3 -3
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +135 -167
- package/front_end/panels/layer_viewer/Layers3DView.ts +10 -23
- package/front_end/panels/layer_viewer/layer_viewer-meta.ts +27 -0
- package/front_end/panels/lighthouse/LighthouseController.ts +44 -55
- package/front_end/panels/lighthouse/LighthousePanel.ts +9 -9
- package/front_end/panels/lighthouse/LighthouseReportSelector.ts +2 -2
- package/front_end/panels/lighthouse/LighthouseStartView.ts +9 -12
- package/front_end/panels/lighthouse/LighthouseStatusView.ts +33 -33
- package/front_end/panels/lighthouse/RadioSetting.ts +1 -1
- package/front_end/panels/lighthouse/lighthouse-meta.ts +131 -1
- package/front_end/panels/media/EventDisplayTable.ts +67 -94
- package/front_end/panels/media/PlayerListView.ts +1 -1
- package/front_end/panels/media/eventDisplayTable.css +9 -4
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +5 -5
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +1 -1
- package/front_end/panels/network/EventSourceMessagesView.ts +98 -107
- package/front_end/panels/network/NetworkLogViewColumns.ts +1 -1
- package/front_end/panels/network/NetworkWaterfallColumn.ts +1 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +2 -2
- package/front_end/panels/network/RequestCookiesView.ts +2 -2
- package/front_end/panels/network/RequestHeadersView.ts +5 -5
- package/front_end/panels/network/RequestPayloadView.ts +4 -4
- package/front_end/panels/network/RequestTimingView.ts +2 -2
- package/front_end/panels/network/components/DirectSocketConnectionView.ts +1 -1
- package/front_end/panels/network/eventSourceMessagesView.css +12 -3
- package/front_end/panels/network/networkTimingTable.css +2 -2
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +1 -1
- package/front_end/panels/profiler/BottomUpProfileDataGrid.ts +25 -29
- package/front_end/panels/profiler/HeapProfileView.ts +308 -247
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +13 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +30 -10
- package/front_end/panels/profiler/HeapTimelineOverview.ts +5 -2
- package/front_end/panels/profiler/ProfileDataGrid.ts +128 -157
- package/front_end/panels/profiler/ProfileFlameChartDataProvider.ts +17 -5
- package/front_end/panels/profiler/ProfilesPanel.ts +2 -2
- package/front_end/panels/profiler/TopDownProfileDataGrid.ts +17 -21
- package/front_end/panels/profiler/profilesPanel.css +9 -13
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +2 -2
- package/front_end/panels/recorder/CreateRecordingView.ts +4 -4
- package/front_end/panels/recorder/RecorderPanel.ts +6 -6
- package/front_end/panels/recorder/RecordingView.ts +1 -1
- package/front_end/panels/recorder/ReplaySection.ts +1 -1
- package/front_end/panels/recorder/StepView.ts +1 -1
- package/front_end/panels/recorder/injected/rollup.config.mjs +1 -1
- package/front_end/panels/search/SearchView.ts +1 -1
- package/front_end/panels/security/SecurityPanel.ts +54 -41
- package/front_end/panels/sensors/LocationsSettingsTab.ts +246 -233
- package/front_end/panels/sensors/SensorsView.ts +1 -1
- package/front_end/panels/settings/AISettingsTab.ts +11 -10
- package/front_end/panels/settings/SettingsScreen.ts +29 -24
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -2
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +5 -5
- package/front_end/panels/sources/BreakpointEditDialog.ts +2 -2
- package/front_end/panels/sources/BreakpointsView.ts +1 -1
- package/front_end/panels/sources/CallStackSidebarPane.ts +2 -2
- package/front_end/panels/sources/DebuggerPausedMessage.ts +2 -2
- package/front_end/panels/sources/DebuggerPlugin.ts +25 -22
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -1
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +7 -5
- package/front_end/panels/sources/sources-meta.ts +1 -1
- package/front_end/panels/timeline/CountersGraph.ts +1 -2
- package/front_end/panels/timeline/ExtensionTrackAppender.ts +1 -1
- package/front_end/panels/timeline/TimelineDetailsView.ts +2 -2
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +2 -2
- package/front_end/panels/timeline/TimelineFlameChartView.ts +4 -4
- package/front_end/panels/timeline/TimelinePaintProfilerView.ts +1 -1
- package/front_end/panels/timeline/TimelinePanel.ts +53 -81
- package/front_end/panels/timeline/TimelineSelectorStatsView.ts +10 -3
- package/front_end/panels/timeline/TimelineUIUtils.ts +18 -4
- package/front_end/panels/timeline/TrackConfigBanner.ts +1 -1
- package/front_end/panels/timeline/components/ExportTraceOptions.ts +1 -1
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +8 -9
- package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +1 -1
- package/front_end/panels/timeline/components/TimelineRangeSummaryView.ts +1 -1
- package/front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts +2 -2
- package/front_end/panels/timeline/components/insights/LCPBreakdown.ts +1 -1
- package/front_end/panels/timeline/components/insights/LegacyJavaScript.ts +1 -1
- package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +2 -2
- package/front_end/panels/timeline/overlays/OverlaysImpl.ts +5 -0
- package/front_end/panels/timeline/overlays/components/TimespanBreakdownOverlay.ts +13 -8
- package/front_end/panels/timeline/overlays/components/timespanBreakdownOverlay.css +1 -0
- package/front_end/panels/timeline/timeline-meta.ts +169 -0
- package/front_end/panels/timeline/timelineFlameChartView.css +5 -0
- package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
- package/front_end/panels/whats_new/ReleaseNoteText.ts +9 -9
- package/front_end/panels/whats_new/resources/WNDT.md +7 -8
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/web-vitals/README.chromium +2 -2
- package/front_end/third_party/web-vitals/package/README.md +120 -19
- package/front_end/third_party/web-vitals/package/attribution.d.ts +16 -0
- package/front_end/third_party/web-vitals/package/attribution.js +18 -0
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.d.ts +1 -7
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.js +53 -32
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.d.ts +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +43 -12
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.js +21 -3
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.js +30 -24
- package/front_end/third_party/web-vitals/package/dist/modules/lib/FCPEntryManager.d.ts +3 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/FCPEntryManager.js +18 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.d.ts +2 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.js +18 -2
- package/front_end/third_party/web-vitals/package/dist/modules/lib/LCPEntryManager.d.ts +1 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/LCPEntryManager.js +1 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/bindReporter.d.ts +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/getLoadState.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getLoadState.js +7 -7
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.js +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.js +4 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.d.ts +7 -3
- package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.js +20 -11
- package/front_end/third_party/web-vitals/package/dist/modules/lib/initUnique.js +8 -3
- package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.d.ts +3 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.js +19 -4
- package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/interactionCountPolyfill.js +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/lib/softNavs.d.ts +3 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/softNavs.js +38 -0
- package/front_end/third_party/web-vitals/package/dist/modules/lib/whenIdleOrHidden.js +5 -1
- package/front_end/third_party/web-vitals/package/dist/modules/onCLS.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/onCLS.js +30 -11
- package/front_end/third_party/web-vitals/package/dist/modules/onFCP.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/onFCP.js +36 -4
- package/front_end/third_party/web-vitals/package/dist/modules/onINP.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/onINP.js +42 -22
- package/front_end/third_party/web-vitals/package/dist/modules/onLCP.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/onLCP.js +109 -30
- package/front_end/third_party/web-vitals/package/dist/modules/onTTFB.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/onTTFB.js +25 -7
- package/front_end/third_party/web-vitals/package/dist/modules/types/base.d.ts +24 -1
- package/front_end/third_party/web-vitals/package/dist/modules/types/fcp.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/types/inp.d.ts +14 -6
- package/front_end/third_party/web-vitals/package/dist/modules/types/lcp.d.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/types/ttfb.d.ts +2 -2
- package/front_end/third_party/web-vitals/package/dist/modules/types.d.ts +26 -4
- package/front_end/third_party/web-vitals/package/package.json +21 -22
- package/front_end/third_party/web-vitals/package/src/attribution/onCLS.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/attribution/onFCP.ts +62 -39
- package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +52 -15
- package/front_end/third_party/web-vitals/package/src/attribution/onLCP.ts +25 -7
- package/front_end/third_party/web-vitals/package/src/attribution/onTTFB.ts +43 -37
- package/front_end/third_party/web-vitals/package/src/lib/{polyfills/getFirstHiddenTimePolyfill.ts → FCPEntryManager.ts} +4 -14
- package/front_end/third_party/web-vitals/package/src/lib/InteractionManager.ts +22 -2
- package/front_end/third_party/web-vitals/package/src/lib/LCPEntryManager.ts +1 -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/getLoadState.ts +11 -12
- package/front_end/third_party/web-vitals/package/src/lib/getSelector.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/lib/getVisibilityWatcher.ts +4 -1
- package/front_end/third_party/web-vitals/package/src/lib/initMetric.ts +24 -11
- package/front_end/third_party/web-vitals/package/src/lib/initUnique.ts +12 -4
- package/front_end/third_party/web-vitals/package/src/lib/observe.ts +26 -5
- package/front_end/third_party/web-vitals/package/src/lib/polyfills/interactionCountPolyfill.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/lib/softNavs.ts +48 -0
- package/front_end/third_party/web-vitals/package/src/lib/whenIdleOrHidden.ts +12 -4
- package/front_end/third_party/web-vitals/package/src/onCLS.ts +75 -18
- package/front_end/third_party/web-vitals/package/src/onFCP.ts +66 -7
- package/front_end/third_party/web-vitals/package/src/onINP.ts +100 -39
- package/front_end/third_party/web-vitals/package/src/onLCP.ts +169 -34
- package/front_end/third_party/web-vitals/package/src/onTTFB.ts +50 -13
- package/front_end/third_party/web-vitals/package/src/types/base.ts +31 -10
- package/front_end/third_party/web-vitals/package/src/types/fcp.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/types/inp.ts +14 -6
- package/front_end/third_party/web-vitals/package/src/types/lcp.ts +1 -1
- package/front_end/third_party/web-vitals/package/src/types/ttfb.ts +2 -2
- package/front_end/third_party/web-vitals/package/src/types.ts +32 -9
- package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +11 -11
- package/front_end/third_party/web-vitals/rebuild.sh +2 -2
- package/front_end/third_party/web-vitals/web-vitals-tsconfig.json +2 -0
- package/front_end/ui/components/buttons/Button.ts +16 -0
- package/front_end/ui/components/dialogs/Dialog.ts +1 -1
- package/front_end/ui/components/highlighting/HighlightManager.ts +6 -1
- package/front_end/ui/components/highlighting/highlighting.ts +1 -1
- package/front_end/ui/components/icon_button/FileSourceIcon.ts +1 -1
- package/front_end/ui/components/linkifier/LinkifierImpl.ts +1 -1
- package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +2 -2
- package/front_end/ui/components/settings/SettingCheckbox.ts +12 -7
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +2 -2
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +6 -6
- package/front_end/ui/components/text_editor/javascript.ts +3 -1
- package/front_end/ui/components/tooltips/Tooltip.ts +1 -1
- package/front_end/ui/legacy/ContextMenu.ts +12 -2
- package/front_end/ui/legacy/ListControl.ts +1 -1
- package/front_end/ui/legacy/SelectMenu.docs.ts +17 -19
- package/front_end/ui/legacy/Toolbar.ts +4 -1
- package/front_end/ui/legacy/Treeoutline.ts +1 -1
- package/front_end/ui/legacy/components/color_picker/spectrum.css +1 -2
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -1
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +50 -4
- package/front_end/ui/legacy/components/object_ui/JavaScriptREPL.ts +3 -1
- package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +4 -4
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +8 -7
- package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +14 -11
- package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +1 -1
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +15 -5
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +4 -4
- package/front_end/ui/legacy/components/utils/Linkifier.ts +5 -1
- package/front_end/ui/lit/render.ts +1 -1
- package/front_end/ui/settings/SettingUIRegistration.ts +8 -3
- package/front_end/ui/visual_logging/KnownContextValues.ts +8 -0
- package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
- package/inspector_overlay/main.ts +1 -1
- package/mcp/mcp.ts +5 -4
- package/package.json +13 -13
- package/front_end/models/ai_assistance/AgentProject.ts +0 -261
- package/front_end/models/ai_assistance/agents/PatchAgent.ts +0 -306
- package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +0 -45
- package/front_end/models/text_utils/text_utils.ts +0 -5
- package/front_end/panels/ai_assistance/PatchWidget.ts +0 -867
- package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +0 -368
- package/front_end/panels/ai_assistance/selectWorkspaceDialog.css +0 -92
|
@@ -16,40 +16,61 @@
|
|
|
16
16
|
import { getBFCacheRestoreTime } from '../lib/bfcache.js';
|
|
17
17
|
import { getLoadState } from '../lib/getLoadState.js';
|
|
18
18
|
import { getNavigationEntry } from '../lib/getNavigationEntry.js';
|
|
19
|
+
import { initUnique } from '../lib/initUnique.js';
|
|
20
|
+
import { FCPEntryManager } from '../lib/FCPEntryManager.js';
|
|
21
|
+
import { checkSoftNavsEnabled } from '../lib/softNavs.js';
|
|
19
22
|
import { onFCP as unattributedOnFCP } from '../onFCP.js';
|
|
20
|
-
const attributeFCP = (metric) => {
|
|
21
|
-
// Use a default object if no other attribution has been set.
|
|
22
|
-
let attribution = {
|
|
23
|
-
timeToFirstByte: 0,
|
|
24
|
-
firstByteToFCP: metric.value,
|
|
25
|
-
loadState: getLoadState(getBFCacheRestoreTime()),
|
|
26
|
-
};
|
|
27
|
-
if (metric.entries.length) {
|
|
28
|
-
const navigationEntry = getNavigationEntry();
|
|
29
|
-
const fcpEntry = metric.entries.at(-1);
|
|
30
|
-
if (navigationEntry) {
|
|
31
|
-
const activationStart = navigationEntry.activationStart || 0;
|
|
32
|
-
const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
|
|
33
|
-
attribution = {
|
|
34
|
-
timeToFirstByte: ttfb,
|
|
35
|
-
firstByteToFCP: metric.value - ttfb,
|
|
36
|
-
loadState: getLoadState(metric.entries[0].startTime),
|
|
37
|
-
navigationEntry,
|
|
38
|
-
fcpEntry,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// Use `Object.assign()` to ensure the original metric object is returned.
|
|
43
|
-
const metricWithAttribution = Object.assign(metric, { attribution });
|
|
44
|
-
return metricWithAttribution;
|
|
45
|
-
};
|
|
46
|
-
/**
|
|
47
|
-
* Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and
|
|
48
|
-
* calls the `callback` function once the value is ready, along with the
|
|
49
|
-
* relevant `paint` performance entry used to determine the value. The reported
|
|
50
|
-
* value is a `DOMHighResTimeStamp`.
|
|
51
|
-
*/
|
|
52
23
|
export const onFCP = (onReport, opts = {}) => {
|
|
24
|
+
opts = Object.assign({}, opts);
|
|
25
|
+
// Init the fcpEntryManager (which will already be initialised in the
|
|
26
|
+
// unattributed onFCP method if soft navigation reporting is enabled
|
|
27
|
+
// and so will return that fcpEntryManager, rather than a new one)
|
|
28
|
+
const fcpEntryManager = initUnique(opts, FCPEntryManager);
|
|
29
|
+
if (checkSoftNavsEnabled(opts)) {
|
|
30
|
+
fcpEntryManager._softNavigationEntryMap = new Map();
|
|
31
|
+
}
|
|
32
|
+
const attributeFCP = (metric) => {
|
|
33
|
+
// Use a default object if no other attribution has been set.
|
|
34
|
+
let attribution = {
|
|
35
|
+
timeToFirstByte: 0,
|
|
36
|
+
firstByteToFCP: metric.value,
|
|
37
|
+
loadState: getLoadState(getBFCacheRestoreTime()),
|
|
38
|
+
};
|
|
39
|
+
if (metric.navigationType !== 'soft-navigation') {
|
|
40
|
+
if (metric.entries.length) {
|
|
41
|
+
const navigationEntry = getNavigationEntry();
|
|
42
|
+
const fcpEntry = metric.entries.at(-1);
|
|
43
|
+
if (navigationEntry) {
|
|
44
|
+
const responseStart = navigationEntry.responseStart;
|
|
45
|
+
const activationStart = navigationEntry.activationStart || 0;
|
|
46
|
+
const ttfb = Math.max(0, responseStart - activationStart);
|
|
47
|
+
attribution = {
|
|
48
|
+
timeToFirstByte: ttfb,
|
|
49
|
+
firstByteToFCP: metric.value - ttfb,
|
|
50
|
+
loadState: getLoadState(metric.entries[0].startTime),
|
|
51
|
+
navigationEntry,
|
|
52
|
+
fcpEntry,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Lookup the soft navigation entry. Do not use getEntriesByType since
|
|
59
|
+
// that is limited to the first 50 navigation entries due to buffer size.
|
|
60
|
+
const navigationEntry = fcpEntryManager._softNavigationEntryMap?.get(metric.navigationId);
|
|
61
|
+
if (navigationEntry) {
|
|
62
|
+
attribution = {
|
|
63
|
+
timeToFirstByte: 0,
|
|
64
|
+
firstByteToFCP: metric.value,
|
|
65
|
+
loadState: 'complete',
|
|
66
|
+
navigationEntry,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Use `Object.assign()` to ensure the original metric object is returned.
|
|
71
|
+
const metricWithAttribution = Object.assign(metric, { attribution });
|
|
72
|
+
return metricWithAttribution;
|
|
73
|
+
};
|
|
53
74
|
unattributedOnFCP((metric) => {
|
|
54
75
|
onReport(attributeFCP(metric));
|
|
55
76
|
}, opts);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { INPAttributionReportOpts, INPMetricWithAttribution } from '../types.js';
|
|
1
|
+
import type { INPAttributionReportOpts, INPMetricWithAttribution } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Calculates the [INP](https://web.dev/articles/inp) value for the current
|
|
4
4
|
* page and calls the `callback` function once the value is ready, along with
|
|
@@ -16,7 +16,7 @@ import { INPAttributionReportOpts, INPMetricWithAttribution } from '../types.js'
|
|
|
16
16
|
*
|
|
17
17
|
* A custom `includeProcessedEventEntries` configuration option can optionally
|
|
18
18
|
* be passed to control whether the `processedEventEntries` array in the
|
|
19
|
-
* attribution object is populated. The default value is `
|
|
19
|
+
* attribution object is populated. The default value is `false`.
|
|
20
20
|
*
|
|
21
21
|
* If the `reportAllChanges` configuration option is set to `true`, the
|
|
22
22
|
* `callback` function will be called as soon as the value is initially
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { getLoadState } from '../lib/getLoadState.js';
|
|
17
17
|
import { getSelector } from '../lib/getSelector.js';
|
|
18
18
|
import { initUnique } from '../lib/initUnique.js';
|
|
19
|
-
import { InteractionManager } from '../lib/InteractionManager.js';
|
|
19
|
+
import { InteractionManager, } from '../lib/InteractionManager.js';
|
|
20
20
|
import { observe } from '../lib/observe.js';
|
|
21
21
|
import { whenIdleOrHidden } from '../lib/whenIdleOrHidden.js';
|
|
22
22
|
import { onINP as unattributedOnINP } from '../onINP.js';
|
|
@@ -45,7 +45,7 @@ const MAX_PENDING_FRAMES = 10;
|
|
|
45
45
|
*
|
|
46
46
|
* A custom `includeProcessedEventEntries` configuration option can optionally
|
|
47
47
|
* be passed to control whether the `processedEventEntries` array in the
|
|
48
|
-
* attribution object is populated. The default value is `
|
|
48
|
+
* attribution object is populated. The default value is `false`.
|
|
49
49
|
*
|
|
50
50
|
* If the `reportAllChanges` configuration option is set to `true`, the
|
|
51
51
|
* `callback` function will be called as soon as the value is initially
|
|
@@ -95,11 +95,19 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
95
95
|
};
|
|
96
96
|
const saveInteractionTarget = (interaction) => {
|
|
97
97
|
if (!interactionTargetMap.get(interaction)) {
|
|
98
|
-
|
|
98
|
+
// Use find to get first selector
|
|
99
|
+
const node = interaction.entries.find((e) => e.target)?.target;
|
|
99
100
|
if (node) {
|
|
100
101
|
const customTarget = opts.generateTarget?.(node) ?? getSelector(node);
|
|
101
102
|
interactionTargetMap.set(interaction, customTarget);
|
|
102
103
|
}
|
|
104
|
+
else {
|
|
105
|
+
// Fall back to targetSelector
|
|
106
|
+
const selector = interaction.entries.find((e) => e.targetSelector)?.targetSelector;
|
|
107
|
+
if (selector) {
|
|
108
|
+
interactionTargetMap.set(interaction, selector);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
103
111
|
}
|
|
104
112
|
};
|
|
105
113
|
/**
|
|
@@ -129,7 +137,7 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
129
137
|
group.processingEnd = Math.max(entry.processingEnd, group.processingEnd);
|
|
130
138
|
// processedEventEntries can be quite large, so only include them if
|
|
131
139
|
// the user explicitly requests them (default is to include).
|
|
132
|
-
if (opts.includeProcessedEventEntries
|
|
140
|
+
if (opts.includeProcessedEventEntries) {
|
|
133
141
|
group.entries.push(entry);
|
|
134
142
|
}
|
|
135
143
|
break;
|
|
@@ -144,7 +152,7 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
144
152
|
renderTime,
|
|
145
153
|
// processedEventEntries can be quite large, so only include them if
|
|
146
154
|
// the user explicitly requests them (default is to include).
|
|
147
|
-
entries: opts.includeProcessedEventEntries
|
|
155
|
+
entries: opts.includeProcessedEventEntries ? [entry] : [],
|
|
148
156
|
};
|
|
149
157
|
pendingEntriesGroups.push(group);
|
|
150
158
|
}
|
|
@@ -216,6 +224,7 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
216
224
|
rating: 'good',
|
|
217
225
|
value: entry.duration,
|
|
218
226
|
delta: entry.duration,
|
|
227
|
+
navigationId: entry.navigationId,
|
|
219
228
|
navigationType: 'navigate',
|
|
220
229
|
id: 'N/A',
|
|
221
230
|
});
|
|
@@ -242,11 +251,15 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
242
251
|
return intersectingLoAFs;
|
|
243
252
|
};
|
|
244
253
|
const attributeLoAFDetails = (attribution) => {
|
|
245
|
-
|
|
246
|
-
|
|
254
|
+
const interactionTime = attribution.interactionTime;
|
|
255
|
+
const nextPaintTime = attribution.nextPaintTime;
|
|
256
|
+
// If there is no LoAF data, interactionTime or paintTime
|
|
257
|
+
// then nothing further to attribute here.
|
|
258
|
+
if (!attribution.longAnimationFrameEntries?.length ||
|
|
259
|
+
!interactionTime ||
|
|
260
|
+
!nextPaintTime) {
|
|
247
261
|
return;
|
|
248
262
|
}
|
|
249
|
-
const interactionTime = attribution.interactionTime;
|
|
250
263
|
const inputDelay = attribution.inputDelay;
|
|
251
264
|
const processingDuration = attribution.processingDuration;
|
|
252
265
|
// Stats across all LoAF entries and scripts.
|
|
@@ -302,7 +315,7 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
302
315
|
? lastLoAF.startTime + lastLoAF.duration
|
|
303
316
|
: 0;
|
|
304
317
|
if (lastLoAFEndTime >= interactionTime + inputDelay + processingDuration) {
|
|
305
|
-
totalPaintDuration =
|
|
318
|
+
totalPaintDuration = nextPaintTime - lastLoAFEndTime;
|
|
306
319
|
}
|
|
307
320
|
if (longestScriptEntry && longestScriptSubpart) {
|
|
308
321
|
attribution.longestScript = {
|
|
@@ -315,16 +328,34 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
315
328
|
attribution.totalStyleAndLayoutDuration = totalStyleAndLayoutDuration;
|
|
316
329
|
attribution.totalPaintDuration = totalPaintDuration;
|
|
317
330
|
attribution.totalUnattributedDuration =
|
|
318
|
-
|
|
331
|
+
nextPaintTime -
|
|
319
332
|
interactionTime -
|
|
320
333
|
totalScriptDuration -
|
|
321
334
|
totalStyleAndLayoutDuration -
|
|
322
335
|
totalPaintDuration;
|
|
323
336
|
};
|
|
324
337
|
const attributeINP = (metric) => {
|
|
338
|
+
// Soft navs and bfcache can have a dummy INP as no first-input entry to
|
|
339
|
+
// fall back on so we report dummy values when the interactionCount has
|
|
340
|
+
// gone up, even if no entry was emitted.
|
|
341
|
+
// See https://github.com/GoogleChrome/web-vitals/issues/724
|
|
342
|
+
// All other INPs should have at least one entry, but we'll do same dummy
|
|
343
|
+
// processing if they don't for some reason.
|
|
344
|
+
if (metric.entries.length === 0) {
|
|
345
|
+
const navStartTime = metric.navigationStartTime || 0;
|
|
346
|
+
const attribution = {
|
|
347
|
+
processedEventEntries: [],
|
|
348
|
+
longAnimationFrameEntries: [],
|
|
349
|
+
inputDelay: 0,
|
|
350
|
+
processingDuration: 0,
|
|
351
|
+
presentationDelay: metric.value,
|
|
352
|
+
loadState: getLoadState(navStartTime),
|
|
353
|
+
};
|
|
354
|
+
return Object.assign(metric, { attribution });
|
|
355
|
+
}
|
|
325
356
|
const firstEntry = metric.entries[0];
|
|
326
357
|
const group = entryToEntriesGroupMap.get(firstEntry);
|
|
327
|
-
const processingStart =
|
|
358
|
+
const processingStart = group.processingStart;
|
|
328
359
|
// Due to the fact that durations can be rounded down to the nearest 8ms,
|
|
329
360
|
// we have to clamp `nextPaintTime` so it doesn't appear to occur before
|
|
330
361
|
// processing starts. Note: we can't use `processingEnd` since processing
|
|
@@ -368,7 +399,7 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
368
399
|
return Object.assign(metric, { attribution });
|
|
369
400
|
};
|
|
370
401
|
// Start observing LoAF entries for attribution.
|
|
371
|
-
observe('long-animation-frame', handleLoAFEntries);
|
|
402
|
+
observe(['long-animation-frame'], handleLoAFEntries, opts);
|
|
372
403
|
unattributedOnINP((metric) => {
|
|
373
404
|
onReport(attributeINP(metric));
|
|
374
405
|
}, opts);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LCPMetricWithAttribution, AttributionReportOpts } from '../types.js';
|
|
1
|
+
import type { LCPMetricWithAttribution, AttributionReportOpts } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
|
|
4
4
|
* calls the `callback` function once the value is ready (along with the
|
|
@@ -17,6 +17,7 @@ import { getNavigationEntry } from '../lib/getNavigationEntry.js';
|
|
|
17
17
|
import { getSelector } from '../lib/getSelector.js';
|
|
18
18
|
import { initUnique } from '../lib/initUnique.js';
|
|
19
19
|
import { LCPEntryManager } from '../lib/LCPEntryManager.js';
|
|
20
|
+
import { checkSoftNavsEnabled } from '../lib/softNavs.js';
|
|
20
21
|
import { onLCP as unattributedOnLCP } from '../onLCP.js';
|
|
21
22
|
/**
|
|
22
23
|
* Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
|
|
@@ -37,6 +38,9 @@ export const onLCP = (onReport, opts = {}) => {
|
|
|
37
38
|
opts = Object.assign({}, opts);
|
|
38
39
|
const lcpEntryManager = initUnique(opts, LCPEntryManager);
|
|
39
40
|
const lcpTargetMap = new WeakMap();
|
|
41
|
+
if (checkSoftNavsEnabled(opts)) {
|
|
42
|
+
lcpEntryManager._softNavigationEntryMap = new Map();
|
|
43
|
+
}
|
|
40
44
|
lcpEntryManager._onBeforeProcessingEntry = (entry) => {
|
|
41
45
|
const node = entry.element;
|
|
42
46
|
if (node) {
|
|
@@ -75,10 +79,24 @@ export const onLCP = (onReport, opts = {}) => {
|
|
|
75
79
|
}
|
|
76
80
|
// Get subparts from navigation entry. Do this last as occasionally
|
|
77
81
|
// Safari seems to fail to find a navigation entry.
|
|
78
|
-
|
|
82
|
+
let navigationEntry;
|
|
83
|
+
let activationStart = 0;
|
|
84
|
+
let responseStart = 0;
|
|
85
|
+
if (metric.navigationType !== 'soft-navigation') {
|
|
86
|
+
navigationEntry = getNavigationEntry();
|
|
87
|
+
activationStart = navigationEntry?.activationStart ?? 0;
|
|
88
|
+
responseStart = navigationEntry?.responseStart ?? 0;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Set activationStart to the navigation start time
|
|
92
|
+
activationStart = metric.navigationStartTime || 0;
|
|
93
|
+
// Lookup the soft navigation entry. Do not use getEntriesByType since
|
|
94
|
+
// that is limited to the first 50 navigation entries due to buffer
|
|
95
|
+
// size.
|
|
96
|
+
navigationEntry = lcpEntryManager._softNavigationEntryMap?.get(metric.navigationId);
|
|
97
|
+
}
|
|
79
98
|
if (navigationEntry) {
|
|
80
|
-
const
|
|
81
|
-
const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
|
|
99
|
+
const ttfb = Math.max(0, responseStart - activationStart);
|
|
82
100
|
const lcpRequestStart = Math.max(ttfb,
|
|
83
101
|
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
|
|
84
102
|
lcpResourceEntry
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TTFBMetricWithAttribution, AttributionReportOpts } from '../types.js';
|
|
1
|
+
import type { 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,
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { onTTFB as unattributedOnTTFB } from '../onTTFB.js';
|
|
17
17
|
const attributeTTFB = (metric) => {
|
|
18
|
+
const navigationEntry = metric.entries[0];
|
|
18
19
|
// Use a default object if no other attribution has been set.
|
|
19
20
|
let attribution = {
|
|
20
21
|
waitingDuration: 0,
|
|
@@ -22,32 +23,37 @@ const attributeTTFB = (metric) => {
|
|
|
22
23
|
dnsDuration: 0,
|
|
23
24
|
connectionDuration: 0,
|
|
24
25
|
requestDuration: 0,
|
|
26
|
+
// There should only be one instance per TTFB metric
|
|
27
|
+
navigationEntry: navigationEntry,
|
|
25
28
|
};
|
|
26
29
|
if (metric.entries.length) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
30
|
+
// If it's the hard nav, then can give attribution.
|
|
31
|
+
// Otherwise it's 0 so the defaults are fine.
|
|
32
|
+
if (navigationEntry instanceof PerformanceNavigationTiming) {
|
|
33
|
+
const activationStart = navigationEntry.activationStart || 0;
|
|
34
|
+
// Measure from workerStart or fetchStart so any service worker startup
|
|
35
|
+
// time is included in cacheDuration (which also includes other sw time
|
|
36
|
+
// anyway, that cannot be accurately split out cross-browser).
|
|
37
|
+
const waitEnd = Math.max((navigationEntry.workerStart || navigationEntry.fetchStart || 0) -
|
|
38
|
+
activationStart, 0);
|
|
39
|
+
const dnsStart = Math.max(navigationEntry.domainLookupStart - activationStart, 0);
|
|
40
|
+
const connectStart = Math.max(navigationEntry.connectStart - activationStart, 0);
|
|
41
|
+
const connectEnd = Math.max(navigationEntry.connectEnd - activationStart, 0);
|
|
42
|
+
attribution = {
|
|
43
|
+
waitingDuration: waitEnd,
|
|
44
|
+
cacheDuration: dnsStart - waitEnd,
|
|
45
|
+
// dnsEnd usually equals connectStart but use connectStart over dnsEnd
|
|
46
|
+
// for dnsDuration in case there ever is a gap.
|
|
47
|
+
dnsDuration: connectStart - dnsStart,
|
|
48
|
+
connectionDuration: connectEnd - connectStart,
|
|
49
|
+
// There is often a gap between connectEnd and requestStart. Attribute
|
|
50
|
+
// that to requestDuration so connectionDuration remains 0 for
|
|
51
|
+
// service worker controlled requests were connectStart and connectEnd
|
|
52
|
+
// are the same.
|
|
53
|
+
requestDuration: metric.value - connectEnd,
|
|
54
|
+
navigationEntry: navigationEntry,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
// Use `Object.assign()` to ensure the original metric object is returned.
|
|
53
59
|
const metricWithAttribution = Object.assign(metric, { attribution });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 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 FCPEntryManager {
|
|
17
|
+
_softNavigationEntryMap;
|
|
18
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Metric } from '../types.js';
|
|
1
2
|
export interface Interaction {
|
|
2
3
|
_latency: number;
|
|
3
4
|
id: number;
|
|
@@ -22,7 +23,7 @@ export declare class InteractionManager {
|
|
|
22
23
|
* Returns the estimated p98 longest interaction based on the stored
|
|
23
24
|
* interaction candidates and the interaction count for the current page.
|
|
24
25
|
*/
|
|
25
|
-
_estimateP98LongestInteraction(): Interaction;
|
|
26
|
+
_estimateP98LongestInteraction(navigationType: Metric['navigationType']): Interaction;
|
|
26
27
|
/**
|
|
27
28
|
* Takes a performance entry and adds it to the list of worst interactions
|
|
28
29
|
* if its duration is long enough to make it among the worst. If the
|
|
@@ -50,8 +50,24 @@ export class InteractionManager {
|
|
|
50
50
|
* Returns the estimated p98 longest interaction based on the stored
|
|
51
51
|
* interaction candidates and the interaction count for the current page.
|
|
52
52
|
*/
|
|
53
|
-
_estimateP98LongestInteraction() {
|
|
54
|
-
const
|
|
53
|
+
_estimateP98LongestInteraction(navigationType) {
|
|
54
|
+
const interactionCountForNavigation = getInteractionCountForNavigation();
|
|
55
|
+
const candidateInteractionIndex = Math.min(this._longestInteractionList.length - 1, Math.floor(interactionCountForNavigation / 50));
|
|
56
|
+
// If we have a non-zero interactionCountForNavigation but no
|
|
57
|
+
// candidateInteractionIndex, then it's below the 16ms limit
|
|
58
|
+
// so report a dummy 8ms interaction. This is only needed for
|
|
59
|
+
// soft-navs and bfcache restores as `first-input` handles the
|
|
60
|
+
// rest.
|
|
61
|
+
if (interactionCountForNavigation &&
|
|
62
|
+
candidateInteractionIndex === -1 &&
|
|
63
|
+
(navigationType === 'soft-navigation' ||
|
|
64
|
+
navigationType === 'back-forward-cache')) {
|
|
65
|
+
return {
|
|
66
|
+
_latency: 8,
|
|
67
|
+
id: -1,
|
|
68
|
+
entries: [],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
55
71
|
return this._longestInteractionList[candidateInteractionIndex];
|
|
56
72
|
}
|
|
57
73
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MetricType, MetricRatingThresholds } from '../types.js';
|
|
1
|
+
import type { MetricType, MetricRatingThresholds } from '../types.js';
|
|
2
2
|
export declare const bindReporter: <MetricName extends MetricType["name"]>(callback: (metric: Extract<MetricType, {
|
|
3
3
|
name: MetricName;
|
|
4
4
|
}>) => void, metric: Extract<MetricType, {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { LoadState } from '../types.js';
|
|
1
|
+
import type { LoadState } from '../types.js';
|
|
2
2
|
export declare const getLoadState: (timestamp: number) => LoadState;
|
|
@@ -20,19 +20,19 @@ export const getLoadState = (timestamp) => {
|
|
|
20
20
|
// since the timestamp has to be the current time or earlier.
|
|
21
21
|
return 'loading';
|
|
22
22
|
}
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
if (timestamp <
|
|
23
|
+
const hardNavEntry = getNavigationEntry();
|
|
24
|
+
if (hardNavEntry) {
|
|
25
|
+
if (timestamp < hardNavEntry.domInteractive) {
|
|
26
26
|
return 'loading';
|
|
27
27
|
}
|
|
28
|
-
if (
|
|
29
|
-
timestamp <
|
|
28
|
+
else if (hardNavEntry.domContentLoadedEventStart === 0 ||
|
|
29
|
+
timestamp < hardNavEntry.domContentLoadedEventStart) {
|
|
30
30
|
// If the `domContentLoadedEventStart` timestamp has not yet been
|
|
31
31
|
// set, or if the given timestamp is less than that value.
|
|
32
32
|
return 'dom-interactive';
|
|
33
33
|
}
|
|
34
|
-
if (
|
|
35
|
-
timestamp <
|
|
34
|
+
else if (hardNavEntry.domComplete === 0 ||
|
|
35
|
+
timestamp < hardNavEntry.domComplete) {
|
|
36
36
|
// If the `domComplete` timestamp has not yet been
|
|
37
37
|
// set, or if the given timestamp is less than that value.
|
|
38
38
|
return 'dom-content-loaded';
|
|
@@ -27,7 +27,7 @@ export const getSelector = (node) => {
|
|
|
27
27
|
const el = node;
|
|
28
28
|
const part = el.id
|
|
29
29
|
? '#' + el.id
|
|
30
|
-
: [getName(el), ...Array.from(el.classList).sort()].join('.');
|
|
30
|
+
: [getName(el), ...Array.from(el.classList ?? []).sort()].join('.');
|
|
31
31
|
if (sel.length + part.length > MAX_LEN - 1) {
|
|
32
32
|
return sel || part;
|
|
33
33
|
}
|
|
@@ -53,7 +53,10 @@ const onVisibilityUpdate = (event) => {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
-
export const getVisibilityWatcher = () => {
|
|
56
|
+
export const getVisibilityWatcher = (reset = false) => {
|
|
57
|
+
if (reset) {
|
|
58
|
+
firstHiddenTime = Infinity;
|
|
59
|
+
}
|
|
57
60
|
if (firstHiddenTime < 0) {
|
|
58
61
|
// Check if we have a previous hidden `visibility-state` performance entry.
|
|
59
62
|
const activationStart = getActivationStart();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MetricType } from '../types.js';
|
|
2
|
-
export declare const initMetric: <MetricName extends MetricType["name"]>(name: MetricName, value?: number) => {
|
|
1
|
+
import type { MetricType } from '../types.js';
|
|
2
|
+
export declare const initMetric: <MetricName extends MetricType["name"]>(name: MetricName, value?: number, navigationType?: MetricType["navigationType"], navigationId?: number, navigationInteractionId?: number, navigationURL?: string, navigationStartTime?: number) => {
|
|
3
3
|
name: MetricName;
|
|
4
4
|
value: number;
|
|
5
5
|
rating: "good";
|
|
@@ -16,5 +16,9 @@ export declare const initMetric: <MetricName extends MetricType["name"]>(name: M
|
|
|
16
16
|
name: MetricName;
|
|
17
17
|
}>)["entries"];
|
|
18
18
|
id: string;
|
|
19
|
-
navigationType: "reload" | "navigate" | "back-forward" | "back-forward-cache" | "prerender" | "restore";
|
|
19
|
+
navigationType: "reload" | "navigate" | "soft-navigation" | "back-forward" | "back-forward-cache" | "prerender" | "restore";
|
|
20
|
+
navigationId: number;
|
|
21
|
+
navigationInteractionId: number | undefined;
|
|
22
|
+
navigationURL: string | undefined;
|
|
23
|
+
navigationStartTime: number;
|
|
20
24
|
};
|
|
@@ -17,21 +17,26 @@ 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 = -1) => {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
export const initMetric = (name, value = -1, navigationType, navigationId = 0, navigationInteractionId, navigationURL, navigationStartTime) => {
|
|
21
|
+
const hardNavEntry = getNavigationEntry();
|
|
22
|
+
const hardNavId = hardNavEntry?.navigationId || 0;
|
|
23
|
+
let _navigationType = 'navigate';
|
|
24
|
+
if (navigationType) {
|
|
25
|
+
// If it was passed in, then use that
|
|
26
|
+
_navigationType = navigationType;
|
|
25
27
|
}
|
|
26
|
-
else if (
|
|
28
|
+
else if (getBFCacheRestoreTime() >= 0) {
|
|
29
|
+
_navigationType = 'back-forward-cache';
|
|
30
|
+
}
|
|
31
|
+
else if (hardNavEntry) {
|
|
27
32
|
if (document.prerendering || getActivationStart() > 0) {
|
|
28
|
-
|
|
33
|
+
_navigationType = 'prerender';
|
|
29
34
|
}
|
|
30
35
|
else if (document.wasDiscarded) {
|
|
31
|
-
|
|
36
|
+
_navigationType = 'restore';
|
|
32
37
|
}
|
|
33
|
-
else if (
|
|
34
|
-
|
|
38
|
+
else if (hardNavEntry.type) {
|
|
39
|
+
_navigationType = hardNavEntry.type.replace(/_/g, '-');
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
// Use `entries` type specific for the metric.
|
|
@@ -43,6 +48,10 @@ export const initMetric = (name, value = -1) => {
|
|
|
43
48
|
delta: 0,
|
|
44
49
|
entries,
|
|
45
50
|
id: generateUniqueID(),
|
|
46
|
-
navigationType,
|
|
51
|
+
navigationType: _navigationType,
|
|
52
|
+
navigationId: navigationId || hardNavId,
|
|
53
|
+
navigationInteractionId: navigationInteractionId,
|
|
54
|
+
navigationURL: navigationURL || hardNavEntry?.name,
|
|
55
|
+
navigationStartTime: navigationStartTime || 0,
|
|
47
56
|
};
|
|
48
57
|
};
|
|
@@ -20,8 +20,13 @@ const instanceMap = new WeakMap();
|
|
|
20
20
|
* identity object was previously used.
|
|
21
21
|
*/
|
|
22
22
|
export function initUnique(identityObj, ClassObj) {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
let classInstances = instanceMap.get(ClassObj);
|
|
24
|
+
if (!classInstances) {
|
|
25
|
+
classInstances = new WeakMap();
|
|
26
|
+
instanceMap.set(ClassObj, classInstances);
|
|
25
27
|
}
|
|
26
|
-
|
|
28
|
+
if (!classInstances.get(identityObj)) {
|
|
29
|
+
classInstances.set(identityObj, new ClassObj());
|
|
30
|
+
}
|
|
31
|
+
return classInstances.get(identityObj);
|
|
27
32
|
}
|