chrome-devtools-frontend 1.0.1695017 → 1.0.1696961
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/eslint.config.mjs +4 -1
- package/front_end/core/common/Base64.ts +14 -4
- package/front_end/core/common/Gzip.ts +1 -1
- package/front_end/core/common/Object.ts +0 -1
- package/front_end/core/platform/Size.ts +43 -0
- package/front_end/core/platform/api/HostRuntime.ts +14 -0
- package/front_end/core/platform/browser/HostRuntime.ts +66 -0
- package/front_end/core/platform/node/HostRuntime.ts +12 -3
- package/front_end/core/platform/platform.ts +1 -0
- package/front_end/core/sdk/AccessibilityModel.ts +2 -2
- package/front_end/core/sdk/CSSMatchedStyles.ts +2 -0
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +29 -0
- package/front_end/core/sdk/CSSStyleSheetHeader.ts +2 -2
- package/front_end/core/sdk/ConsoleModel.ts +3 -3
- package/front_end/core/sdk/DOMModel.ts +10 -6
- package/front_end/core/sdk/DebuggerModel.ts +6 -0
- package/front_end/core/sdk/NetworkRequest.ts +19 -19
- package/front_end/core/sdk/RuntimeModel.ts +5 -0
- package/front_end/core/sdk/Script.ts +2 -2
- package/front_end/core/sdk/ServerTiming.ts +6 -6
- package/front_end/core/sdk/SourceMap.ts +112 -14
- package/front_end/core/sdk/SourceMapRangeMappings.ts +43 -0
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +15 -10
- package/front_end/core/sdk/SourceMapScopesInfo.ts +92 -10
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +1 -1
- package/front_end/entrypoints/inspector_main/RenderingOptions.ts +6 -6
- package/front_end/entrypoints/main/MainImpl.ts +1 -1
- package/front_end/generated/InspectorBackendCommands.ts +6 -3
- package/front_end/generated/protocol-mapping.d.ts +7 -0
- package/front_end/generated/protocol-proxy-api.d.ts +5 -0
- package/front_end/generated/protocol.ts +36 -3
- package/front_end/models/ai_assistance/AiAgent2.ts +27 -27
- package/front_end/models/ai_assistance/agents/AiAgent.ts +4 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/contexts/AccessibilityContext.ts +1 -0
- package/front_end/models/ai_assistance/contexts/DOMNodeContext.ts +5 -4
- package/front_end/models/ai_assistance/contexts/FileContext.ts +1 -0
- package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +1 -0
- package/front_end/models/ai_assistance/contexts/RequestContext.ts +1 -0
- package/front_end/models/ai_assistance/contexts/StorageContext.ts +1 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +5 -5
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +6 -6
- package/front_end/models/ai_assistance/tools/GetElementAccessibilityDetails.ts +5 -8
- package/front_end/models/ai_assistance/tools/GetNetworkRequestDetails.ts +4 -8
- package/front_end/models/ai_assistance/tools/GetSourceContent.ts +7 -5
- package/front_end/models/ai_assistance/tools/GetStyles.ts +10 -6
- package/front_end/models/ai_assistance/tools/ListSources.ts +26 -7
- package/front_end/models/ai_assistance/tools/ResolveDevtoolsNodePath.ts +5 -10
- package/front_end/models/ai_assistance/tools/Tool.ts +8 -1
- package/front_end/models/bindings/FileUtils.ts +18 -40
- package/front_end/models/bindings/TempFile.ts +5 -12
- package/front_end/models/comment_manager/CommentManager.ts +30 -6
- package/front_end/models/crux-manager/CrUXManager.ts +8 -5
- package/front_end/models/emulation/DeviceModeModel.ts +55 -105
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +1 -1
- package/front_end/models/issues_manager/CookieIssue.ts +1 -1
- package/front_end/models/issues_manager/DeprecationIssue.ts +2 -2
- package/front_end/models/javascript_metadata/NativeFunctions.ts +1 -5
- package/front_end/models/live-metrics/LiveMetrics.ts +1 -1
- package/front_end/models/persistence/IsolatedFileSystem.ts +16 -23
- package/front_end/models/trace/insights/DuplicatedJavaScript.ts +1 -1
- package/front_end/models/trace/insights/INPBreakdown.ts +1 -1
- package/front_end/models/trace/insights/ImageDelivery.ts +3 -3
- package/front_end/models/trace/insights/LCPDiscovery.ts +2 -2
- package/front_end/models/trace/insights/NetworkDependencyTree.ts +3 -3
- package/front_end/models/trace/insights/Viewport.ts +1 -1
- package/front_end/models/trace/types/Overlays.ts +2 -2
- package/front_end/panels/accessibility/AccessibilityNodeView.ts +2 -2
- package/front_end/panels/accessibility/AccessibilitySubPane.ts +0 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +74 -18
- package/front_end/panels/ai_assistance/components/AIv2MarkdownRenderer.ts +14 -3
- package/front_end/panels/ai_assistance/components/ChatInput.ts +1 -1
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +1 -1
- package/front_end/panels/animation/AnimationUI.ts +1 -1
- package/front_end/panels/application/AppManifestView.ts +9 -11
- package/front_end/panels/application/ApplicationPanelSidebar.ts +9 -9
- package/front_end/panels/application/BackgroundServiceView.ts +1 -1
- package/front_end/panels/application/CookieItemsView.ts +1 -1
- package/front_end/panels/application/DOMStorageItemsView.ts +1 -1
- package/front_end/panels/application/DeviceBoundSessionsView.ts +2 -2
- package/front_end/panels/application/FrameDetailsView.ts +5 -5
- package/front_end/panels/application/IndexedDBViews.ts +2 -2
- package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -2
- package/front_end/panels/application/ReportingApiView.ts +1 -1
- package/front_end/panels/application/ServiceWorkerCacheTreeElement.ts +1 -1
- package/front_end/panels/application/ServiceWorkersView.ts +1 -1
- package/front_end/panels/application/StorageBucketsTreeElement.ts +1 -1
- package/front_end/panels/application/WebMCPView.ts +1 -1
- package/front_end/panels/application/components/AdsView.ts +136 -7
- package/front_end/panels/application/components/BackForwardCacheStrings.ts +116 -117
- package/front_end/panels/application/components/BackForwardCacheView.ts +7 -7
- package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +2 -2
- package/front_end/panels/application/components/PermissionsPolicySection.ts +2 -2
- package/front_end/panels/application/components/ProtocolHandlersView.ts +1 -1
- package/front_end/panels/application/components/ReportsGrid.ts +1 -1
- package/front_end/panels/application/components/StorageMetadataView.ts +1 -1
- package/front_end/panels/application/components/TrustTokensView.ts +3 -3
- package/front_end/panels/application/components/adScriptsTable.css +22 -0
- package/front_end/panels/application/preloading/PreloadingView.ts +20 -22
- package/front_end/panels/application/preloading/components/MismatchedPreloadingGrid.ts +9 -9
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +31 -33
- package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +23 -23
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +4 -4
- package/front_end/panels/application/preloading/components/PreloadingString.ts +161 -161
- package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -6
- package/front_end/panels/application/preloading/components/RuleSetGrid.ts +8 -8
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +32 -32
- package/front_end/panels/application/resourcesPanel.css +17 -17
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +1 -1
- package/front_end/panels/changes/ChangesView.ts +1 -1
- package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +1 -1
- package/front_end/panels/common/CPUThrottlingOption.ts +0 -1
- package/front_end/panels/common/GdpSignUpDialog.ts +3 -4
- package/front_end/panels/common/GeminiRebrandPromoDialog.ts +1 -1
- package/front_end/panels/console/ConsoleInsightTeaser.ts +1 -1
- package/front_end/panels/console/ConsolePinPane.ts +0 -1
- package/front_end/panels/console/ConsoleView.ts +2 -3
- package/front_end/panels/console/ConsoleViewMessage.ts +2 -3
- package/front_end/panels/coverage/CoverageListView.ts +6 -6
- package/front_end/panels/coverage/CoverageView.ts +7 -7
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +1 -1
- package/front_end/panels/elements/CSSRuleValidator.ts +10 -10
- package/front_end/panels/elements/ElementsPanel.ts +3 -3
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
- package/front_end/panels/elements/ElementsTreeOutline.ts +1 -1
- package/front_end/panels/elements/LayoutPane.ts +1 -1
- package/front_end/panels/elements/StylePropertyTreeElement.ts +85 -2
- package/front_end/panels/elements/StylesSidebarPane.ts +3 -3
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +2 -1
- package/front_end/panels/emulation/DeviceModeView.ts +1 -1
- package/front_end/panels/event_listeners/EventListenersView.ts +57 -89
- package/front_end/panels/explain/components/ConsoleInsight.ts +4 -4
- package/front_end/panels/issues/AffectedPartitioningBlobURLView.ts +3 -3
- package/front_end/panels/issues/IssuesPane.ts +1 -1
- package/front_end/panels/layer_viewer/Layers3DView.ts +4 -4
- package/front_end/panels/layers/LayerTreeModel.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseController.ts +4 -4
- package/front_end/panels/lighthouse/LighthouseStatusView.ts +10 -10
- package/front_end/panels/lighthouse/LighthouseTimespanView.ts +2 -2
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +1 -1
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +1 -1
- package/front_end/panels/media/MainView.ts +2 -2
- package/front_end/panels/mobile_throttling/CalibrationController.ts +4 -1
- package/front_end/panels/mobile_throttling/NetworkPanelIndicator.ts +1 -1
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +10 -0
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +3 -3
- package/front_end/panels/network/NetworkConfigView.ts +26 -16
- package/front_end/panels/network/NetworkItemView.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +4 -5
- package/front_end/panels/network/NetworkPanel.ts +1 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +3 -3
- package/front_end/panels/network/RequestCookiesView.ts +2 -2
- package/front_end/panels/network/RequestPayloadView.ts +0 -2
- package/front_end/panels/network/RequestTimingView.ts +1 -1
- package/front_end/panels/network/ResourceChunkView.ts +1 -1
- package/front_end/panels/network/components/HeaderSectionRow.ts +2 -2
- package/front_end/panels/network/components/RequestHeaderSection.ts +1 -1
- package/front_end/panels/network/components/RequestTrustTokensView.ts +7 -7
- package/front_end/panels/network/components/ResponseHeaderSection.ts +3 -4
- package/front_end/panels/network/network-meta.ts +1 -1
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +1 -1
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +10 -10
- package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
- package/front_end/panels/profiler/IsolateSelector.ts +4 -4
- package/front_end/panels/profiler/ModuleUIStrings.ts +1 -1
- package/front_end/panels/profiler/ProfilesPanel.ts +2 -3
- package/front_end/panels/recorder/RecorderPanel.ts +1 -1
- package/front_end/panels/search/SearchView.ts +6 -6
- package/front_end/panels/security/SecurityModel.ts +4 -4
- package/front_end/panels/security/SecurityPanel.ts +83 -54
- package/front_end/panels/security/SecurityPanelSidebar.ts +41 -5
- package/front_end/panels/security/sidebar.css +9 -10
- package/front_end/panels/sensors/SensorsView.ts +1 -1
- package/front_end/panels/settings/AISettingsTab.ts +9 -9
- package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +1 -1
- package/front_end/panels/settings/KeybindsSettingsTab.ts +2 -2
- package/front_end/panels/settings/SettingsScreen.ts +156 -109
- package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
- package/front_end/panels/settings/components/SyncSection.ts +3 -3
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +13 -13
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -2
- package/front_end/panels/snippets/SnippetsQuickOpen.ts +1 -1
- package/front_end/panels/sources/CSSPlugin.ts +3 -3
- package/front_end/panels/sources/DebuggerPlugin.ts +4 -4
- package/front_end/panels/sources/NavigatorView.ts +3 -3
- package/front_end/panels/sources/OutlineQuickOpen.ts +1 -1
- package/front_end/panels/sources/PersistenceActions.ts +2 -2
- package/front_end/panels/sources/SourcesNavigator.ts +5 -5
- package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +0 -1
- package/front_end/panels/sources/components/HeadersView.ts +1 -1
- package/front_end/panels/timeline/LayoutShiftsTrackAppender.ts +1 -1
- package/front_end/panels/timeline/TimelinePaintProfilerView.ts +1 -1
- package/front_end/panels/timeline/TimelineUIUtils.ts +0 -1
- package/front_end/panels/timeline/components/ExportTraceOptions.ts +2 -2
- package/front_end/panels/timeline/components/FieldSettingsDialog.ts +4 -4
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
- package/front_end/panels/timeline/components/LiveMetricsView.ts +7 -7
- package/front_end/panels/timeline/components/MetricCard.ts +3 -3
- package/front_end/panels/timeline/components/MetricCompareStrings.ts +12 -14
- package/front_end/panels/timeline/components/OriginMap.ts +3 -3
- package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +4 -4
- package/front_end/panels/timeline/overlays/OverlaysImpl.ts +6 -0
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +1 -1
- package/front_end/panels/timeline/overlays/components/TimespanBreakdownOverlay.ts +3 -1
- package/front_end/panels/timeline/timelineMiniMap.css +9 -9
- package/front_end/panels/timeline/timelineStatusDialog.css +9 -9
- package/front_end/panels/web_audio/WebAudioView.ts +1 -1
- package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +114 -3
- package/front_end/ui/comments/CommentOverlayManager.ts +95 -16
- package/front_end/ui/components/dialogs/TypeToAllowDialog.ts +1 -1
- package/front_end/ui/components/markdown_view/codeBlock.css +3 -8
- package/front_end/ui/components/markdown_view/markdownView.css +2 -7
- package/front_end/ui/components/panel_feedback/PanelFeedback.ts +2 -2
- package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
- package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +4 -4
- package/front_end/ui/components/text_editor/AiCodeGenerationTeaser.ts +3 -3
- package/front_end/{models → ui}/geometry/GeometryImpl.ts +4 -40
- package/front_end/ui/legacy/GlassPane.ts +1 -1
- package/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts +2 -2
- package/front_end/ui/legacy/SoftDropDown.ts +1 -1
- package/front_end/ui/legacy/SplitWidget.ts +1 -1
- package/front_end/ui/legacy/SuggestBox.ts +1 -1
- package/front_end/ui/legacy/TabbedPane.ts +1 -1
- package/front_end/ui/legacy/TargetCrashedScreen.ts +2 -2
- package/front_end/ui/legacy/Treeoutline.ts +5 -1
- package/front_end/ui/legacy/UIUtils.ts +1 -1
- package/front_end/ui/legacy/Widget.ts +1 -1
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -1
- package/front_end/ui/legacy/components/inline_editor/AnimationTimingModel.ts +1 -1
- package/front_end/ui/legacy/components/inline_editor/AnimationTimingUI.ts +1 -1
- package/front_end/ui/legacy/components/inline_editor/BezierUI.ts +1 -1
- package/front_end/ui/legacy/components/inline_editor/CSSAngleUtils.ts +1 -1
- package/front_end/ui/legacy/components/inline_editor/CSSShadowEditor.ts +1 -1
- package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +204 -17
- package/front_end/ui/legacy/components/inline_editor/positionAreaEditor.css +6 -0
- package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +7 -9
- package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +12 -0
- package/package.json +7 -4
- /package/front_end/{models → ui}/geometry/geometry.ts +0 -0
package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt
CHANGED
|
@@ -942,23 +942,23 @@ The following images could be optimized:
|
|
|
942
942
|
### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg (eventKey: s-1212, ts: 59728701403)
|
|
943
943
|
- Potential savings: 1.1 MB
|
|
944
944
|
- Optimizations:
|
|
945
|
-
Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size
|
|
945
|
+
Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size (Est 1.1 MB)
|
|
946
946
|
|
|
947
947
|
### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/dobetterweb/lighthouse-rotating.gif (eventKey: s-1216, ts: 59728702014)
|
|
948
948
|
- Potential savings: 682 kB
|
|
949
949
|
- Optimizations:
|
|
950
|
-
Using video formats instead of GIFs can improve the download size of animated content
|
|
950
|
+
Using video formats instead of GIFs can improve the download size of animated content (Est 682 kB)
|
|
951
951
|
|
|
952
952
|
### https://onlinepngtools.com/images/examples-onlinepngtools/elephant-hd-quality.png (eventKey: s-1228, ts: 59728702737)
|
|
953
953
|
- Potential savings: 176 kB
|
|
954
954
|
- Optimizations:
|
|
955
|
-
Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size
|
|
955
|
+
Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size (Est 134.1 kB)
|
|
956
956
|
This image file is larger than it needs to be (640x436) for its displayed dimensions (200x136). Use responsive images to reduce the image download size. (Est 162.9 kB)
|
|
957
957
|
|
|
958
958
|
### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg?fm=webp (eventKey: s-1224, ts: 59728702313)
|
|
959
959
|
- Potential savings: 49.8 kB
|
|
960
960
|
- Optimizations:
|
|
961
|
-
Increasing the image compression factor could improve this image’s download size
|
|
961
|
+
Increasing the image compression factor could improve this image’s download size (Est 49.8 kB)
|
|
962
962
|
|
|
963
963
|
### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/byte-efficiency/lighthouse-2048x1356.webp (eventKey: s-1226, ts: 59728702539)
|
|
964
964
|
- Potential savings: 41.4 kB
|
|
@@ -1258,7 +1258,7 @@ The webpage is not optimized for mobile viewing.
|
|
|
1258
1258
|
|
|
1259
1259
|
The viewport meta tag is missing.
|
|
1260
1260
|
|
|
1261
|
-
Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
|
|
1261
|
+
Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
|
|
1262
1262
|
|
|
1263
1263
|
## Estimated savings: none
|
|
1264
1264
|
|
package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt
CHANGED
|
@@ -351,7 +351,7 @@ Available insights:
|
|
|
351
351
|
example question: Help me optimize my CLS score
|
|
352
352
|
example question: How can I prevent layout shifts on this page?
|
|
353
353
|
- insight name: NetworkDependencyTree
|
|
354
|
-
description: [Avoid chaining critical requests](https://developer.chrome.com/docs/performance/insights/network-dependency-tree) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load
|
|
354
|
+
description: [Avoid chaining critical requests](https://developer.chrome.com/docs/performance/insights/network-dependency-tree) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load
|
|
355
355
|
relevant trace bounds: {min: 157423489126µs, max: 157426527569µs}
|
|
356
356
|
example question: How do I optimize my network dependency tree?
|
|
357
357
|
- insight name: ImageDelivery
|
|
@@ -498,7 +498,7 @@ Available insights:
|
|
|
498
498
|
example question: Which LCP subpart was most problematic?
|
|
499
499
|
example question: What can I do to reduce the LCP time for this page load?
|
|
500
500
|
- insight name: LCPDiscovery
|
|
501
|
-
description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading
|
|
501
|
+
description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading
|
|
502
502
|
relevant trace bounds: {min: 59728656735µs, max: 59729209036µs}
|
|
503
503
|
example question: Suggest fixes to reduce my LCP
|
|
504
504
|
example question: What can I do to reduce my LCP discovery time?
|
|
@@ -516,7 +516,7 @@ Available insights:
|
|
|
516
516
|
example question: How do I decrease the initial loading time of my page?
|
|
517
517
|
example question: Did anything slow down the request for this document?
|
|
518
518
|
- insight name: Viewport
|
|
519
|
-
description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
|
|
519
|
+
description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
|
|
520
520
|
relevant trace bounds: {min: 59728649746µs, max: 59734400108µs}
|
|
521
521
|
estimated metric savings: INP 0 ms
|
|
522
522
|
example question: How do I make sure my page is optimized for mobile viewing?
|
|
@@ -582,7 +582,7 @@ Available insights:
|
|
|
582
582
|
example question: Which LCP subpart was most problematic?
|
|
583
583
|
example question: What can I do to reduce the LCP time for this page load?
|
|
584
584
|
- insight name: LCPDiscovery
|
|
585
|
-
description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading
|
|
585
|
+
description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading
|
|
586
586
|
relevant trace bounds: {min: 59728656735µs, max: 59729209036µs}
|
|
587
587
|
example question: Suggest fixes to reduce my LCP
|
|
588
588
|
example question: What can I do to reduce my LCP discovery time?
|
|
@@ -600,7 +600,7 @@ Available insights:
|
|
|
600
600
|
example question: How do I decrease the initial loading time of my page?
|
|
601
601
|
example question: Did anything slow down the request for this document?
|
|
602
602
|
- insight name: Viewport
|
|
603
|
-
description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
|
|
603
|
+
description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
|
|
604
604
|
relevant trace bounds: {min: 59728649746µs, max: 59734400108µs}
|
|
605
605
|
estimated metric savings: INP 0 ms
|
|
606
606
|
example question: How do I make sure my page is optimized for mobile viewing?
|
|
@@ -635,7 +635,7 @@ Metrics (lab / observed):
|
|
|
635
635
|
Metrics (field / real users): n/a – no data for this page in CrUX
|
|
636
636
|
Available insights:
|
|
637
637
|
- insight name: INPBreakdown
|
|
638
|
-
description: Start investigating [how to improve INP](https://developer.chrome.com/docs/performance/insights/inp-breakdown) by looking at the longest subpart
|
|
638
|
+
description: Start investigating [how to improve INP](https://developer.chrome.com/docs/performance/insights/inp-breakdown) by looking at the longest subpart
|
|
639
639
|
relevant trace bounds: {min: 337944870984µs, max: 337945010222µs}
|
|
640
640
|
example question: Suggest fixes for my longest interaction
|
|
641
641
|
example question: Why is a large INP score problematic?
|
|
@@ -6,7 +6,6 @@ import * as Host from '../../../core/host/host.js';
|
|
|
6
6
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
7
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
8
8
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
9
|
-
import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
|
|
10
9
|
|
|
11
10
|
import {
|
|
12
11
|
type BaseToolCapability,
|
|
@@ -82,9 +81,6 @@ export class GetElementAccessibilityDetailsTool implements
|
|
|
82
81
|
context: BaseToolCapability&TargetCapability&OriginLockCapability,
|
|
83
82
|
): Promise<DataHandlerResult<string>> {
|
|
84
83
|
const establishedOrigin = context.getEstablishedOrigin();
|
|
85
|
-
if (!establishedOrigin || establishedOrigin.isOpaque()) {
|
|
86
|
-
return {error: 'Error: Origin lock is not established.'};
|
|
87
|
-
}
|
|
88
84
|
|
|
89
85
|
const target = context.getTarget();
|
|
90
86
|
if (!target) {
|
|
@@ -100,13 +96,14 @@ export class GetElementAccessibilityDetailsTool implements
|
|
|
100
96
|
return {error: 'Error: Could not resolve element by ID.'};
|
|
101
97
|
}
|
|
102
98
|
|
|
103
|
-
const nodeContext = new DOMNodeContext(resolved);
|
|
104
99
|
// Security check: Ensure the element matches the active conversation's origin lock.
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
// Because getTarget() returns the primary page target to support resolving elements
|
|
101
|
+
// across frames, origin validation must be enforced directly on the resolved node.
|
|
102
|
+
if (!isOriginAllowedByLock(establishedOrigin, resolved.securityOrigin())) {
|
|
103
|
+
return {error: 'Error: Node does not belong to the current origin.'};
|
|
107
104
|
}
|
|
108
105
|
|
|
109
|
-
const axModel = target.model(SDK.AccessibilityModel.AccessibilityModel);
|
|
106
|
+
const axModel = resolved.domModel().target().model(SDK.AccessibilityModel.AccessibilityModel);
|
|
110
107
|
if (!axModel) {
|
|
111
108
|
return {error: 'Error: Accessibility model not found.'};
|
|
112
109
|
}
|
|
@@ -79,13 +79,6 @@ export class GetNetworkRequestDetailsTool implements
|
|
|
79
79
|
// We only allow inspecting requests matching the conversation's established origin.
|
|
80
80
|
const establishedOrigin = context.getEstablishedOrigin();
|
|
81
81
|
|
|
82
|
-
// Opaque origins are never allowed to be used as context.
|
|
83
|
-
if (!establishedOrigin || establishedOrigin.isOpaque()) {
|
|
84
|
-
return {
|
|
85
|
-
error: 'Opaque origin not allowed',
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
82
|
// eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
|
|
90
83
|
const networkLog = this.#networkLog ?? Logs.NetworkLog.NetworkLog.instance();
|
|
91
84
|
const request = networkLog.requests().find(req => {
|
|
@@ -97,7 +90,10 @@ export class GetNetworkRequestDetailsTool implements
|
|
|
97
90
|
return isOriginAllowedByLock(establishedOrigin, req.initiatorSecurityOrigin());
|
|
98
91
|
});
|
|
99
92
|
|
|
100
|
-
|
|
93
|
+
// If establishedOrigin is undefined or opaque, isOriginAllowedByLock() fails closed,
|
|
94
|
+
// so find() will never return a request. We check establishedOrigin here as a defensive
|
|
95
|
+
// guard and to narrow the type for NetworkRequestFormatter below.
|
|
96
|
+
if (!establishedOrigin || !request) {
|
|
101
97
|
return {
|
|
102
98
|
error: 'No request found',
|
|
103
99
|
};
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
6
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
7
|
import * as TextUtils from '../../../core/text_utils/text_utils.js';
|
|
8
|
-
import {FileContext} from '../contexts/FileContext.js';
|
|
9
8
|
import {FileFormatter} from '../data_formatters/FileFormatter.js';
|
|
10
9
|
|
|
11
10
|
import {ListSourcesTool} from './ListSources.js';
|
|
@@ -13,7 +12,6 @@ import {
|
|
|
13
12
|
type BaseToolCapability,
|
|
14
13
|
type DataHandlerResult,
|
|
15
14
|
type DataTool,
|
|
16
|
-
isOriginAllowedByLock,
|
|
17
15
|
type OriginLockCapability,
|
|
18
16
|
type ToolArgs,
|
|
19
17
|
ToolName,
|
|
@@ -67,9 +65,13 @@ export class GetSourceContentTool implements
|
|
|
67
65
|
context: BaseToolCapability&OriginLockCapability,
|
|
68
66
|
): Promise<DataHandlerResult<{content: string}>> {
|
|
69
67
|
const establishedOrigin = context.getEstablishedOrigin();
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
if (!establishedOrigin) {
|
|
69
|
+
return {
|
|
70
|
+
error: 'Unable to find file.',
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const file = ListSourcesTool.getSourceById(args.id, establishedOrigin);
|
|
73
75
|
|
|
74
76
|
if (!file) {
|
|
75
77
|
return {
|
|
@@ -6,7 +6,6 @@ import * as Host from '../../../core/host/host.js';
|
|
|
6
6
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
7
7
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
8
8
|
import type {ComputedStyleAiWidget, FunctionHandlerOptions} from '../agents/AiAgent.js';
|
|
9
|
-
import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
|
|
10
9
|
|
|
11
10
|
import {
|
|
12
11
|
type BaseToolCapability,
|
|
@@ -78,6 +77,12 @@ export class GetStylesTool implements
|
|
|
78
77
|
};
|
|
79
78
|
}
|
|
80
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Handles the request to retrieve computed and authored CSS styles for specified elements.
|
|
82
|
+
*
|
|
83
|
+
* Resolves element backend node IDs using the primary page target and verifies that each
|
|
84
|
+
* element's security origin matches the established origin lock before querying CSS models.
|
|
85
|
+
*/
|
|
81
86
|
async handler(
|
|
82
87
|
params: GetStylesArgs,
|
|
83
88
|
context: BaseToolCapability&TargetCapability&OriginLockCapability,
|
|
@@ -93,9 +98,6 @@ export class GetStylesTool implements
|
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
const establishedOrigin = context.getEstablishedOrigin();
|
|
96
|
-
if (!establishedOrigin || establishedOrigin.isOpaque()) {
|
|
97
|
-
return {error: 'Error: Origin lock is not established.'};
|
|
98
|
-
}
|
|
99
101
|
|
|
100
102
|
for (const uid of params.elements) {
|
|
101
103
|
result[uid] = {computed: {}, authored: {}};
|
|
@@ -104,8 +106,10 @@ export class GetStylesTool implements
|
|
|
104
106
|
if (!resolved) {
|
|
105
107
|
return {error: 'Error: Could not find the element with uid=' + uid};
|
|
106
108
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
// Security check: Ensure the resolved element belongs to the locked origin.
|
|
110
|
+
// Because getTarget() returns the primary page target to support resolving elements
|
|
111
|
+
// across frames, origin validation must be enforced directly on the resolved node.
|
|
112
|
+
if (!isOriginAllowedByLock(establishedOrigin, resolved.securityOrigin())) {
|
|
109
113
|
return {error: 'Error: Node does not belong to the current origin.'};
|
|
110
114
|
}
|
|
111
115
|
const styles = await resolved.domModel().cssModel().getComputedStyle(resolved.id);
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
6
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
|
+
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
7
8
|
import * as Workspace from '../../workspace/workspace.js';
|
|
8
9
|
import {FileContext} from '../contexts/FileContext.js';
|
|
9
10
|
|
|
@@ -46,9 +47,15 @@ export class ListSourcesTool implements
|
|
|
46
47
|
ListSourcesTool.uiSourceCodeId = new WeakMap();
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
static getUISourceCodes(
|
|
51
|
+
establishedOrigin: SDK.SecurityOrigin.SecurityOrigin,
|
|
52
|
+
// eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
|
|
53
|
+
workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance(),
|
|
54
|
+
): Workspace.UISourceCode.UISourceCode[] {
|
|
55
|
+
if (establishedOrigin.isOpaque()) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
|
|
52
59
|
const projects =
|
|
53
60
|
workspace.projects().filter(project => project.type() === Workspace.Workspace.projectTypes.Network);
|
|
54
61
|
const uiSourceCodes = new Map<string, Workspace.UISourceCode.UISourceCode>();
|
|
@@ -68,7 +75,21 @@ export class ListSourcesTool implements
|
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
77
|
|
|
71
|
-
return [...uiSourceCodes.values()]
|
|
78
|
+
return [...uiSourceCodes.values()].filter(
|
|
79
|
+
file => isOriginAllowedByLock(establishedOrigin, FileContext.originForUISourceCode(file)));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static getSourceById(
|
|
83
|
+
id: number,
|
|
84
|
+
establishedOrigin: SDK.SecurityOrigin.SecurityOrigin,
|
|
85
|
+
// eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
|
|
86
|
+
workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance(),
|
|
87
|
+
): Workspace.UISourceCode.UISourceCode|undefined {
|
|
88
|
+
if (establishedOrigin.isOpaque()) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
return ListSourcesTool.getUISourceCodes(establishedOrigin, workspace)
|
|
92
|
+
.find(file => ListSourcesTool.uiSourceCodeId.get(file) === id);
|
|
72
93
|
}
|
|
73
94
|
|
|
74
95
|
readonly parameters: Host.AidaClient.FunctionObjectParam<never> = {
|
|
@@ -100,9 +121,7 @@ export class ListSourcesTool implements
|
|
|
100
121
|
};
|
|
101
122
|
}
|
|
102
123
|
|
|
103
|
-
const files = ListSourcesTool.getUISourceCodes()
|
|
104
|
-
return isOriginAllowedByLock(establishedOrigin, FileContext.originForUISourceCode(file));
|
|
105
|
-
});
|
|
124
|
+
const files = ListSourcesTool.getUISourceCodes(establishedOrigin);
|
|
106
125
|
|
|
107
126
|
return {
|
|
108
127
|
result: {
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
6
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
7
|
-
import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
|
|
8
7
|
|
|
9
8
|
import {
|
|
10
9
|
type BaseToolCapability,
|
|
@@ -85,11 +84,6 @@ export class ResolveDevtoolsNodePathTool implements DataTool<ResolveDevtoolsNode
|
|
|
85
84
|
params: ResolveDevtoolsNodePathArgs,
|
|
86
85
|
context: BaseToolCapability&TargetCapability&OriginLockCapability,
|
|
87
86
|
): Promise<DataHandlerResult<{backendNodeId: number}>> {
|
|
88
|
-
const establishedOrigin = context.getEstablishedOrigin();
|
|
89
|
-
if (!establishedOrigin || establishedOrigin.isOpaque()) {
|
|
90
|
-
return {error: 'Error: Origin lock is not established.'};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
87
|
const target = context.getTarget();
|
|
94
88
|
const domModel = target?.model(SDK.DOMModel.DOMModel);
|
|
95
89
|
if (!domModel) {
|
|
@@ -102,7 +96,8 @@ export class ResolveDevtoolsNodePathTool implements DataTool<ResolveDevtoolsNode
|
|
|
102
96
|
// and ensures the node is loaded into the frontend DOM model, returning its ID.
|
|
103
97
|
nodeId = await domModel.pushNodeByPathToFrontend(params.path);
|
|
104
98
|
} catch {
|
|
105
|
-
// pushNodeByPathToFrontend
|
|
99
|
+
// pushNodeByPathToFrontend throws when the path is invalid or the node cannot be found.
|
|
100
|
+
// Swallow the error here so execution falls through to the structured error response below.
|
|
106
101
|
}
|
|
107
102
|
if (!nodeId) {
|
|
108
103
|
return {error: 'Error: Could not find node by path.'};
|
|
@@ -113,11 +108,11 @@ export class ResolveDevtoolsNodePathTool implements DataTool<ResolveDevtoolsNode
|
|
|
113
108
|
return {error: 'Error: Could not retrieve resolved node.'};
|
|
114
109
|
}
|
|
115
110
|
|
|
116
|
-
const
|
|
111
|
+
const establishedOrigin = context.getEstablishedOrigin();
|
|
117
112
|
// Security check: Ensure the resolved node belongs to the same origin
|
|
118
113
|
// that this AI assistance session is locked to, preventing cross-origin access.
|
|
119
|
-
if (!isOriginAllowedByLock(establishedOrigin,
|
|
120
|
-
return {error: 'Error: Node does not belong to the
|
|
114
|
+
if (!isOriginAllowedByLock(establishedOrigin, node.securityOrigin())) {
|
|
115
|
+
return {error: 'Error: Node does not belong to the current origin.'};
|
|
121
116
|
}
|
|
122
117
|
|
|
123
118
|
return {
|
|
@@ -106,7 +106,14 @@ export interface StyleMutationCapability {
|
|
|
106
106
|
*/
|
|
107
107
|
export interface TargetCapability {
|
|
108
108
|
/**
|
|
109
|
-
* Returns the
|
|
109
|
+
* Returns the primary SDK Target for the inspected page.
|
|
110
|
+
*
|
|
111
|
+
* WARNING: This method does not perform a security origin check. When a conversation
|
|
112
|
+
* is locked to an iframe or subframe origin, this still returns the primary page target
|
|
113
|
+
* so tools can resolve DOM nodes and frame hierarchies across frames.
|
|
114
|
+
*
|
|
115
|
+
* Tools that consume this target must independently validate the security origin of
|
|
116
|
+
* any resolved entities (e.g. via `node.securityOrigin()`) against `getEstablishedOrigin()`.
|
|
110
117
|
*/
|
|
111
118
|
getTarget(): SDK.Target.Target|null;
|
|
112
119
|
}
|
|
@@ -16,7 +16,7 @@ export interface ChunkedReader {
|
|
|
16
16
|
|
|
17
17
|
cancel(): void;
|
|
18
18
|
|
|
19
|
-
error():
|
|
19
|
+
error(): DOMException|Error|null;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export class ChunkedFileReader implements ChunkedReader {
|
|
@@ -26,12 +26,11 @@ export class ChunkedFileReader implements ChunkedReader {
|
|
|
26
26
|
#streamReader: ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>|null;
|
|
27
27
|
readonly #chunkSize: number;
|
|
28
28
|
readonly #chunkTransferredCallback: ((arg0: ChunkedReader) => void)|undefined;
|
|
29
|
-
readonly #decoder
|
|
29
|
+
readonly #decoder = new TextDecoder();
|
|
30
30
|
#isCanceled: boolean;
|
|
31
31
|
#error: DOMException|null;
|
|
32
32
|
#transferFinished!: (arg0: boolean) => void;
|
|
33
33
|
#output?: Common.StringOutputStream.OutputStream;
|
|
34
|
-
#reader?: FileReader|null;
|
|
35
34
|
|
|
36
35
|
constructor(file: File, chunkSize?: number, chunkTransferredCallback?: ((arg0: ChunkedReader) => void)) {
|
|
37
36
|
this.#file = file;
|
|
@@ -39,7 +38,6 @@ export class ChunkedFileReader implements ChunkedReader {
|
|
|
39
38
|
this.#loadedSize = 0;
|
|
40
39
|
this.#chunkSize = (chunkSize) ? chunkSize : Number.MAX_VALUE;
|
|
41
40
|
this.#chunkTransferredCallback = chunkTransferredCallback;
|
|
42
|
-
this.#decoder = new TextDecoder();
|
|
43
41
|
this.#isCanceled = false;
|
|
44
42
|
this.#error = null;
|
|
45
43
|
this.#streamReader = null;
|
|
@@ -54,10 +52,6 @@ export class ChunkedFileReader implements ChunkedReader {
|
|
|
54
52
|
const fileStream = this.#file.stream();
|
|
55
53
|
const stream = Common.Gzip.decompressStream(fileStream);
|
|
56
54
|
this.#streamReader = stream.getReader();
|
|
57
|
-
} else {
|
|
58
|
-
this.#reader = new FileReader();
|
|
59
|
-
this.#reader.onload = this.onChunkLoaded.bind(this);
|
|
60
|
-
this.#reader.onerror = this.onError.bind(this);
|
|
61
55
|
}
|
|
62
56
|
|
|
63
57
|
this.#output = output;
|
|
@@ -91,26 +85,6 @@ export class ChunkedFileReader implements ChunkedReader {
|
|
|
91
85
|
return this.#error;
|
|
92
86
|
}
|
|
93
87
|
|
|
94
|
-
private onChunkLoaded(event: Event): void {
|
|
95
|
-
if (this.#isCanceled) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const eventTarget = (event.target as FileReader);
|
|
100
|
-
if (eventTarget.readyState !== FileReader.DONE) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!this.#reader) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const buffer = (this.#reader.result as ArrayBuffer);
|
|
109
|
-
this.#loadedSize += buffer.byteLength;
|
|
110
|
-
const endOfFile = this.#loadedSize === this.#fileSize;
|
|
111
|
-
void this.decodeChunkBuffer(buffer, endOfFile);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
88
|
private async decodeChunkBuffer(buffer: ArrayBuffer, endOfFile: boolean): Promise<void> {
|
|
115
89
|
if (!this.#output) {
|
|
116
90
|
return;
|
|
@@ -136,7 +110,6 @@ export class ChunkedFileReader implements ChunkedReader {
|
|
|
136
110
|
return;
|
|
137
111
|
}
|
|
138
112
|
this.#file = null;
|
|
139
|
-
this.#reader = null;
|
|
140
113
|
await this.#output.close();
|
|
141
114
|
this.#transferFinished(!this.#error);
|
|
142
115
|
}
|
|
@@ -153,19 +126,24 @@ export class ChunkedFileReader implements ChunkedReader {
|
|
|
153
126
|
return await this.finishRead();
|
|
154
127
|
}
|
|
155
128
|
void this.decodeChunkBuffer(value.buffer, false);
|
|
129
|
+
return;
|
|
156
130
|
}
|
|
157
|
-
if (this.#reader) {
|
|
158
|
-
const chunkStart = this.#loadedSize;
|
|
159
|
-
const chunkEnd = Math.min(this.#fileSize, chunkStart + this.#chunkSize);
|
|
160
|
-
const nextPart = this.#file.slice(chunkStart, chunkEnd);
|
|
161
|
-
this.#reader.readAsArrayBuffer(nextPart);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
131
|
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
132
|
+
const chunkStart = this.#loadedSize;
|
|
133
|
+
const chunkEnd = Math.min(this.#fileSize, chunkStart + this.#chunkSize);
|
|
134
|
+
const nextPart = this.#file.slice(chunkStart, chunkEnd);
|
|
135
|
+
try {
|
|
136
|
+
const buffer = await nextPart.arrayBuffer();
|
|
137
|
+
if (this.#isCanceled) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.#loadedSize += buffer.byteLength;
|
|
141
|
+
const endOfFile = this.#loadedSize === this.#fileSize;
|
|
142
|
+
void this.decodeChunkBuffer(buffer, endOfFile);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
this.#error = error as DOMException;
|
|
145
|
+
this.#transferFinished(false);
|
|
146
|
+
}
|
|
169
147
|
}
|
|
170
148
|
}
|
|
171
149
|
|
|
@@ -38,23 +38,16 @@ export class TempFile {
|
|
|
38
38
|
this.#lastBlob.slice((startOffset as number), (endOffset as number)) :
|
|
39
39
|
this.#lastBlob;
|
|
40
40
|
|
|
41
|
-
const reader = new FileReader();
|
|
42
41
|
try {
|
|
43
|
-
await
|
|
44
|
-
reader.onloadend = resolve;
|
|
45
|
-
reader.onerror = reject;
|
|
46
|
-
reader.readAsText(blob);
|
|
47
|
-
});
|
|
42
|
+
return await blob.text();
|
|
48
43
|
} catch (error) {
|
|
49
|
-
this.#console.error('Failed to read from temp file: ' + error.message);
|
|
44
|
+
this.#console.error('Failed to read from temp file: ' + (error as Error).message);
|
|
45
|
+
return null;
|
|
50
46
|
}
|
|
51
|
-
|
|
52
|
-
return reader.result as string | null;
|
|
53
47
|
}
|
|
54
48
|
|
|
55
|
-
async copyToOutputStream(
|
|
56
|
-
|
|
57
|
-
progress?: ((arg0: ChunkedReader) => void)): Promise<DOMError|null> {
|
|
49
|
+
async copyToOutputStream(outputStream: Common.StringOutputStream.OutputStream,
|
|
50
|
+
progress?: ((arg0: ChunkedReader) => void)): Promise<DOMException|Error|null> {
|
|
58
51
|
if (!this.#lastBlob) {
|
|
59
52
|
void outputStream.close();
|
|
60
53
|
return null;
|
|
@@ -18,6 +18,21 @@ export interface DOMNodeAnchorSignature {
|
|
|
18
18
|
targetId: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export interface TimelineAnchorSignature {
|
|
22
|
+
/** Identifier of the trace to scope comments to a specific recording */
|
|
23
|
+
traceId: string;
|
|
24
|
+
/** Serializable key from Trace.EventsSerializer (e.g. 'r-123', 'p-1-2-3-4', 's-5') */
|
|
25
|
+
traceEventKey: string;
|
|
26
|
+
/** Primary event title or category name */
|
|
27
|
+
entryName: string;
|
|
28
|
+
/** Event start timestamp in microseconds */
|
|
29
|
+
startTimeMicro: number;
|
|
30
|
+
/** Chart location */
|
|
31
|
+
chartLocation: 'main'|'network';
|
|
32
|
+
/** Event duration in microseconds (omitted for instant markers) */
|
|
33
|
+
durationMicro?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
export interface CommentAnchorSignature {
|
|
22
37
|
/** Visual logging tree path, e.g. "Panel: elements > Pane: styles > TreeOutline > TreeItem: color" */
|
|
23
38
|
vePath: string;
|
|
@@ -33,6 +48,8 @@ export interface CommentAnchorSignature {
|
|
|
33
48
|
node?: DOMNodeAnchorSignature;
|
|
34
49
|
/** Optional editor anchor coordinates for CodeMirror text editors */
|
|
35
50
|
editor?: EditorAnchorSignature;
|
|
51
|
+
/** Optional timeline flamechart anchor coordinates for Performance panel trace entries */
|
|
52
|
+
timeline?: TimelineAnchorSignature;
|
|
36
53
|
}
|
|
37
54
|
|
|
38
55
|
export interface Comment {
|
|
@@ -41,13 +58,19 @@ export interface Comment {
|
|
|
41
58
|
timestamp: number;
|
|
42
59
|
}
|
|
43
60
|
|
|
61
|
+
export interface ChangeRecord {
|
|
62
|
+
id: string;
|
|
63
|
+
description: string;
|
|
64
|
+
timestamp: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
44
67
|
export interface CommentThread {
|
|
45
68
|
id: string;
|
|
46
69
|
anchor: CommentAnchorSignature;
|
|
47
70
|
comments: Comment[];
|
|
48
71
|
status: 'ACTIVE'|'RESOLVED';
|
|
49
72
|
transmitted?: boolean;
|
|
50
|
-
changes?:
|
|
73
|
+
changes?: ChangeRecord[];
|
|
51
74
|
index: number;
|
|
52
75
|
}
|
|
53
76
|
|
|
@@ -83,21 +106,22 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
83
106
|
|
|
84
107
|
createCommentThread(
|
|
85
108
|
anchor: CommentAnchorSignature,
|
|
86
|
-
text
|
|
109
|
+
text?: string,
|
|
87
110
|
author: 'DEVELOPER'|'AGENT' = 'DEVELOPER',
|
|
88
|
-
changes?:
|
|
111
|
+
changes?: ChangeRecord[],
|
|
89
112
|
): CommentThread {
|
|
90
113
|
const index = this.#nextId++;
|
|
91
114
|
const id = `comment-${index}`;
|
|
92
|
-
const
|
|
115
|
+
const comments: Comment[] = text ? [{
|
|
93
116
|
author,
|
|
94
117
|
text,
|
|
95
118
|
timestamp: Date.now(),
|
|
96
|
-
}
|
|
119
|
+
}] :
|
|
120
|
+
[];
|
|
97
121
|
const thread: CommentThread = {
|
|
98
122
|
id,
|
|
99
123
|
anchor,
|
|
100
|
-
comments
|
|
124
|
+
comments,
|
|
101
125
|
status: 'ACTIVE',
|
|
102
126
|
transmitted: false,
|
|
103
127
|
changes,
|
|
@@ -12,7 +12,7 @@ const UIStrings = {
|
|
|
12
12
|
/**
|
|
13
13
|
* @description Warning message indicating that the user will see real user data for a URL which is different from the URL they are currently looking at.
|
|
14
14
|
*/
|
|
15
|
-
fieldOverrideWarning: 'Field metrics are for a different URL than the current page
|
|
15
|
+
fieldOverrideWarning: 'Field metrics are for a different URL than the current page',
|
|
16
16
|
} as const;
|
|
17
17
|
|
|
18
18
|
const str_ = i18n.i18n.registerUIStrings('models/crux-manager/CrUXManager.ts', UIStrings);
|
|
@@ -366,18 +366,21 @@ export class CrUXManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
|
366
366
|
if (response.status === 404) {
|
|
367
367
|
// This is how CrUX tells us that there is not data available for the provided url/origin
|
|
368
368
|
// Since it's a valid response, just return null instead of throwing an error.
|
|
369
|
-
if (responseData
|
|
370
|
-
|
|
369
|
+
if (typeof responseData === 'object' && responseData && 'error' in responseData) {
|
|
370
|
+
const error = (responseData as {error?: {status?: string}}).error;
|
|
371
|
+
if (error?.status === 'NOT_FOUND') {
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
371
374
|
}
|
|
372
375
|
|
|
373
376
|
throw new Error(`Failed to fetch data from CrUX server (Status code: ${response.status})`);
|
|
374
377
|
}
|
|
375
378
|
|
|
376
|
-
if (!('record' in responseData)) {
|
|
379
|
+
if (typeof responseData !== 'object' || !responseData || !('record' in responseData)) {
|
|
377
380
|
throw new Error(`Failed to find data in CrUX response: ${JSON.stringify(responseData)}`);
|
|
378
381
|
}
|
|
379
382
|
|
|
380
|
-
return responseData;
|
|
383
|
+
return responseData as CrUXResponse;
|
|
381
384
|
}
|
|
382
385
|
|
|
383
386
|
#getAutoDeviceScope(): DeviceScope {
|