chrome-devtools-frontend 1.0.1586699 → 1.0.1587572

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 (26) hide show
  1. package/front_end/entrypoint_template.html +5 -1
  2. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  3. package/front_end/generated/protocol.ts +2 -0
  4. package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -2
  5. package/front_end/panels/elements/ElementsPanel.ts +114 -15
  6. package/front_end/panels/network/NetworkItemView.ts +4 -3
  7. package/front_end/panels/network/{components/RequestHeadersView.ts → RequestHeadersView.ts} +30 -34
  8. package/front_end/panels/network/components/RequestHeaderSection.ts +3 -0
  9. package/front_end/panels/network/components/components.ts +0 -2
  10. package/front_end/panels/network/network.ts +3 -0
  11. package/front_end/third_party/chromium/README.chromium +1 -1
  12. package/front_end/third_party/puppeteer/README.chromium +2 -2
  13. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  14. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  15. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  16. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  17. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +3 -3
  18. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  19. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  20. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  21. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  22. package/front_end/third_party/puppeteer/package/package.json +1 -1
  23. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  24. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  25. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +113 -133
  26. package/package.json +1 -1
@@ -14,7 +14,11 @@
14
14
  }
15
15
  }
16
16
  </style>
17
- <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' https://chrome-devtools-frontend.appspot.com">
17
+ <meta
18
+ http-equiv="Content-Security-Policy"
19
+ content="default-src 'self' devtools: data:; style-src 'self' 'unsafe-inline' devtools:; object-src 'none'; script-src
20
+ 'self' https://chrome-devtools-frontend.appspot.com; img-src 'self' data:; frame-src * data:; connect-src data:
21
+ https://chromeuxreport.googleapis.com 'self' devtools:;">
18
22
  <meta name="referrer" content="no-referrer">
19
23
  <script type="module" src="./entrypoints/%ENTRYPOINT_NAME%/%ENTRYPOINT_NAME%.js"></script>
20
24
  <link href="./application_tokens.css" rel="stylesheet">
@@ -857,7 +857,7 @@ inspectorBackend.registerCommand("Network.disable", [], [], "Disables network tr
857
857
  inspectorBackend.registerCommand("Network.emulateNetworkConditions", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}, {"name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null}, {"name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null}, {"name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null}], [], "Activates emulation of network conditions. This command is deprecated in favor of the emulateNetworkConditionsByRule and overrideNetworkState commands, which can be used together to the same effect.");
858
858
  inspectorBackend.registerCommand("Network.emulateNetworkConditionsByRule", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "matchedNetworkConditions", "type": "array", "optional": false, "description": "Configure conditions for matching requests. If multiple entries match a request, the first entry wins. Global conditions can be configured by leaving the urlPattern for the conditions empty. These global conditions are also applied for throttling of p2p connections.", "typeRef": "Network.NetworkConditions"}], ["ruleIds"], "Activates emulation of network conditions for individual requests using URL match patterns. Unlike the deprecated Network.emulateNetworkConditions this method does not affect `navigator` state. Use Network.overrideNetworkState to explicitly modify `navigator` behavior.");
859
859
  inspectorBackend.registerCommand("Network.overrideNetworkState", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}], [], "Override the state of navigator.onLine and navigator.connection.");
