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
package/AUTHORS CHANGED
@@ -124,6 +124,7 @@ Yoichiro Hibara <hibarayoichiro871@gmail.com>
124
124
  Yoni Feigelson <yfeigelson@gmail.com>
125
125
  Young Min Kim <y@ylem.kim>
126
126
  Yuan Zhuang <joann.yuanzhuang@gmail.com>
127
+ Zeeshan Ahmad <zeeshanahmad125114@gmail.com>
127
128
  Zuyao Chen <zuyaocat@gmail.com>
128
129
  # Please DO NOT APPEND here. See comments at the top of the file.
129
130
  # END individuals section.
@@ -121,7 +121,7 @@ There are multiple variants of the DevTools application.
121
121
  The main DevTools application is [devtools_app.ts](../front_end/entrypoints/devtools_app/devtools_app.ts), which developers can open via F12 or "Right click -> Inspect element" in their Chromium browser.
122
122
  Other application entrypoints are a dedicated tool for debugging Node on which multiple targets can be inspected ([node_app.ts](../front_end/entrypoints/node_app/node_app.ts)), a non-browser context debugger for V8 targets ([js_app.ts](../front_end/entrypoints/js_app/js_app.ts)), a (service) worker context ([worker_app.ts](../front_end/entrypoints/worker_app/worker_app.ts)), remote debugging of (Android) devices ([inspector.ts](../front_end/entrypoints/inspector/inspector.ts)) and a basic version of DevTools which was initially intended for non-browser targets but doesn't have any particular use case that differentiates it from the other variants ([ndb_app.ts](../front_end/entrypoints/ndb_app/ndb_app.ts)).
123
123
 
124
- Each application entrypoint has a corresponding `.html` file with the same name, that is automatically in the frontend generated and can be loaded by the Chromium DevTools backend.
124
+ Each application entrypoint has a corresponding `.html` file with the same name, that is automatically generated in the frontend and can be loaded by the Chromium DevTools backend.
125
125
  The JavaScript files import the relevant "meta" files containing the declarations of DevTools features.
126
126
 
127
127
  ## Upfront declaration of DevTools features
