chrome-devtools-frontend 1.0.1721762 → 1.0.1726686
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/review-ui-widgets/SKILL.md +7 -7
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +12 -0
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +3 -3
- package/.agents/skills/ui-widgets/SKILL.md +2 -1
- package/docs/cookbook/dependencies.md +57 -11
- package/docs/get_the_code.md +15 -0
- package/front_end/core/i18n/collect-ui-strings.js +58 -12
- package/front_end/core/i18n/i18nImpl.ts +1 -1
- package/front_end/core/root/Runtime.ts +1 -1
- package/front_end/core/sdk/ResourceTreeModel.ts +16 -0
- package/front_end/core/sdk/WebAuthnModel.ts +17 -10
- package/front_end/entrypoints/js_app/js_app.ts +2 -5
- package/front_end/entrypoints/node_app/node_app.ts +2 -3
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/protocol.ts +17 -0
- package/front_end/models/ai_assistance/skills/lighthouse.md +2 -1
- package/front_end/models/ai_assistance/skills/network.md +1 -0
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +26 -2
- package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +1 -1
- package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +2 -7
- package/front_end/models/ai_assistance/tools/RunLighthouse.ts +2 -2
- package/front_end/models/comment_manager/CD4ABridge.ts +4 -0
- package/front_end/models/comment_manager/CommentManager.ts +0 -6
- package/front_end/models/comment_manager/CommentThread.ts +39 -19
- package/front_end/models/elements/StyleChanges.ts +66 -0
- package/front_end/models/trace/EventsSerializer.ts +2 -7
- package/front_end/models/trace/ModelImpl.ts +0 -2
- package/front_end/models/trace/handlers/FlowsHandler.ts +37 -29
- package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +13 -6
- package/front_end/models/trace/helpers/SyntheticEvents.ts +10 -37
- package/front_end/models/trace/insights/RenderBlocking.ts +3 -1
- package/front_end/models/trace/lantern/simulation/Simulator.ts +4 -0
- package/front_end/models/trace/lantern/types/Lantern.ts +1 -0
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +92 -0
- package/front_end/panels/accessibility/SourceOrderView.ts +1 -1
- package/front_end/panels/accessibility/accessibilityAnnouncementRecordingListView.css +3 -1
- package/front_end/panels/accessibility/accessibilityAnnouncementRecordingView.css +12 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +90 -0
- package/front_end/panels/application/StorageView.ts +348 -254
- package/front_end/panels/application/SubAppsView.ts +159 -0
- package/front_end/panels/application/application.ts +2 -0
- package/front_end/panels/application/preloading/PreloadingView.ts +360 -336
- package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +3 -3
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +6 -3
- package/front_end/panels/application/preloading/components/RuleSetGrid.ts +17 -17
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -2
- package/front_end/panels/application/preloading/preloadingView.css +12 -4
- package/front_end/panels/application/preloading/preloadingViewDropDown.css +1 -1
- package/front_end/panels/application/storageView.css +16 -21
- package/front_end/panels/application/subAppsView.css +21 -0
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -2
- package/front_end/panels/browser_debugger/browser_debugger-meta.ts +6 -8
- package/front_end/panels/comments/CommentsPane.ts +26 -9
- package/front_end/panels/comments/commentsPane.css +25 -6
- package/front_end/panels/common/CommentThreadWidget.ts +2 -2
- package/front_end/panels/common/CommentsOverlayWidget.ts +94 -35
- package/front_end/panels/common/commentThreadWidget.css +17 -0
- package/front_end/panels/common/commentsOverlay.css +5 -10
- package/front_end/panels/common/common-meta.ts +11 -1
- package/front_end/panels/elements/ClassesPaneWidget.ts +133 -89
- package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +7 -33
- package/front_end/panels/elements/DOMTreeElementWidget.ts +3 -1
- package/front_end/panels/elements/DOMTreeWidget.ts +19 -3
- package/front_end/panels/elements/ElementStatePaneWidget.ts +11 -1
- package/front_end/panels/elements/PropertyRenderer.ts +3 -2
- package/front_end/panels/elements/StyleEditorWidget.ts +87 -39
- package/front_end/panels/elements/StylePropertiesSection.ts +32 -5
- package/front_end/panels/elements/StylePropertyTreeElement.ts +227 -162
- package/front_end/panels/elements/StylesSidebarPane.ts +1 -0
- package/front_end/panels/event_listeners/EventListenersView.ts +11 -8
- package/front_end/panels/layer_viewer/Layers3DView.ts +21 -37
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
- package/front_end/panels/network/NetworkConfigView.ts +12 -10
- package/front_end/panels/network/NetworkDataGridNode.ts +3 -1
- package/front_end/panels/network/RequestConditionsDrawer.ts +1 -1
- package/front_end/panels/network/RequestPayloadView.ts +12 -5
- package/front_end/panels/network/networkConfigView.css +8 -8
- package/front_end/panels/profiler/HeapProfileView.ts +28 -6
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +7 -3
- package/front_end/panels/protocol_monitor/JSONEditor.ts +0 -1
- package/front_end/panels/recorder/RecorderPanel.ts +2 -2
- package/front_end/panels/screencast/ScreencastView.ts +3 -6
- package/front_end/panels/security/SecurityPanelSidebar.ts +0 -31
- package/front_end/panels/settings/SettingsScreen.ts +1 -1
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +9 -16
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +358 -345
- package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +136 -121
- package/front_end/panels/sources/NavigatorView.ts +105 -45
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +8 -5
- package/front_end/panels/sources/SourcesNavigator.ts +421 -213
- package/front_end/panels/sources/SourcesPanel.ts +9 -5
- package/front_end/panels/sources/TabbedEditorContainer.ts +41 -18
- package/front_end/panels/sources/UISourceCodeFrame.ts +1 -1
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +10 -5
- package/front_end/panels/sources/sources-meta.ts +4 -15
- package/front_end/panels/sources/sourcesNavigator.css +5 -0
- package/front_end/panels/timeline/ModificationsManager.ts +0 -2
- package/front_end/panels/timeline/README.md +2 -0
- package/front_end/panels/timeline/TimelineCommentContext.ts +171 -0
- package/front_end/panels/timeline/TimelineCommentController.ts +168 -30
- package/front_end/panels/timeline/TimelinePanel.ts +4 -0
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
- package/front_end/panels/timeline/timeline.ts +2 -0
- package/front_end/panels/timeline/utils/Treemap.ts +8 -0
- package/front_end/panels/webauthn/WebauthnPane.ts +15 -13
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +113 -3
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +21311 -20981
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +36 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js +22 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +20 -18
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts +20 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +40 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +3 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts +2 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js +41 -5
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js +23 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Input.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js +13 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.d.ts +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.js +18 -11
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Request.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +8 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +24 -12
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js +13 -7
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +5 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts +22 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js +75 -9
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.d.ts +18 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.js +8 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkEventManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +65 -26
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js +19 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.js +4 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ScreenRecording.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js +4 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts +2 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js +95 -8
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts +0 -8
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js +8 -24
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.d.ts +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js +5 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts +9 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.js +10 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/WaitTask.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts +10 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js +30 -5
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.d.ts +2 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.js +33 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/Poller.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +1 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.d.ts +4 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/encoding.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/encoding.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +113 -3
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/Browser.ts +42 -0
- package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +25 -22
- package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +22 -2
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +45 -2
- package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +79 -32
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +32 -12
- package/front_end/third_party/puppeteer/package/src/bidi/Input.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +18 -2
- package/front_end/third_party/puppeteer/package/src/bidi/core/Request.ts +21 -13
- package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +12 -2
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +37 -16
- package/front_end/third_party/puppeteer/package/src/cdp/EmulationManager.ts +14 -11
- package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +7 -1
- package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +101 -14
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkEventManager.ts +26 -6
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +111 -29
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +37 -1
- package/front_end/third_party/puppeteer/package/src/cdp/ScreenRecording.ts +5 -4
- package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +5 -0
- package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +122 -7
- package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +13 -33
- package/front_end/third_party/puppeteer/package/src/common/BrowserWebSocketTransport.ts +10 -5
- package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +10 -0
- package/front_end/third_party/puppeteer/package/src/common/WaitTask.ts +12 -0
- package/front_end/third_party/puppeteer/package/src/common/util.ts +39 -5
- package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/injected/Poller.ts +35 -3
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +4 -2
- package/front_end/third_party/puppeteer/package/src/node/NodeWebSocketTransport.ts +5 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/encoding.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +3 -0
- package/front_end/ui/comments/CommentOverlayManager.ts +2 -4
- package/front_end/ui/components/lists/List.ts +14 -1
- package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +23 -14
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +3 -0
- package/front_end/ui/helpers/OpenInNewTab.ts +8 -0
- package/front_end/ui/legacy/LinkContextMenuProvider.ts +1 -1
- package/front_end/ui/legacy/ListWidget.ts +14 -18
- package/front_end/ui/legacy/TabbedPane.ts +46 -3
- package/front_end/ui/legacy/Toolbar.ts +0 -1
- package/front_end/ui/legacy/Treeoutline.ts +10 -3
- package/front_end/ui/legacy/UIUtils.ts +5 -2
- package/front_end/ui/legacy/components/inline_editor/Swatches.ts +19 -6
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +20 -11
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +27 -7
- package/front_end/ui/visual_logging/KnownContextValues.ts +5 -0
- package/package.json +1 -1
|
@@ -114,13 +114,8 @@ export class ListNetworkRequestsTool implements
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
return {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
name: 'NETWORK_REQUESTS_LIST',
|
|
120
|
-
data: {
|
|
121
|
-
requests: [],
|
|
122
|
-
},
|
|
123
|
-
}],
|
|
117
|
+
error:
|
|
118
|
+
'No network requests have been recorded. DevTools only records requests made while DevTools is open and network recording is enabled (and the log has not been cleared). Ask the user to ensure network recording is enabled, reload the page or repeat the action that triggers the request, and try again.',
|
|
124
119
|
};
|
|
125
120
|
}
|
|
126
121
|
|
|
@@ -45,9 +45,9 @@ export class RunLighthouseTool implements
|
|
|
45
45
|
},
|
|
46
46
|
categoryId: {
|
|
47
47
|
type: Host.AidaClient.ParametersTypes.STRING,
|
|
48
|
-
// The experimental 'agentic-browsing' category is
|
|
48
|
+
// The experimental 'agentic-browsing' category is listed separately from the standard categories and restricted to explicit user requests so the agent does not invoke it unprompted. It is also excluded when 'all' is provided (see `LighthouseController.getCategoryIDs`).
|
|
49
49
|
description:
|
|
50
|
-
'Lighthouse category. Use "all" to run all categories, or specify a category: "accessibility", "performance", "best-practices", "seo".',
|
|
50
|
+
'Lighthouse category. Use "all" to run all categories, or specify a category: "accessibility", "performance", "best-practices", "seo". Use "agentic-browsing" only when the user explicitly asks for an agentic browsing audit (how well AI agents can navigate and use the page, including WebMCP). "all" does not include "agentic-browsing". Run "agentic-browsing" in "navigation" mode, because its WebMCP audits only run in "navigation" mode.',
|
|
51
51
|
nullable: false,
|
|
52
52
|
},
|
|
53
53
|
mode: {
|
|
@@ -113,6 +113,10 @@ export class CD4ABridge extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
|
113
113
|
details.push(`- Editor: ${editorInfo}`);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
for (const line of thread.anchor.agentContext ?? []) {
|
|
117
|
+
details.push(`- ${line}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
116
120
|
if (details.length === 0) {
|
|
117
121
|
return rawText;
|
|
118
122
|
}
|
|
@@ -48,11 +48,6 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
48
48
|
#commentMode = false;
|
|
49
49
|
#agentAttached = false;
|
|
50
50
|
|
|
51
|
-
constructor() {
|
|
52
|
-
super();
|
|
53
|
-
CommentThread.resetIndex();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
51
|
#onThreadChanged(): void {
|
|
57
52
|
this.dispatchEventToListeners(Events.COMMENT_THREADS_CHANGED, this.getCommentThreads());
|
|
58
53
|
}
|
|
@@ -174,7 +169,6 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
174
169
|
thread.removeEventListener(CommentThreadEvents.CHANGED, this.#onThreadChanged, this);
|
|
175
170
|
}
|
|
176
171
|
this.#commentThreads.clear();
|
|
177
|
-
CommentThread.resetIndex();
|
|
178
172
|
this.dispatchEventToListeners(Events.COMMENT_THREADS_CHANGED, []);
|
|
179
173
|
}
|
|
180
174
|
}
|
|
@@ -22,7 +22,10 @@ export interface DOMNodeAnchorSignature {
|
|
|
22
22
|
export interface TimelineAnchorSignature {
|
|
23
23
|
/** Identifier of the trace to scope comments to a specific recording */
|
|
24
24
|
traceId: string;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Serializable key from Trace.EventsSerializer (e.g. 'r-123', 'p-1-2-3-4', 's-5'), or
|
|
27
|
+
* 'fc-<chartLocation>-<entryIndex>' for flame chart entries that EventsSerializer cannot key.
|
|
28
|
+
*/
|
|
26
29
|
traceEventKey: string;
|
|
27
30
|
/** Primary event title or category name */
|
|
28
31
|
entryName: string;
|
|
@@ -51,6 +54,22 @@ export interface CommentAnchorSignature {
|
|
|
51
54
|
editor?: EditorAnchorSignature;
|
|
52
55
|
/** Optional timeline flamechart anchor coordinates for Performance panel trace entries */
|
|
53
56
|
timeline?: TimelineAnchorSignature;
|
|
57
|
+
/**
|
|
58
|
+
* Optional formatted lines that give the AI agent context about the
|
|
59
|
+
* anchored target beyond the VE path and text signature, for example the
|
|
60
|
+
* timing and warnings of a Performance panel trace entry. CD4ABridge
|
|
61
|
+
* appends each line to the comment text that it sends to the agent.
|
|
62
|
+
*
|
|
63
|
+
* These lines are only context for the agent. They are not used to
|
|
64
|
+
* re-match the anchor to its target; the other fields of this signature
|
|
65
|
+
* do that.
|
|
66
|
+
*
|
|
67
|
+
* Currently only the Performance panel sets this field. Before adding
|
|
68
|
+
* context here, consider whether it belongs in a new field on this
|
|
69
|
+
* signature instead. This field is only for text that is already
|
|
70
|
+
* formatted for the agent, not for data that other code needs to read.
|
|
71
|
+
*/
|
|
72
|
+
agentContext?: string[];
|
|
54
73
|
}
|
|
55
74
|
|
|
56
75
|
export interface Comment {
|
|
@@ -77,17 +96,11 @@ export interface CommentThreadOptions {
|
|
|
77
96
|
}
|
|
78
97
|
|
|
79
98
|
export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
80
|
-
static #nextIndex = 1;
|
|
81
|
-
|
|
82
|
-
static resetIndex(): void {
|
|
83
|
-
CommentThread.#nextIndex = 1;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
99
|
readonly id: string = crypto.randomUUID();
|
|
87
100
|
readonly anchor: CommentAnchorSignature;
|
|
88
101
|
/** True for comments generated from the change tracker. */
|
|
89
102
|
readonly isGeneratedComment: boolean;
|
|
90
|
-
#
|
|
103
|
+
#isOrphaned = false;
|
|
91
104
|
comments: Comment[];
|
|
92
105
|
status: CommentThreadStatus = 'DRAFT';
|
|
93
106
|
transmitted: boolean = false;
|
|
@@ -99,8 +112,16 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
99
112
|
this.isGeneratedComment = Boolean(options.isGeneratedComment);
|
|
100
113
|
}
|
|
101
114
|
|
|
102
|
-
get
|
|
103
|
-
return this.#
|
|
115
|
+
get isOrphaned(): boolean {
|
|
116
|
+
return this.#isOrphaned;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
setOrphaned(isOrphaned: boolean): void {
|
|
120
|
+
if (this.#isOrphaned === isOrphaned) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.#isOrphaned = isOrphaned;
|
|
124
|
+
this.dispatchEventToListeners(Events.CHANGED);
|
|
104
125
|
}
|
|
105
126
|
|
|
106
127
|
/**
|
|
@@ -137,9 +158,6 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
137
158
|
let changed = this.#saveText(text, author);
|
|
138
159
|
if (this.status === 'DRAFT') {
|
|
139
160
|
this.#recordCommentCreated();
|
|
140
|
-
if (this.#savedIndex === undefined) {
|
|
141
|
-
this.#savedIndex = CommentThread.#nextIndex++;
|
|
142
|
-
}
|
|
143
161
|
this.status = 'ACTIVE';
|
|
144
162
|
changed = true;
|
|
145
163
|
}
|
|
@@ -167,9 +185,6 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
167
185
|
this.#recordCommentCreated();
|
|
168
186
|
}
|
|
169
187
|
if (this.status === 'DRAFT' || this.status === 'ACTIVE') {
|
|
170
|
-
if (this.#savedIndex === undefined) {
|
|
171
|
-
this.#savedIndex = CommentThread.#nextIndex++;
|
|
172
|
-
}
|
|
173
188
|
this.status = 'SENT_TO_AGENT';
|
|
174
189
|
changed = true;
|
|
175
190
|
}
|
|
@@ -186,10 +201,15 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
186
201
|
timestamp: Date.now(),
|
|
187
202
|
});
|
|
188
203
|
}
|
|
189
|
-
if (this.#savedIndex === undefined) {
|
|
190
|
-
this.#savedIndex = CommentThread.#nextIndex++;
|
|
191
|
-
}
|
|
192
204
|
this.status = 'RESOLVED';
|
|
193
205
|
this.dispatchEventToListeners(Events.CHANGED);
|
|
194
206
|
}
|
|
195
207
|
}
|
|
208
|
+
|
|
209
|
+
export class RevealableThread {
|
|
210
|
+
constructor(
|
|
211
|
+
readonly thread: CommentThread,
|
|
212
|
+
readonly position?: {left: number, top: number},
|
|
213
|
+
) {
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -95,3 +95,69 @@ export function trackStylePropertyToggle(
|
|
|
95
95
|
}
|
|
96
96
|
tracker.trackChange(describeStylePropertyToggle(toggle), buildAnchor(STYLES_PANE_VE_PATH, node));
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
export function trackStyleRuleAdded(
|
|
100
|
+
tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
|
|
101
|
+
node: SDK.DOMModel.DOMNode,
|
|
102
|
+
selector: string,
|
|
103
|
+
): void {
|
|
104
|
+
if (!tracker?.isTracking) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const trimmedSelector = Platform.StringUtilities.collapseWhitespace(selector.trim());
|
|
108
|
+
if (!trimmedSelector) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
tracker.trackChange(
|
|
112
|
+
`Added style rule "${trimValue(trimmedSelector)}"`,
|
|
113
|
+
buildAnchor(STYLES_PANE_VE_PATH, node),
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function trackRuleHeaderChange(
|
|
118
|
+
tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
|
|
119
|
+
node: SDK.DOMModel.DOMNode,
|
|
120
|
+
headerDescription: string,
|
|
121
|
+
oldText: string,
|
|
122
|
+
newText: string,
|
|
123
|
+
): void {
|
|
124
|
+
if (!tracker?.isTracking) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const trimmedOld = Platform.StringUtilities.collapseWhitespace(oldText.trim());
|
|
128
|
+
const trimmedNew = Platform.StringUtilities.collapseWhitespace(newText.trim());
|
|
129
|
+
if (!trimmedOld || !trimmedNew || trimmedOld === trimmedNew) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
tracker.trackChange(
|
|
133
|
+
`Changed ${headerDescription} from "${trimValue(trimmedOld)}" to "${trimValue(trimmedNew)}"`,
|
|
134
|
+
buildAnchor(STYLES_PANE_VE_PATH, node),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function trackStyleSelectorChange(
|
|
139
|
+
tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
|
|
140
|
+
node: SDK.DOMModel.DOMNode,
|
|
141
|
+
oldSelector: string,
|
|
142
|
+
newSelector: string,
|
|
143
|
+
): void {
|
|
144
|
+
trackRuleHeaderChange(tracker, node, 'style rule selector', oldSelector, newSelector);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function trackPropertyRuleNameChange(
|
|
148
|
+
tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
|
|
149
|
+
node: SDK.DOMModel.DOMNode,
|
|
150
|
+
oldName: string,
|
|
151
|
+
newName: string,
|
|
152
|
+
): void {
|
|
153
|
+
trackRuleHeaderChange(tracker, node, '@property rule name', oldName, newName);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function trackKeyframeKeyChange(
|
|
157
|
+
tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
|
|
158
|
+
node: SDK.DOMModel.DOMNode,
|
|
159
|
+
oldKey: string,
|
|
160
|
+
newKey: string,
|
|
161
|
+
): void {
|
|
162
|
+
trackRuleHeaderChange(tracker, node, 'keyframe key', oldKey, newKey);
|
|
163
|
+
}
|
|
@@ -84,13 +84,8 @@ export class EventsSerializer {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
if (EventsSerializer.isSyntheticEventKey(eventValues)) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (!syntheticEvent) {
|
|
90
|
-
throw new Error(`Unknown trace event. Attempted to get a synthetic event from an unknown raw event index: ${
|
|
91
|
-
eventValues.rawIndex}`);
|
|
92
|
-
}
|
|
93
|
-
return syntheticEvent;
|
|
87
|
+
return Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().syntheticEventForRawEventIndex(
|
|
88
|
+
eventValues.rawIndex);
|
|
94
89
|
}
|
|
95
90
|
|
|
96
91
|
if (EventsSerializer.isRawEventKey(eventValues)) {
|
|
@@ -110,8 +110,6 @@ export class Model extends EventTarget {
|
|
|
110
110
|
}
|
|
111
111
|
const file = this.#storeAndCreateParsedTraceFile(
|
|
112
112
|
syntheticEventsManager, traceEvents, metadata, this.#processor.data, this.#processor.insights);
|
|
113
|
-
// Reclaim memory used by the temporary event-to-index lookup map now that trace parsing is complete.
|
|
114
|
-
syntheticEventsManager.clearRegistrationIndex();
|
|
115
113
|
// We only push the file onto this.#traces here once we know it's valid
|
|
116
114
|
// and there's been no errors in the parsing.
|
|
117
115
|
this.#traces.push(file);
|
|
@@ -14,7 +14,7 @@ import * as Types from '../types/types.js';
|
|
|
14
14
|
// included, while the amount of `step` phase events can be >= 0.
|
|
15
15
|
|
|
16
16
|
// A flow phase event is assigned to a trace event when their cat, tid,
|
|
17
|
-
// pid and ts are equal (see
|
|
17
|
+
// pid and ts are equal (see findBinding()).
|
|
18
18
|
|
|
19
19
|
// It's possible for a single event to belong to multiple flows. In that
|
|
20
20
|
// case, it will have multiple corresponding flow phase events (one
|
|
@@ -26,24 +26,27 @@ import * as Types from '../types/types.js';
|
|
|
26
26
|
// there are any corresponding flow phase events at all).
|
|
27
27
|
let flowDataByGroupToken = new Map<string, number>();
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* The flows bound to one flow binding tuple (timestamp, process id,
|
|
31
|
+
* thread id and category).
|
|
32
|
+
*/
|
|
33
|
+
interface FlowBinding {
|
|
34
|
+
ts: Types.Timing.Micro;
|
|
35
|
+
pid: Types.Events.ProcessID;
|
|
36
|
+
tid: Types.Events.ThreadID;
|
|
37
|
+
cat: string;
|
|
30
38
|
flows: Set<number>;
|
|
31
39
|
bindingParsed: boolean;
|
|
32
40
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// corresponding flow data. However, this token would be calculated for
|
|
43
|
-
// every event in a trace, resulting in a lot of memory overhead and
|
|
44
|
-
// major GC triggering. So we are trading off readability for
|
|
45
|
-
// performance.
|
|
46
|
-
let boundFlowData: FlowBindingTuple = new Map();
|
|
41
|
+
|
|
42
|
+
// Trace timestamps are microseconds and too large to be small integers
|
|
43
|
+
// in V8, so a Map keyed by the timestamp hashes a heap number on every
|
|
44
|
+
// lookup. Every non-flow event in a trace is looked up here, so this
|
|
45
|
+
// map is keyed by the low 30 bits of the timestamp instead, which are
|
|
46
|
+
// always a small integer. Bindings that share a key are told apart by
|
|
47
|
+
// comparing the full flow binding tuple.
|
|
48
|
+
const TS_KEY_MASK = 0x3fffffff;
|
|
49
|
+
let boundFlowData = new Map<number, FlowBinding[]>();
|
|
47
50
|
|
|
48
51
|
let flowsById = new Map<number, Map<Types.Timing.Micro, Types.Events.Event>>();
|
|
49
52
|
let flowEvents: Types.Events.FlowEvent[] = [];
|
|
@@ -67,8 +70,17 @@ export function handleEvent(event: Types.Events.Event): void {
|
|
|
67
70
|
nonFlowEvents.push(event);
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
function findBinding(bindings: FlowBinding[], event: Types.Events.Event): FlowBinding|undefined {
|
|
74
|
+
return bindings.find(binding => binding.ts === event.ts && binding.pid === event.pid && binding.tid === event.tid &&
|
|
75
|
+
binding.cat === event.cat);
|
|
76
|
+
}
|
|
77
|
+
|
|
70
78
|
function processNonFlowEvent(event: Types.Events.Event): void {
|
|
71
|
-
const
|
|
79
|
+
const bindings = boundFlowData.get(event.ts & TS_KEY_MASK);
|
|
80
|
+
if (!bindings) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const flowDataForEvent = findBinding(bindings, event);
|
|
72
84
|
if (!flowDataForEvent) {
|
|
73
85
|
return;
|
|
74
86
|
}
|
|
@@ -95,9 +107,8 @@ function processFlowEvent(flowPhaseEvent: Types.Events.FlowEvent): void {
|
|
|
95
107
|
const flowGroup = flowGroupTokenForFlowPhaseEvent(flowPhaseEvent);
|
|
96
108
|
switch (flowPhaseEvent.ph) {
|
|
97
109
|
case (Types.Events.Phase.FLOW_START): {
|
|
98
|
-
const flowMetadata = {flowId: flowPhaseEvent.id, times: new Map([[flowPhaseEvent.ts, undefined]])};
|
|
99
110
|
flowDataByGroupToken.set(flowGroup, flowPhaseEvent.id);
|
|
100
|
-
addFlowIdToEventBinding(flowPhaseEvent,
|
|
111
|
+
addFlowIdToEventBinding(flowPhaseEvent, flowPhaseEvent.id);
|
|
101
112
|
return;
|
|
102
113
|
}
|
|
103
114
|
case (Types.Events.Phase.FLOW_STEP): {
|
|
@@ -125,22 +136,19 @@ function processFlowEvent(flowPhaseEvent: Types.Events.FlowEvent): void {
|
|
|
125
136
|
}
|
|
126
137
|
}
|
|
127
138
|
|
|
128
|
-
type MapValueType<T extends Map<unknown, unknown>> = NonNullable<ReturnType<T['get']>>;
|
|
129
139
|
/**
|
|
130
140
|
* A single trace event can belong to multiple flows. This method
|
|
131
141
|
* tracks which flows (flowId) an event belongs to given its flow
|
|
132
142
|
* binding tuple (made of its ts, pid, tid and cat).
|
|
133
143
|
*/
|
|
134
144
|
function addFlowIdToEventBinding(event: Types.Events.Event, flowId: number): void {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
Platform.MapUtilities.getWithDefault(flowsByCat, event.cat, () => ({flows: new Set(), bindingParsed: false}));
|
|
143
|
-
flowData.flows.add(flowId);
|
|
145
|
+
const bindings = Platform.MapUtilities.getWithDefault(boundFlowData, event.ts & TS_KEY_MASK, () => []);
|
|
146
|
+
let binding = findBinding(bindings, event);
|
|
147
|
+
if (!binding) {
|
|
148
|
+
binding = {ts: event.ts, pid: event.pid, tid: event.tid, cat: event.cat, flows: new Set(), bindingParsed: false};
|
|
149
|
+
bindings.push(binding);
|
|
150
|
+
}
|
|
151
|
+
binding.flows.add(flowId);
|
|
144
152
|
}
|
|
145
153
|
|
|
146
154
|
/**
|
|
@@ -283,14 +283,21 @@ export async function finalize(): Promise<void> {
|
|
|
283
283
|
*/
|
|
284
284
|
// @ts-expect-error
|
|
285
285
|
const isLightrider = globalThis.isLightrider;
|
|
286
|
-
if (isLightrider && request.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
286
|
+
if (isLightrider && request.receiveResponse?.args.data.headers) {
|
|
287
|
+
if (request.resourceFinish) {
|
|
288
|
+
const lrSizeHeader = request.receiveResponse.args.data.headers.find(h => h.name === 'X-TotalFetchedSize');
|
|
289
|
+
if (lrSizeHeader) {
|
|
290
|
+
const size = parseFloat(lrSizeHeader.value);
|
|
291
|
+
if (!isNaN(size)) {
|
|
292
|
+
request.resourceFinish.args.data.encodedDataLength = size;
|
|
293
|
+
}
|
|
292
294
|
}
|
|
293
295
|
}
|
|
296
|
+
|
|
297
|
+
const isH2 = request.receiveResponse.args.data.headers.some(h => h.name === 'X-ProtocolIsH2');
|
|
298
|
+
if (isH2) {
|
|
299
|
+
request.receiveResponse.args.data.protocol = 'h2';
|
|
300
|
+
}
|
|
294
301
|
}
|
|
295
302
|
|
|
296
303
|
// If a ResourceFinish event with an encoded data length is received,
|
|
@@ -8,12 +8,14 @@ let activeManager: SyntheticEventsManager|null = null;
|
|
|
8
8
|
|
|
9
9
|
export class SyntheticEventsManager {
|
|
10
10
|
/**
|
|
11
|
-
* All synthetic entries created in a trace
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* All synthetic entries created in a trace, keyed by the raw trace event
|
|
12
|
+
* they are based on. (ProfileCalls and layout shift clusters are excluded
|
|
13
|
+
* because they are not based on a real trace event.) Keying by the raw
|
|
14
|
+
* event rather than by its index in the raw events array means
|
|
15
|
+
* registration does not need to look up the index, which would require a
|
|
16
|
+
* map of every raw event in the trace.
|
|
15
17
|
*/
|
|
16
|
-
#
|
|
18
|
+
#syntheticEventByRawEvent = new WeakMap<Types.Events.Event, Types.Events.SyntheticBased>();
|
|
17
19
|
/**
|
|
18
20
|
* All raw entries from a trace.
|
|
19
21
|
*/
|
|
@@ -56,55 +58,26 @@ export class SyntheticEventsManager {
|
|
|
56
58
|
this.#rawTraceEvents = rawEvents;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
#rawEventIndexes: Map<Types.Events.Event, number>|null = null;
|
|
60
|
-
|
|
61
|
-
#getRawEventIndex(event: Types.Events.Event): number {
|
|
62
|
-
if (!this.#rawEventIndexes) {
|
|
63
|
-
this.#rawEventIndexes = new Map();
|
|
64
|
-
for (let i = 0; i < this.#rawTraceEvents.length; i++) {
|
|
65
|
-
this.#rawEventIndexes.set(this.#rawTraceEvents[i], i);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return this.#rawEventIndexes.get(event) ?? -1;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Clears the transient raw event index map.
|
|
73
|
-
* During trace parsing, this map provides O(1) lookups for registering synthetic events.
|
|
74
|
-
* Once parsing is complete, queries look up synthetic events exclusively by index in
|
|
75
|
-
* `#syntheticTraces`, so this map is discarded to reclaim memory.
|
|
76
|
-
*/
|
|
77
|
-
clearRegistrationIndex(): void {
|
|
78
|
-
this.#rawEventIndexes = null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
61
|
/**
|
|
82
62
|
* Registers and returns a branded synthetic event. Synthetic events need to
|
|
83
63
|
* be created with this method to ensure they are registered and made
|
|
84
64
|
* available to load events using serialized keys.
|
|
85
65
|
*/
|
|
86
66
|
#registerSyntheticEvent<T extends Types.Events.SyntheticBased>(syntheticEvent: Omit<T, '_tag'>): T {
|
|
87
|
-
const rawIndex = this.#getRawEventIndex(syntheticEvent.rawSourceEvent);
|
|
88
|
-
if (rawIndex < 0) {
|
|
89
|
-
throw new Error('Attempted to register a synthetic event paired to an unknown raw event.');
|
|
90
|
-
}
|
|
91
67
|
const eventAsSynthetic = syntheticEvent as T;
|
|
92
|
-
this.#
|
|
68
|
+
this.#syntheticEventByRawEvent.set(syntheticEvent.rawSourceEvent, eventAsSynthetic);
|
|
93
69
|
return eventAsSynthetic;
|
|
94
70
|
}
|
|
95
71
|
|
|
96
72
|
syntheticEventForRawEventIndex(rawEventIndex: number): Types.Events.SyntheticBased {
|
|
97
|
-
const
|
|
73
|
+
const rawEvent = this.#rawTraceEvents.at(rawEventIndex);
|
|
74
|
+
const syntheticEvent = rawEvent && this.#syntheticEventByRawEvent.get(rawEvent);
|
|
98
75
|
if (!syntheticEvent) {
|
|
99
76
|
throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${rawEventIndex}`);
|
|
100
77
|
}
|
|
101
78
|
return syntheticEvent;
|
|
102
79
|
}
|
|
103
80
|
|
|
104
|
-
getSyntheticTraces(): Types.Events.SyntheticBased[] {
|
|
105
|
-
return this.#syntheticTraces;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
81
|
getRawTraceEvents(): readonly Types.Events.Event[] {
|
|
109
82
|
return this.#rawTraceEvents;
|
|
110
83
|
}
|
|
@@ -82,18 +82,20 @@ function getNodesAndTimingByRequestId(nodeTimings: Lantern.Simulation.Result['no
|
|
|
82
82
|
|
|
83
83
|
let duration = nodeTiming.duration;
|
|
84
84
|
let startTime = nodeTiming.startTime;
|
|
85
|
+
let queuedTime = nodeTiming.queuedTime;
|
|
85
86
|
for (const redirect of node.request.redirects ?? []) {
|
|
86
87
|
const redirectTiming = timingByNodeId.get(redirect.requestId);
|
|
87
88
|
if (redirectTiming) {
|
|
88
89
|
duration += redirectTiming.duration;
|
|
89
90
|
startTime = Math.min(startTime, redirectTiming.startTime);
|
|
91
|
+
queuedTime = Math.min(queuedTime, redirectTiming.queuedTime);
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
const backendRequestId = node.request.rawRequest?.args.data.requestId ?? node.request.requestId;
|
|
94
96
|
requestIdToNode.set(backendRequestId, {
|
|
95
97
|
node,
|
|
96
|
-
nodeTiming: {startTime, endTime: nodeTiming.endTime, duration},
|
|
98
|
+
nodeTiming: {startTime, endTime: nodeTiming.endTime, queuedTime, duration},
|
|
97
99
|
});
|
|
98
100
|
}
|
|
99
101
|
|
|
@@ -262,6 +262,9 @@ class Simulator<T = Lantern.AnyNetworkObject> {
|
|
|
262
262
|
if (!connection) {
|
|
263
263
|
return;
|
|
264
264
|
}
|
|
265
|
+
if (this.nodeTimings.getQueued(node).queuedTime === totalElapsedTime) {
|
|
266
|
+
connection.setH2OverflowBytesDownloaded(0);
|
|
267
|
+
}
|
|
265
268
|
}
|
|
266
269
|
|
|
267
270
|
this.markNodeAsInProgress(node, totalElapsedTime);
|
|
@@ -430,6 +433,7 @@ class Simulator<T = Lantern.AnyNetworkObject> {
|
|
|
430
433
|
{
|
|
431
434
|
startTime: timing.startTime,
|
|
432
435
|
endTime: timing.endTime,
|
|
436
|
+
queuedTime: timing.queuedTime,
|
|
433
437
|
duration: timing.endTime - timing.startTime,
|
|
434
438
|
},
|
|
435
439
|
];
|
|
@@ -89,11 +89,86 @@ const UIStrings = {
|
|
|
89
89
|
* @description Fallback reason shown when an unknown error occurs while blocking recording.
|
|
90
90
|
*/
|
|
91
91
|
unknownError: 'Unknown error',
|
|
92
|
+
/**
|
|
93
|
+
* @description Accessible label for the grabber handle used to vertically resize the announcements pane.
|
|
94
|
+
*/
|
|
95
|
+
resizeAnnouncementsPane: 'Resize announcements pane',
|
|
92
96
|
} as const;
|
|
93
97
|
const str_ = i18n.i18n.registerUIStrings('panels/accessibility/AccessibilityAnnouncementRecordingView.ts', UIStrings);
|
|
94
98
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
95
99
|
|
|
96
100
|
export const BINDING_NAME = '__announcementsRecorderBinding';
|
|
101
|
+
const MIN_MAIN_PANE_HEIGHT = 150;
|
|
102
|
+
const KEYBOARD_RESIZE_STEP = 10;
|
|
103
|
+
let isDragging = false;
|
|
104
|
+
let resizeStartY = 0;
|
|
105
|
+
let resizeStartHeight = MIN_MAIN_PANE_HEIGHT;
|
|
106
|
+
|
|
107
|
+
function onResizerPointerDown(event: PointerEvent): void {
|
|
108
|
+
if (event.button !== 0) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const resizerEl = event.currentTarget as HTMLElement | null;
|
|
112
|
+
const mainPane = resizerEl?.parentElement?.querySelector<HTMLElement>('.announcements-main-pane');
|
|
113
|
+
if (!resizerEl || !mainPane) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
isDragging = true;
|
|
117
|
+
resizeStartY = event.clientY;
|
|
118
|
+
resizeStartHeight = mainPane.getBoundingClientRect().height;
|
|
119
|
+
try {
|
|
120
|
+
resizerEl.setPointerCapture(event.pointerId);
|
|
121
|
+
} catch {
|
|
122
|
+
// Pointer capture may fail on synthetic events in unit tests.
|
|
123
|
+
}
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function onResizerPointerMove(event: PointerEvent): void {
|
|
128
|
+
const resizerEl = event.currentTarget as HTMLElement | null;
|
|
129
|
+
if (!resizerEl || !isDragging) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const mainPane = resizerEl.parentElement?.querySelector<HTMLElement>('.announcements-main-pane');
|
|
133
|
+
if (!mainPane) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const delta = event.clientY - resizeStartY;
|
|
137
|
+
const newHeight = Math.max(MIN_MAIN_PANE_HEIGHT, resizeStartHeight + delta);
|
|
138
|
+
mainPane.style.height = `${newHeight}px`;
|
|
139
|
+
mainPane.style.flex = 'none';
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function onResizerPointerUp(event: PointerEvent): void {
|
|
143
|
+
isDragging = false;
|
|
144
|
+
const resizerEl = event.currentTarget as HTMLElement | null;
|
|
145
|
+
if (resizerEl) {
|
|
146
|
+
try {
|
|
147
|
+
if (resizerEl.hasPointerCapture(event.pointerId)) {
|
|
148
|
+
resizerEl.releasePointerCapture(event.pointerId);
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
// Ignored for synthetic events in unit tests.
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function onResizerKeyDown(event: KeyboardEvent): void {
|
|
157
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const resizerEl = event.currentTarget as HTMLElement | null;
|
|
161
|
+
const mainPane = resizerEl?.parentElement?.querySelector<HTMLElement>('.announcements-main-pane');
|
|
162
|
+
if (!mainPane) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
event.preventDefault();
|
|
166
|
+
const delta = event.key === 'ArrowDown' ? KEYBOARD_RESIZE_STEP : -KEYBOARD_RESIZE_STEP;
|
|
167
|
+
const currentHeight = mainPane.getBoundingClientRect().height;
|
|
168
|
+
const newHeight = Math.max(MIN_MAIN_PANE_HEIGHT, currentHeight + delta);
|
|
169
|
+
mainPane.style.height = `${newHeight}px`;
|
|
170
|
+
mainPane.style.flex = 'none';
|
|
171
|
+
}
|
|
97
172
|
|
|
98
173
|
export enum AnnouncementApi {
|
|
99
174
|
ARIA_LIVE = 'aria-live',
|
|
@@ -218,6 +293,23 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
218
293
|
@reveal-in-a11y-tree=${(e: CustomEvent<A11yAnnouncement>) => input.onRevealInA11yTree(e.detail)}>
|
|
219
294
|
</devtools-widget>
|
|
220
295
|
</div>
|
|
296
|
+
<div
|
|
297
|
+
class="announcements-resizer"
|
|
298
|
+
role="separator"
|
|
299
|
+
aria-orientation="horizontal"
|
|
300
|
+
aria-label=${i18nString(UIStrings.resizeAnnouncementsPane)}
|
|
301
|
+
title=${i18nString(UIStrings.resizeAnnouncementsPane)}
|
|
302
|
+
tabindex="0"
|
|
303
|
+
jslog=${VisualLogging.resizer('accessibility-announcements.resizer').track({
|
|
304
|
+
drag: true,
|
|
305
|
+
keydown: 'ArrowUp|ArrowDown',
|
|
306
|
+
})}
|
|
307
|
+
@pointerdown=${onResizerPointerDown}
|
|
308
|
+
@pointermove=${onResizerPointerMove}
|
|
309
|
+
@pointerup=${onResizerPointerUp}
|
|
310
|
+
@lostpointercapture=${onResizerPointerUp}
|
|
311
|
+
@keydown=${onResizerKeyDown}>
|
|
312
|
+
</div>
|
|
221
313
|
</div>`,
|
|
222
314
|
target);
|
|
223
315
|
// clang-format on
|
|
@@ -72,7 +72,7 @@ const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
72
72
|
}
|
|
73
73
|
<devtools-checkbox class="source-order-checkbox"
|
|
74
74
|
jslog=${VisualLogging.toggle().track({click: true})}
|
|
75
|
-
|
|
75
|
+
.checked=${Boolean(input.showSourceOrder)}
|
|
76
76
|
@change=${onShowSourceOrderChanged}>
|
|
77
77
|
${i18nString(UIStrings.showSourceOrder)}
|
|
78
78
|
</devtools-checkbox>
|