chrome-devtools-frontend 1.0.1704172 → 1.0.1706026

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.
Files changed (100) hide show
  1. package/AUTHORS +1 -0
  2. package/docs/architecture_of_devtools.md +1 -1
  3. package/docs/cookbook/localization.md +2 -2
  4. package/eslint.config.mjs +1 -0
  5. package/front_end/Images/src/nodejsHex.svg +28 -0
  6. package/front_end/core/common/README.md +4 -3
  7. package/front_end/core/sdk/CPUThrottlingManager.ts +14 -10
  8. package/front_end/core/sdk/DOMModel.ts +65 -20
  9. package/front_end/core/sdk/DebuggerModel.ts +0 -4
  10. package/front_end/core/sdk/PageResourceLoader.ts +12 -11
  11. package/front_end/core/sdk/SourceMap.ts +7 -5
  12. package/front_end/core/sdk/SourceMapFunctionRanges.ts +22 -37
  13. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +3 -3
  14. package/front_end/core/sdk/SourceMapScopesInfo.ts +50 -62
  15. package/front_end/entrypoints/formatter_actions/formatter_actions.ts +18 -0
  16. package/front_end/entrypoints/formatter_worker/Substitute.ts +9 -8
  17. package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +9 -4
  18. package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +140 -20
  19. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +16 -5
  20. package/front_end/entrypoints/inspector_main/nodeIcon.css +1 -1
  21. package/front_end/foundation/Universe.ts +9 -0
  22. package/front_end/generated/InspectorBackendCommands.ts +4 -3
  23. package/front_end/generated/protocol.ts +17 -1
  24. package/front_end/models/ai_assistance/AiConversation.ts +16 -3
  25. package/front_end/models/ai_assistance/skills/accessibility.md +8 -7
  26. package/front_end/models/formatter/FormatterWorkerPool.ts +14 -4
  27. package/front_end/models/javascript_metadata/NativeFunctions.ts +6 -2
  28. package/front_end/models/source_map_scopes/NamesResolver.ts +69 -42
  29. package/front_end/models/source_map_scopes/ScopeChainModel.ts +13 -45
  30. package/front_end/models/source_map_scopes/ScopeChainResolver.ts +101 -0
  31. package/front_end/models/source_map_scopes/source_map_scopes.ts +2 -0
  32. package/front_end/panels/application/BackgroundServiceView.ts +1 -0
  33. package/front_end/panels/application/components/AdsView.ts +6 -6
  34. package/front_end/panels/application/components/BackForwardCacheView.ts +1 -1
  35. package/front_end/panels/console/ConsolePrompt.ts +2 -1
  36. package/front_end/panels/elements/CSSRuleValidator.ts +3 -0
  37. package/front_end/panels/elements/ClassesPaneWidget.ts +4 -1
  38. package/front_end/panels/elements/LayoutPane.ts +17 -20
  39. package/front_end/panels/network/NetworkLogViewColumns.ts +10 -3
  40. package/front_end/panels/network/ShowMoreDetailsWidget.ts +1 -1
  41. package/front_end/panels/security/SecurityPanel.ts +14 -7
  42. package/front_end/panels/sources/BreakpointEditDialog.ts +13 -1
  43. package/front_end/panels/sources/DebuggerPlugin.ts +69 -58
  44. package/front_end/panels/sources/EditingLocationHistoryManager.ts +6 -6
  45. package/front_end/panels/sources/OpenFileQuickOpen.ts +2 -2
  46. package/front_end/panels/sources/Plugin.ts +3 -2
  47. package/front_end/panels/sources/ResourceOriginPlugin.ts +14 -17
  48. package/front_end/panels/sources/ScopeChainSidebarPane.ts +2 -2
  49. package/front_end/panels/sources/SourcesPanel.ts +1 -1
  50. package/front_end/panels/sources/SourcesView.ts +25 -82
  51. package/front_end/panels/sources/TabbedEditorContainer.ts +75 -21
  52. package/front_end/panels/sources/UISourceCodeFrame.ts +22 -13
  53. package/front_end/panels/sources/sourcesView.css +17 -27
  54. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +1 -0
  55. package/front_end/third_party/chromium/README.chromium +1 -1
  56. package/front_end/third_party/source-map-scopes-codec/README.chromium +2 -2
  57. package/front_end/third_party/source-map-scopes-codec/package/CONTRIBUTING.md +14 -1
  58. package/front_end/third_party/source-map-scopes-codec/package/README.md +8 -6
  59. package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts +4 -1
  60. package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts.map +1 -1
  61. package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts +3 -1
  62. package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts.map +1 -1
  63. package/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts.map +1 -1
  64. package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts +4 -3
  65. package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts.map +1 -1
  66. package/front_end/third_party/source-map-scopes-codec/package/deno.json +6 -2
  67. package/front_end/third_party/source-map-scopes-codec/package/package.json +1 -1
  68. package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js +18 -2
  69. package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js.map +1 -1
  70. package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.ts +22 -3
  71. package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js +33 -5
  72. package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js.map +1 -1
  73. package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.ts +41 -5
  74. package/front_end/third_party/source-map-scopes-codec/package/src/codec.js +0 -2
  75. package/front_end/third_party/source-map-scopes-codec/package/src/codec.js.map +1 -1
  76. package/front_end/third_party/source-map-scopes-codec/package/src/codec.ts +4 -3
  77. package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +99 -36
  78. package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +1 -1
  79. package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +143 -49
  80. package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js +3 -1
  81. package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js.map +1 -1
  82. package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.ts +3 -1
  83. package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +40 -18
  84. package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +1 -1
  85. package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +51 -21
  86. package/front_end/third_party/source-map-scopes-codec/package/src/scopes.ts +4 -3
  87. package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js +18 -4
  88. package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js.map +1 -1
  89. package/front_end/third_party/source-map-scopes-codec/package/src/vlq.ts +18 -4
  90. package/front_end/ui/comments/CommentOverlayManager.ts +23 -10
  91. package/front_end/ui/components/text_editor/javascript.ts +128 -52
  92. package/front_end/ui/legacy/README.md +12 -12
  93. package/front_end/ui/legacy/SearchableView.ts +125 -74
  94. package/front_end/ui/legacy/components/source_frame/FontView.ts +5 -5
  95. package/front_end/ui/legacy/components/source_frame/ImageView.ts +13 -13
  96. package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +2 -6
  97. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +3 -2
  98. package/mcp/mcp.ts +1 -0
  99. package/package.json +1 -1
  100. package/front_end/Images/nodeIcon.avif +0 -0