@@ -286,8 +286,8 @@ const UIStrings = {
286
286
 
287
287
  ## How to prevent a term being localized
288
288
 
289
- Any text within the backticks will not be translated. For example, if the
290
- 'robots.txt' in string 'Requesting for robots.txt …' should not be translated:
289
+ Any text within the backticks will not be translated. For example,
290
+ 'robots.txt' in the string 'Requesting for robots.txt …' should not be translated:
291
291
 
292
292
  ```ts
293
293
  // in example.js file
package/eslint.config.mjs CHANGED
@@ -628,6 +628,7 @@ export default defineConfig([
628
628
  '@devtools/l10n-no-i18nString-calls-module-instantiation': 'error',
629
629
  '@devtools/l10n-no-uistrings-export': 'error',
630
630
  '@devtools/l10n-no-unused-message': 'error',
631
+ '@devtools/l10n-uistrings-sentence-punctuation': 'error',
631
632
  '@devtools/l10n-uistrings-text-style': 'error',
632
633
  },
633
634
  },
@@ -0,0 +1,28 @@
1
+ <svg width="200" height="200" viewBox="0 0 44 50" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <clipPath id="hexClip">
4
+ <path d="M22.8725 0.4166C22.136 0 21.2616 0 20.5253 0.4166L1.1505 11.6694C0.4142 12.0862 0 12.8733 0 13.707V36.2584C0 37.0921 0.4602 37.8791 1.1505 38.296L20.5253 49.5487C21.2616 49.9653 22.136 49.9653 22.8725 49.5487L42.2471 38.296C42.9836 37.8791 43.3976 37.0921 43.3976 36.2584V13.707C43.3976 12.8733 42.9375 12.0862 42.2471 11.6694L22.8725 0.4166Z" />
5
+ </clipPath>
6
+ <linearGradient id="main" x1="30.33" y1="8.56" x2="14.9" y2="44.7" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#3F8B3D"/>
8
+ <stop offset="0.64" stop-color="#3F873F"/>
9
+ <stop offset="0.93" stop-color="#3DA92E"/>
10
+ <stop offset="1" stop-color="#3DAE2B"/>
11
+ </linearGradient>
12
+ <linearGradient id="r1" x1="18.8" y1="26.8" x2="68" y2="0.4" gradientUnits="userSpaceOnUse">
13
+ <stop offset="0.14" stop-color="#3F873F"/>
14
+ <stop offset="0.4" stop-color="#52A044"/>
15
+ <stop offset="0.71" stop-color="#64B749"/>
16
+ <stop offset="0.91" stop-color="#6ABF4B"/>
17
+ </linearGradient>
18
+ <linearGradient id="r2" x1="0.25" y1="24.5" x2="44" y2="24.5" gradientUnits="userSpaceOnUse">
19
+ <stop offset="0.09" stop-color="#6ABF4B"/>
20
+ <stop offset="0.29" stop-color="#64B749"/>
21
+ <stop offset="0.6" stop-color="#52A044"/>
22
+ <stop offset="0.86" stop-color="#3F873F"/>
23
+ </linearGradient>
24
+ </defs>
25
+ <path fill="url(#main)" d="M22.8725 0.4166C22.136 0 21.2616 0 20.5253 0.4166L1.1505 11.6694C0.4142 12.0862 0 12.8733 0 13.707V36.2584C0 37.0921 0.4602 37.8791 1.1505 38.296L20.5253 49.5487C21.2616 49.9653 22.136 49.9653 22.8725 49.5487L42.2471 38.296C42.9836 37.8791 43.3976 37.0921 43.3976 36.2584V13.707C43.3976 12.8733 42.9375 12.0862 42.2471 11.6694L22.8725 0.4166Z" />
26
+ <polygon fill="url(#r1)" clip-path="url(#hexClip)" points="21.698901,-1.046618 43.20532,11.948247 21.698901,51.072715 0.152778,38.055107" />
27
+ <polygon fill="url(#r2)" clip-path="url(#hexClip)" points="21.698901,-1.046618 0.152778,11.948247 21.698901,51.072715 43.20532,38.055107" />
28
+ </svg>
@@ -6,14 +6,15 @@ A settings registration is represented by the `SettingRegistration` interface, d
6
6
 
7
7
  All settings have to be registered using the function `Common.Settings.registerSettingExtension` which expects an object of type `SettingRegistration` as parameter.
8
8
 
9
- As an example, take the registration of the `showHTMLComments` setting, which allows users to determine if HTML comments are shown in the Elements tree:
9
+ As an example, take the registration of the `show-html-comments` setting, which allows users to determine if HTML comments are shown in the Elements tree:
10
10
 
11
11
  ```ts
12
12
  Common.Settings.registerSettingExtension({
13
13
  category: Common.Settings.SettingCategory.ELEMENTS,
14
+ storageType: Common.Settings.SettingStorageType.SYNCED,
14
15
  order: 3,
15
- title: ls`Show HTML comments`,
16
- settingName: 'showHTMLComments',
16
+ title: ls`HTML comments`,
17
+ settingName: 'show-html-comments',
17
18
  settingType: Common.Settings.SettingType.BOOLEAN,
18
19
  defaultValue: true,
19
20
  options: [
@@ -191,19 +191,22 @@ export class CPUThrottlingManager extends Common.ObjectWrapper.ObjectWrapper<Eve
191
191
  }
192
192
  }
193
193
 
194
- #isCPUPerformanceOverrideActive(): boolean {
195
- return this.#manualCPUPerformanceOverride !== undefined || this.#cpuThrottlingRate !== 1;
194
+ #activeCPUPerformanceOverride(): CPUPerformanceTier|undefined {
195
+ // If neither a manual override nor CPU throttling is enabled, no override is active.
196
+ if (this.#manualCPUPerformanceOverride === undefined && this.#cpuThrottlingRate === 1) {
197
+ return undefined;
198
+ }
199
+ return this.effectiveCPUPerformanceTier();
196
200
  }
197
201
 
198
202
  #syncCPUPerformanceTier(): void {
199
- const effectiveTier = this.effectiveCPUPerformanceTier();
200
203
  // Synchronize with Chromium backend, via CDP.
201
- const activeOverride = this.#isCPUPerformanceOverrideActive() ? effectiveTier : undefined;
204
+ const activeOverride = this.#activeCPUPerformanceOverride();
202
205
  for (const emulationModel of this.#targetManager.models(EmulationModel)) {
203
206
  void emulationModel.setCPUPerformanceOverride(activeOverride);
204
207
  }
205
208
  // Notify UI and other listeners.
206
- this.dispatchEventToListeners(Events.CPU_PERFORMANCE_TIER_CHANGED, effectiveTier);
209
+ this.dispatchEventToListeners(Events.CPU_PERFORMANCE_TIER_CHANGED, this.effectiveCPUPerformanceTier());
207
210
  }
