chrome-devtools-frontend 1.0.1698733 → 1.0.1699061

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 (59) hide show
  1. package/.agents/skills/devtools-verification/SKILL.md +19 -0
  2. package/.agents/skills/{repro-flaky-tests → fix-tests}/SKILL.md +2 -2
  3. package/front_end/core/sdk/DOMModel.ts +3 -5
  4. package/front_end/core/sdk/NetworkManager.ts +2 -2
  5. package/front_end/core/sdk/OverlayModel.ts +11 -12
  6. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +84 -32
  7. package/front_end/models/emulation/DeviceModeModel.ts +1 -1
  8. package/front_end/models/issues_manager/CookieIssue.ts +0 -13
  9. package/front_end/models/source_map_scopes/NamesResolver.ts +11 -3
  10. package/front_end/models/source_map_scopes/ScopeChainModel.ts +10 -6
  11. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +281 -3
  12. package/front_end/panels/accessibility/accessibilityAnnouncementRecordingView.css +85 -0
  13. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +1 -2
  14. package/front_end/panels/animation/AnimationTimeline.ts +1 -1
  15. package/front_end/panels/application/CrashReportContextView.ts +1 -1
  16. package/front_end/panels/application/IndexedDBViews.ts +1 -1
  17. package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -0
  18. package/front_end/panels/application/components/AdsView.ts +63 -1
  19. package/front_end/panels/application/components/adsView.css +11 -1
  20. package/front_end/panels/common/CommentThreadWidget.ts +1 -16
  21. package/front_end/panels/common/commentThreadWidget.css +0 -12
  22. package/front_end/panels/elements/CSSRuleValidator.ts +1 -1
  23. package/front_end/panels/elements/ElementsPanel.ts +4 -4
  24. package/front_end/panels/elements/ElementsTreeElement.ts +7 -2
  25. package/front_end/panels/elements/ElementsTreeOutline.ts +14 -26
  26. package/front_end/panels/elements/elementsTreeOutline.css +4 -4
  27. package/front_end/panels/lighthouse/LighthouseController.ts +1 -1
  28. package/front_end/panels/mobile_throttling/NetworkPanelIndicator.ts +1 -1
  29. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +1 -1
  30. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +1 -1
  31. package/front_end/panels/recorder/StepView.ts +19 -4
  32. package/front_end/panels/recorder/TimelineSection.ts +1 -1
  33. package/front_end/panels/settings/BackendLinkingSettingsTab.ts +2 -1
  34. package/front_end/panels/settings/EditFileSystemView.ts +1 -1
  35. package/front_end/panels/sources/CallStackSidebarPane.ts +1 -1
  36. package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
  37. package/front_end/panels/timeline/components/DetailsView.ts +3 -3
  38. package/front_end/panels/timeline/components/OriginMap.ts +1 -1
  39. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -3
  40. package/front_end/third_party/chromium/README.chromium +1 -1
  41. package/front_end/ui/components/buttons/Button.ts +19 -1
  42. package/front_end/ui/legacy/ContextMenu.ts +16 -1
  43. package/front_end/ui/legacy/PlusButton.ts +5 -6
  44. package/front_end/ui/legacy/Treeoutline.ts +2 -0
  45. package/front_end/ui/legacy/Widget.ts +33 -0
  46. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +3 -0
  47. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +14 -4
  48. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +22 -25
  49. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  50. package/package.json +1 -1
  51. package/.agents/skills/devtools-ci/SKILL.md +0 -65
  52. package/.agents/skills/evaluate-ai-css-completion/SKILL.md +0 -143
  53. package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +0 -104
  54. package/.agents/skills/fixing-skipped-tests/SKILL.md +0 -32
  55. package/.agents/skills/gerrit-cli/SKILL.md +0 -74
  56. package/.agents/skills/gerrit-cli/references/commands.md +0 -169
  57. package/.agents/skills/gerrit-cli/references/workflows.md +0 -63
  58. package/.agents/skills/gerrit-cli/scripts/import_upstream.py +0 -85
  59. package/front_end/models/issues_manager/descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +0 -4
@@ -20,6 +20,25 @@ description: "MANDATORY: Activate this skill ANY TIME you need to build the proj
20
20
  - `npm run lint` will execute ESLint and StyleLint. It will report any violations and automatically fix them where possible.