@@ -545,7 +545,8 @@ inspectorBackend.registerCommand("Emulation.setSafeAreaInsetsOverride", [{"name"
545
545
  inspectorBackend.registerCommand("Emulation.setVirtualKeyboardGeometryOverride", [{"name": "keyboardRect", "type": "object", "optional": true, "description": "", "typeRef": "DOM.Rect"}], [], "Overrides virtual keyboard geometry in CSS pixels, relative to the top-level viewport. The provided rect is used for navigator.virtualKeyboard.boundingRect, geometrychange events, and env(keyboard-inset-*) values on the inspected frame. The override applies independently of navigator.virtualKeyboard.overlaysContent so clients can preview overlay geometry without mutating page state. Values are rounded to the nearest CSS pixel. Omitting the rect clears the override.");
546
546
  inspectorBackend.registerEnum("Emulation.SetDeviceMetricsOverrideRequestScrollbarType", {Overlay: "overlay", Default: "default"});
547
547
  inspectorBackend.registerEnum("Emulation.SetDeviceMetricsOverrideRequestViewportMeta", {Enable: "enable", Default: "default"});
548
- inspectorBackend.registerCommand("Emulation.setDeviceMetricsOverride", [{"name": "width", "type": "number", "optional": false, "description": "Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override.", "typeRef": null}, {"name": "height", "type": "number", "optional": false, "description": "Overriding height value in pixels (minimum 0, maximum 10000000). 0 disables the override.", "typeRef": null}, {"name": "deviceScaleFactor", "type": "number", "optional": false, "description": "Overriding device scale factor value. 0 disables the override.", "typeRef": null}, {"name": "mobile", "type": "boolean", "optional": false, "description": "Whether to emulate mobile device. This includes viewport meta tag, overlay scrollbars, text autosizing and more.", "typeRef": null}, {"name": "scale", "type": "number", "optional": true, "description": "Scale to apply to resulting view image.", "typeRef": null}, {"name": "screenWidth", "type": "number", "optional": true, "description": "Overriding screen width value in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "screenHeight", "type": "number", "optional": true, "description": "Overriding screen height value in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "positionX", "type": "number", "optional": true, "description": "Overriding view X position on screen in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "positionY", "type": "number", "optional": true, "description": "Overriding view Y position on screen in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "dontSetVisibleSize", "type": "boolean", "optional": true, "description": "Do not set visible view size, rely upon explicit setVisibleSize call.", "typeRef": null}, {"name": "screenOrientation", "type": "object", "optional": true, "description": "Screen orientation override.", "typeRef": "Emulation.ScreenOrientation"}, {"name": "viewport", "type": "object", "optional": true, "description": "If set, the visible area of the page will be overridden to this viewport. This viewport change is not observed by the page, e.g. viewport-relative elements do not change positions.", "typeRef": "Page.Viewport"}, {"name": "displayFeature", "type": "object", "optional": true, "description": "If set, the display feature of a multi-segment screen. If not set, multi-segment support is turned-off. Deprecated, use Emulation.setDisplayFeaturesOverride.", "typeRef": "Emulation.DisplayFeature"}, {"name": "devicePosture", "type": "object", "optional": true, "description": "If set, the posture of a foldable device. If not set the posture is set to continuous. Deprecated, use Emulation.setDevicePostureOverride.", "typeRef": "Emulation.DevicePosture"}, {"name": "scrollbarType", "type": "string", "optional": true, "description": "Scrollbar type. Default: `default`.", "typeRef": "Emulation.SetDeviceMetricsOverrideRequestScrollbarType"}, {"name": "screenOrientationLockEmulation", "type": "boolean", "optional": true, "description": "If set to true, enables screen orientation lock emulation, which intercepts screen.orientation.lock() calls from the page and reports orientation changes via screenOrientationLockChanged events. This is useful for emulating mobile device orientation lock behavior in responsive design mode.", "typeRef": null}, {"name": "viewportMeta", "type": "string", "optional": true, "description": "Viewport meta tag behavior. Default: `default`. Note: if `mobile` is `true`, the viewport meta tag is always enabled.", "typeRef": "Emulation.SetDeviceMetricsOverrideRequestViewportMeta"}], [], "Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results).");
548
+ inspectorBackend.registerEnum("Emulation.SetDeviceMetricsOverrideRequestTextLayoutMode", {Mobile: "mobile", Default: "default"});
549
+ inspectorBackend.registerCommand("Emulation.setDeviceMetricsOverride", [{"name": "width", "type": "number", "optional": false, "description": "Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override.", "typeRef": null}, {"name": "height", "type": "number", "optional": false, "description": "Overriding height value in pixels (minimum 0, maximum 10000000). 0 disables the override.", "typeRef": null}, {"name": "deviceScaleFactor", "type": "number", "optional": false, "description": "Overriding device scale factor value. 0 disables the override.", "typeRef": null}, {"name": "mobile", "type": "boolean", "optional": false, "description": "Whether to emulate mobile device. This includes viewport meta tag, overlay scrollbars, text autosizing and more.", "typeRef": null}, {"name": "scale", "type": "number", "optional": true, "description": "Scale to apply to resulting view image.", "typeRef": null}, {"name": "screenWidth", "type": "number", "optional": true, "description": "Overriding screen width value in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "screenHeight", "type": "number", "optional": true, "description": "Overriding screen height value in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "positionX", "type": "number", "optional": true, "description": "Overriding view X position on screen in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "positionY", "type": "number", "optional": true, "description": "Overriding view Y position on screen in pixels (minimum 0, maximum 10000000).", "typeRef": null}, {"name": "dontSetVisibleSize", "type": "boolean", "optional": true, "description": "Do not set visible view size, rely upon explicit setVisibleSize call.", "typeRef": null}, {"name": "screenOrientation", "type": "object", "optional": true, "description": "Screen orientation override.", "typeRef": "Emulation.ScreenOrientation"}, {"name": "viewport", "type": "object", "optional": true, "description": "If set, the visible area of the page will be overridden to this viewport. This viewport change is not observed by the page, e.g. viewport-relative elements do not change positions.", "typeRef": "Page.Viewport"}, {"name": "displayFeature", "type": "object", "optional": true, "description": "If set, the display feature of a multi-segment screen. If not set, multi-segment support is turned-off. Deprecated, use Emulation.setDisplayFeaturesOverride.", "typeRef": "Emulation.DisplayFeature"}, {"name": "devicePosture", "type": "object", "optional": true, "description": "If set, the posture of a foldable device. If not set the posture is set to continuous. Deprecated, use Emulation.setDevicePostureOverride.", "typeRef": "Emulation.DevicePosture"}, {"name": "scrollbarType", "type": "string", "optional": true, "description": "Scrollbar type. Default: `default`.", "typeRef": "Emulation.SetDeviceMetricsOverrideRequestScrollbarType"}, {"name": "screenOrientationLockEmulation", "type": "boolean", "optional": true, "description": "If set to true, enables screen orientation lock emulation, which intercepts screen.orientation.lock() calls from the page and reports orientation changes via screenOrientationLockChanged events. This is useful for emulating mobile device orientation lock behavior in responsive design mode.", "typeRef": null}, {"name": "viewportMeta", "type": "string", "optional": true, "description": "Viewport meta tag behavior. Default: `default`. Note: if `mobile` is `true`, the viewport meta tag is always enabled.", "typeRef": "Emulation.SetDeviceMetricsOverrideRequestViewportMeta"}, {"name": "textLayoutMode", "type": "string", "optional": true, "description": "Text layout mode. Default: `default`. Note: if `mobile` is `true`, mobile text layout mode (text autosizing) is always enabled.", "typeRef": "Emulation.SetDeviceMetricsOverrideRequestTextLayoutMode"}], [], "Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results).");
549
550
  inspectorBackend.registerCommand("Emulation.setDevicePostureOverride", [{"name": "posture", "type": "object", "optional": false, "description": "", "typeRef": "Emulation.DevicePosture"}], [], "Start reporting the given posture value to the Device Posture API. This override can also be set in setDeviceMetricsOverride().");
550
551
  inspectorBackend.registerCommand("Emulation.clearDevicePostureOverride", [], [], "Clears a device posture override set with either setDeviceMetricsOverride() or setDevicePostureOverride() and starts using posture information from the platform again. Does nothing if no override is set.");
551
552
  inspectorBackend.registerCommand("Emulation.setDisplayFeaturesOverride", [{"name": "features", "type": "array", "optional": false, "description": "", "typeRef": "Emulation.DisplayFeature"}], [], "Start using the given display features to pupulate the Viewport Segments API. This override can also be set in setDeviceMetricsOverride().");
@@ -1240,7 +1241,7 @@ inspectorBackend.registerEvent("Preload.ruleSetUpdated", ["ruleSet"]);
1240
1241
  inspectorBackend.registerEvent("Preload.ruleSetRemoved", ["id"]);
1241
1242
  inspectorBackend.registerEvent("Preload.preloadEnabledStateUpdated", ["disabledByPreference", "disabledByDataSaver", "disabledByBatterySaver", "disabledByHoldbackPrefetchSpeculationRules", "disabledByHoldbackPrerenderSpeculationRules"]);
1242
1243
  inspectorBackend.registerEvent("Preload.prefetchStatusUpdated", ["key", "pipelineId", "initiatingFrameId", "prefetchUrl", "status", "prefetchStatus", "requestId"]);
1243
- inspectorBackend.registerEvent("Preload.prerenderStatusUpdated", ["key", "pipelineId", "status", "prerenderStatus", "disallowedMojoInterface", "mismatchedHeaders"]);
1244
+ inspectorBackend.registerEvent("Preload.prerenderStatusUpdated", ["key", "pipelineId", "status", "effectiveAction", "prerenderStatus", "disallowedMojoInterface", "mismatchedHeaders"]);
1244
1245
  inspectorBackend.registerEvent("Preload.preloadingAttemptSourcesUpdated", ["loaderId", "preloadingAttemptSources"]);
1245
1246
  inspectorBackend.registerCommand("Preload.enable", [], [], "");
1246
1247
  inspectorBackend.registerCommand("Preload.disable", [], [], "");
@@ -1563,7 +1564,7 @@ inspectorBackend.registerType("Debugger.Location", [{"name": "scriptId", "type":
1563
1564
  inspectorBackend.registerType("Debugger.ScriptPosition", [{"name": "lineNumber", "type": "number", "optional": false, "description": "", "typeRef": null}, {"name": "columnNumber", "type": "number", "optional": false, "description": "", "typeRef": null}]);
1564
1565
  inspectorBackend.registerType("Debugger.LocationRange", [{"name": "scriptId", "type": "string", "optional": false, "description": "", "typeRef": "Runtime.ScriptId"}, {"name": "start", "type": "object", "optional": false, "description": "", "typeRef": "Debugger.ScriptPosition"}, {"name": "end", "type": "object", "optional": false, "description": "", "typeRef": "Debugger.ScriptPosition"}]);
1565
1566
  inspectorBackend.registerType("Debugger.CallFrame", [{"name": "callFrameId", "type": "string", "optional": false, "description": "Call frame identifier. This identifier is only valid while the virtual machine is paused.", "typeRef": "Debugger.CallFrameId"}, {"name": "functionName", "type": "string", "optional": false, "description": "Name of the JavaScript function called on this call frame.", "typeRef": null}, {"name": "functionLocation", "type": "object", "optional": true, "description": "Location in the source code.", "typeRef": "Debugger.Location"}, {"name": "location", "type": "object", "optional": false, "description": "Location in the source code.", "typeRef": "Debugger.Location"}, {"name": "url", "type": "string", "optional": false, "description": "JavaScript script name or url. Deprecated in favor of using the `location.scriptId` to resolve the URL via a previously sent `Debugger.scriptParsed` event.", "typeRef": null}, {"name": "scopeChain", "type": "array", "optional": false, "description": "Scope chain for this call frame.", "typeRef": "Debugger.Scope"}, {"name": "this", "type": "object", "optional": false, "description": "`this` object for this call frame.", "typeRef": "Runtime.RemoteObject"}, {"name": "returnValue", "type": "object", "optional": true, "description": "The value being returned, if the function is at return point.", "typeRef": "Runtime.RemoteObject"}, {"name": "canBeRestarted", "type": "boolean", "optional": true, "description": "Valid only while the VM is paused and indicates whether this frame can be restarted or not. Note that a `true` value here does not guarantee that Debugger#restartFrame with this CallFrameId will be successful, but it is very likely.", "typeRef": null}]);
1566
- inspectorBackend.registerType("Debugger.Scope", [{"name": "type", "type": "string", "optional": false, "description": "Scope type.", "typeRef": null}, {"name": "object", "type": "object", "optional": false, "description": "Object representing the scope. For `global` and `with` scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties.", "typeRef": "Runtime.RemoteObject"}, {"name": "name", "type": "string", "optional": true, "description": "", "typeRef": null}, {"name": "startLocation", "type": "object", "optional": true, "description": "Location in the source code where scope starts", "typeRef": "Debugger.Location"}, {"name": "endLocation", "type": "object", "optional": true, "description": "Location in the source code where scope ends", "typeRef": "Debugger.Location"}, {"name": "empty", "type": "boolean", "optional": true, "description": "True if the scope does not declare any variables or have a runtime context. Only present if true. Empty scopes are retained in the scope chain because they can be targeted via `evaluateOnCallFrame` (using `scopeNumber`) or matched against scopes in source maps.", "typeRef": null}]);
1567
+ inspectorBackend.registerType("Debugger.Scope", [{"name": "type", "type": "string", "optional": false, "description": "Scope type.", "typeRef": null}, {"name": "object", "type": "object", "optional": false, "description": "Object representing the scope. For `global` and `with` scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties.", "typeRef": "Runtime.RemoteObject"}, {"name": "name", "type": "string", "optional": true, "description": "", "typeRef": null}, {"name": "startLocation", "type": "object", "optional": true, "description": "Location in the source code where scope starts", "typeRef": "Debugger.Location"}, {"name": "endLocation", "type": "object", "optional": true, "description": "Location in the source code where scope ends", "typeRef": "Debugger.Location"}, {"name": "empty", "type": "boolean", "optional": true, "description": "True if the scope does not declare any variables. Only present if true. Empty scopes are retained in the scope chain because they can be targeted via `evaluateOnCallFrame` (using `scopeNumber`) or matched against scopes in source maps.", "typeRef": null}]);
1567
1568
  inspectorBackend.registerType("Debugger.SearchMatch", [{"name": "lineNumber", "type": "number", "optional": false, "description": "Line number in resource content.", "typeRef": null}, {"name": "lineContent", "type": "string", "optional": false, "description": "Line with match content.", "typeRef": null}]);
1568
1569
  inspectorBackend.registerType("Debugger.BreakLocation", [{"name": "scriptId", "type": "string", "optional": false, "description": "Script identifier as reported in the `Debugger.scriptParsed`.", "typeRef": "Runtime.ScriptId"}, {"name": "lineNumber", "type": "number", "optional": false, "description": "Line number in the script (0-based).", "typeRef": null}, {"name": "columnNumber", "type": "number", "optional": true, "description": "Column number in the script (0-based).", "typeRef": null}, {"name": "type", "type": "string", "optional": true, "description": "", "typeRef": null}]);
1569
1570
  inspectorBackend.registerType("Debugger.WasmDisassemblyChunk", [{"name": "lines", "type": "array", "optional": false, "description": "The next chunk of disassembled lines.", "typeRef": "string"}, {"name": "bytecodeOffsets", "type": "array", "optional": false, "description": "The bytecode offsets describing the start of each line.", "typeRef": "integer"}]);
@@ -7517,6 +7517,11 @@ export namespace Emulation {
7517
7517
  Default = 'default',
7518
7518
  }
7519
7519
 
7520
+ export const enum SetDeviceMetricsOverrideRequestTextLayoutMode {
7521
+ Mobile = 'mobile',
7522
+ Default = 'default',
7523
+ }
7524
+
7520
7525
  export interface SetDeviceMetricsOverrideRequest {
7521
7526
  /**
7522
7527
  * Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override.
@@ -7599,6 +7604,11 @@ export namespace Emulation {
7599
7604
  * the viewport meta tag is always enabled.
7600
7605
  */
7601
7606
  viewportMeta?: SetDeviceMetricsOverrideRequestViewportMeta;
7607
+ /**
7608
+ * Text layout mode. Default: `default`. Note: if `mobile` is `true`,
7609
+ * mobile text layout mode (text autosizing) is always enabled.
7610
+ */
7611
+ textLayoutMode?: SetDeviceMetricsOverrideRequestTextLayoutMode;
7602
7612
  }
7603
7613
 
7604
7614
  export interface SetDevicePostureOverrideRequest {
@@ -17557,6 +17567,12 @@ export namespace Preload {
17557
17567
  key: PreloadingAttemptKey;
17558
17568
  pipelineId: PreloadPipelineId;
17559
17569
  status: PreloadingStatus;
17570
+ /**
17571
+ * The action currently performed by this attempt. This differs from
17572
+ * `key.action` after a prerender-until-script attempt is upgraded in place
17573
+ * to a full prerender.
17574
+ */
17575
+ effectiveAction?: SpeculationAction;
17560
17576
  prerenderStatus?: PrerenderFinalStatus;
17561
17577
  /**
17562
17578
  * This is used to give users more information about the name of Mojo interface
@@ -20728,7 +20744,7 @@ export namespace Debugger {
20728
20744
  */
20729
20745
  endLocation?: Location;
20730
20746
  /**
20731
- * True if the scope does not declare any variables or have a runtime context.
20747
+ * True if the scope does not declare any variables.
20732
20748
  * Only present if true.
20733
20749
  * Empty scopes are retained in the scope chain because
20734
20750
  * they can be targeted via `evaluateOnCallFrame` (using `scopeNumber`) or
@@ -1,6 +1,7 @@
1
1
  // Copyright 2024 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
+ import type * as Common from '../../core/common/common.js';
4
5
  import * as Host from '../../core/host/host.js';
5
6
  import * as Platform from '../../core/platform/platform.js';
6
7
  import * as Root from '../../core/root/root.js';
@@ -435,11 +436,16 @@ export class AiConversation {
435
436
  ): AsyncGenerator<ResponseData, void, void> {
436
437
  this.#navigationOccurredDuringRun = false;
437
438
  const originAtRunStart = this.#origin ?? getPrimaryPageSecurityOrigin(this.#targetManager);
438
- const listener = (): void => {
439
+ const listener = (event: Common.EventTarget.EventTargetEvent<
440
+ SDK.ResourceTreeModel.EventTypes[SDK.ResourceTreeModel.Events.PrimaryPageChanged]>): void => {
439
441
  // Prevent the agent from executing tools or reading data from an untrusted origin
440
442
  // if the page navigates unexpectedly during execution.
441
- const newInspectedURL = this.#targetManager.primaryPageTarget()?.inspectedURL();
442
- const newOrigin = newInspectedURL ? SDK.SecurityOrigin.SecurityOrigin.create(newInspectedURL) : undefined;
443
+ const frame = event.data.frame;
444
+ if (frame.resourceTreeModel().target() !== this.#targetManager.primaryPageTarget()) {
445
+ return;
446
+ }
447
+ const newOrigin = frame.securityOrigin();
448
+ const newInspectedURL = frame.url;
443
449
  const isSameOrigin = Boolean(originAtRunStart && newOrigin && originAtRunStart.isSameOriginWith(newOrigin));
444
450
  const isAllowedNavigation =
445
451
  Boolean(newInspectedURL && ALLOWED_PAGE_NAVIGATIONS.some(allowed => newInspectedURL.startsWith(allowed)));
@@ -608,6 +614,9 @@ function isAiAssistanceServerSideLoggingAllowed(): boolean {
608
614
  /**
609
615
  * Returns the security origin of the primary page target.
610
616
  *
617
+ * Resolves the canonical SecurityOrigin from the main frame, falling back to
618
+ * the inspected URL as a last resort in test environments where no frame exists.
619
+ *
611
620
  * @param targetManager Target manager used to locate the primary page target.
612
621
  * @returns The parsed SecurityOrigin, or undefined if no target or inspected URL exists.
613
622
  */
@@ -615,6 +624,10 @@ function getPrimaryPageSecurityOrigin(
615
624
  targetManager: SDK.TargetManager.TargetManager,
616
625
  ): SDK.SecurityOrigin.SecurityOrigin|undefined {
617
626
  const target = targetManager.primaryPageTarget();
627
+ const frameOrigin = target?.model(SDK.ResourceTreeModel.ResourceTreeModel)?.mainFrame?.securityOrigin();
628
+ if (frameOrigin) {
629
+ return frameOrigin;
630
+ }
618
631
  const inspectedURL = target?.inspectedURL();
619
632
  return inspectedURL ? SDK.SecurityOrigin.SecurityOrigin.create(inspectedURL) : undefined;
620
633
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: accessibility
3
- description: Accessibility audits, ARIA properties, accessible tree inspection, color contrast, and screen reader semantics.
3
+ description: Accessibility audits, running Lighthouse accessibility audits and reports, ARIA properties, accessible tree inspection, color contrast, and screen reader semantics.
4
4
  allowed-tools:
5
5
  - getLighthouseAudits
6
6
  - resolveDevtoolsNodePath
@@ -19,12 +19,13 @@ You are an expert accessibility debugging assistant.
19
19
  - Use `getStyles` on the backend node ID to inspect layout, color contrast, or font properties.
20
20
 
21
21
  2. **Lighthouse Accessibility Audits (`getLighthouseAudits` & `runLighthouse`)**:
22
- - If an active Lighthouse report context exists, query it via `getLighthouseAudits` with `categoryId: 'accessibility'`.
23
- - If no active report exists or new audits are needed, use `runLighthouse` with `categoryId: 'accessibility'`:
24
- - Use `"navigation"` mode for full page-load audits.
25
- - Use `"snapshot"` mode to re-evaluate live in-page DOM/CSS modifications without reloading.
26
- - Use `"timespan"` mode for user interaction flows.
27
- - Always honor explicit mode requests from the user.
22
+ - If the user asks for a Lighthouse audit or report (such as recording a report or checking accessibility scores), or if audits are needed:
23
+ - If an active Lighthouse report context already exists and no fresh audit is requested, query it via `getLighthouseAudits` with `categoryId: 'accessibility'`.
24
+ - If no active report exists or a fresh audit is requested, use `runLighthouse` with `categoryId: 'accessibility'`:
25
+ - Use `"navigation"` mode for full page-load audits.
26
+ - Use `"snapshot"` mode to re-evaluate live in-page DOM/CSS modifications without reloading.
27
+ - Use `"timespan"` mode for user interaction flows.
28
+ - Always honor explicit mode requests from the user.
28
29
  - When an audit references failing elements by DevTools node path (e.g. `"1,HTML,1,BODY,2,BUTTON"`), use `resolveDevtoolsNodePath` to resolve the path to a `backendNodeId`, then call `getElementAccessibilityDetails` or `getStyles`.
29
30
 
30
31
  3. **Dynamic Interaction Verification (`executeJavaScript`)**:
@@ -5,7 +5,12 @@
5
5
  import * as Platform from '../../core/platform/platform.js';
6
6
  import * as FormatterActions from '../../entrypoints/formatter_actions/formatter_actions.js';
7
7
 
8
- export {DefinitionKind, ScopeKind, type ScopeTreeNode} from '../../entrypoints/formatter_actions/formatter_actions.js';
8
+ export {
9
+ DefinitionKind,
10
+ ScopeKind,
11
+ type ScopeTreeNode,
12
+ type ScopeVariableMapping,
13
+ } from '../../entrypoints/formatter_actions/formatter_actions.js';
9
14
 
10
15
  let formatterWorkerPoolInstance: FormatterWorkerPool|undefined;
11
16
 
@@ -134,12 +139,17 @@ export class FormatterWorkerPool {
134
139
  return this.runTask(FormatterActions.FormatterActions.FORMAT, parameters) as Promise<FormatterActions.FormatResult>;
135
140
  }
136
141
 
137
- javaScriptSubstitute(expression: string, mapping: Array<Map<string, string|null>>): Promise<string> {
138
- if (mapping.every(m => m.size === 0)) {
142
+ javaScriptSubstitute(expression: string, mapping: FormatterActions.ScopeVariableMapping[]): Promise<string> {
143
+ if (mapping.every(scope => scope.bindings.size === 0)) {
139
144
  return Promise.resolve(expression);
140
145
  }
141
146
  return this.runTask(FormatterActions.FormatterActions.JAVASCRIPT_SUBSTITUTE, {content: expression, mapping})
142
- .then(result => result || '');
147
+ .then((result: string|{error: string}|null) => {
148
+ if (result && typeof result === 'object') {
149
+ throw new Error(result.error);
150
+ }
151
+ return result || '';
152
+ });
143
153
  }
144
154
 
145
155
  javaScriptScopeTree(expression: string, sourceType: 'module'|'script' = 'script'):
@@ -8972,11 +8972,15 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
8972
8972
  signatures: [["type","?eventInitDict"]]
8973
8973
  },
8974
8974
  {
8975
- name: "TouchEvent",
8975
+ name: "ToolActivatedEvent",
8976
8976
  signatures: [["type","?eventInitDict"]]
8977
8977
  },
8978
8978
  {
8979
- name: "WebMCPEvent",
8979
+ name: "ToolCancelEvent",
8980
+ signatures: [["type","?eventInitDict"]]
8981
+ },
8982
+ {
8983
+ name: "TouchEvent",
8980
8984
  signatures: [["type","?eventInitDict"]]
8981
8985
  },
8982
8986
  {
@@ -9,13 +9,25 @@ import * as Protocol from '../../generated/protocol.js';
9
9
  import type * as Bindings from '../bindings/bindings.js';
10
10
  import * as Formatter from '../formatter/formatter.js';
11
11
 
12
+ /**
13
+ * The result of resolving a generated scope via the source map's mappings/names.
14
+ */
15
+ interface ResolvedScope {
16
+ /** Generated name -> authored name, for generated names that we could map. */
17
+ variableMapping: Map<string, string>;
18
+ thisMapping: string|null;
19
+ /** All generated names declared by the scope, including ones that we couldn't map. */
20
+ generatedNames: string[];
21
+ }
22
+
12
23
  interface CachedScopeMap {
13
24
  sourceMap: SDK.SourceMap.SourceMap|undefined;
14
- mappingPromise: Promise<{variableMapping: Map<string, string>, thisMapping: string|null}>;
25
+ mappingPromise: Promise<ResolvedScope>;
15
26
  }
16
27
 
17
28
  const scopeToCachedIdentifiersMap = new WeakMap<Formatter.FormatterWorkerPool.ScopeTreeNode, CachedScopeMap>();
18
- const cachedMapByCallFrame = new WeakMap<SDK.DebuggerModel.CallFrame, Array<Map<string, string|null>>>();
29
+ const cachedMapByCallFrame =
30
+ new WeakMap<SDK.DebuggerModel.CallFrame, Formatter.FormatterWorkerPool.ScopeVariableMapping[]>();
19
31
 
20
32
  export async function getTextFor(contentProvider: TextUtils.ContentProvider.ContentProvider):
21
33
  Promise<TextUtils.Text.Text|null> {
@@ -193,13 +205,13 @@ const enum Punctuation {
193
205
  const resolveDebuggerScope =
194
206
  async(scope: SDK.DebuggerModel.ScopeChainEntry,
195
207
  debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding):
196
- Promise<{variableMapping: Map<string, string>, thisMapping: string | null}> => {
208
+ Promise<ResolvedScope> => {
197
209
  if (!scope.callFrame()
198
210
  .debuggerModel.target()
199
211
  .targetManager()
200
212
  .settings.resolve(SDK.SDKSettings.jsSourceMapsEnabledSettingDescriptor)
201
213
  .get()) {
202
- return {variableMapping: new Map(), thisMapping: null};
214
+ return {variableMapping: new Map(), thisMapping: null, generatedNames: []};
203
215
  }
204
216
  const script = scope.callFrame().script;
205
217
  const scopeChain = await findScopeChainForDebuggerScope(scope);
@@ -208,10 +220,10 @@ const resolveDebuggerScope =
208
220
 
209
221
  const resolveScope = async(script: SDK.Script.Script, scopeChain: Formatter.FormatterWorkerPool.ScopeTreeNode[],
210
222
  debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding):
211
- Promise<{variableMapping: Map<string, string>, thisMapping: string | null}> => {
223
+ Promise<ResolvedScope> => {
212
224
  const parsedScope = scopeChain[scopeChain.length - 1];
213
225
  if (!parsedScope) {
214
- return {variableMapping: new Map<string, string>(), thisMapping: null};
226
+ return {variableMapping: new Map<string, string>(), thisMapping: null, generatedNames: []};
215
227
  }
216
228
  let cachedScopeMap = scopeToCachedIdentifiersMap.get(parsedScope);
217
229
  const sourceMap = script.sourceMap();
@@ -223,7 +235,7 @@ const resolveScope = async(script: SDK.Script.Script, scopeChain: Formatter.Form
223
235
  let thisMapping = null;
224
236
 
225
237
  if (!sourceMap) {
226
- return {variableMapping, thisMapping};
238
+ return {variableMapping, thisMapping, generatedNames: []};
227
239
  }
228
240
  // Extract as much as possible from SourceMap and resolve
229
241
  // missing identifier names from SourceMap ranges.
@@ -261,7 +273,7 @@ const resolveScope = async(script: SDK.Script.Script, scopeChain: Formatter.Form
261
273
 
262
274
  const parsedVariables = await scopeIdentifiers(script, parsedScope, scopeChain.slice(0, -1));
263
275
  if (!parsedVariables) {
264
- return {variableMapping, thisMapping};
276
+ return {variableMapping, thisMapping, generatedNames: []};
265
277
  }
266
278
  for (const id of parsedVariables.boundVariables) {
267
279
  resolveEntry(id, sourceName => {
@@ -279,7 +291,8 @@ const resolveScope = async(script: SDK.Script.Script, scopeChain: Formatter.Form
279
291
  });
280
292
  }
281
293
  await Promise.all(promises).then(getScopeResolvedForTest());
282
- return {variableMapping, thisMapping};
294
+ const generatedNames = parsedVariables.boundVariables.map(id => id.name);
295
+ return {variableMapping, thisMapping, generatedNames};
283
296
  })();
284
297
  cachedScopeMap = {sourceMap, mappingPromise: identifiersPromise};
285
298
  scopeToCachedIdentifiersMap.set(parsedScope, {sourceMap, mappingPromise: identifiersPromise});
@@ -395,31 +408,46 @@ export const resolveScopeChain =
395
408
  }
396
409
 
397
410
  if (callFrame.script.isWasm()) {
398
- return callFrame.scopeChain().filter(scope => !scope.empty());
411
+ return callFrame.scopeChain();
399
412
  }
400
413
  const thisObject = await resolveThisObject(callFrame, debuggerWorkspaceBinding);
401
- const scopes = callFrame.scopeChain().filter(scope => !scope.empty() ||
402
- scope.type() === Protocol.Debugger.ScopeType.Local);
403
- return scopes.map(scope => new ScopeWithSourceMappedVariables(scope, thisObject, debuggerWorkspaceBinding));
414
+ return callFrame.scopeChain().map(
415
+ scope => new ScopeWithSourceMappedVariables(scope, thisObject, debuggerWorkspaceBinding));
404
416
  };
405
417
 
406
- function reverseScopeMapping(variableMapping: Map<string, string>): Map<string, string|null> {
407
- const result = new Map<string, string|null>();
408
- for (const [compiledName, originalName] of variableMapping) {
409
- if (originalName && !result.has(originalName)) {
410
- result.set(originalName, compiledName);
418
+ /**
419
+ * Converts the generated name -> authored name mapping of a resolved scope into the
420
+ * authored name -> generated name form expected by `javaScriptSubstitute`.
421
+ */
422
+ function toScopeVariableMapping({variableMapping, generatedNames}: ResolvedScope):
423
+ Formatter.FormatterWorkerPool.ScopeVariableMapping {
424
+ const bindings = new Map<string, string|null>();
425
+ for (const [generatedName, authoredName] of variableMapping) {
426
+ // Multiple generated names can map to the same authored name. We pick the first one. The worker still
427
+ // learns about the others via `generatedNames`, which it needs to detect shadowing of outer bindings.
428
+ if (authoredName && !bindings.has(authoredName)) {
429
+ bindings.set(authoredName, generatedName);
411
430
  }
412
431
  }
413
- return result;
432
+ return {bindings, generatedNames};
433
+ }
434
+
435
+ /**
436
+ * Source map scopes don't tell us which generated names a generated range declares. The worker falls back
437
+ * to the free identifiers of the binding expressions in that case.
438
+ */
439
+ function fromSourceMapScopes(mappedVariables: Array<Map<string, string|null>>):
440
+ Formatter.FormatterWorkerPool.ScopeVariableMapping[] {
441
+ return mappedVariables.map(bindings => ({bindings, generatedNames: []}));
414
442
  }
415
443
 
416
444
  /**
417
- * @returns An array of mappings (from inner-most to outer-most scope) of original name -> compiled name or binding expression.
445
+ * @returns An array of scopes (from inner-most to outer-most) with their original name -> compiled name or binding expression mappings.
418
446
  */
419
447
  export const allVariablesInCallFrame = async(
420
448
  callFrame: SDK.DebuggerModel.CallFrame,
421
449
  debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding):
422
- Promise<Array<Map<string, string|null>>> => {
450
+ Promise<Formatter.FormatterWorkerPool.ScopeVariableMapping[]> => {
423
451
  if (!callFrame.debuggerModel.target()
424
452
  .targetManager()
425
453
  .settings.resolve(SDK.SDKSettings.jsSourceMapsEnabledSettingDescriptor)
@@ -437,36 +465,37 @@ export const allVariablesInCallFrame = async(
437
465
  const mappedVariables =
438
466
  sourceMap?.resolveMappedVariablesAtPosition(callFrame.location(), callFrame.returnValue() !== null);
439
467
  if (mappedVariables) {
440
- cachedMapByCallFrame.set(callFrame, mappedVariables);
441
- return mappedVariables;
468
+ const result = fromSourceMapScopes(mappedVariables);
469
+ cachedMapByCallFrame.set(callFrame, result);
470
+ return result;
442
471
  }
443
472
  }
444
473
 
445
- const scopeChain = callFrame.scopeChain().filter(scope => !scope.empty());
446
- const nameMappings =
474
+ const scopeChain = callFrame.scopeChain();
475
+ const resolvedScopes =
447
476
  await Promise.all(scopeChain.map(scope => resolveDebuggerScope(scope, debuggerWorkspaceBinding)));
448
- const reverseMapping = nameMappings.map(({variableMapping}) => reverseScopeMapping(variableMapping));
449
- cachedMapByCallFrame.set(callFrame, reverseMapping);
450
- return reverseMapping;
477
+ const result = resolvedScopes.map(toScopeVariableMapping);
478
+ cachedMapByCallFrame.set(callFrame, result);
479
+ return result;
451
480
  };
452
481
 
453
482
  /**
454
- * @returns An array of mappings (from inner-most to outer-most scope) of original name -> compiled name or binding expression.
483
+ * @returns An array of scopes (from inner-most to outer-most) with their original name -> compiled name or binding expression mappings.
455
484
  */
456
485
  export const allVariablesAtPosition =
457
486
  async(location: SDK.DebuggerModel.Location,
458
487
  debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding):
459
- Promise<Array<Map<string, string|null>>> => {
460
- const reverseMapping: Array<Map<string, string|null>> = [];
488
+ Promise<Formatter.FormatterWorkerPool.ScopeVariableMapping[]> => {
489
+ const result: Formatter.FormatterWorkerPool.ScopeVariableMapping[] = [];
461
490
  const script = location.script();
462
491
  if (!script) {
463
- return reverseMapping;
492
+ return result;
464
493
  }
465
494
  if (!script.debuggerModel.target()
466
495
  .targetManager()
467
496
  .settings.resolve(SDK.SDKSettings.jsSourceMapsEnabledSettingDescriptor)
468
497
  .get()) {
469
- return reverseMapping;
498
+ return result;
470
499
  }
471
500
 
472
501
  if (Root.Runtime.hostConfig.devToolsSourceMapScopesInSourcesPanel?.enabled) {
@@ -474,13 +503,13 @@ export const allVariablesAtPosition =
474
503
  script.sourceMap() ?? await script.debuggerModel.sourceMapManager().sourceMapForClientPromise(script);
475
504
  const mappedVariables = sourceMap?.resolveMappedVariablesAtPosition(location);
476
505
  if (mappedVariables) {
477
- return mappedVariables;
506
+ return fromSourceMapScopes(mappedVariables);
478
507
  }
479
508
  }
480
509
 
481
510
  const scopeTreeAndText = await computeScopeTree(script);
482
511
  if (!scopeTreeAndText) {
483
- return reverseMapping;
512
+ return result;
484
513
  }
485
514
 
486
515
  const {scopeTree, text} = scopeTreeAndText;
@@ -489,24 +518,22 @@ export const allVariablesAtPosition =
489
518
  const scopeChain = findScopeChain(scopeTree, {start: locationOffset, end: locationOffset});
490
519
 
491
520
  while (scopeChain.length > 0) {
492
- const {variableMapping} = await resolveScope(script, scopeChain, debuggerWorkspaceBinding);
493
- reverseMapping.push(reverseScopeMapping(variableMapping));
521
+ result.push(toScopeVariableMapping(await resolveScope(script, scopeChain, debuggerWorkspaceBinding)));
494
522
  scopeChain.pop();
495
523
  }
496
- return reverseMapping;
524
+ return result;
497
525
  };
498
526
 
499
527
  export const resolveThisObject = async(
500
528
  callFrame: SDK.DebuggerModel.CallFrame,
501
529
  debuggerWorkspaceBinding:
502
530
  Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding): Promise<SDK.RemoteObject.RemoteObject|null> => {
503
- const innermostScope =
504
- callFrame.scopeChain().find(scope => !scope.empty() || scope.type() === Protocol.Debugger.ScopeType.Local);
505
- if (!innermostScope) {
531
+ const scopeChain = callFrame.scopeChain();
532
+ if (scopeChain.length === 0) {
506
533
  return callFrame.thisObject();
507
534
  }
508
535
 
509
- const {thisMapping} = await resolveDebuggerScope(innermostScope, debuggerWorkspaceBinding);
536
+ const {thisMapping} = await resolveDebuggerScope(scopeChain[0], debuggerWorkspaceBinding);
510
537
  if (!thisMapping) {
511
538
  return callFrame.thisObject();
512
539
  }
@@ -3,10 +3,9 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
- import * as SDK from '../../core/sdk/sdk.js';
7
- import type * as Bindings from '../bindings/bindings.js';
6
+ import type * as SDK from '../../core/sdk/sdk.js';
8
7
 
9
- import {resolveScopeChain} from './NamesResolver.js';
8
+ import {Events as ScopeChainResolverEvents, type ScopeChainResolver} from './ScopeChainResolver.js';
10
9
 
11
10
  /**
12
11
  * This class is responsible for resolving / updating the scope chain for a specific {@link SDK.DebuggerModel.CallFrame}
@@ -18,57 +17,35 @@ import {resolveScopeChain} from './NamesResolver.js';
18
17
  *
19
18
  * Source maps can be enabled/disabled dynamically and debugger plugins can attach debug info after the fact.
20
19
  *
21
- * This class tracks all that and sends events with the latest scope chain for a specific call frame.
20
+ * The {@link ScopeChainResolver} tracks all that and invalidates its cache accordingly. This class
21
+ * sends events with the latest scope chain for a specific call frame.
22
22
  */
23
23
  export class ScopeChainModel extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
24
- static readonly #cachedScopeChainByCallFrame =
25
- new WeakMap<SDK.DebuggerModel.CallFrame, Promise<SDK.DebuggerModel.ScopeChainEntry[]>>();
26
-
27
24
  readonly #callFrame: SDK.DebuggerModel.CallFrame;
28
- readonly #debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding;
25
+ readonly #scopeChainResolver: ScopeChainResolver;
29
26
 
30
27
  /** We use the `Throttler` here to make sure that `#boundUpdate` is not run multiple times simultanously */
31
28
  readonly #throttler = new Common.Throttler.Throttler(5);
32
29
  readonly #boundUpdate = this.#update.bind(this);
33
30
 
34
- constructor(callFrame: SDK.DebuggerModel.CallFrame,
35
- debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding) {
31
+ constructor(callFrame: SDK.DebuggerModel.CallFrame, scopeChainResolver: ScopeChainResolver) {
36
32
  super();
37
33
  this.#callFrame = callFrame;
38
- this.#debuggerWorkspaceBinding = debuggerWorkspaceBinding;
39
- this.#callFrame.debuggerModel.addEventListener(
40
- SDK.DebuggerModel.Events.DebugInfoAttached, this.#debugInfoAttached, this);
41
- this.#callFrame.debuggerModel.sourceMapManager().addEventListener(SDK.SourceMapManager.Events.SourceMapAttached,
42
- this.#sourceMapChanged, this);
43
- this.#callFrame.debuggerModel.sourceMapManager().addEventListener(SDK.SourceMapManager.Events.SourceMapDetached,
44
- this.#sourceMapChanged, this);
34
+ this.#scopeChainResolver = scopeChainResolver;
35
+ this.#scopeChainResolver.addEventListener(ScopeChainResolverEvents.SCOPE_CHAIN_INVALIDATED,
36
+ this.#scopeChainInvalidated, this);
45
37
 
46
38
  void this.#throttler.schedule(this.#boundUpdate);
47
39
  }
48
40
 
49
41
  dispose(): void {
50
- this.#callFrame.debuggerModel.removeEventListener(
51
- SDK.DebuggerModel.Events.DebugInfoAttached, this.#debugInfoAttached, this);
52
- this.#callFrame.debuggerModel.sourceMapManager().removeEventListener(SDK.SourceMapManager.Events.SourceMapAttached,
53
- this.#sourceMapChanged, this);
54
- this.#callFrame.debuggerModel.sourceMapManager().removeEventListener(SDK.SourceMapManager.Events.SourceMapDetached,
55
- this.#sourceMapChanged, this);
42
+ this.#scopeChainResolver.removeEventListener(ScopeChainResolverEvents.SCOPE_CHAIN_INVALIDATED,
43
+ this.#scopeChainInvalidated, this);
56
44
  this.listeners?.clear();
57
45
  }
58
46
 
59
- static resolveScopeChain(callFrame: SDK.DebuggerModel.CallFrame,
60
- debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding):
61
- Promise<SDK.DebuggerModel.ScopeChainEntry[]> {
62
- let cachedPromise = ScopeChainModel.#cachedScopeChainByCallFrame.get(callFrame);
63
- if (!cachedPromise) {
64
- cachedPromise = resolveScopeChain(callFrame, debuggerWorkspaceBinding);
65
- ScopeChainModel.#cachedScopeChainByCallFrame.set(callFrame, cachedPromise);
66
- }
67
- return cachedPromise;
68
- }
69
-
70
47
  resolveScopeChain(): Promise<SDK.DebuggerModel.ScopeChainEntry[]> {
71
- return ScopeChainModel.resolveScopeChain(this.#callFrame, this.#debuggerWorkspaceBinding);
48
+ return this.#scopeChainResolver.resolveScopeChain(this.#callFrame);
72
49
  }
73
50
 
74
51
  async #update(): Promise<void> {
@@ -76,17 +53,8 @@ export class ScopeChainModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
76
53
  this.dispatchEventToListeners(Events.SCOPE_CHAIN_UPDATED, new ScopeChain(scopeChain));
77
54
  }
78
55
 
79
- #debugInfoAttached(event: Common.EventTarget.EventTargetEvent<SDK.Script.Script>): void {
56
+ #scopeChainInvalidated(event: Common.EventTarget.EventTargetEvent<SDK.Script.Script>): void {
80
57
  if (event.data === this.#callFrame.script) {
81
- ScopeChainModel.#cachedScopeChainByCallFrame.delete(this.#callFrame);
82
- void this.#throttler.schedule(this.#boundUpdate);
83
- }
84
- }
85
-
86
- #sourceMapChanged(event: Common.EventTarget
87
- .EventTargetEvent<{client: SDK.Script.Script, sourceMap: SDK.SourceMap.SourceMap}>): void {
88
- if (event.data.client === this.#callFrame.script) {
89
- ScopeChainModel.#cachedScopeChainByCallFrame.delete(this.#callFrame);
90
58
  void this.#throttler.schedule(this.#boundUpdate);
91
59
  }
92
60
  }