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.
- package/AUTHORS +1 -0
- package/docs/architecture_of_devtools.md +1 -1
- package/docs/cookbook/localization.md +2 -2
- package/eslint.config.mjs +1 -0
- package/front_end/Images/src/nodejsHex.svg +28 -0
- package/front_end/core/common/README.md +4 -3
- package/front_end/core/sdk/CPUThrottlingManager.ts +14 -10
- package/front_end/core/sdk/DOMModel.ts +65 -20
- package/front_end/core/sdk/DebuggerModel.ts +0 -4
- package/front_end/core/sdk/PageResourceLoader.ts +12 -11
- package/front_end/core/sdk/SourceMap.ts +7 -5
- package/front_end/core/sdk/SourceMapFunctionRanges.ts +22 -37
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +3 -3
- package/front_end/core/sdk/SourceMapScopesInfo.ts +50 -62
- package/front_end/entrypoints/formatter_actions/formatter_actions.ts +18 -0
- package/front_end/entrypoints/formatter_worker/Substitute.ts +9 -8
- package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +9 -4
- package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +140 -20
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +16 -5
- package/front_end/entrypoints/inspector_main/nodeIcon.css +1 -1
- package/front_end/foundation/Universe.ts +9 -0
- package/front_end/generated/InspectorBackendCommands.ts +4 -3
- package/front_end/generated/protocol.ts +17 -1
- package/front_end/models/ai_assistance/AiConversation.ts +16 -3
- package/front_end/models/ai_assistance/skills/accessibility.md +8 -7
- package/front_end/models/formatter/FormatterWorkerPool.ts +14 -4
- package/front_end/models/javascript_metadata/NativeFunctions.ts +6 -2
- package/front_end/models/source_map_scopes/NamesResolver.ts +69 -42
- package/front_end/models/source_map_scopes/ScopeChainModel.ts +13 -45
- package/front_end/models/source_map_scopes/ScopeChainResolver.ts +101 -0
- package/front_end/models/source_map_scopes/source_map_scopes.ts +2 -0
- package/front_end/panels/application/BackgroundServiceView.ts +1 -0
- package/front_end/panels/application/components/AdsView.ts +6 -6
- package/front_end/panels/application/components/BackForwardCacheView.ts +1 -1
- package/front_end/panels/console/ConsolePrompt.ts +2 -1
- package/front_end/panels/elements/CSSRuleValidator.ts +3 -0
- package/front_end/panels/elements/ClassesPaneWidget.ts +4 -1
- package/front_end/panels/elements/LayoutPane.ts +17 -20
- package/front_end/panels/network/NetworkLogViewColumns.ts +10 -3
- package/front_end/panels/network/ShowMoreDetailsWidget.ts +1 -1
- package/front_end/panels/security/SecurityPanel.ts +14 -7
- package/front_end/panels/sources/BreakpointEditDialog.ts +13 -1
- package/front_end/panels/sources/DebuggerPlugin.ts +69 -58
- package/front_end/panels/sources/EditingLocationHistoryManager.ts +6 -6
- package/front_end/panels/sources/OpenFileQuickOpen.ts +2 -2
- package/front_end/panels/sources/Plugin.ts +3 -2
- package/front_end/panels/sources/ResourceOriginPlugin.ts +14 -17
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +2 -2
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/SourcesView.ts +25 -82
- package/front_end/panels/sources/TabbedEditorContainer.ts +75 -21
- package/front_end/panels/sources/UISourceCodeFrame.ts +22 -13
- package/front_end/panels/sources/sourcesView.css +17 -27
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +1 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/source-map-scopes-codec/README.chromium +2 -2
- package/front_end/third_party/source-map-scopes-codec/package/CONTRIBUTING.md +14 -1
- package/front_end/third_party/source-map-scopes-codec/package/README.md +8 -6
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts +4 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/deno.json +6 -2
- package/front_end/third_party/source-map-scopes-codec/package/package.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js +18 -2
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.ts +22 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js +33 -5
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.ts +41 -5
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js +0 -2
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +99 -36
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +143 -49
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.ts +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +40 -18
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +51 -21
- package/front_end/third_party/source-map-scopes-codec/package/src/scopes.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js +18 -4
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.ts +18 -4
- package/front_end/ui/comments/CommentOverlayManager.ts +23 -10
- package/front_end/ui/components/text_editor/javascript.ts +128 -52
- package/front_end/ui/legacy/README.md +12 -12
- package/front_end/ui/legacy/SearchableView.ts +125 -74
- package/front_end/ui/legacy/components/source_frame/FontView.ts +5 -5
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +13 -13
- package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +2 -6
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +3 -2
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
- 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.
|
|
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
|
|
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
|
|
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 = (
|
|
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
|
|
442
|
-
|
|
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
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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 {
|
|
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:
|
|
138
|
-
if (mapping.every(
|
|
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
|
|
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: "
|
|
8975
|
+
name: "ToolActivatedEvent",
|
|
8976
8976
|
signatures: [["type","?eventInitDict"]]
|
|
8977
8977
|
},
|
|
8978
8978
|
{
|
|
8979
|
-
name: "
|
|
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<
|
|
25
|
+
mappingPromise: Promise<ResolvedScope>;
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
const scopeToCachedIdentifiersMap = new WeakMap<Formatter.FormatterWorkerPool.ScopeTreeNode, CachedScopeMap>();
|
|
18
|
-
const cachedMapByCallFrame =
|
|
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<
|
|
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<
|
|
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
|
-
|
|
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()
|
|
411
|
+
return callFrame.scopeChain();
|
|
399
412
|
}
|
|
400
413
|
const thisObject = await resolveThisObject(callFrame, debuggerWorkspaceBinding);
|
|
401
|
-
|
|
402
|
-
|
|
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
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
|
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
|
|
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<
|
|
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
|
-
|
|
441
|
-
|
|
468
|
+
const result = fromSourceMapScopes(mappedVariables);
|
|
469
|
+
cachedMapByCallFrame.set(callFrame, result);
|
|
470
|
+
return result;
|
|
442
471
|
}
|
|
443
472
|
}
|
|
444
473
|
|
|
445
|
-
const scopeChain = callFrame.scopeChain()
|
|
446
|
-
const
|
|
474
|
+
const scopeChain = callFrame.scopeChain();
|
|
475
|
+
const resolvedScopes =
|
|
447
476
|
await Promise.all(scopeChain.map(scope => resolveDebuggerScope(scope, debuggerWorkspaceBinding)));
|
|
448
|
-
const
|
|
449
|
-
cachedMapByCallFrame.set(callFrame,
|
|
450
|
-
return
|
|
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
|
|
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<
|
|
460
|
-
const
|
|
488
|
+
Promise<Formatter.FormatterWorkerPool.ScopeVariableMapping[]> => {
|
|
489
|
+
const result: Formatter.FormatterWorkerPool.ScopeVariableMapping[] = [];
|
|
461
490
|
const script = location.script();
|
|
462
491
|
if (!script) {
|
|
463
|
-
return
|
|
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
|
|
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
|
|
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
|
-
|
|
493
|
-
reverseMapping.push(reverseScopeMapping(variableMapping));
|
|
521
|
+
result.push(toScopeVariableMapping(await resolveScope(script, scopeChain, debuggerWorkspaceBinding)));
|
|
494
522
|
scopeChain.pop();
|
|
495
523
|
}
|
|
496
|
-
return
|
|
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
|
|
504
|
-
|
|
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(
|
|
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 {
|
|
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
|
-
*
|
|
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 #
|
|
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.#
|
|
39
|
-
this.#
|
|
40
|
-
|
|
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.#
|
|
51
|
-
|
|
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
|
|
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
|
-
#
|
|
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
|
}
|