21
21
  - To run the linter on a specific file or directory, you can run `npm run lint -- <PATH>` where `PATH` is a path to a file or directory. This will also automatically fix violations where possible.
22
22
 
23
+ ## Fetching Tryjob Results, Failure Logs, & Screenshot Goldens
24
+
25
+ Use `scripts/tools/get_cl_test_results.py` to fetch all tryjob build statuses, per-test failure logs, Blink web test text diffs, and screenshot artifacts (`actual_image`, `expected_image`, `image_diff`) for a CL in one command:
26
+
27
+ ```bash
28
+ # Fetch all build statuses, failure logs, and artifacts for a CL into an output directory:
29
+ scripts/tools/get_cl_test_results.py --cl <CL_NUMBER> --output-dir <OUTPUT_DIR>
30
+
31
+ # Filter for specific failing tests (e.g. DOMTreeWidget) or specific builders:
32
+ scripts/tools/get_cl_test_results.py --cl <CL_NUMBER> --test-filter "DOMTreeWidget" --output-dir <OUTPUT_DIR>
33
+
34
+ # Also apply Linux actual_image screenshot artifacts directly to test/goldens/linux/...:
35
+ scripts/tools/get_cl_test_results.py --cl <CL_NUMBER> --output-dir <OUTPUT_DIR> --apply-goldens
36
+ ```
37
+
38
+ ### Screenshot Golden & Inspection Rules
39
+ - **Linux-only goldens**: Never generate, update, or commit golden PNGs from macOS. Screenshot tests in DevTools only use Linux goldens (`test/goldens/linux/...`) produced by Linux trybots (`dtf_linux_rel` / `dtf_linux_dbg`). Do not run screenshot tests locally on macOS to verify goldens.
40
+ - **Multimodal inspection only**: Always inspect `actual_image.png`, `expected_image.png`, and `image_diff.png` directly using your multimodal file viewer (`view_file`). Never write or run programmatic image comparison scripts.
41
+
23
42
  ## Best practices
24
43
 
25
44
  - Run tests often to verify your changes.
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: repro-flaky-tests
3
- description: Reproduce and investigate flakiness in a test.
2
+ name: fix-tests
3
+ description: Use this skill to reproduce and fix flaky and disabled tests.
4
4
  ---
5
5
 
6
6
  # Workflow
@@ -1319,12 +1319,10 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
1319
1319
  return;
1320
1320
  }
1321
1321
 
1322
- const result = await node.callFunction(scrollIntoViewInPage);
1323
- if (!result) {
1324
- return;
1325
- }
1326
-
1322
+ // Highlight synchronously before scrolling to avoid out-of-order highlights
1323
+ // if asynchronous scroll calls resolve late during rapid navigation.
1327
1324
  node.highlightForTwoSeconds();
1325
+ await node.callFunction(scrollIntoViewInPage);
1328
1326
  }
1329
1327
 