208
211
 
209
212
  setCPUThrottlingRate(rate: number): void {
@@ -282,9 +285,9 @@ export class CPUThrottlingManager extends Common.ObjectWrapper.ObjectWrapper<Eve
282
285
  }
283
286
 
284
287
  async updateHostDefaultCPUPerformanceTier(): Promise<void> {
285
- if (this.#isCPUPerformanceOverrideActive()) {
286
- // We do not want to update the host default tier when it is overridden
287
- // (in which case, `navigator.cpuPerformance` would return the override).
288
+ if (this.#activeCPUPerformanceOverride() !== undefined) {
289
+ // We do not want to update the host default tier if an override has already been sent
290
+ // to the backend (in which case, `navigator.cpuPerformance` would return the override).
288
291
  return;
289
292
  }
290
293
  const target = this.#targetManager.primaryPageTarget();
@@ -314,8 +317,9 @@ export class CPUThrottlingManager extends Common.ObjectWrapper.ObjectWrapper<Eve
314
317
  if (this.#hardwareConcurrency !== undefined) {
315
318
  void emulationModel.setHardwareConcurrency(this.#hardwareConcurrency);
316
319
  }
317
- if (this.#isCPUPerformanceOverrideActive()) {
318
- void emulationModel.setCPUPerformanceOverride(this.effectiveCPUPerformanceTier());
320
+ const activeOverride = this.#activeCPUPerformanceOverride();
321
+ if (activeOverride !== undefined) {
322
+ void emulationModel.setCPUPerformanceOverride(activeOverride);
319
323
  }
320
324
 
321
325
  // If there are any callers blocked on a getHardwareConcurrency call, let's wake them now.
@@ -319,7 +319,7 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
319
319
 
320
320
  const frameOwnerTags = new Set(['EMBED', 'IFRAME', 'OBJECT', 'FENCEDFRAME']);
321
321
  if (payload.contentDocument) {
322
- this.contentDocumentInternal = new DOMDocument(this.#domModel, payload.contentDocument);
322
+ this.contentDocumentInternal = new DOMDocument(this.#domModel, payload.contentDocument, payload.frameId);
323
323
  this.contentDocumentInternal.parentNode = this;
324
324
  this.childrenInternal = [];
325
325
  } else if (payload.frameId && frameOwnerTags.has(payload.nodeName)) {
@@ -1391,17 +1391,27 @@ export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventType
1391
1391
  }
1392
1392
 
1393
1393
  async takeSnapshot(ownerDocumentSnapshot?: DOMDocument): Promise<DOMNode> {
1394
- const snapshot = (this instanceof DOMDocument) ? new DOMDocumentSnapshot(this.domModel(), {
1395
- nodeId: this.id,
1396
- backendNodeId: this.backendNodeId(),
1397
- nodeType: this.nodeType(),
1398
- nodeName: this.nodeName(),
1399
- localName: this.localName(),
1400
- nodeValue: this.nodeValueInternal,
1401
- documentURL: this.documentURL,
1402
- baseURL: this.baseURL,
1403
- } as Protocol.DOM.Node) :
1404
- new DOMNodeSnapshot(this.domModel());
1394
+ let snapshot: DOMNode;
1395
+ if (this instanceof DOMDocument) {
1396
+ const doc: DOMDocument = this;
1397
+ snapshot = new DOMDocumentSnapshot(
1398
+ this.domModel(),
1399
+ {
1400
+ nodeId: this.id,
1401
+ backendNodeId: this.backendNodeId(),
1402
+ nodeType: this.nodeType(),
1403
+ nodeName: this.nodeName(),
1404
+ localName: this.localName(),
1405
+ nodeValue: this.nodeValueInternal,
1406
+ documentURL: this.documentURL,
1407
+ baseURL: this.baseURL,
1408
+ } as Protocol.DOM.Node,
1409
+ this.frameId(),
1410
+ doc.securityOrigin(),
1411
+ );
1412
+ } else {
1413
+ snapshot = new DOMNodeSnapshot(this.domModel());
1414
+ }
1405
1415
  snapshot.id = this.id;
1406
1416
  snapshot.#backendNodeId = this.#backendNodeId;
1407
1417
  snapshot.#frameOwnerFrameId = this.#frameOwnerFrameId;
@@ -1573,16 +1583,28 @@ export class DOMDocument extends DOMNode {
1573
1583
  documentElement: DOMNode|null;
1574
1584
  #documentURL: Platform.DevToolsPath.UrlString;
1575
1585
  #baseURL: Platform.DevToolsPath.UrlString;
1586
+ #frameId: Protocol.Page.FrameId|null;
1576
1587
  #securityOrigin: SecurityOrigin;
1577
1588
 
1578
- constructor(domModel: DOMModel, payload: Protocol.DOM.Node) {
1589
+ constructor(
1590
+ domModel: DOMModel,
1591
+ payload: Protocol.DOM.Node,
1592
+ frameId?: Protocol.Page.FrameId|null,
1593
+ ) {
1579
1594
  super(domModel);
1580
1595
  this.body = null;
1581
1596
  this.documentElement = null;
1582
1597
  this.init(this, false, payload);
1583
1598
  this.#documentURL = (payload.documentURL || '') as Platform.DevToolsPath.UrlString;
1584
1599
  this.#baseURL = (payload.baseURL || '') as Platform.DevToolsPath.UrlString;
1585
- this.#securityOrigin = SecurityOrigin.create(this.#documentURL);
1600
+ this.#frameId = frameId ?? null;
1601
+
1602
+ const resourceTreeModel = this.domModel().target().model(ResourceTreeModel);
1603
+ const frame = this.#frameId ? resourceTreeModel?.frameForId(this.#frameId) : resourceTreeModel?.mainFrame;
1604
+ // In production, DOMDocument should always resolve its security origin from an
1605
+ // associated frame, but falls back to SecurityOrigin.create() as a last resort
1606
+ // for test environments where no frame exists.
1607
+ this.#securityOrigin = frame?.securityOrigin() ?? SecurityOrigin.create(this.#documentURL);
1586
1608
  }
1587
1609
 
1588
1610
  get documentURL(): Platform.DevToolsPath.UrlString {
@@ -1593,10 +1615,14 @@ export class DOMDocument extends DOMNode {
1593
1615
  return this.#baseURL;
1594
1616
  }
1595
1617
 
1618
+ override frameId(): Protocol.Page.FrameId|null {
1619
+ return this.#frameId;
1620
+ }
1621
+
1596
1622
  /**
1597
1623
  * Returns the security origin of this document.
1598
1624
  *
1599
- * The security origin is derived from the document URL and is recomputed
1625
+ * The security origin is resolved from the document's frame and is recomputed
1600
1626
  * when the document navigates to a new URL via `setDocumentURL`.
1601
1627
  */
1602
1628
  override securityOrigin(): SecurityOrigin {
@@ -1604,12 +1630,14 @@ export class DOMDocument extends DOMNode {
1604
1630
  }
1605
1631
 
1606
1632
  /**
1607
- * Updates the document and base URLs, and recomputes the document's security origin.
1633
+ * Updates the document and base URLs, and updates the document's security origin.
1608
1634
  */
1609
- setDocumentURL(url: Platform.DevToolsPath.UrlString): void {
1635
+ setDocumentURL(url: Platform.DevToolsPath.UrlString, securityOrigin?: SecurityOrigin|null): void {
1610
1636
  this.#documentURL = url;
1611
1637
  this.#baseURL = url;
1612
- this.#securityOrigin = SecurityOrigin.create(url);
1638
+ // Prefer the canonical security origin from the frame, falling back to creating
1639
+ // an origin from the URL as a last resort for test environments.
1640
+ this.#securityOrigin = securityOrigin ?? SecurityOrigin.create(url);
1613
1641
  }
1614
1642
  }
1615
1643
 
@@ -1695,7 +1723,7 @@ export class DOMModel extends SDKModel<EventTypes> {
1695
1723
  if (node) {
1696
1724
  const contentDocument = node.contentDocument();
1697
1725
  if (contentDocument && contentDocument.documentURL !== frame.url) {
1698
- contentDocument.setDocumentURL(frame.url);
1726
+ contentDocument.setDocumentURL(frame.url, frame.securityOrigin());
1699
1727
  this.dispatchEventToListeners(Events.DocumentURLChanged, contentDocument);
1700
1728
  }
1701
1729
  }
@@ -1879,7 +1907,8 @@ export class DOMModel extends SDKModel<EventTypes> {
1879
1907
  this.idToDOMNode = new Map();
1880
1908
  this.frameIdToOwnerNode = new Map();
1881
1909
  if (payload && 'nodeId' in payload) {
1882
- this.#document = new DOMDocument(this, payload);
1910
+ const mainFrameId = this.target().model(ResourceTreeModel)?.mainFrame?.id;
1911
+ this.#document = new DOMDocument(this, payload, mainFrameId);
1883
1912
  } else {
1884
1913
  this.#document = null;
1885
1914
  }
@@ -2543,6 +2572,22 @@ export class DOMNodeSnapshot extends DOMNode {
2543
2572
  }
2544
2573
 
2545
2574
  export class DOMDocumentSnapshot extends DOMDocument {
2575
+ readonly #snapshotSecurityOrigin: SecurityOrigin;
2576
+
2577
+ constructor(
2578
+ domModel: DOMModel,
2579
+ payload: Protocol.DOM.Node,
2580
+ frameId: Protocol.Page.FrameId|null|undefined,
2581
+ securityOrigin: SecurityOrigin,
2582
+ ) {
2583
+ super(domModel, payload, frameId);
2584
+ this.#snapshotSecurityOrigin = securityOrigin;
2585
+ }
2586
+
2587
+ override securityOrigin(): SecurityOrigin {
2588
+ return this.#snapshotSecurityOrigin;
2589
+ }
2590
+
2546
2591
  override init(
2547
2592
  _doc: DOMDocument|null, _isInShadowTree: boolean, _payload: Protocol.DOM.Node,
2548
2593
  _retainedNodes?: Set<Protocol.DOM.BackendNodeId>|undefined): void {
@@ -1480,10 +1480,6 @@ export class Scope implements ScopeChainEntry {
1480
1480
  return undefined;
1481
1481
  }
1482
1482
 
1483
- empty(): boolean {
1484
- return Boolean(this.#payload.empty);
1485
- }
1486
-
1487
1483
  extraProperties(): RemoteObjectProperty[] {
1488
1484
  if (this !== this.#callFrame.localScope() || this.#callFrame.script.isWasm()) {
1489
1485
  return [];
@@ -343,24 +343,25 @@ export class PageResourceLoader extends Common.ObjectWrapper.ObjectWrapper<Event
343
343
  // directive is present. A null/error response keeps the guard armed so that a
344
344
  // detached-frame or protocol-error path cannot fall through to loadFromHostBindings.
345
345
  let mustEnforceCSP = isHttp;
346
- if (isHttp && initiator.target) {
347
- const networkManager = initiator.target.model(NetworkManager);
346
+ let frameTarget: Target|null = initiator.target;
347
+ while (frameTarget && !frameTarget.model(ResourceTreeModel)) {
348
+ frameTarget = frameTarget.parentTarget();
349
+ }
350
+ const frameId = initiator.frameId ?? frameTarget?.model(ResourceTreeModel)?.mainFrame?.id ?? null;
351
+ if (isHttp && frameTarget) {
352
+ const networkManager = frameTarget.model(NetworkManager);
348
353
  if (networkManager) {
349
- let status = await networkManager.getSecurityIsolationStatus(initiator.frameId);
350
- if (!status && initiator.frameId) {
351
- status = await networkManager.getSecurityIsolationStatus(null);
352
- }
353
- if (status) {
354
- const csps = status.csp ?? [];
355
- mustEnforceCSP = csps.some(csp => csp.effectiveDirectives.includes('connect-src') ||
356
- csp.effectiveDirectives.includes('default-src'));
354
+ const status = await networkManager.getSecurityIsolationStatus(frameId);
355
+ if (status?.csp) {
356
+ mustEnforceCSP = status.csp.some(csp => csp.effectiveDirectives.includes('connect-src') ||
357
+ csp.effectiveDirectives.includes('default-src'));
357
358
  }
358
359
  }
359
360
  }
360
361
 
361
362
  try {
362
363
  Host.userMetrics.developerResourceLoaded(Host.UserMetrics.DeveloperResourceLoaded.LOAD_THROUGH_PAGE_VIA_TARGET);
363
- const result = await this.loadFromTarget(initiator.target, initiator.frameId, url, isBinary);
364
+ const result = await this.loadFromTarget(frameTarget ?? initiator.target, frameId, url, isBinary);
364
365
  return result;
365
366
  } catch (e) {
366
367
  if (e instanceof Error) {
@@ -33,7 +33,8 @@ export interface SourceMapV3Object {
33
33
 
34
34
  names?: string[];
35
35
  ignoreList?: number[];
36
- scopes?: string;
36
+ scopes?: Array<string|null>;
37
+ ranges?: string[];
37
38
  rangeMappings?: string;
38
39
  debugId?: string;
39
40
  x_google_linecount?: number;
@@ -609,11 +610,11 @@ export class SourceMap {
609
610
  if (!this.#scopesInfo) {
610
611
  this.#scopesInfo = new SourceMapScopesInfo(this, {scopes: [], ranges: []});
611
612
  }
612
- if (map.scopes) {
613
+ if (map.scopes || map.ranges) {
613
614
  const {scopes, ranges} = ScopesCodec.decode(
614
615
  map as ScopesCodec.SourceMapJson,
615
616
  {mode: ScopesCodec.DecodeMode.LAX, generatedOffset: {line: baseLineNumber, column: baseColumnNumber}});
616
- this.#scopesInfo.addOriginalScopes(scopes);
617
+ this.#scopesInfo.addOriginalScopes(scopes.length ? scopes : new Array(map.sources.length).fill(null));
617
618
  this.#scopesInfo.addGeneratedRanges(ranges);
618
619
  } else if (map.x_com_bloomberg_sourcesFunctionMappings) {
619
620
  const originalScopes = this.parseBloombergScopes(map);
@@ -662,7 +663,7 @@ export class SourceMap {
662
663
  }
663
664
  }
664
665
 
665
- private parseBloombergScopes(map: SourceMapV3Object): Array<ScopesCodec.OriginalScope|null> {
666
+ private parseBloombergScopes(map: SourceMapV3Object): Array<ScopesCodec.OriginalScope[]|null> {
666
667
  const scopeList = map.x_com_bloomberg_sourcesFunctionMappings;
667
668
  if (!scopeList) {
668
669
  throw new Error('Cant decode pasta scopes without x_com_bloomberg_sourcesFunctionMappings field');
@@ -851,7 +852,8 @@ export class SourceMap {
851
852
  }
852
853
 
853
854
  const {line, column} = scriptRelativePosition(location);
854
- return this.#scopesInfo.resolveMappedVariablesAtPosition(line, column, ignoreInnerBlockScopes);
855
+ return this.#scopesInfo.resolveMappedVariablesAtPosition(line, column, ignoreInnerBlockScopes,
856
+ location.inlineFrameIndex);
855
857
  }
856
858
 
857
859
  findOriginalFunctionName(position: ScopesCodec.Position): string|null {
@@ -13,19 +13,16 @@ export interface NamedFunctionRange {
13
13
  }
14
14
 
15
15
  /**
16
- * Turns a list of {@link NamedFunctionRange}s into a single {@link OriginalScope} tree nested
17
- * according to the start/end position. Each range is turned into a OriginalScope with the `isStackFrame`
16
+ * Turns a list of {@link NamedFunctionRange}s into a list of {@link OriginalScope} trees nested
17
+ * according to the start/end position. Each range is turned into an OriginalScope with the `isStackFrame`
18
18
  * bit set to denote it as a function and a generic "Function" label.
19
19
  *
20
- * We nest all these function scopes underneath a single global scope that always starts at (0, 0) and
21
- * reaches to the largest end position.
22
- *
23
20
  * `ranges` can be unsorted but will be sorted in-place.
24
21
  *
25
22
  * @throws if the ranges are not nested properly. Concretely: start < end for each range, and no
26
23
  * "straddling" (i.e. partially overlapping ranges).
27
24
  */
28
- export function buildOriginalScopes(ranges: NamedFunctionRange[]): ScopesCodec.OriginalScope {
25
+ export function buildOriginalScopes(ranges: NamedFunctionRange[]): ScopesCodec.OriginalScope[] {
29
26
  validateStartBeforeEnd(ranges);
30
27
 
31
28
  // 1. Sort ranges by ascending start position.
@@ -33,27 +30,15 @@ export function buildOriginalScopes(ranges: NamedFunctionRange[]): ScopesCodec.O
33
30
  // with the higher end position first, because it's the parent.
34
31
  ranges.sort((a, b) => comparePositions(a.start, b.start) || comparePositions(b.end, a.end));
35
32
 
36
- const root: ScopesCodec.OriginalScope = {
37
- start: {line: 0, column: 0},
38
- end: {line: Number.POSITIVE_INFINITY, column: Number.POSITIVE_INFINITY},
39
- kind: 'Global',
40
- isStackFrame: false,
41
- children: [],
42
- variables: [],
43
- };
44
-
45
- // 2. Build the tree from the ranges.
46
- const stack: ScopesCodec.OriginalScope[] = [root];
33
+ // 2. Build the trees from the ranges.
34
+ const roots: ScopesCodec.OriginalScope[] = [];
35
+ const stack: ScopesCodec.OriginalScope[] = [];
47
36
  for (const range of ranges) {
48
37
  // Pop all scopes that precede the current entry (to find the right parent).
49
- let stackTop = stack.at(-1) as ScopesCodec.OriginalScope;
50
- while (true) {
51
- if (comparePositions(stackTop.end, range.start) <= 0) {
52
- stack.pop();
53
- stackTop = stack.at(-1) as ScopesCodec.OriginalScope;
54
- } else {
55
- break;
56
- }
38
+ let stackTop = stack.at(-1);
39
+ while (stackTop && comparePositions(stackTop.end, range.start) <= 0) {
40
+ stack.pop();
41
+ stackTop = stack.at(-1);
57
42
  }
58
43
 
59
44
  /*
@@ -66,22 +51,21 @@ export function buildOriginalScopes(ranges: NamedFunctionRange[]): ScopesCodec.O
66
51
  *
67
52
  *i.e.: B.start < A.end < B.end
68
53
  */
69
- if (comparePositions(range.start, stackTop.end) < 0 && comparePositions(stackTop.end, range.end) < 0) {
70
- throw new Error(`Range ${JSON.stringify(range)} and ${JSON.stringify(stackTop)} partially overlap.`);
54
+ if (stackTop && comparePositions(range.start, stackTop.end) < 0 && comparePositions(stackTop.end, range.end) < 0) {
55
+ throw new Error(`Range ${JSON.stringify(range)} and ${
56
+ JSON.stringify(stackTop, (key, value) => key === 'parent' ? undefined : value)} partially overlap.`);
71
57
  }
72
58
 
73
- const scope = createScopeFrom(range);
74
- stackTop.children.push(scope);
59
+ const scope = createScopeFrom(range, stackTop);
60
+ if (stackTop) {
61
+ stackTop.children.push(scope);
62
+ } else {
63
+ roots.push(scope);
64
+ }
75
65
  stack.push(scope);
76
66
  }
77
67
 
78
- // 3. Update root.end.
79
- const lastChild = root.children.at(-1);
80
- if (lastChild) {
81
- root.end = lastChild.end;
82
- }
83
-
84
- return root;
68
+ return roots;
85
69
  }
86
70
 
87
71
  function validateStartBeforeEnd(ranges: NamedFunctionRange[]): void {
@@ -92,11 +76,12 @@ function validateStartBeforeEnd(ranges: NamedFunctionRange[]): void {
92
76
  }
93
77
  }
94
78
 
95
- function createScopeFrom(range: NamedFunctionRange): ScopesCodec.OriginalScope {
79
+ function createScopeFrom(range: NamedFunctionRange, parent?: ScopesCodec.OriginalScope): ScopesCodec.OriginalScope {
96
80
  return {
97
81
  ...range,
98
82
  kind: 'Function',
99
83
  isStackFrame: true,
84
+ parent,
100
85
  children: [],
101
86
  variables: [],
102
87
  };
@@ -183,7 +183,7 @@ class SourceMapScopeRemoteObject extends RemoteObjectImpl {
183
183
  if (value === null) {
184
184
  return SourceMapScopeRemoteObject.#unavailableProperty(variable);
185
185
  }
186
- return new RemoteObjectProperty(variable, value, /* enumerable */ false, /* writable */ false, /* isOwn */ true,
186
+ return new RemoteObjectProperty(variable, value, /* enumerable */ true, /* writable */ false, /* isOwn */ true,
187
187
  /* wasThrown */ false);
188
188
  });
189
189
 
@@ -269,7 +269,7 @@ class SourceMapScopeRemoteObject extends RemoteObjectImpl {
269
269
  }
270
270
 
271
271
  static #unavailableProperty(name: string): RemoteObjectProperty {
272
- return new RemoteObjectProperty(
273
- name, null, /* enumerable */ false, /* writeable */ false, /* isOwn */ true, /* wasThrown */ false);
272
+ return new RemoteObjectProperty(name, null, /* enumerable */ true, /* writeable */ false, /* isOwn */ true,
273
+ /* wasThrown */ false);
274
274
  }
275
275
  }