860
- inspectorBackend.registerCommand("Network.enable", [{"name": "maxTotalBufferSize", "type": "number", "optional": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxResourceBufferSize", "type": "number", "optional": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxPostDataSize", "type": "number", "optional": true, "description": "Longest post body size (in bytes) that would be included in requestWillBeSent notification", "typeRef": null}, {"name": "reportDirectSocketTraffic", "type": "boolean", "optional": true, "description": "Whether DirectSocket chunk send/receive events should be reported.", "typeRef": null}, {"name": "enableDurableMessages", "type": "boolean", "optional": true, "description": "Enable storing response bodies outside of renderer, so that these survive a cross-process navigation. Requires maxTotalBufferSize to be set. Currently defaults to false. This field is being deprecated in favor of the dedicated configureDurableMessages command, due to the possibility of deadlocks when awaiting Network.enable before issuing Runtime.runIfWaitingForDebugger.", "typeRef": null}], [], "Enables network tracking, network events will now be delivered to the client.");
860
+ inspectorBackend.registerCommand("Network.enable", [{"name": "maxTotalBufferSize", "type": "number", "optional": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc). This is the maximum number of bytes that will be collected by this DevTools session.", "typeRef": null}, {"name": "maxResourceBufferSize", "type": "number", "optional": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxPostDataSize", "type": "number", "optional": true, "description": "Longest post body size (in bytes) that would be included in requestWillBeSent notification", "typeRef": null}, {"name": "reportDirectSocketTraffic", "type": "boolean", "optional": true, "description": "Whether DirectSocket chunk send/receive events should be reported.", "typeRef": null}, {"name": "enableDurableMessages", "type": "boolean", "optional": true, "description": "Enable storing response bodies outside of renderer, so that these survive a cross-process navigation. Requires maxTotalBufferSize to be set. Currently defaults to false. This field is being deprecated in favor of the dedicated configureDurableMessages command, due to the possibility of deadlocks when awaiting Network.enable before issuing Runtime.runIfWaitingForDebugger.", "typeRef": null}], [], "Enables network tracking, network events will now be delivered to the client.");
861
861
  inspectorBackend.registerCommand("Network.configureDurableMessages", [{"name": "maxTotalBufferSize", "type": "number", "optional": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxResourceBufferSize", "type": "number", "optional": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}], [], "Configures storing response bodies outside of renderer, so that these survive a cross-process navigation. If maxTotalBufferSize is not set, durable messages are disabled.");
862
862
  inspectorBackend.registerCommand("Network.getAllCookies", [], ["cookies"], "Returns all browser cookies. Depending on the backend support, will return detailed cookie information in the `cookies` field. Deprecated. Use Storage.getCookies instead.");
863
863
  inspectorBackend.registerCommand("Network.getCertificate", [{"name": "origin", "type": "string", "optional": false, "description": "Origin to get certificate for.", "typeRef": null}], ["tableNames"], "Returns the DER-encoded certificate.");
@@ -11896,6 +11896,8 @@ export namespace Network {
11896
11896
  export interface EnableRequest {
11897
11897
  /**
11898
11898
  * Buffer size in bytes to use when preserving network payloads (XHRs, etc).
11899
+ * This is the maximum number of bytes that will be collected by this
11900
+ * DevTools session.
11899
11901
  */
11900
11902
  maxTotalBufferSize?: integer;
11901
11903
  /**
@@ -15,7 +15,6 @@ import * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrappe
15
15
  import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';
16
16
  import * as UI from '../../ui/legacy/legacy.js';
17
17
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
18
- import * as NetworkComponents from '../network/components/components.js';
19
18
  import * as Network from '../network/network.js';
20
19
 
21
20
  import * as ApplicationComponents from './components/components.js';
@@ -545,7 +544,7 @@ export class RequestView extends UI.Widget.VBox {
545
544
  this.tabbedPane.appendTab(
546
545
  'headers', i18nString(UIStrings.headers),
547
546
  LegacyWrapper.LegacyWrapper.legacyWrapper(
548
- UI.Widget.VBox, new NetworkComponents.RequestHeadersView.RequestHeadersView(request)));
547
+ UI.Widget.VBox, new Network.RequestHeadersView.RequestHeadersView(request)));
549
548
  this.tabbedPane.appendTab(
550
549
  'preview', i18nString(UIStrings.preview), new Network.RequestPreviewView.RequestPreviewView(request));
551
550
  this.tabbedPane.show(this.element);
@@ -227,6 +227,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
227
227
  domTreeButton?: HTMLElement;
228
228
  private selectedNodeOnReset?: SDK.DOMModel.DOMNode;
229
229
  private hasNonDefaultSelectedNode?: boolean;
230
+ #restorationGeneration = 0;
230
231
  private searchConfig?: UI.SearchableView.SearchConfig;
231
232
  private omitDefaultSelection?: boolean;
232
233
  private notFirstInspectElement?: boolean;
@@ -609,6 +610,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
609
610
  if (focus) {
610
611
  this.selectedNodeOnReset = selectedNode;
611
612
  this.hasNonDefaultSelectedNode = true;
613
+ this.#restorationGeneration++;
612
614
  }
613
615
 
614
616
  const executionContexts = selectedNode.domModel().runtimeModel().executionContexts();
@@ -645,32 +647,128 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
645
647
  }
646
648
 
647
649
  const savedSelectedNodeOnReset = this.selectedNodeOnReset;
648
- void restoreNode.call(this, domModel, this.selectedNodeOnReset || null);
650
+ void this.restoreSelectedNodeAfterUpdate(domModel, this.selectedNodeOnReset || null, savedSelectedNodeOnReset);
651
+ }
652
+
653
+ /**
654
+ * Best-effort restoration of the previously focused node after a reload.
655
+ *
656
+ * The CDP path-based mechanism works well for stable DOMs, but can be
657
+ * unreliable for pages that render asynchronously after the initial
658
+ * document update. To improve reliability we retry a few times, and also
659
+ * fall back to evaluating a JS path (document.querySelector(...)) when
660
+ * possible.
661
+ *
662
+ * Node resolution (computation) is separated from view state updates:
663
+ * resolveNode returns a DOMNode|null, and this method handles selection.
664
+ */
665
+ private async restoreSelectedNodeAfterUpdate(
666
+ domModel: SDK.DOMModel.DOMModel, staleNode: SDK.DOMModel.DOMNode|null,
667
+ savedSelectedNodeOnReset: SDK.DOMModel.DOMNode|undefined): Promise<void> {
668
+ // Fast path: no previous node to restore -- just select the fallback
669
+ // synchronously so callers that check selection immediately still work.
670
+ if (!staleNode) {
671
+ this.trySetFallbackSelection(domModel);
672
+ return;
673
+ }
674
+
675
+ const nodePath = staleNode.path();
676
+
677
+ // Keep the panel usable quickly by selecting a reasonable default node as
678
+ // soon as we can, but continue trying to restore the stale node.
679
+ let didSetFallbackSelection = false;
649
680
 
650
- async function restoreNode(
651
- this: ElementsPanel, domModel: SDK.DOMModel.DOMModel, staleNode: SDK.DOMModel.DOMNode|null): Promise<void> {
652
- const nodePath = staleNode ? staleNode.path() : null;
653
- const restoredNodeId = nodePath ? await domModel.pushNodeByPathToFrontend(nodePath) : null;
681
+ // Retry with exponential-ish backoff, capping total wait at ~3s.
682
+ // Most async-rendered pages settle well within this window.
683
+ const attemptDelaysMs = [0, 250, 500, 1000, 1500];
654
684
 
685
+ // Capture the restoration generation so any user interaction (node
686
+ // selection, style editing, node reveal, etc.) cancels pending retries.
687
+ const restorationGeneration = this.#restorationGeneration;
688
+
689
+ for (let attempt = 0; attempt < attemptDelaysMs.length; ++attempt) {
655
690
  if (savedSelectedNodeOnReset !== this.selectedNodeOnReset) {
656
691
  return;
657
692
  }
658
- let node = domModel.nodeForId(restoredNodeId);
659
- if (!node) {
660
- const inspectedDocument = domModel.existingDocument();
661
- node = inspectedDocument ? inspectedDocument.body || inspectedDocument.documentElement : null;
693
+ if (this.hasNonDefaultSelectedNode || this.pendingNodeReveal ||
694
+ restorationGeneration !== this.#restorationGeneration) {
695
+ return;
662
696
  }
663
- // If `node` is null here, the document hasn't been transmitted from the backend yet
664
- // and isn't in a valid state to have a default-selected node. Another document update
665
- // should be forthcoming. In the meantime, don't set the default-selected node or notify
666
- // the test that it's ready, because it isn't.
667
- if (node) {
668
- this.setDefaultSelectedNode(node);
697
+
698
+ if (attemptDelaysMs[attempt]) {
699
+ await new Promise<void>(resolve => window.setTimeout(resolve, attemptDelaysMs[attempt]));
700
+ }
701
+
702
+ if (savedSelectedNodeOnReset !== this.selectedNodeOnReset) {
703
+ return;
704
+ }
705
+ if (this.hasNonDefaultSelectedNode || this.pendingNodeReveal ||
706
+ restorationGeneration !== this.#restorationGeneration) {
707
+ return;
708
+ }
709
+
710
+ // Computation: resolve the node without touching view state.
711
+ const restoredNode = await this.resolveNodeForRestoration(domModel, nodePath);
712
+
713
+ if (restoredNode) {
714
+ this.setDefaultSelectedNode(restoredNode);
669
715
  this.lastSelectedNodeSelectedForTest();
716
+ return;
717
+ }
718
+
719
+ if (!didSetFallbackSelection) {
720
+ // If we cannot compute a fallback selection yet, the document likely
721
+ // has not been transmitted from the backend and isn't in a valid state
722
+ // to have a default-selected node. Another document update should be
723
+ // forthcoming. In the meantime, don't notify tests that selection is
724
+ // ready, because it isn't.
725
+ if (!this.trySetFallbackSelection(domModel)) {
726
+ return;
727
+ }
728
+ didSetFallbackSelection = true;
670
729
  }
671
730
  }
672
731
  }
673
732
 
733
+ /**
734
+ * Attempts to resolve a DOM node by its CDP path.
735
+ * Pure computation -- does not modify view state.
736
+ */
737
+ private async resolveNodeForRestoration(domModel: SDK.DOMModel.DOMModel, nodePath: string|null):
738
+ Promise<SDK.DOMModel.DOMNode|null> {
739
+ try {
740
+ if (nodePath) {
741
+ const restoredNodeId = await domModel.pushNodeByPathToFrontend(nodePath);
742
+ const restoredNode = domModel.nodeForId(restoredNodeId);
743
+ if (restoredNode) {
744
+ return restoredNode;
745
+ }
746
+ }
747
+ } catch {
748
+ // CDP calls (pushNodeByPathToFrontend) can reject when the target or
749
+ // session is closed, e.g. if the page navigates again while we are
750
+ // retrying. Safe to swallow: we either retry on the next iteration or
751
+ // fall through to the fallback node.
752
+ }
753
+ return null;
754
+ }
755
+
756
+ private trySetFallbackSelection(domModel: SDK.DOMModel.DOMModel): boolean {
757
+ const inspectedDocument = domModel.existingDocument();
758
+ const fallbackNode = inspectedDocument ? inspectedDocument.body || inspectedDocument.documentElement : null;
759
+ if (!fallbackNode) {
760
+ return false;
761
+ }
762
+
763
+ this.setDefaultSelectedNode(fallbackNode);
764
+ this.lastSelectedNodeSelectedForTest();
765
+ return true;
766
+ }
767
+
768
+ cancelPendingRestoration(): void {
769
+ this.#restorationGeneration++;
770
+ }
771
+
674
772
  private lastSelectedNodeSelectedForTest(): void {
675
773
  }
676
774
 
@@ -1373,6 +1471,7 @@ export class DOMNodeRevealer implements Common.Revealer.Revealer<
1373
1471
  omitFocus?: boolean): Promise<void> {
1374
1472
  const panel = ElementsPanel.instance();
1375
1473
  panel.pendingNodeReveal = true;
1474
+ panel.cancelPendingRestoration();
1376
1475
 
1377
1476
  return (new Promise<void>(revealPromise)).catch((reason: Error) => {
1378
1477
  let message: string;
@@ -22,6 +22,7 @@ import * as NetworkComponents from './components/components.js';
22
22
  import {EventSourceMessagesView} from './EventSourceMessagesView.js';
23
23
  import {RequestCookiesView} from './RequestCookiesView.js';
24
24
  import {RequestDeviceBoundSessionsView} from './RequestDeviceBoundSessionsView.js';
25
+ import * as RequestHeadersView from './RequestHeadersView.js';
25
26
  import {RequestInitiatorView} from './RequestInitiatorView.js';
26
27
  import {RequestPayloadView} from './RequestPayloadView.js';
27
28
  import {RequestPreviewView} from './RequestPreviewView.js';
@@ -148,7 +149,7 @@ const requestToPreviewView = new WeakMap<SDK.NetworkRequest.NetworkRequest, Requ
148
149
  export class NetworkItemView extends UI.TabbedPane.TabbedPane {
149
150
  #request: SDK.NetworkRequest.NetworkRequest;
150
151
  readonly #resourceViewTabSetting: Common.Settings.Setting<NetworkForward.UIRequestLocation.UIRequestTabs>;
151
- readonly #headersViewComponent: NetworkComponents.RequestHeadersView.RequestHeadersView|undefined;
152
+ readonly #headersViewComponent: RequestHeadersView.RequestHeadersView|undefined;
152
153
  #payloadView: RequestPayloadView|null = null;
153
154
  readonly #responseView: RequestResponseView|undefined;
154
155
  #cookiesView: RequestCookiesView|null = null;
@@ -174,7 +175,7 @@ export class NetworkItemView extends UI.TabbedPane.TabbedPane {
174
175
  i18nString(UIStrings.headers));
175
176
  } else {
176
177
  this.#firstTab = NetworkForward.UIRequestLocation.UIRequestTabs.HEADERS_COMPONENT;
177
- this.#headersViewComponent = new NetworkComponents.RequestHeadersView.RequestHeadersView(request);
178
+ this.#headersViewComponent = new RequestHeadersView.RequestHeadersView(request);
178
179
  this.appendTab(
179
180
  NetworkForward.UIRequestLocation.UIRequestTabs.HEADERS_COMPONENT, i18nString(UIStrings.headers),
180
181
  LegacyWrapper.LegacyWrapper.legacyWrapper(UI.Widget.VBox, this.#headersViewComponent),
@@ -426,7 +427,7 @@ export class NetworkItemView extends UI.TabbedPane.TabbedPane {
426
427
  this.#headersViewComponent?.revealHeader(section, header);
427
428
  }
428
429
 
429
- getHeadersViewComponent(): NetworkComponents.RequestHeadersView.RequestHeadersView|undefined {
430
+ getHeadersViewComponent(): RequestHeadersView.RequestHeadersView|undefined {
430
431
  return this.#headersViewComponent;
431
432
  }
432
433
  }
@@ -2,31 +2,26 @@
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
  /* eslint-disable @devtools/no-lit-render-outside-of-view */
5
- import '../../../ui/kit/kit.js';
6
-
7
- import * as Common from '../../../core/common/common.js';
8
- import * as Host from '../../../core/host/host.js';
9
- import * as i18n from '../../../core/i18n/i18n.js';
10
- import * as Platform from '../../../core/platform/platform.js';
11
- import * as SDK from '../../../core/sdk/sdk.js';
12
- import * as Persistence from '../../../models/persistence/persistence.js';
13
- import * as Workspace from '../../../models/workspace/workspace.js';
14
- import * as NetworkForward from '../../../panels/network/forward/forward.js';
15
- import * as Buttons from '../../../ui/components/buttons/buttons.js';
16
- import * as Input from '../../../ui/components/input/input.js';
17
- import * as LegacyWrapper from '../../../ui/components/legacy_wrapper/legacy_wrapper.js';
18
- import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
19
- import * as UI from '../../../ui/legacy/legacy.js';
20
- import * as Lit from '../../../ui/lit/lit.js';
21
- import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
22
- import * as Sources from '../../sources/sources.js';
23
-
24
- import {RequestHeaderSection} from './RequestHeaderSection.js';
25
- import requestHeadersViewStyles from './RequestHeadersView.css.js';
26
- import {
27
- RESPONSE_HEADER_SECTION_DATA_KEY,
28
- type ResponseHeaderSectionData,
29
- } from './ResponseHeaderSection.js';
5
+ import '../../ui/kit/kit.js';
6
+
7
+ import * as Common from '../../core/common/common.js';
8
+ import * as Host from '../../core/host/host.js';
9
+ import * as i18n from '../../core/i18n/i18n.js';
10
+ import * as Platform from '../../core/platform/platform.js';
11
+ import * as SDK from '../../core/sdk/sdk.js';
12
+ import * as Persistence from '../../models/persistence/persistence.js';
13
+ import * as Workspace from '../../models/workspace/workspace.js';
14
+ import * as NetworkForward from '../../panels/network/forward/forward.js';
15
+ import * as Buttons from '../../ui/components/buttons/buttons.js';
16
+ import * as Input from '../../ui/components/input/input.js';
17
+ import * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';
18
+ import * as RenderCoordinator from '../../ui/components/render_coordinator/render_coordinator.js';
19
+ import * as UI from '../../ui/legacy/legacy.js';
20
+ import * as Lit from '../../ui/lit/lit.js';
21
+ import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
22
+ import * as Sources from '../sources/sources.js';
23
+
24
+ import * as NetworkComponents from './components/components.js';
30
25
 
31
26
  const RAW_HEADER_CUTOFF = 3000;
32
27
  const {render, html} = Lit;
@@ -105,7 +100,7 @@ const UIStrings = {
105
100
  */
106
101
  statusCode: 'Status Code',
107
102
  } as const;
108
- const str_ = i18n.i18n.registerUIStrings('panels/network/components/RequestHeadersView.ts', UIStrings);
103
+ const str_ = i18n.i18n.registerUIStrings('panels/network/RequestHeadersView.ts', UIStrings);
109
104
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
110
105
 
111
106
  export class RequestHeadersView extends LegacyWrapper.LegacyWrapper.WrappableComponent {
@@ -146,7 +141,7 @@ export class RequestHeadersView extends LegacyWrapper.LegacyWrapper.WrappableCom
146
141
  }
147
142
 
148
143
  #resetAndRefreshHeadersView(): void {
149
- this.#request.deleteAssociatedData(RESPONSE_HEADER_SECTION_DATA_KEY);
144
+ this.#request.deleteAssociatedData(NetworkComponents.ResponseHeaderSection.RESPONSE_HEADER_SECTION_DATA_KEY);
150
145
  void this.render();
151
146
  }
152
147
 
@@ -194,7 +189,7 @@ export class RequestHeadersView extends LegacyWrapper.LegacyWrapper.WrappableCom
194
189
  // Disabled until https://crbug.com/1079231 is fixed.
195
190
  // clang-format off
196
191
  render(html`
197
- <style>${requestHeadersViewStyles}</style>
192
+ <style>${NetworkComponents.RequestHeaderSection.requestHeadersViewStyles}</style>
198
193
  <style>${Input.checkboxStyles}</style>
199
194
  ${this.#renderGeneralSection()}
200
195
  ${this.#renderEarlyHintsHeaders()}
@@ -230,7 +225,7 @@ export class RequestHeadersView extends LegacyWrapper.LegacyWrapper.WrappableCom
230
225
  <devtools-early-hints-header-section .data=${{
231
226
  request: this.#request,
232
227
  toReveal: this.#toReveal,
233
- } as ResponseHeaderSectionData}></devtools-early-hints-header-section>
228
+ } as NetworkComponents.ResponseHeaderSection.ResponseHeaderSectionData}></devtools-early-hints-header-section>
234
229
  `
235
230
  });
236
231
  }
@@ -260,7 +255,7 @@ export class RequestHeadersView extends LegacyWrapper.LegacyWrapper.WrappableCom
260
255
  <devtools-response-header-section .data=${{
261
256
  request: this.#request,
262
257
  toReveal: this.#toReveal,
263
- } as ResponseHeaderSectionData} jslog=${
258
+ } as NetworkComponents.ResponseHeaderSection.ResponseHeaderSectionData} jslog=${
264
259
  VisualLogging.section('response-headers')}></devtools-response-header-section>
265
260
  `
266
261
  });
@@ -344,10 +339,11 @@ export class RequestHeadersView extends LegacyWrapper.LegacyWrapper.WrappableCom
344
339
  contents: (this.#showRequestHeadersText && requestHeadersText) ?
345
340
  this.#renderRawHeaders(requestHeadersText, false) :
346
341
  html`
347
- <devtools-widget .widgetConfig=${UI.Widget.widgetConfig(RequestHeaderSection, {
348
- request: this.#request,
349
- toReveal: this.#toReveal,
350
- })} jslog=${VisualLogging.section('request-headers')}></devtools-widget>`
342
+ <devtools-widget .widgetConfig=${
343
+ UI.Widget.widgetConfig(NetworkComponents.RequestHeaderSection.RequestHeaderSection, {
344
+ request: this.#request,
345
+ toReveal: this.#toReveal,
346
+ })} jslog=${VisualLogging.section('request-headers')}></devtools-widget>`
351
347
  });
352
348
  }
353
349
 
@@ -14,6 +14,9 @@ import * as NetworkForward from '../forward/forward.js';
14
14
 
15
15
  import {EditingAllowedStatus, type HeaderDescriptor} from './HeaderSectionRow.js';
16
16
  import requestHeaderSectionStyles from './RequestHeaderSection.css.js';
17
+ import requestHeadersViewStyles from './RequestHeadersView.css.js';
18
+
19
+ export {requestHeadersViewStyles};
17
20
 
18
21
  const {render, html} = Lit;
19
22
 
@@ -6,7 +6,6 @@ import * as DirectSocketConnectionView from './DirectSocketConnectionView.js';
6
6
  import * as EditableSpan from './EditableSpan.js';
7
7
  import * as HeaderSectionRow from './HeaderSectionRow.js';
8
8
  import * as RequestHeaderSection from './RequestHeaderSection.js';
9
- import * as RequestHeadersView from './RequestHeadersView.js';
10
9
  import * as RequestTrustTokensView from './RequestTrustTokensView.js';
11
10
  import * as ResponseHeaderSection from './ResponseHeaderSection.js';
12
11
 
@@ -15,7 +14,6 @@ export {
15
14
  EditableSpan,
16
15
  HeaderSectionRow,
17
16
  RequestHeaderSection,
18
- RequestHeadersView,
19
17
  RequestTrustTokensView,
20
18
  ResponseHeaderSection,
21
19
  };
@@ -18,6 +18,7 @@ import './NetworkSearchScope.js';
18
18
  import './NetworkWaterfallColumn.js';
19
19
  import './RequestCookiesView.js';
20
20
  import './RequestHTMLView.js';
21
+ import './RequestHeadersView.js';
21
22
  import './RequestInitiatorView.js';
22
23
  import './RequestResponseView.js';
23
24
  import './RequestPreviewView.js';
@@ -44,6 +45,7 @@ import * as NetworkWaterfallColumn from './NetworkWaterfallColumn.js';
44
45
  import * as RequestConditionsDrawer from './RequestConditionsDrawer.js';
45
46
  import * as RequestCookiesView from './RequestCookiesView.js';
46
47
  import * as RequestDeviceBoundSessionsView from './RequestDeviceBoundSessionsView.js';
48
+ import * as RequestHeadersView from './RequestHeadersView.js';
47
49
  import * as RequestHTMLView from './RequestHTMLView.js';
48
50
  import * as RequestInitiatorView from './RequestInitiatorView.js';
49
51
  import * as RequestPayloadView from './RequestPayloadView.js';
@@ -72,6 +74,7 @@ export {
72
74
  RequestConditionsDrawer,
73
75
  RequestCookiesView,
74
76
  RequestDeviceBoundSessionsView,
77
+ RequestHeadersView,
75
78
  RequestHTMLView,
76
79
  RequestInitiatorView,
77
80
  RequestPayloadView,
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: https://chromium.googlesource.com/chromium/src
3
3
  Version: N/A
4
- Revision: 649f914735bb39cbd9bfe68673921ced1cc2e71f
4
+ Revision: ca9006bfc6f6f58d2fcd25b7c78dbd3b1289f949
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE
@@ -1,10 +1,10 @@
1
1
  Name: Puppeteer Core
2
2
  Short Name: Puppeteer Core
3
3
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/puppeteer-core
4
- Version: 24.37.4
4
+ Version: 24.37.5
5
5
  License: Apache-2.0
6
6
  License File: LICENSE
7
- Revision: c771d9cc0c6c3611532e18d89291c2d734f736ab
7
+ Revision: fcb37e3b3a4f6b55b6f81a40811243260bcea16f
8
8
  Security Critical: no
9
9
  Shipped: yes
10
10
  Update Mechanism: Autoroll
@@ -7,8 +7,8 @@
7
7
  * @internal
8
8
  */
9
9
  export declare const PUPPETEER_REVISIONS: Readonly<{
10
- chrome: "145.0.7632.76";
11
- 'chrome-headless-shell': "145.0.7632.76";
10
+ chrome: "145.0.7632.77";
11
+ 'chrome-headless-shell': "145.0.7632.77";
12
12
  firefox: "stable_147.0.4";
13
13
  }>;
14
14
  //# sourceMappingURL=revisions.d.ts.map
@@ -10,8 +10,8 @@ exports.PUPPETEER_REVISIONS = void 0;
10
10
  * @internal
11
11
  */
12
12
  exports.PUPPETEER_REVISIONS = Object.freeze({
13
- chrome: '145.0.7632.76',
14
- 'chrome-headless-shell': '145.0.7632.76',
13
+ chrome: '145.0.7632.77',
14
+ 'chrome-headless-shell': '145.0.7632.77',
15
15
  firefox: 'stable_147.0.4',
16
16
  });
17
17
  //# sourceMappingURL=revisions.js.map
@@ -3,5 +3,5 @@
3
3
  * Copyright 2025 Google Inc.
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- export declare const packageVersion = "24.37.4";
6
+ export declare const packageVersion = "24.37.5";
7
7
  //# sourceMappingURL=version.d.ts.map
@@ -8,6 +8,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.packageVersion = void 0;
9
9
  // If moved update release-please config
10
10
  // x-release-please-start-version
11
- exports.packageVersion = '24.37.4';
11
+ exports.packageVersion = '24.37.5';
12
12
  // x-release-please-end
13
13
  //# sourceMappingURL=version.js.map
@@ -3050,7 +3050,7 @@ var Puppeteer = function (exports, _PuppeteerURL, _LazyArg, _ARIAQueryHandler, _
3050
3050
  */
3051
3051
  // If moved update release-please config
3052
3052
  // x-release-please-start-version
3053
- const packageVersion = '24.37.4';
3053
+ const packageVersion = '24.37.5';
3054
3054
  // x-release-please-end
3055
3055
 
3056
3056
  /**
@@ -25247,8 +25247,8 @@ var Puppeteer = function (exports, _PuppeteerURL, _LazyArg, _ARIAQueryHandler, _
25247
25247
  * @internal
25248
25248
  */
25249
25249
  const PUPPETEER_REVISIONS = Object.freeze({
25250
- chrome: '145.0.7632.76',
25251
- 'chrome-headless-shell': '145.0.7632.76',
25250
+ chrome: '145.0.7632.77',
25251
+ 'chrome-headless-shell': '145.0.7632.77',
25252
25252
  firefox: 'stable_147.0.4'
25253
25253
  });
25254
25254
 
@@ -7,8 +7,8 @@
7
7
  * @internal
8
8
  */
9
9
  export declare const PUPPETEER_REVISIONS: Readonly<{
10
- chrome: "145.0.7632.76";
11
- 'chrome-headless-shell': "145.0.7632.76";
10
+ chrome: "145.0.7632.77";
11
+ 'chrome-headless-shell': "145.0.7632.77";
12
12
  firefox: "stable_147.0.4";
13
13
  }>;
14
14
  //# sourceMappingURL=revisions.d.ts.map
@@ -7,8 +7,8 @@
7
7
  * @internal
8
8
  */
9
9
  export const PUPPETEER_REVISIONS = Object.freeze({
10
- chrome: '145.0.7632.76',
11
- 'chrome-headless-shell': '145.0.7632.76',
10
+ chrome: '145.0.7632.77',
11
+ 'chrome-headless-shell': '145.0.7632.77',
12
12
  firefox: 'stable_147.0.4',
13
13
  });
14
14
  //# sourceMappingURL=revisions.js.map
@@ -3,5 +3,5 @@
3
3
  * Copyright 2025 Google Inc.
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- export declare const packageVersion = "24.37.4";
6
+ export declare const packageVersion = "24.37.5";
7
7
  //# sourceMappingURL=version.d.ts.map
@@ -5,6 +5,6 @@
5
5
  */
6
6
  // If moved update release-please config
7
7
  // x-release-please-start-version
8
- export const packageVersion = '24.37.4';
8
+ export const packageVersion = '24.37.5';
9
9
  // x-release-please-end
10
10
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "puppeteer-core",
3
- "version": "24.37.4",
3
+ "version": "24.37.5",
4
4
  "description": "A high-level API to control headless Chrome over the DevTools Protocol",
5
5
  "keywords": [
6
6
  "puppeteer",
@@ -8,7 +8,7 @@
8
8
  * @internal
9
9
  */
10
10
  export const PUPPETEER_REVISIONS = Object.freeze({
11
- chrome: '145.0.7632.76',
12
- 'chrome-headless-shell': '145.0.7632.76',
11
+ chrome: '145.0.7632.77',
12
+ 'chrome-headless-shell': '145.0.7632.77',
13
13
  firefox: 'stable_147.0.4',
14
14
  });
@@ -6,5 +6,5 @@
6
6
 
7
7
  // If moved update release-please config
8
8
  // x-release-please-start-version
9
- export const packageVersion = '24.37.4';
9
+ export const packageVersion = '24.37.5';
10
10
  // x-release-please-end
@@ -37,14 +37,14 @@ import * as i18n from '../../../../core/i18n/i18n.js';
37
37
  import * as SDK from '../../../../core/sdk/sdk.js';
38
38
  import * as StackTrace from '../../../../models/stack_trace/stack_trace.js';
39
39
  import * as Workspace from '../../../../models/workspace/workspace.js';
40
- import {Directives, html, render} from '../../../lit/lit.js';
40
+ import {Directives, html, nothing, render, type TemplateResult} from '../../../lit/lit.js';
41
41
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
42
42
  import * as UI from '../../legacy.js';
43
43
 
44
44
  import jsUtilsStyles from './jsUtils.css.js';
45
45
  import {Linkifier} from './Linkifier.js';
46
46
 
47
- const {classMap, createRef, ref} = Directives;
47
+ const {classMap} = Directives;
48
48
 
49
49
  const UIStrings = {
50
50
  /**
@@ -97,134 +97,105 @@ export interface ViewInput {
97
97
  widthConstrained?: boolean;
98
98
  showColumnNumber?: boolean;
99
99
  expandable?: boolean;
100
+ expanded?: boolean;
101
+ showIgnoreListed?: boolean;
102
+ onExpand: () => void;
103
+ onShowMore: () => void;
104
+ onShowLess: () => void;
100
105
  }
101
106
 
102
- export type View = (input: ViewInput, output: {table?: HTMLElement}, target: HTMLElement) => void;
107
+ export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
103
108
 
104
109
  export const DEFAULT_VIEW: View = (input, output, target) => {
110
+ let renderExpandButton = Boolean(input.expandable);
111
+ const maybeRenderExpandButton = (): TemplateResult => {
112
+ // clang-format off
113
+ const result = html`
114
+ ${renderExpandButton ? html`
115
+ <button class="arrow-icon-button" jslog=${VisualLogging.expand().track({click: true})} @click=${input.onExpand}>
116
+ <span class="arrow-icon"></span>
117
+ </button>
118
+ ` : '\n'}`;
119
+ // clang-format on
120
+ renderExpandButton = false;
121
+ return result;
122
+ };
123
+
105
124
  const classes = {
106
125
  'stack-preview-container': true,
107
126
  'width-constrained': Boolean(input.widthConstrained),
127
+ expandable: Boolean(input.expandable),
128
+ expanded: Boolean(input.expanded),
129
+ 'show-hidden-rows': Boolean(input.showIgnoreListed),
108
130
  };
109
- // TODO(crbug.com/483576322): Remove once fully migrated.
110
- const tableRef = createRef<HTMLElement>();
131
+ const {stackTrace} = input;
111
132
  // clang-format off
112
133
  render(html`
113
134
  <style>${jsUtilsStyles}</style>
114
- <table class=${classMap(classes)} ${ref(tableRef)}>
135
+ <table class=${classMap(classes)}>
136
+ ${stackTrace ? html`
137
+ ${[stackTrace.syncFragment, ...stackTrace.asyncFragments].map(fragment => html`
138
+ <tbody>
139
+ ${'description' in fragment ? html`
140
+ <tr class="stack-preview-async-row">
141
+ <td>${maybeRenderExpandButton()}</td>
142
+ <td class="stack-preview-async-description">
143
+ ${UI.UIUtils.asyncFragmentLabel(stackTrace, fragment as StackTrace.StackTrace.AsyncFragment)}
144
+ </td>
145
+ <td></td>
146
+ <td></td>
147
+ </tr>
148
+ ` : nothing}
149
+ ${fragment.frames.map((frame, i) => {
150
+ const previousStackFrameWasBreakpointCondition = i > 0 && [
151
+ SDK.DebuggerModel.COND_BREAKPOINT_SOURCE_URL,
152
+ SDK.DebuggerModel.LOGPOINT_SOURCE_URL,
153
+ ].includes(fragment.frames[i - 1].url ?? '');
154
+ const link = Linkifier.linkifyStackTraceFrame(frame, {
155
+ showColumnNumber: Boolean(input.showColumnNumber),
156
+ tabStop: Boolean(input.tabStops),
157
+ inlineFrameIndex: 0,
158
+ revealBreakpoint: previousStackFrameWasBreakpointCondition,
159
+ maxLength: UI.UIUtils.MaxLengthForDisplayedURLsInConsole,
160
+ });
161
+ link.setAttribute('jslog', `${VisualLogging.link('stack-trace').track({click: true})}`);
162
+ link.addEventListener('contextmenu', populateContextMenu.bind(null, link));
163
+ return html`
164
+ <tr>
165
+ <td>${maybeRenderExpandButton()}</td>
166
+ <td class="function-name">
167
+ ${UI.UIUtils.beautifyFunctionName(frame.name ?? '')}
168
+ </td>
169
+ <td> @ </td>
170
+ <td class="link">${link}</td>
171
+ </tr>
172
+ `;})}
173
+ </tbody>
174
+ `)}
175
+ <tfoot>
176
+ <tr class="show-all-link">
177
+ <td></td>
178
+ <td colspan="3">
179
+ <span class="link" @click=${input.onShowMore}>
180
+ <span class="css-inserted-text" data-inserted-text=${i18nString(UIStrings.showMoreFrames)}></span>
181
+ </span>
182
+ </td>
183
+ </tr>
184
+ <tr class="show-less-link">
185
+ <td></td>
186
+ <td colspan="3">
187
+ <span class="link" @click=${input.onShowLess}>
188
+ <span class="css-inserted-text" data-inserted-text=${i18nString(UIStrings.showLess)}></span>
189
+ </span>
190
+ </td>
191
+ </tr>
192
+ </tfoot>
193
+ ` : nothing}
115
194
  </table>
116
195
  `, target);
117
196
  // clang-format on
118
- output.table = tableRef.value;
119
197
  };
120
198
 
121
- function renderStackTraceTable(
122
- container: Element,
123
- parent: Element,
124
- stackTrace: StackTrace.StackTrace.StackTrace,
125
- options: Options,
126
- ): void {
127
- container.removeChildren();
128
-
129
- function buildStackTraceRowsHelper(fragment: StackTrace.StackTrace.Fragment|StackTrace.StackTrace.AsyncFragment):
130
- Array<StackTraceRegularRow|StackTraceAsyncRow> {
131
- const stackTraceRows: Array<StackTraceRegularRow|StackTraceAsyncRow> = [];
132
- if ('description' in fragment) {
133
- stackTraceRows.push({asyncDescription: UI.UIUtils.asyncFragmentLabel(stackTrace, fragment)});
134
- }
135
- let previousStackFrameWasBreakpointCondition = false;
136
- for (const frame of fragment.frames) {
137
- const functionName = UI.UIUtils.beautifyFunctionName(frame.name ?? '');
138
- const link = Linkifier.linkifyStackTraceFrame(frame, {
139
- showColumnNumber: Boolean(options.showColumnNumber),
140
- tabStop: Boolean(options.tabStops),
141
- inlineFrameIndex: 0,
142
- revealBreakpoint: previousStackFrameWasBreakpointCondition,
143
- maxLength: UI.UIUtils.MaxLengthForDisplayedURLsInConsole,
144
- });
145
- link.setAttribute('jslog', `${VisualLogging.link('stack-trace').track({click: true})}`);
146
- link.addEventListener('contextmenu', populateContextMenu.bind(null, link));
147
-
148
- stackTraceRows.push({functionName, link});
149
- previousStackFrameWasBreakpointCondition = [
150
- SDK.DebuggerModel.COND_BREAKPOINT_SOURCE_URL,
151
- SDK.DebuggerModel.LOGPOINT_SOURCE_URL,
152
- ].includes(frame.url ?? '');
153
- }
154
-
155
- return stackTraceRows;
156
- }
157
-
158
- // The tableSection groups one or more synchronous call frames together.
159
- // Wherever there is an asynchronous call, a new section is created.
160
- let firstRow = true;
161
- for (const fragment of [stackTrace.syncFragment, ...stackTrace.asyncFragments]) {
162
- if (fragment.frames.length === 0) {
163
- continue;
164
- }
165
-
166
- const stackTraceRows = buildStackTraceRowsHelper(fragment);
167
- const tableSection = container.createChild('tbody');
168
- for (const item of stackTraceRows) {
169
- const row = tableSection.createChild('tr');
170
- if (firstRow && options.expandable) {
171
- const button = row.createChild('td').createChild('button', 'arrow-icon-button');
172
- button.createChild('span', 'arrow-icon');
173
- parent.classList.add('expandable');
174
- container.classList.add('expandable');
175
- button.addEventListener('click', () => {
176
- button.setAttribute('jslog', `${VisualLogging.expand().track({click: true})}`);
177
- parent.classList.toggle('expanded');
178
- container.classList.toggle('expanded');
179
- });
180
- firstRow = false;
181
- } else {
182
- row.createChild('td').textContent = '\n';
183
- }
184
- if ('asyncDescription' in item) {
185
- row.createChild('td', 'stack-preview-async-description').textContent = item.asyncDescription;
186
- row.createChild('td');
187
- row.createChild('td');
188
- row.classList.add('stack-preview-async-row');
189
- } else {
190
- row.createChild('td', 'function-name').textContent = item.functionName;
191
- row.createChild('td').textContent = ' @ ';
192
- row.createChild('td', 'link').appendChild(item.link);
193
- }
194
- }
195
- }
196
-
197
- const tableSection = container.createChild('tfoot');
198
- const showAllRow = tableSection.createChild('tr', 'show-all-link');
199
- showAllRow.createChild('td');
200
- const cell = showAllRow.createChild('td');
201
- cell.colSpan = 4;
202
- const showAllLink = cell.createChild('span', 'link');
203
- // Don't directly put the text of the link in the DOM, as it will likely be
204
- // invisible and it may be confusing if it is copied to the clipboard.
205
- showAllLink.createChild('span', 'css-inserted-text')
206
- .setAttribute('data-inserted-text', i18nString(UIStrings.showMoreFrames));
207
- showAllLink.addEventListener('click', () => {
208
- container.classList.add('show-hidden-rows');
209
- parent.classList.add('show-hidden-rows');
210
- // If we are in a popup, this will trigger a re-layout
211
- UI.GlassPane.GlassPane.containerMoved(container);
212
- }, false);
213
- const showLessRow = tableSection.createChild('tr', 'show-less-link');
214
- showLessRow.createChild('td');
215
- const showLesscell = showLessRow.createChild('td');
216
- showLesscell.colSpan = 4;
217
- const showLessLink = showLesscell.createChild('span', 'link');
218
- showLessLink.createChild('span', 'css-inserted-text')
219
- .setAttribute('data-inserted-text', i18nString(UIStrings.showLess));
220
- showLessLink.addEventListener('click', () => {
221
- container.classList.remove('show-hidden-rows');
222
- parent.classList.remove('show-hidden-rows');
223
- // If we are in a popup, this will trigger a re-layout
224
- UI.GlassPane.GlassPane.containerMoved(container);
225
- }, false);
226
- }
227
-
228
199
  export interface Options {
229
200
  tabStops?: boolean;
230
201
  // Whether the width of stack trace preview
@@ -235,20 +206,13 @@ export interface Options {
235
206
  expandable?: boolean;
236
207
  }
237
208
 
238
- interface StackTraceRegularRow {
239
- functionName: string;
240
- link: HTMLElement;
241
- }
242
-
243
- interface StackTraceAsyncRow {
244
- asyncDescription: string;
245
- }
246
-
247
209
  export class StackTracePreviewContent extends UI.Widget.Widget {
248
210
  readonly #view: View;
249
211
 
250
212
  #stackTrace?: StackTrace.StackTrace.StackTrace;
251
213
  #options: Options = {};
214
+ #expanded = false;
215
+ #showIgnoreListed = false;
252
216
 
253
217
  constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
254
218
  super(element, {useShadowDom: true, classes: ['monospace', 'stack-preview-container']});
@@ -264,17 +228,20 @@ export class StackTracePreviewContent extends UI.Widget.Widget {
264
228
  }
265
229
 
266
230
  override performUpdate(): void {
267
- const output: {table?: HTMLElement} = {};
268
- this.#view(
269
- {
270
- stackTrace: this.#stackTrace,
271
- ...this.#options,
272
- },
273
- output, this.contentElement);
231
+ this.element.classList.toggle('expandable', this.#options.expandable);
232
+ this.element.classList.toggle('expanded', this.#expanded);
233
+ this.element.classList.toggle('show-hidden-rows', this.#showIgnoreListed);
274
234
 
275
- if (this.#stackTrace && output.table) {
276
- renderStackTraceTable(output.table, this.element, this.#stackTrace, this.#options);
277
- }
235
+ const input: ViewInput = {
236
+ stackTrace: this.#stackTrace,
237
+ ...this.#options,
238
+ expanded: this.#expanded,
239
+ showIgnoreListed: this.#showIgnoreListed,
240
+ onExpand: this.#onExpand.bind(this),
241
+ onShowMore: this.#onShowMoreLess.bind(this, true),
242
+ onShowLess: this.#onShowMoreLess.bind(this, false),
243
+ };
244
+ this.#view(input, {}, this.contentElement);
278
245
  }
279
246
 
280
247
  get linkElements(): readonly HTMLElement[] {
@@ -294,4 +261,17 @@ export class StackTracePreviewContent extends UI.Widget.Widget {
294
261
  this.#stackTrace.addEventListener(StackTrace.StackTrace.Events.UPDATED, this.requestUpdate, this);
295
262
  this.requestUpdate();
296
263
  }
264
+
265
+ #onShowMoreLess(more: boolean): void {
266
+ this.#showIgnoreListed = more;
267
+ this.requestUpdate();
268
+
269
+ // If we are in a popup, this will trigger a re-layout
270
+ void this.updateComplete.then(() => UI.GlassPane.GlassPane.containerMoved(this.contentElement));
271
+ }
272
+
273
+ #onExpand(): void {
274
+ this.#expanded = !this.#expanded;
275
+ this.requestUpdate();
276
+ }
297
277
  }
package/package.json CHANGED
@@ -105,5 +105,5 @@
105
105
  "flat-cache": "6.1.12"
106
106
  }
107
107
  },
108
- "version": "1.0.1586699"
108
+ "version": "1.0.1587572"
109
109
  }