1330
1328
  async focus(): Promise<void> {
@@ -93,14 +93,14 @@ const UIStrings = {
93
93
  * @example {GET} PH2
94
94
  * @example {https://example.com} PH3
95
95
  */
96
- sFailedLoadingSS: '{PH1} failed loading: {PH2} "{PH3}".',
96
+ sFailedLoadingSS: '{PH1} failed loading: {PH2} "{PH3}"',
97
97
  /**
98
98
  * @description Console message when a request finished loading.
99
99
  * @example {XHR} PH1
100
100
  * @example {GET} PH2
101
101
  * @example {https://example.com} PH3
102
102
  */
103
- sFinishedLoadingSS: '{PH1} finished loading: {PH2} "{PH3}".',
103
+ sFinishedLoadingSS: '{PH1} finished loading: {PH2} "{PH3}"',
104
104
  /**
105
105
  * @description One of direct socket connection statuses.
106
106
  */
@@ -342,13 +342,13 @@ export class OverlayModel extends SDKModel<EventTypes> implements ProtocolProxyA
342
342
  // overlay, so that it is not cleared by the highlight
343
343
  return;
344
344
  }
345
- clearTimeout(this.#hideHighlightTimeout);
346
- this.#hideHighlightTimeout = undefined;
345
+ clearTimeout(this.#hideHighlightTimeout);
346
+ this.#hideHighlightTimeout = undefined;
347
347
 
348
- const highlightConfig = this.buildHighlightConfig(mode);
349
- if (typeof showInfo !== 'undefined') {
350
- highlightConfig.showInfo = showInfo;
351
- }
348
+ const highlightConfig = this.buildHighlightConfig(mode);
349
+ if (typeof showInfo !== 'undefined') {
350
+ highlightConfig.showInfo = showInfo;
351
+ }
352
352
  this.#highlighter.highlightInOverlay(data, highlightConfig);
353
353
  }
354
354
 
@@ -496,12 +496,11 @@ export class OverlayModel extends SDKModel<EventTypes> implements ProtocolProxyA
496
496
  }
497
497
 
498
498
  private delayedHideHighlight(delay: number): void {
499
- if (this.#hideHighlightTimeout === undefined) {
500
- this.#hideHighlightTimeout = globalThis.setTimeout(
501
- () => this.highlightInOverlay({clear: true}),
502
- delay,
503
- );
504
- }
499
+ clearTimeout(this.#hideHighlightTimeout);
500
+ this.#hideHighlightTimeout = globalThis.setTimeout(
501
+ () => this.highlightInOverlay({clear: true}),
502
+ delay,
503
+ );
505
504
  }
506
505
 
507
506
  highlightFrame(frameId: Protocol.Page.FrameId): void {
@@ -46,6 +46,7 @@ export class SourceMapScopeChainEntry implements ScopeChainEntry {
46
46
  readonly #isInnerMostFunction: boolean;
47
47
  readonly #returnValue?: RemoteObject;
48
48
  readonly #scopeNumber?: number;
49
+ #object?: SourceMapScopeRemoteObject;
49
50
 
50
51
  /**
51
52
  * @param isInnerMostFunction If `scope` is the innermost 'function' scope. Only used for labeling as we name the
@@ -63,6 +64,10 @@ export class SourceMapScopeChainEntry implements ScopeChainEntry {
63
64
  this.#scopeNumber = scopeNumber;
64
65
  }
65
66
 
67
+ originalScope(): ScopesCodec.OriginalScope {
68
+ return this.#scope;
69
+ }
70
+
66
71
  extraProperties(): RemoteObjectProperty[] {
67
72
  const extraProperties = [];
68
73
  if (this.#isInnerMostFunction && this.#callFrame.exception) {
@@ -118,7 +123,10 @@ export class SourceMapScopeChainEntry implements ScopeChainEntry {
118
123
  }
119
124
 
120
125
  object(): RemoteObject {
121
- return new SourceMapScopeRemoteObject(this.#callFrame, this.#scope, this.#range, this.#scopeNumber);
126
+ if (!this.#object) {
127
+ this.#object = new SourceMapScopeRemoteObject(this.#callFrame, this.#scope, this.#range, this.#scopeNumber);
128
+ }
129
+ return this.#object;
122
130
  }
123
131
 
124
132
  description(): string {
@@ -135,6 +143,8 @@ class SourceMapScopeRemoteObject extends RemoteObjectImpl {
135
143
  readonly #scope: ScopesCodec.OriginalScope;
136
144
  readonly #range?: ScopesCodec.GeneratedRange;
137
145
  readonly #scopeNumber?: number;
146
+ #propertiesPromise?: Promise<GetPropertiesResult>;
147
+ #cachedWithPreview = false;
138
148
 
139
149
  constructor(callFrame: CallFrame, scope: ScopesCodec.OriginalScope, range: ScopesCodec.GeneratedRange|undefined,
140
150
  scopeNumber: number|undefined) {
@@ -153,60 +163,102 @@ class SourceMapScopeRemoteObject extends RemoteObjectImpl {
153
163
  if (accessorPropertiesOnly) {
154
164
  return {properties: [], internalProperties: []};
155
165
  }
166
+ if (!this.#propertiesPromise || (generatePreview && !this.#cachedWithPreview)) {
167
+ this.#cachedWithPreview = generatePreview;
168
+ this.#propertiesPromise = this.#evaluateProperties(generatePreview);
169
+ }
170
+ return await this.#propertiesPromise;
171
+ }
156
172
 
173
+ async #evaluateProperties(generatePreview: boolean): Promise<GetPropertiesResult> {
157
174
  if (this.#scope.variables.length === 0) {
158
175
  return {properties: [], internalProperties: []};
159
176
  }
160
-
161
177
  const expressions = this.#scope.variables.map((_, index) => this.#findExpression(index));
178
+ const values = await this.#evaluateAsBatch(expressions, generatePreview) ??
179
+ await this.#evaluateSeparately(expressions, generatePreview);
162
180
 
163
- if (expressions.every(expr => expr === null)) {
164
- const properties = this.#scope.variables.map(v => SourceMapScopeRemoteObject.#unavailableProperty(v));
165
- return {properties, internalProperties: []};
166
- }
181
+ const properties = this.#scope.variables.map((variable, index) => {
182
+ const value = values[index];
183
+ if (value === null) {
184
+ return SourceMapScopeRemoteObject.#unavailableProperty(variable);
185
+ }
186
+ return new RemoteObjectProperty(variable, value, /* enumerable */ false, /* writable */ false, /* isOwn */ true,
187
+ /* wasThrown */ false);
188
+ });
189
+
190
+ return {properties, internalProperties: []};
191
+ }
167
192
 
