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
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
interface PerformanceEntryMap {
|
|
2
2
|
'event': PerformanceEventTiming[];
|
|
3
3
|
'first-input': PerformanceEventTiming[];
|
|
4
|
+
'interaction-contentful-paint': InteractionContentfulPaint[];
|
|
4
5
|
'layout-shift': LayoutShift[];
|
|
5
6
|
'largest-contentful-paint': LargestContentfulPaint[];
|
|
6
7
|
'long-animation-frame': PerformanceLongAnimationFrameTiming[];
|
|
7
8
|
'paint': PerformancePaintTiming[];
|
|
8
9
|
'navigation': PerformanceNavigationTiming[];
|
|
9
10
|
'resource': PerformanceResourceTiming[];
|
|
11
|
+
'soft-navigation': PerformanceSoftNavigation[];
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* Takes a performance entry type and a callback function, and creates a
|
|
@@ -16,5 +18,5 @@ interface PerformanceEntryMap {
|
|
|
16
18
|
* This function also feature-detects entry support and wraps the logic in a
|
|
17
19
|
* try/catch to avoid errors in unsupporting browsers.
|
|
18
20
|
*/
|
|
19
|
-
export declare const observe: <K extends keyof PerformanceEntryMap>(
|
|
21
|
+
export declare const observe: <K extends keyof PerformanceEntryMap>(types: K[], callback: (entries: Array<PerformanceEntryMap[K][number]>) => void, opts?: PerformanceObserverInit) => PerformanceObserver | undefined;
|
|
20
22
|
export {};
|
|
@@ -21,18 +21,33 @@
|
|
|
21
21
|
* This function also feature-detects entry support and wraps the logic in a
|
|
22
22
|
* try/catch to avoid errors in unsupporting browsers.
|
|
23
23
|
*/
|
|
24
|
-
export const observe = (
|
|
24
|
+
export const observe = (types, callback, opts = {}) => {
|
|
25
25
|
try {
|
|
26
|
-
|
|
26
|
+
const supportedTypes = types.filter((t) => PerformanceObserver.supportedEntryTypes.includes(t));
|
|
27
|
+
if (supportedTypes.length > 0) {
|
|
27
28
|
const po = new PerformanceObserver((list) => {
|
|
28
29
|
// Delay by a microtask to workaround a bug in Safari where the
|
|
29
30
|
// callback is invoked immediately, rather than in a separate task.
|
|
30
31
|
// See: https://github.com/GoogleChrome/web-vitals/issues/277
|
|
31
32
|
queueMicrotask(() => {
|
|
32
|
-
|
|
33
|
+
const entries = list.getEntries();
|
|
34
|
+
// When observing more than one entry type, entries from different
|
|
35
|
+
// types can be delivered out of order, so sort by end time
|
|
36
|
+
// (startTime + duration) to ensure they're in the right order.
|
|
37
|
+
// See: https://github.com/w3c/performance-timeline/issues/224
|
|
38
|
+
if (supportedTypes.length > 1) {
|
|
39
|
+
entries.sort((a, b) => {
|
|
40
|
+
const scoreA = a.startTime + a.duration;
|
|
41
|
+
const scoreB = b.startTime + b.duration;
|
|
42
|
+
return scoreA - scoreB;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
callback(entries);
|
|
33
46
|
});
|
|
34
47
|
});
|
|
35
|
-
|
|
48
|
+
for (const t of supportedTypes) {
|
|
49
|
+
po.observe({ type: t, buffered: true, ...opts });
|
|
50
|
+
}
|
|
36
51
|
return po;
|
|
37
52
|
}
|
|
38
53
|
}
|
|
@@ -42,7 +42,7 @@ export const getInteractionCount = () => {
|
|
|
42
42
|
export const initInteractionCountPolyfill = () => {
|
|
43
43
|
if ('interactionCount' in performance || po)
|
|
44
44
|
return;
|
|
45
|
-
po = observe('event', updateEstimate, {
|
|
45
|
+
po = observe(['event'], updateEstimate, {
|
|
46
46
|
durationThreshold: 0,
|
|
47
47
|
});
|
|
48
48
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 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 const checkSoftNavsEnabled = (opts) => {
|
|
17
|
+
return (PerformanceObserver.supportedEntryTypes.includes('soft-navigation') &&
|
|
18
|
+
// Older implementations expose the value as an attribute rather than the
|
|
19
|
+
// method. We only support the newer method as that was what was launched
|
|
20
|
+
// to stable unflagged.
|
|
21
|
+
typeof globalThis.PerformanceSoftNavigation?.prototype
|
|
22
|
+
?.getLargestInteractionContentfulPaint === 'function' &&
|
|
23
|
+
opts &&
|
|
24
|
+
opts.reportSoftNavs);
|
|
25
|
+
};
|
|
26
|
+
// Stores a soft navigation entry keyed by its navigationId, keeping only
|
|
27
|
+
// the 2 most recent entries so the map cannot grow unbounded.
|
|
28
|
+
export const storeSoftNavEntry = (map, entry) => {
|
|
29
|
+
map.set(entry.navigationId, entry);
|
|
30
|
+
// Clean up older entries to prevent memory leaks, keeping only
|
|
31
|
+
// the 2 most recent entries.
|
|
32
|
+
if (map.size > 2) {
|
|
33
|
+
const firstKey = map.keys().next().value;
|
|
34
|
+
if (firstKey !== undefined) {
|
|
35
|
+
map.delete(firstKey);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -19,6 +19,10 @@ import { runOnce } from './runOnce.js';
|
|
|
19
19
|
* if the browser's visibility state is (or becomes) hidden.
|
|
20
20
|
*/
|
|
21
21
|
export const whenIdleOrHidden = (cb) => {
|
|
22
|
+
// Cap the requestIdleCallback to 1 sec for very busy apps
|
|
23
|
+
// https://github.com/GoogleChrome/web-vitals/issues/754
|
|
24
|
+
// If not using rIC, then the setTimeout timeout should be 0
|
|
25
|
+
const timeout = 'requestIdleCallback' in globalThis ? 1000 : 0;
|
|
22
26
|
const rIC = globalThis.requestIdleCallback || setTimeout;
|
|
23
27
|
const cIC = globalThis.cancelIdleCallback || clearTimeout;
|
|
24
28
|
// If the document is hidden, run the callback immediately, otherwise
|
|
@@ -37,6 +41,6 @@ export const whenIdleOrHidden = (cb) => {
|
|
|
37
41
|
idleHandle = rIC(() => {
|
|
38
42
|
removeEventListener('visibilitychange', onHidden, { capture: true });
|
|
39
43
|
wrappedCb();
|
|
40
|
-
});
|
|
44
|
+
}, { timeout: timeout });
|
|
41
45
|
}
|
|
42
46
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CLSMetric, MetricRatingThresholds, ReportOpts } from './types.js';
|
|
1
|
+
import type { CLSMetric, MetricRatingThresholds, ReportOpts } from './types.js';
|
|
2
2
|
/** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */
|
|
3
3
|
export declare const CLSThresholds: MetricRatingThresholds;
|
|
4
4
|
/**
|
|
@@ -13,16 +13,17 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { onBFCacheRestore } from './lib/bfcache.js';
|
|
16
|
+
import { getBFCacheRestoreTime, onBFCacheRestore } from './lib/bfcache.js';
|
|
17
17
|
import { bindReporter } from './lib/bindReporter.js';
|
|
18
18
|
import { doubleRAF } from './lib/doubleRAF.js';
|
|
19
|
+
import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
|
|
19
20
|
import { initMetric } from './lib/initMetric.js';
|
|
20
21
|
import { initUnique } from './lib/initUnique.js';
|
|
21
22
|
import { LayoutShiftManager } from './lib/LayoutShiftManager.js';
|
|
22
23
|
import { observe } from './lib/observe.js';
|
|
24
|
+
import { checkSoftNavsEnabled } from './lib/softNavs.js';
|
|
23
25
|
import { runOnce } from './lib/runOnce.js';
|
|
24
26
|
import { onFCP } from './onFCP.js';
|
|
25
|
-
import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
|
|
26
27
|
/** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */
|
|
27
28
|
export const CLSThresholds = [0.1, 0.25];
|
|
28
29
|
/**
|
|
@@ -54,19 +55,39 @@ export const onCLS = (onReport, opts = {}) => {
|
|
|
54
55
|
let metric = initMetric('CLS', 0);
|
|
55
56
|
let report;
|
|
56
57
|
const layoutShiftManager = initUnique(opts, LayoutShiftManager);
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
const initNewCLSMetric = (navigationType, navigationId, navigationInteractionId, navigationURL, navigationStartTime) => {
|
|
59
|
+
metric = initMetric('CLS', 0, navigationType, navigationId, navigationInteractionId, navigationURL, navigationStartTime);
|
|
60
|
+
layoutShiftManager._sessionValue = 0;
|
|
61
|
+
report = bindReporter(onReport, metric, CLSThresholds, opts.reportAllChanges);
|
|
62
|
+
};
|
|
63
|
+
const updateAndReportMetric = (forceReport = false) => {
|
|
61
64
|
// If the current session value is larger than the current CLS value,
|
|
62
65
|
// update CLS and the entries contributing to it.
|
|
63
66
|
if (layoutShiftManager._sessionValue > metric.value) {
|
|
64
67
|
metric.value = layoutShiftManager._sessionValue;
|
|
65
68
|
metric.entries = layoutShiftManager._sessionEntries;
|
|
66
|
-
report();
|
|
67
69
|
}
|
|
70
|
+
report(forceReport);
|
|
68
71
|
};
|
|
69
|
-
const
|
|
72
|
+
const handleSoftNavEntry = (entry) => {
|
|
73
|
+
updateAndReportMetric(true);
|
|
74
|
+
initNewCLSMetric('soft-navigation', entry.navigationId, entry.interactionId, entry.name, entry.startTime);
|
|
75
|
+
};
|
|
76
|
+
const handleEntries = (entries) => {
|
|
77
|
+
for (const entry of entries) {
|
|
78
|
+
if (entry.entryType === 'soft-navigation') {
|
|
79
|
+
handleSoftNavEntry(entry);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
layoutShiftManager._processEntry(entry);
|
|
83
|
+
}
|
|
84
|
+
updateAndReportMetric();
|
|
85
|
+
};
|
|
86
|
+
const types = ['layout-shift'];
|
|
87
|
+
if (checkSoftNavsEnabled(opts)) {
|
|
88
|
+
types.push('soft-navigation');
|
|
89
|
+
}
|
|
90
|
+
const po = observe(types, handleEntries);
|
|
70
91
|
if (po) {
|
|
71
92
|
report = bindReporter(onReport, metric, CLSThresholds, opts.reportAllChanges);
|
|
72
93
|
visibilityWatcher.onHidden(() => {
|
|
@@ -76,9 +97,7 @@ export const onCLS = (onReport, opts = {}) => {
|
|
|
76
97
|
// Only report after a bfcache restore if the `PerformanceObserver`
|
|
77
98
|
// successfully registered.
|
|
78
99
|
onBFCacheRestore(() => {
|
|
79
|
-
|
|
80
|
-
metric = initMetric('CLS', 0);
|
|
81
|
-
report = bindReporter(onReport, metric, CLSThresholds, opts.reportAllChanges);
|
|
100
|
+
initNewCLSMetric('back-forward-cache', metric.navigationId, metric.navigationInteractionId, metric.navigationURL, getBFCacheRestoreTime());
|
|
82
101
|
doubleRAF(report);
|
|
83
102
|
});
|
|
84
103
|
// Queue a task to report (if nothing else triggers a report first).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FCPMetric, MetricRatingThresholds, ReportOpts } from './types.js';
|
|
1
|
+
import type { FCPMetric, MetricRatingThresholds, ReportOpts } from './types.js';
|
|
2
2
|
/** Thresholds for FCP. See https://web.dev/articles/fcp#what_is_a_good_fcp_score */
|
|
3
3
|
export declare const FCPThresholds: MetricRatingThresholds;
|
|
4
4
|
/**
|
|
@@ -13,13 +13,16 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { onBFCacheRestore } from './lib/bfcache.js';
|
|
17
16
|
import { bindReporter } from './lib/bindReporter.js';
|
|
17
|
+
import { checkSoftNavsEnabled, storeSoftNavEntry } from './lib/softNavs.js';
|
|
18
18
|
import { doubleRAF } from './lib/doubleRAF.js';
|
|
19
19
|
import { getActivationStart } from './lib/getActivationStart.js';
|
|
20
20
|
import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
|
|
21
21
|
import { initMetric } from './lib/initMetric.js';
|
|
22
|
+
import { initUnique } from './lib/initUnique.js';
|
|
23
|
+
import { FCPEntryManager } from './lib/FCPEntryManager.js';
|
|
22
24
|
import { observe } from './lib/observe.js';
|
|
25
|
+
import { getBFCacheRestoreTime, onBFCacheRestore } from './lib/bfcache.js';
|
|
23
26
|
import { whenActivated } from './lib/whenActivated.js';
|
|
24
27
|
/** Thresholds for FCP. See https://web.dev/articles/fcp#what_is_a_good_fcp_score */
|
|
25
28
|
export const FCPThresholds = [1800, 3000];
|
|
@@ -30,7 +33,12 @@ export const FCPThresholds = [1800, 3000];
|
|
|
30
33
|
* value is a `DOMHighResTimeStamp`.
|
|
31
34
|
*/
|
|
32
35
|
export const onFCP = (onReport, opts = {}) => {
|
|
36
|
+
const softNavsEnabled = checkSoftNavsEnabled(opts);
|
|
33
37
|
whenActivated(() => {
|
|
38
|
+
// Create a new FCP entry manager for each page activation
|
|
39
|
+
// This allows us to track soft navigations separately
|
|
40
|
+
// needed when attribution is enabled.
|
|
41
|
+
const fcpEntryManager = initUnique(opts, FCPEntryManager);
|
|
34
42
|
const visibilityWatcher = getVisibilityWatcher();
|
|
35
43
|
let metric = initMetric('FCP');
|
|
36
44
|
let report;
|
|
@@ -38,7 +46,7 @@ export const onFCP = (onReport, opts = {}) => {
|
|
|
38
46
|
for (const entry of entries) {
|
|
39
47
|
if (entry.name === 'first-contentful-paint') {
|
|
40
48
|
po.disconnect();
|
|
41
|
-
// Only report if the page wasn't hidden prior to
|
|
49
|
+
// Only report if the page wasn't hidden prior to FCP.
|
|
42
50
|
if (entry.startTime < visibilityWatcher.firstHiddenTime) {
|
|
43
51
|
// The activationStart reference is used because FCP should be
|
|
44
52
|
// relative to page activation rather than navigation start if the
|
|
@@ -46,18 +54,20 @@ export const onFCP = (onReport, opts = {}) => {
|
|
|
46
54
|
// after the FCP, this time should be clamped at 0.
|
|
47
55
|
metric.value = Math.max(entry.startTime - getActivationStart(), 0);
|
|
48
56
|
metric.entries.push(entry);
|
|
57
|
+
metric.navigationId = entry.navigationId || metric.navigationId;
|
|
58
|
+
// FCP should only be reported once so can report right away
|
|
49
59
|
report(true);
|
|
50
60
|
}
|
|
51
61
|
}
|
|
52
62
|
}
|
|
53
63
|
};
|
|
54
|
-
const po = observe('paint', handleEntries);
|
|
64
|
+
const po = observe(['paint'], handleEntries);
|
|
55
65
|
if (po) {
|
|
56
66
|
report = bindReporter(onReport, metric, FCPThresholds, opts.reportAllChanges);
|
|
57
67
|
// Only report after a bfcache restore if the `PerformanceObserver`
|
|
58
68
|
// successfully registered or the `paint` entry exists.
|
|
59
69
|
onBFCacheRestore((event) => {
|
|
60
|
-
metric = initMetric('FCP');
|
|
70
|
+
metric = initMetric('FCP', -1, 'back-forward-cache', metric.navigationId, metric.navigationInteractionId, metric.navigationURL, getBFCacheRestoreTime());
|
|
61
71
|
report = bindReporter(onReport, metric, FCPThresholds, opts.reportAllChanges);
|
|
62
72
|
doubleRAF(() => {
|
|
63
73
|
metric.value = performance.now() - event.timeStamp;
|
|
@@ -65,5 +75,27 @@ export const onFCP = (onReport, opts = {}) => {
|
|
|
65
75
|
});
|
|
66
76
|
});
|
|
67
77
|
}
|
|
78
|
+
if (softNavsEnabled) {
|
|
79
|
+
// As first-contentful-paint is only reported once, we can handle soft
|
|
80
|
+
// navigations afterwards on their own for simplicity, as no need to
|
|
81
|
+
// observe both and sort the entries like for the other metrics
|
|
82
|
+
const handleSoftNavEntries = (entries) => {
|
|
83
|
+
entries.forEach((entry) => {
|
|
84
|
+
// Store the soft navigation entries in the entry manager so that
|
|
85
|
+
// they can be retrieved for attribution if necessary. This code
|
|
86
|
+
// is only used when attribution is enabled which sets the
|
|
87
|
+
// _softNavigationEntryMap.
|
|
88
|
+
if (fcpEntryManager._softNavigationEntryMap && entry.navigationId) {
|
|
89
|
+
storeSoftNavEntry(fcpEntryManager._softNavigationEntryMap, entry);
|
|
90
|
+
}
|
|
91
|
+
// Clamp FCP at 0. It should never be less, but better safe than sorry.
|
|
92
|
+
const FCPTime = Math.max((entry.presentationTime || entry.paintTime || 0) - entry.startTime, 0);
|
|
93
|
+
metric = initMetric('FCP', FCPTime, 'soft-navigation', entry.navigationId, entry.interactionId, entry.name, entry.startTime);
|
|
94
|
+
report = bindReporter(onReport, metric, FCPThresholds, opts.reportAllChanges);
|
|
95
|
+
report(true);
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
observe(['soft-navigation'], handleSoftNavEntries, opts);
|
|
99
|
+
}
|
|
68
100
|
});
|
|
69
101
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { INPMetric, MetricRatingThresholds, INPReportOpts } from './types.js';
|
|
1
|
+
import type { INPMetric, MetricRatingThresholds, INPReportOpts } from './types.js';
|
|
2
2
|
/** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */
|
|
3
3
|
export declare const INPThresholds: MetricRatingThresholds;
|
|
4
4
|
/**
|
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { onBFCacheRestore } from './lib/bfcache.js';
|
|
16
|
+
import { getBFCacheRestoreTime, onBFCacheRestore } from './lib/bfcache.js';
|
|
17
17
|
import { bindReporter } from './lib/bindReporter.js';
|
|
18
18
|
import { initMetric } from './lib/initMetric.js';
|
|
19
19
|
import { initUnique } from './lib/initUnique.js';
|
|
20
20
|
import { InteractionManager } from './lib/InteractionManager.js';
|
|
21
21
|
import { observe } from './lib/observe.js';
|
|
22
|
+
import { checkSoftNavsEnabled } from './lib/softNavs.js';
|
|
22
23
|
import { initInteractionCountPolyfill } from './lib/polyfills/interactionCountPolyfill.js';
|
|
23
24
|
import { whenActivated } from './lib/whenActivated.js';
|
|
24
25
|
import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
|
|
@@ -27,6 +28,12 @@ import { whenIdleOrHidden } from './lib/whenIdleOrHidden.js';
|
|
|
27
28
|
export const INPThresholds = [200, 500];
|
|
28
29
|
// The default `durationThreshold` used across this library for observing
|
|
29
30
|
// `event` entries via PerformanceObserver.
|
|
31
|
+
// Event Timing entries have their durations rounded to the nearest 8ms,
|
|
32
|
+
// so a duration of 40ms would be any event that spans 2.5 or more frames
|
|
33
|
+
// at 60Hz. This threshold is chosen to strike a balance between usefulness
|
|
34
|
+
// and performance. Running this callback for any interaction that spans
|
|
35
|
+
// just one or two frames is likely not worth the insight that could be
|
|
36
|
+
// gained.
|
|
30
37
|
const DEFAULT_DURATION_THRESHOLD = 40;
|
|
31
38
|
/**
|
|
32
39
|
* Calculates the [INP](https://web.dev/articles/inp) value for the current
|
|
@@ -70,7 +77,25 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
70
77
|
let metric = initMetric('INP');
|
|
71
78
|
let report;
|
|
72
79
|
const interactionManager = initUnique(opts, InteractionManager);
|
|
73
|
-
const
|
|
80
|
+
const initNewINPMetric = (navigationType, navigationId, navigationInteractionId, navigationURL, navigationStartTime) => {
|
|
81
|
+
interactionManager._resetInteractions();
|
|
82
|
+
metric = initMetric('INP', -1, navigationType, navigationId, navigationInteractionId, navigationURL, navigationStartTime);
|
|
83
|
+
report = bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges);
|
|
84
|
+
};
|
|
85
|
+
const updateINPMetric = () => {
|
|
86
|
+
const inp = interactionManager._estimateP98LongestInteraction(metric.navigationType);
|
|
87
|
+
if (inp && inp._latency !== metric.value) {
|
|
88
|
+
metric.value = inp._latency;
|
|
89
|
+
metric.entries = inp.entries;
|
|
90
|
+
report();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const handleSoftNavEntry = (entry) => {
|
|
94
|
+
updateINPMetric();
|
|
95
|
+
report(true);
|
|
96
|
+
initNewINPMetric('soft-navigation', entry.navigationId, entry.interactionId, entry.name, entry.startTime);
|
|
97
|
+
};
|
|
98
|
+
const handleEntries = (entries, forceReport = false) => {
|
|
74
99
|
// Queue the `handleEntries()` callback in the next idle task.
|
|
75
100
|
// This is needed to increase the chances that all event entries that
|
|
76
101
|
// occurred between the user interaction and the next paint
|
|
@@ -79,40 +104,35 @@ export const onINP = (onReport, opts = {}) => {
|
|
|
79
104
|
// 123+ that if rolled out fully may make this no longer necessary.
|
|
80
105
|
whenIdleOrHidden(() => {
|
|
81
106
|
for (const entry of entries) {
|
|
107
|
+
if (entry.entryType === 'soft-navigation') {
|
|
108
|
+
handleSoftNavEntry(entry);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
82
111
|
interactionManager._processEntry(entry);
|
|
83
112
|
}
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
metric.entries = inp.entries;
|
|
88
|
-
report();
|
|
113
|
+
updateINPMetric();
|
|
114
|
+
if (forceReport) {
|
|
115
|
+
report(true);
|
|
89
116
|
}
|
|
90
117
|
});
|
|
91
118
|
};
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// gained.
|
|
119
|
+
const types = ['event', 'first-input'];
|
|
120
|
+
if (checkSoftNavsEnabled(opts)) {
|
|
121
|
+
types.push('soft-navigation');
|
|
122
|
+
}
|
|
123
|
+
const po = observe(types, handleEntries, {
|
|
124
|
+
...opts,
|
|
99
125
|
durationThreshold: opts.durationThreshold ?? DEFAULT_DURATION_THRESHOLD,
|
|
100
126
|
});
|
|
101
127
|
report = bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges);
|
|
102
128
|
if (po) {
|
|
103
|
-
// Also observe entries of type `first-input`. This is useful in cases
|
|
104
|
-
// where the first interaction is less than the `durationThreshold`.
|
|
105
|
-
po.observe({ type: 'first-input', buffered: true });
|
|
106
129
|
visibilityWatcher.onHidden(() => {
|
|
107
|
-
handleEntries(po.takeRecords());
|
|
108
|
-
report(true);
|
|
130
|
+
handleEntries(po.takeRecords(), true);
|
|
109
131
|
});
|
|
110
132
|
// Only report after a bfcache restore if the `PerformanceObserver`
|
|
111
133
|
// successfully registered.
|
|
112
134
|
onBFCacheRestore(() => {
|
|
113
|
-
|
|
114
|
-
metric = initMetric('INP');
|
|
115
|
-
report = bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges);
|
|
135
|
+
initNewINPMetric('back-forward-cache', metric.navigationId, metric.navigationInteractionId, metric.navigationURL, getBFCacheRestoreTime());
|
|
116
136
|
});
|
|
117
137
|
}
|
|
118
138
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LCPMetric, MetricRatingThresholds, ReportOpts } from './types.js';
|
|
1
|
+
import type { LCPMetric, MetricRatingThresholds, ReportOpts } from './types.js';
|
|
2
2
|
/** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */
|
|
3
3
|
export declare const LCPThresholds: MetricRatingThresholds;
|
|
4
4
|
/**
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { LCPEntryManager } from './lib/LCPEntryManager.js';
|
|
17
|
-
import { onBFCacheRestore } from './lib/bfcache.js';
|
|
17
|
+
import { getBFCacheRestoreTime, onBFCacheRestore } from './lib/bfcache.js';
|
|
18
18
|
import { bindReporter } from './lib/bindReporter.js';
|
|
19
19
|
import { doubleRAF } from './lib/doubleRAF.js';
|
|
20
20
|
import { getActivationStart } from './lib/getActivationStart.js';
|
|
21
|
+
import { checkSoftNavsEnabled, storeSoftNavEntry } from './lib/softNavs.js';
|
|
21
22
|
import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
|
|
22
23
|
import { initMetric } from './lib/initMetric.js';
|
|
23
24
|
import { initUnique } from './lib/initUnique.js';
|
|
24
25
|
import { observe } from './lib/observe.js';
|
|
25
|
-
import { runOnce } from './lib/runOnce.js';
|
|
26
26
|
import { whenActivated } from './lib/whenActivated.js';
|
|
27
27
|
import { whenIdleOrHidden } from './lib/whenIdleOrHidden.js';
|
|
28
28
|
/** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */
|
|
@@ -39,72 +39,151 @@ export const LCPThresholds = [2500, 4000];
|
|
|
39
39
|
* been determined.
|
|
40
40
|
*/
|
|
41
41
|
export const onLCP = (onReport, opts = {}) => {
|
|
42
|
+
// As InteractionContentfulPaint entries used by soft navs can emit after
|
|
43
|
+
// LCP is finalized, we need a flag to know to ignore them.
|
|
44
|
+
let isFinalized = false;
|
|
45
|
+
const softNavsEnabled = checkSoftNavsEnabled(opts);
|
|
42
46
|
whenActivated(() => {
|
|
43
|
-
|
|
47
|
+
let visibilityWatcher = getVisibilityWatcher();
|
|
44
48
|
let metric = initMetric('LCP');
|
|
45
49
|
let report;
|
|
46
50
|
const lcpEntryManager = initUnique(opts, LCPEntryManager);
|
|
51
|
+
const initNewLCPMetric = (navigation, navigationId, navigationInteractionId, navigationURL, navigationStartTime) => {
|
|
52
|
+
metric = initMetric('LCP', -1, navigation, navigationId, navigationInteractionId, navigationURL, navigationStartTime);
|
|
53
|
+
report = bindReporter(onReport, metric, LCPThresholds, opts.reportAllChanges);
|
|
54
|
+
// Reset the finalized flag
|
|
55
|
+
isFinalized = false;
|
|
56
|
+
// If it's a soft nav, then need to reset the visibilityWatcher
|
|
57
|
+
if (navigation === 'soft-navigation') {
|
|
58
|
+
visibilityWatcher = getVisibilityWatcher(true);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const handleSoftNavEntry = (entry) => {
|
|
62
|
+
if (lcpEntryManager._softNavigationEntryMap && entry.navigationId) {
|
|
63
|
+
storeSoftNavEntry(lcpEntryManager._softNavigationEntryMap, entry);
|
|
64
|
+
}
|
|
65
|
+
if (!isFinalized)
|
|
66
|
+
report(true);
|
|
67
|
+
initNewLCPMetric('soft-navigation', entry.navigationId, entry.interactionId, entry.name, entry.startTime);
|
|
68
|
+
// Soft Navs should contain the largest paint until now, so handle that
|
|
69
|
+
// as if it just happened, then listen for more.
|
|
70
|
+
// It can however be null in rare circumstances
|
|
71
|
+
// (see https://github.com/GoogleChrome/web-vitals/issues/725)
|
|
72
|
+
const largestInteractionContentfulPaint = entry.getLargestInteractionContentfulPaint?.();
|
|
73
|
+
if (largestInteractionContentfulPaint) {
|
|
74
|
+
handleEntries([largestInteractionContentfulPaint]);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
47
77
|
const handleEntries = (entries) => {
|
|
48
|
-
// If reportAllChanges is set
|
|
49
|
-
// otherwise only consider the last one.
|
|
50
|
-
if (!opts.reportAllChanges) {
|
|
78
|
+
// If reportAllChanges is set or soft navs is enabled then call this
|
|
79
|
+
// function for each entry, otherwise only consider the last one.
|
|
80
|
+
if (!opts.reportAllChanges && !softNavsEnabled) {
|
|
51
81
|
entries = entries.slice(-1);
|
|
52
82
|
}
|
|
53
83
|
for (const entry of entries) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (entry.
|
|
84
|
+
if (!entry)
|
|
85
|
+
continue;
|
|
86
|
+
if (entry.entryType === 'soft-navigation') {
|
|
87
|
+
handleSoftNavEntry(entry);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
let value = 0;
|
|
91
|
+
let metricEntries = [];
|
|
92
|
+
let renderTime = entry.startTime;
|
|
93
|
+
if (entry.entryType === 'largest-contentful-paint') {
|
|
57
94
|
// The startTime attribute returns the value of the renderTime if it is
|
|
58
95
|
// not 0, and the value of the loadTime otherwise. The activationStart
|
|
59
96
|
// reference is used because LCP should be relative to page activation
|
|
60
97
|
// rather than navigation start if the page was prerendered. But in cases
|
|
61
98
|
// where `activationStart` occurs after the LCP, this time should be
|
|
62
99
|
// clamped at 0.
|
|
63
|
-
|
|
64
|
-
|
|
100
|
+
value = Math.max(entry.startTime - getActivationStart(), 0);
|
|
101
|
+
lcpEntryManager._processEntry(entry);
|
|
102
|
+
metricEntries = [entry];
|
|
103
|
+
}
|
|
104
|
+
else if (entry.entryType === 'interaction-contentful-paint') {
|
|
105
|
+
const ICPEntry = entry;
|
|
106
|
+
// InteractionContentfulPaints should only happen after a
|
|
107
|
+
// PerformanceSoftNavigation so the metric should have been set
|
|
108
|
+
// with a non-zero navigationId mapping to a soft nav.
|
|
109
|
+
if (!metric.navigationId)
|
|
110
|
+
continue;
|
|
111
|
+
// Ignore interactions not for this soft nav
|
|
112
|
+
// (either paints that have bled into this interaction or paints when
|
|
113
|
+
// we should have already finalized)
|
|
114
|
+
if ('interactionId' in ICPEntry &&
|
|
115
|
+
ICPEntry.interactionId != metric.navigationInteractionId) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
renderTime = ICPEntry.largestContentfulPaint?.renderTime || 0;
|
|
119
|
+
// Paints should never be less than 0 but add cap just in case
|
|
120
|
+
value = Math.max(renderTime - entry.startTime, 0);
|
|
121
|
+
if (ICPEntry.largestContentfulPaint) {
|
|
122
|
+
lcpEntryManager._processEntry(ICPEntry.largestContentfulPaint);
|
|
123
|
+
metricEntries = [ICPEntry.largestContentfulPaint];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Only report if the page wasn't hidden prior to LCP.
|
|
127
|
+
if (renderTime < visibilityWatcher.firstHiddenTime) {
|
|
128
|
+
metric.value = value;
|
|
129
|
+
metric.entries = metricEntries;
|
|
65
130
|
report();
|
|
66
131
|
}
|
|
67
132
|
}
|
|
68
133
|
};
|
|
69
|
-
const
|
|
134
|
+
const types = ['largest-contentful-paint'];
|
|
135
|
+
if (softNavsEnabled) {
|
|
136
|
+
types.push('interaction-contentful-paint', 'soft-navigation');
|
|
137
|
+
}
|
|
138
|
+
const po = observe(types, handleEntries);
|
|
70
139
|
if (po) {
|
|
71
140
|
report = bindReporter(onReport, metric, LCPThresholds, opts.reportAllChanges);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
handleEntries(po.takeRecords());
|
|
76
|
-
po.disconnect();
|
|
77
|
-
report(true);
|
|
78
|
-
});
|
|
79
|
-
// Need a separate wrapper to ensure the `runOnce` function above is
|
|
80
|
-
// common for all three functions
|
|
81
|
-
const stopListeningWrapper = (event) => {
|
|
82
|
-
if (event.isTrusted) {
|
|
141
|
+
const finalizeEventTypes = ['keydown', 'click', 'visibilitychange'];
|
|
142
|
+
const finalizeLCP = (event) => {
|
|
143
|
+
if (event.isTrusted && !isFinalized) {
|
|
83
144
|
// Wrap the listener in an idle callback so it's run in a separate
|
|
84
145
|
// task to reduce potential INP impact.
|
|
85
146
|
// https://github.com/GoogleChrome/web-vitals/issues/383
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
147
|
+
const metricIdToFinalize = metric.id;
|
|
148
|
+
whenIdleOrHidden(() => {
|
|
149
|
+
if (!isFinalized) {
|
|
150
|
+
if (!softNavsEnabled) {
|
|
151
|
+
// Do some clean up since these won't be needed anymore.
|
|
152
|
+
po.disconnect();
|
|
153
|
+
for (const type of finalizeEventTypes) {
|
|
154
|
+
removeEventListener(type, finalizeLCP, { capture: true });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// As this is in a whenIdleOrHidden check, whether we're still
|
|
158
|
+
// on the metric you meant to finalize, and ignore if we've moved
|
|
159
|
+
// on in the meantime.
|
|
160
|
+
if (metricIdToFinalize === metric.id) {
|
|
161
|
+
isFinalized = true;
|
|
162
|
+
report(true);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
89
165
|
});
|
|
90
166
|
}
|
|
91
167
|
};
|
|
92
|
-
//
|
|
168
|
+
// Finalize the current LCP after input or visibilitychange.
|
|
169
|
+
// Although the browser will automatically stop emitting entries in these
|
|
170
|
+
// cases, we don't know it's finalized, so we track to allow early report.
|
|
93
171
|
// Note: while scrolling is an input that stops LCP observation, it's
|
|
94
172
|
// unreliable since it can be programmatically generated.
|
|
95
173
|
// See: https://github.com/GoogleChrome/web-vitals/issues/75
|
|
96
|
-
for (const type of
|
|
97
|
-
addEventListener(type,
|
|
174
|
+
for (const type of finalizeEventTypes) {
|
|
175
|
+
addEventListener(type, finalizeLCP, {
|
|
98
176
|
capture: true,
|
|
99
177
|
});
|
|
100
178
|
}
|
|
101
179
|
// Only report after a bfcache restore if the `PerformanceObserver`
|
|
102
180
|
// successfully registered.
|
|
103
181
|
onBFCacheRestore((event) => {
|
|
104
|
-
metric
|
|
182
|
+
initNewLCPMetric('back-forward-cache', metric.navigationId, metric.navigationInteractionId, metric.navigationURL, getBFCacheRestoreTime());
|
|
105
183
|
report = bindReporter(onReport, metric, LCPThresholds, opts.reportAllChanges);
|
|
106
184
|
doubleRAF(() => {
|
|
107
185
|
metric.value = performance.now() - event.timeStamp;
|
|
186
|
+
isFinalized = true;
|
|
108
187
|
report(true);
|
|
109
188
|
});
|
|
110
189
|
});
|