168
- const spreadEntries: string[] = [];
169
- for (const [index, expr] of expressions.entries()) {
170
- if (expr !== null) {
171
- spreadEntries.push(`...(() => { try { return {${index}: eval(${JSON.stringify(expr)})}; } catch {} })()`);
193
+ /**
194
+ * Evaluates all binding expressions of this scope with a single `evaluateOnCallFrame` call.
195
+ *
196
+ * We build an object literal that spreads in one `{index: value}` object per binding, each produced by
197
+ * its own arrow function wrapped in `try`/`catch`. A binding that throws contributes nothing, which is
198
+ * how we tell it apart from one that legitimately evaluates to `undefined`, and it doesn't take the
199
+ * rest of the scope down with it.
200
+ *
201
+ * The expressions are inlined rather than passed to `eval`. `eval` in the evaluated code is the page's
202
+ * `eval`, which a `script-src` CSP without `'unsafe-eval'` blocks. `Runtime.evaluate` can opt out of
203
+ * that via `allowUnsafeEvalBlockedByCSP`, but `Debugger.evaluateOnCallFrame` has no such option.
204
+ * Inlining also means we don't introduce bindings of our own that could shadow the names a binding
205
+ * expression refers to, and arrow functions keep `this` pointing at the paused frame's receiver.
206
+ *
207
+ * @returns The value for each expression, or null if the batch failed as a whole. The latter happens
208
+ * when a binding expression doesn't parse, since that takes out the entire object literal.
209
+ */
210
+ async #evaluateAsBatch(expressions: Array<string|null>,
211
+ generatePreview: boolean): Promise<Array<RemoteObject|null>|null> {
212
+ const spreads: string[] = [];
213
+ for (const [index, expression] of expressions.entries()) {
214
+ if (expression !== null) {
215
+ spreads.push(`...(() => { try { return {${index}: (${expression})}; } catch {} })()`);
172
216
  }
173
217
  }
218
+ if (spreads.length === 0) {
219
+ return expressions.map(() => null);
220
+ }
174
221
 
175
- const batchExpression = `({ __proto__: null, ${spreadEntries.join(', ')} })`;
176
222
  const result = await this.#callFrame.evaluate({
177
- expression: batchExpression,
223
+ expression: `({__proto__: null, ${spreads.join(', ')}})`,
224
+ // The wrapper object is a throw-away. We only need previews for the values inside of it.
178
225
  generatePreview: false,
179
226
  scopeNumber: this.#scopeNumber,
180
227
  });
181
-
182
228
  if ('error' in result || result.exceptionDetails || !result.object) {
183
- const properties = this.#scope.variables.map(v => SourceMapScopeRemoteObject.#unavailableProperty(v));
184
- return {properties, internalProperties: []};
229
+ return null;
185
230
  }
186
231
 
187
- const {properties: objectProperties} = await result.object.getOwnProperties(generatePreview);
232
+ const {properties} = await result.object.getOwnProperties(generatePreview);
188
233
  result.object.release();
189
234
 
190
- const propertyMap = new Map<string, RemoteObjectProperty>();
191
- if (objectProperties) {
192
- for (const prop of objectProperties) {
193
- propertyMap.set(prop.name, prop);
235
+ const valueByIndex = new Map(properties?.map(({name, value}) => [name, value] as const));
236
+ return expressions.map((_, index) => valueByIndex.get(String(index)) ?? null);
237
+ }
238
+
239
+ /**
240
+ * Fallback for when {@link #evaluateAsBatch} fails as a whole, so that a single binding expression
241
+ * that doesn't parse only costs us that one variable.
242
+ */
243
+ async #evaluateSeparately(expressions: Array<string|null>,
244
+ generatePreview: boolean): Promise<Array<RemoteObject|null>> {
245
+ const values: Array<RemoteObject|null> = [];
246
+ for (const expression of expressions) {
247
+ if (expression === null) {
248
+ values.push(null);
249
+ continue;
194
250
  }
195
- }
196
251
 
197
- const properties: RemoteObjectProperty[] = [];
198
- for (const [index, variable] of this.#scope.variables.entries()) {
199
- const prop = propertyMap.get(String(index));
200
- if (!prop || !prop.value) {
201
- properties.push(SourceMapScopeRemoteObject.#unavailableProperty(variable));
252
+ const result = await this.#callFrame.evaluate({expression, generatePreview, scopeNumber: this.#scopeNumber});
253
+ if ('error' in result || result.exceptionDetails) {
254
+ // TODO(crbug.com/40277685): Make these errors user-visible to aid tooling developers.
255
+ // E.g. show the error on hover or expose it in the developer resources panel.
256
+ values.push(null);
202
257
  } else {
203
- properties.push(new RemoteObjectProperty(variable, prop.value, /* enumerable */ false, /* writable */ false,
204
- /* isOwn */ true,
205
- /* wasThrown */ false));
258
+ values.push(result.object);
206
259
  }
207
260
  }
208
-
209
- return {properties, internalProperties: []};
261
+ return values;
210
262
  }
211
263
 
212
264
  /** @returns null if the variable is unavailable at the current paused location */
@@ -219,7 +271,7 @@ class SourceMapScopeRemoteObject extends RemoteObjectImpl {
219
271
  if (typeof expressionOrSubRanges === 'string') {
220
272
  return expressionOrSubRanges;
221
273
  }
222
- if (expressionOrSubRanges === null || expressionOrSubRanges === undefined) {
274
+ if (!expressionOrSubRanges) {
223
275
  return null;
224
276
  }
225
277
 
@@ -70,7 +70,7 @@ const UIStrings = {
70
70
  * @description Error message shown on the Devices settings tab when the user enters an invalid
71
71
  * device pixel ratio for a custom device.
72
72
  */
73
- devicePixelRatioMustBeANumberOr: 'Device pixel ratio must be a number or blank.',
73
+ devicePixelRatioMustBeANumberOr: 'Device pixel ratio must be a number or blank',
74
74
  /**
75
75
  * @description Error message shown on the Devices settings tab when the user enters a device
76
76
  * pixel ratio for a custom device that is too large.
@@ -403,11 +403,6 @@ const excludeDomainNonAscii: LazyMarkdownIssueDescription = {
403
403
  links: [],
404
404
  };
405
405
 
406
- const excludeBlockedWithinRelatedWebsiteSet: LazyMarkdownIssueDescription = {
407
- file: 'cookieExcludeBlockedWithinRelatedWebsiteSet.md',
408
- links: [],
409
- };
410
-
411
406
  const cookieCrossSiteRedirectDowngrade: LazyMarkdownIssueDescription = {
412
407
  file: 'cookieCrossSiteRedirectDowngrade.md',
413
408
  links: [{
@@ -451,14 +446,6 @@ const issueDescriptions = new Map<string, LazyMarkdownIssueDescription>([
451
446
  ['CookieIssue::WarnDomainNonASCII::SetCookie', warnDomainNonAscii],
452
447
  ['CookieIssue::ExcludeDomainNonASCII::ReadCookie', excludeDomainNonAscii],
453
448
  ['CookieIssue::ExcludeDomainNonASCII::SetCookie', excludeDomainNonAscii],
454
- [
455
- 'CookieIssue::ExcludeThirdPartyCookieBlockedInRelatedWebsiteSet::ReadCookie',
456
- excludeBlockedWithinRelatedWebsiteSet,
457
- ],
458
- [
459
- 'CookieIssue::ExcludeThirdPartyCookieBlockedInRelatedWebsiteSet::SetCookie',
460
- excludeBlockedWithinRelatedWebsiteSet,
461
- ],
462
449
  ['CookieIssue::WarnThirdPartyPhaseout::ReadCookie', placeholderDescriptionForInvisibleIssues],
463
450
  ['CookieIssue::WarnThirdPartyPhaseout::SetCookie', placeholderDescriptionForInvisibleIssues],
464
451
  ['CookieIssue::WarnDeprecationTrialMetadata::ReadCookie', placeholderDescriptionForInvisibleIssues],
@@ -2,6 +2,7 @@
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
4
 
5
+ import * as Root from '../../core/root/root.js';
5
6
  import * as SDK from '../../core/sdk/sdk.js';
6
7
  import * as TextUtils from '../../core/text_utils/text_utils.js';
7
8
  import * as Protocol from '../../generated/protocol.js';
@@ -380,9 +381,16 @@ export const resolveScopeChain =
380
381
  return scopeChain;
381
382
  }
382
383
 
383
- // TODO(crbug.com/465968290): Re-enable creating the scope chain from the source map once:
384
- // 1) We have a flag indicating whether the source map contained variable/binding information.
385
- // 2) We have a chrome feature flag.
384
+ if (Root.Runtime.hostConfig.devToolsSourceMapScopesInSourcesPanel?.enabled) {
385
+ let sourceMap = callFrame.script.sourceMap();
386
+ if (!sourceMap && callFrame.debuggerModel?.sourceMapManager) {
387
+ sourceMap = await callFrame.debuggerModel.sourceMapManager().sourceMapForClientPromise(callFrame.script);
388
+ }
389
+ const mappedScopeChain = sourceMap?.resolveScopeChain(callFrame);
390
+ if (mappedScopeChain) {
391
+ return mappedScopeChain;
392
+ }
393
+ }
386
394
 
387
395
  if (callFrame.script.isWasm()) {
388
396
  return callFrame.scopeChain().filter(scope => !scope.empty());
@@ -35,8 +35,10 @@ export class ScopeChainModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
35
35
  this.#debuggerWorkspaceBinding = debuggerWorkspaceBinding;
36
36
  this.#callFrame.debuggerModel.addEventListener(
37
37
  SDK.DebuggerModel.Events.DebugInfoAttached, this.#debugInfoAttached, this);
38
- this.#callFrame.debuggerModel.sourceMapManager().addEventListener(
39
- SDK.SourceMapManager.Events.SourceMapAttached, this.#sourceMapAttached, this);
38
+ this.#callFrame.debuggerModel.sourceMapManager().addEventListener(SDK.SourceMapManager.Events.SourceMapAttached,
39
+ this.#sourceMapChanged, this);
40
+ this.#callFrame.debuggerModel.sourceMapManager().addEventListener(SDK.SourceMapManager.Events.SourceMapDetached,
41
+ this.#sourceMapChanged, this);
40
42
 
41
43
  void this.#throttler.schedule(this.#boundUpdate);
42
44
  }
@@ -44,8 +46,10 @@ export class ScopeChainModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
44
46
  dispose(): void {
45
47
  this.#callFrame.debuggerModel.removeEventListener(
46
48
  SDK.DebuggerModel.Events.DebugInfoAttached, this.#debugInfoAttached, this);
47
- this.#callFrame.debuggerModel.sourceMapManager().removeEventListener(
48
- SDK.SourceMapManager.Events.SourceMapAttached, this.#sourceMapAttached, this);
49
+ this.#callFrame.debuggerModel.sourceMapManager().removeEventListener(SDK.SourceMapManager.Events.SourceMapAttached,
50
+ this.#sourceMapChanged, this);
51
+ this.#callFrame.debuggerModel.sourceMapManager().removeEventListener(SDK.SourceMapManager.Events.SourceMapDetached,
52
+ this.#sourceMapChanged, this);
49
53
  this.listeners?.clear();
50
54
  }
51
55
 
@@ -60,8 +64,8 @@ export class ScopeChainModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
60
64
  }
61
65
  }
62
66
 
63
- #sourceMapAttached(event: Common.EventTarget
64
- .EventTargetEvent<{client: SDK.Script.Script, sourceMap: SDK.SourceMap.SourceMap}>): void {
67
+ #sourceMapChanged(event: Common.EventTarget
68
+ .EventTargetEvent<{client: SDK.Script.Script, sourceMap: SDK.SourceMap.SourceMap}>): void {
65
69
  if (event.data.client === this.#callFrame.script) {
66
70
  void this.#throttler.schedule(this.#boundUpdate);
67
71
  }