chrome-devtools-frontend 1.0.1703574 → 1.0.1704172

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 (69) hide show
  1. package/AUTHORS +1 -0
  2. package/front_end/core/common/ParsedURL.ts +54 -0
  3. package/front_end/core/platform/StringUtilities.ts +65 -0
  4. package/front_end/core/sdk/CPUThrottlingManager.ts +3 -3
  5. package/front_end/core/sdk/SourceMap.ts +3 -3
  6. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +4 -3
  7. package/front_end/core/sdk/SourceMapScopesInfo.ts +17 -5
  8. package/front_end/entrypoints/main/MainImpl.ts +3 -3
  9. package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
  10. package/front_end/models/har/HARFormat.ts +7 -2
  11. package/front_end/models/source_map_scopes/NamesResolver.ts +13 -5
  12. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingListView.ts +33 -1
  13. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +4 -12
  14. package/front_end/panels/application/ApplicationPanelSidebar.ts +58 -60
  15. package/front_end/panels/application/BackForwardCacheTreeElement.ts +1 -1
  16. package/front_end/panels/application/FrameDetailsView.ts +64 -82
  17. package/front_end/panels/application/OpenedWindowDetailsView.ts +20 -21
  18. package/front_end/panels/application/PreloadingTreeElement.ts +3 -3
  19. package/front_end/panels/common/CommentsOverlayWidget.ts +145 -72
  20. package/front_end/panels/common/commentsOverlay.css +34 -23
  21. package/front_end/panels/elements/DOMTreeWidget.ts +29 -10
  22. package/front_end/panels/network/RequestPayloadView.ts +7 -2
  23. package/front_end/panels/network/ShowMoreDetailsWidget.ts +12 -9
  24. package/front_end/panels/sources/DebuggerPlugin.ts +49 -16
  25. package/front_end/panels/sources/SourcesPanel.ts +1 -1
  26. package/front_end/panels/sources/SourcesView.ts +3 -12
  27. package/front_end/panels/sources/TabbedEditorContainer.ts +0 -3
  28. package/front_end/panels/sources/components/HeadersView.ts +193 -123
  29. package/front_end/third_party/chromium/README.chromium +1 -1
  30. package/front_end/third_party/puppeteer/README.chromium +2 -2
  31. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +5 -0
  32. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +24 -32
  33. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts +1 -1
  34. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts.map +1 -1
  35. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js +15 -1
  36. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js.map +1 -1
  37. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +8 -1
  38. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
  39. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +0 -8
  40. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
  41. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +0 -24
  42. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
  43. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts +12 -0
  44. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  45. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +79 -17
  46. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
  47. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js +1 -1
  48. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js.map +1 -1
  49. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  50. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  51. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  52. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  53. package/front_end/third_party/puppeteer/package/lib/types.d.ts +5 -0
  54. package/front_end/third_party/puppeteer/package/package.json +4 -4
  55. package/front_end/third_party/puppeteer/package/src/api/ElementHandle.ts +15 -2
  56. package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +10 -1
  57. package/front_end/third_party/puppeteer/package/src/common/Debug.ts +0 -27
  58. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +96 -17
  59. package/front_end/third_party/puppeteer/package/src/node-env-setup.ts +1 -1
  60. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  61. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  62. package/front_end/ui/comments/CommentAnchorResolver.ts +60 -22
  63. package/front_end/ui/comments/CommentOverlayManager.ts +78 -25
  64. package/front_end/ui/legacy/components/data_grid/DataGridExporter.ts +7 -13
  65. package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +51 -57
  66. package/front_end/ui/legacy/components/source_frame/ImageView.ts +101 -42
  67. package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -2
  68. package/front_end/ui/visual_logging/KnownContextValues.ts +7 -0
  69. package/package.json +1 -1
@@ -11,6 +11,10 @@ const UIStrings = {
11
11
  * @description Text to show more content
12
12
  */
13
13
  showMore: 'Show more',
14
+ /**
15
+ * @description Context menu item to copy the shown text to the clipboard
16
+ */
17
+ copy: 'Copy',
14
18
  } as const;
15
19
  const str_ = i18n.i18n.registerUIStrings('panels/network/ShowMoreDetailsWidget.ts', UIStrings);
16
20
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -20,7 +24,7 @@ interface ViewInput {
20
24
  text: string;
21
25
  showMore: boolean;
22
26
  onToggle: () => void;
23
- copy: CopyMenuItem|null;
27
+ copy: (() => void)|null;
24
28
  }
25
29
  type View = (input: ViewInput, output: object, target: HTMLElement) => void;
26
30
  const MAX_LENGTH = 3000;
@@ -29,7 +33,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
29
33
  const onContextMenuShowMore = (event: Event): void => {
30
34
  const contextMenu = new UI.ContextMenu.ContextMenu(event);
31
35
  if (input.copy) {
32
- contextMenu.clipboardSection().appendItem(input.copy.menuItem, input.copy.handler);
36
+ contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copy), input.copy, {jslogContext: 'copy'});
33
37
  }
34
38
  if (!input.showMore) {
35
39
  contextMenu.newSection().appendItem(i18nString(UIStrings.showMore), input.onToggle, {jslogContext: 'show-more'});
@@ -51,16 +55,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
51
55
  target);
52
56
  };
53
57
 
54
- interface CopyMenuItem {
55
- menuItem: UI.ContextMenu.Item;
56
- handler: () => void;
57
- }
58
-
59
58
  export class ShowMoreDetailsWidget extends UI.Widget.Widget {
60
59
  readonly #view: View;
61
60
  #text = '';
62
61
  #showMore = false;
63
- #copy: CopyMenuItem|null = null;
62
+ #copy: (() => void)|null = null;
64
63
  constructor(target?: HTMLElement, view: View = DEFAULT_VIEW) {
65
64
  super(target);
66
65
  this.#view = view;
@@ -75,7 +74,11 @@ export class ShowMoreDetailsWidget extends UI.Widget.Widget {
75
74
  this.requestUpdate();
76
75
  }
77
76
 
78
- set copy(copy: CopyMenuItem) {
77
+ get copy(): (() => void)|null {
78
+ return this.#copy;
79
+ }
80
+
81
+ set copy(copy: () => void) {
79
82
  this.#copy = copy;
80
83
  this.requestUpdate();
81
84
  }
@@ -583,6 +583,7 @@ export class DebuggerPlugin extends Plugin {
583
583
  }
584
584
 
585
585
  private workingCopyChanged(): void {
586
+ this.#scopeMappingsCache.clear();
586
587
  this.setMuted(this.uiSourceCode.isDirty());
587
588
  }
588
589
 
@@ -666,7 +667,7 @@ export class DebuggerPlugin extends Plugin {
666
667
  return {
667
668
  box,
668
669
  show: async (popover: UI.GlassPane.GlassPane) => {
669
- const scopeMappings = await this.#getScopeMappings(selectedCallFrame);
670
+ const scopeMappings = await this.#getScopeMappings(debuggableFrame) ?? [];
670
671
  const scopedVariable = findVariableInScopeMappings(evaluationText, highlightRange.from, scopeMappings);
671
672
  if (scopedVariable.found) {
672
673
  if (!scopedVariable.value) {
@@ -967,21 +968,18 @@ export class DebuggerPlugin extends Plugin {
967
968
  return offset ?? null;
968
969
  }
969
970
 
970
- #cachedScopeMappings?: {callFrame: SDK.DebuggerModel.CallFrame, promise: Promise<ScopeMapping[]>};
971
+ readonly #scopeMappingsCache = new ScopeMappingsCache(this.uiSourceCode);
971
972
 
972
- #getScopeMappings(callFrame: SDK.DebuggerModel.CallFrame,
973
- resolvedScopeChain?: SDK.DebuggerModel.ScopeChainEntry[]): Promise<ScopeMapping[]> {
974
- if (this.#cachedScopeMappings?.callFrame !== callFrame) {
975
- const url = this.uiSourceCode.url();
976
- this.#cachedScopeMappings = {
977
- callFrame,
978
- promise: computeScopeMappings(
979
- callFrame, location => this.#rawLocationToEditorOffset(location, url),
973
+ /** @returns `null` if the scope mappings can't be used because the file has unsaved edits. */
974
+ #getScopeMappings(debuggableFrame: StackTrace.StackTrace.DebuggableFrameFlavor,
975
+ resolvedScopeChain?: SDK.DebuggerModel.ScopeChainEntry[]): Promise<ScopeMapping[]>|null {
976
+ const url = this.uiSourceCode.url();
977
+ return this.#scopeMappingsCache.get(
978
+ debuggableFrame,
979
+ () => computeScopeMappings(
980
+ debuggableFrame.sdkFrame, location => this.#rawLocationToEditorOffset(location, url),
980
981
  (line, col) => this.editor?.toOffset(this.transformer.uiLocationToEditorLocation(line, col)) ?? null,
981
- resolvedScopeChain),
982
- };
983
- }
984
- return this.#cachedScopeMappings.promise;
982
+ resolvedScopeChain));
985
983
  }
986
984
 
987
985
  private async computeValueDecorations(): Promise<CodeMirror.DecorationSet|null> {
@@ -1040,9 +1038,9 @@ export class DebuggerPlugin extends Plugin {
1040
1038
  return null;
1041
1039
  }
1042
1040
 
1043
- const scopeMappings = await this.#getScopeMappings(callFrame, scopeChain);
1041
+ const scopeMappings = await this.#getScopeMappings(debuggableFrame, scopeChain);
1044
1042
  // After the `await` the DebuggerPlugin could have been disposed. Re-check `this.editor`.
1045
- if (!this.editor || scopeMappings.length === 0) {
1043
+ if (!this.editor || !scopeMappings?.length) {
1046
1044
  return null;
1047
1045
  }
1048
1046
 
@@ -2144,6 +2142,41 @@ export interface ScopeMapping {
2144
2142
  variableMap: Map<string, SDK.RemoteObject.RemoteObject|null>;
2145
2143
  }
2146
2144
 
2145
+ /**
2146
+ * Caches the {@link ScopeMapping}s for the selected frame of a single {@link DebuggerPlugin}.
2147
+ *
2148
+ * The editor offsets in a {@link ScopeMapping} are derived from raw and UI locations, which describe
2149
+ * the committed script content. Once the user edits the file, these offsets no longer match the
2150
+ * editor content. So no mappings are handed out while the UISourceCode has unsaved edits.
2151
+ *
2152
+ * The cache is keyed on the DebuggableFrameFlavor rather than the SDK CallFrame: Re-translating a
2153
+ * frame (e.g. after a source map is attached) produces a new flavor for the same SDK CallFrame.
2154
+ */
2155
+ export class ScopeMappingsCache {
2156
+ readonly #uiSourceCode: Workspace.UISourceCode.UISourceCode;
2157
+ #cached?: {frame: StackTrace.StackTrace.DebuggableFrameFlavor, promise: Promise<ScopeMapping[]>};
2158
+
2159
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
2160
+ this.#uiSourceCode = uiSourceCode;
2161
+ }
2162
+
2163
+ /** @returns the (cached) scope mappings for `frame`, or `null` if the UISourceCode has unsaved edits. */
2164
+ get(frame: StackTrace.StackTrace.DebuggableFrameFlavor,
2165
+ compute: () => Promise<ScopeMapping[]>): Promise<ScopeMapping[]>|null {
2166
+ if (this.#uiSourceCode.isDirty()) {
2167
+ return null;
2168
+ }
2169
+ if (this.#cached?.frame !== frame) {
2170
+ this.#cached = {frame, promise: compute()};
2171
+ }
2172
+ return this.#cached.promise;
2173
+ }
2174
+
2175
+ clear(): void {
2176
+ this.#cached = undefined;
2177
+ }
2178
+ }
2179
+
2147
2180
  export async function computeScopeMappings(
2148
2181
  callFrame: SDK.DebuggerModel.CallFrame,
2149
2182
  rawLocationToEditorOffset: (l: SDK.DebuggerModel.Location|null) => Promise<number|null>,
@@ -327,7 +327,7 @@ export class SourcesPanel extends UI.Panel.Panel implements
327
327
  static updateResizerAndSidebarButtons(panel: SourcesPanel): void {
328
328
  const isInWrapper = Boolean(UI.Context.Context.instance().flavor(QuickSourceView)) &&
329
329
  !UI.InspectorView.InspectorView.instance().isDrawerMinimized();
330
- panel.#sourcesView.setLayoutMode(panel.splitWidget, panel.splitWidget.isVertical(), isInWrapper);
330
+ panel.#sourcesView.setLayoutMode(panel.splitWidget.isVertical(), isInWrapper);
331
331
  }
332
332
 
333
333
  targetAdded(_target: SDK.Target.Target): void {
@@ -16,7 +16,7 @@ import * as Buttons from '../../ui/components/buttons/buttons.js';
16
16
  import * as QuickOpen from '../../ui/legacy/components/quick_open/quick_open.js';
17
17
  import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
18
18
  import * as UI from '../../ui/legacy/legacy.js';
19
- import {Directives, html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
19
+ import {html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
20
20
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
21
21
 
22
22
  import {EditingLocationHistoryManager} from './EditingLocationHistoryManager.js';
@@ -69,7 +69,6 @@ const UIStrings = {
69
69
  const str_ = i18n.i18n.registerUIStrings('panels/sources/SourcesView.ts', UIStrings);
70
70
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
71
71
 
72
- const {ref} = Directives;
73
72
  const {widget, widgetRef} = UI.Widget;
74
73
 
75
74
  export interface ViewInput {
@@ -83,7 +82,6 @@ export interface ViewInput {
83
82
  isVertical: boolean;
84
83
  isInWrapper: boolean;
85
84
  isTraceApp: boolean;
86
- splitWidget?: UI.SplitWidget.SplitWidget;
87
85
  onToggleNavigatorSidebar?: () => void;
88
86
  onToggleDebuggerSidebar?: () => void;
89
87
  breakpointsActive: boolean;
@@ -170,11 +168,7 @@ export const DEFAULT_VIEW: View = (input, output, target): void => {
170
168
  </devtools-widget>
171
169
  </devtools-widget>
172
170
  <div class="sources-toolbar" jslog=${VisualLogging.toolbar('bottom')}>
173
- <devtools-toolbar class="script-view-toolbar" style="flex: auto;" ${ref(el => {
174
- if (el && input.splitWidget) {
175
- input.splitWidget.toggleResizer(el, !input.isVertical && !input.isInWrapper);
176
- }
177
- })}>
171
+ <devtools-toolbar class="script-view-toolbar" style="flex: auto;">
178
172
  ${Array.isArray(input.scriptViewToolbarItems)
179
173
  ? input.scriptViewToolbarItems.map(item => item.element)
180
174
  : input.scriptViewToolbarItems}
@@ -218,7 +212,6 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
218
212
  #debuggerSidebarInitialized = false;
219
213
  #isVertical = false;
220
214
  #isInWrapper = true;
221
- #splitWidget?: UI.SplitWidget.SplitWidget;
222
215
  #breakpointsActive = true;
223
216
  #editorContainerPromise: Promise<TabbedEditorContainer>;
224
217
  #editorContainerResolve!: (container: TabbedEditorContainer) => void;
@@ -295,7 +288,6 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
295
288
  isVertical: this.#isVertical,
296
289
  isInWrapper: this.#isInWrapper,
297
290
  isTraceApp: Root.Runtime.Runtime.isTraceApp(),
298
- splitWidget: this.#splitWidget,
299
291
  onToggleNavigatorSidebar: this.#onToggleNavigatorSidebar,
300
292
  onToggleDebuggerSidebar: this.#onToggleDebuggerSidebar,
301
293
  breakpointsActive: this.#breakpointsActive,
@@ -390,8 +382,7 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
390
382
  this.requestUpdate();
391
383
  }
392
384
 
393
- setLayoutMode(splitWidget: UI.SplitWidget.SplitWidget, isVertical: boolean, isInWrapper: boolean): void {
394
- this.#splitWidget = splitWidget;
385
+ setLayoutMode(isVertical: boolean, isInWrapper: boolean): void {
395
386
  this.#isVertical = isVertical;
396
387
  this.#isInWrapper = isInWrapper;
397
388
  this.requestUpdate();
@@ -291,9 +291,6 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
291
291
  }
292
292
 
293
293
  override performUpdate(): void {
294
- if (false) {
295
- return;
296
- }
297
294
  const shortcuts = [
298
295
  {actionId: 'quick-open.show', description: i18nString(UIStrings.openFile)},
299
296
  {actionId: 'quick-open.show-command-menu', description: i18nString(UIStrings.runCommand)},
@@ -1,8 +1,6 @@
1
1
  // Copyright 2022 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-imperative-dom-api */
5
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
6
4
 
7
5
  import * as Host from '../../../core/host/host.js';
8
6
  import * as i18n from '../../../core/i18n/i18n.js';
@@ -18,7 +16,7 @@ import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
18
16
 
19
17
  import headersViewStyles from './HeadersView.css.js';
20
18
 
21
- const {html} = Lit;
19
+ const {html, Directives: {ref}} = Lit;
22
20
 
23
21
  const UIStrings = {
24
22
  /**
@@ -59,25 +57,70 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
59
57
  const DEFAULT_HEADER_VALUE = 'header value';
60
58
  const getDefaultHeaderName = (i: number): string => `header-name-${i}`;
61
59
 
60
+ export interface WrapperViewInput {
61
+ data: HeadersViewComponentData;
62
+ }
63
+
64
+ export interface WrapperViewOutput {
65
+ component?: HeadersViewComponent;
66
+ }
67
+
68
+ export type WrapperView = (input: WrapperViewInput, output: WrapperViewOutput, target: HTMLElement) => void;
69
+
70
+ // clang-format off
71
+ export const HEADERS_VIEW_DEFAULT_VIEW: WrapperView = (input, output, target) => {
72
+ Lit.render(html`
73
+ <devtools-sources-headers-view
74
+ .data=${input.data}
75
+ ${ref(el => {
76
+ if (el) {
77
+ output.component = el as HeadersViewComponent;
78
+ }
79
+ })}
80
+ ></devtools-sources-headers-view>
81
+ `, target);
82
+ };
83
+ // clang-format on
84
+
62
85
  export class HeadersView extends UI.View.SimpleView {
63
- readonly #headersViewComponent = new HeadersViewComponent();
86
+ #headersViewComponent!: HeadersViewComponent;
64
87
  #uiSourceCode: Workspace.UISourceCode.UISourceCode;
88
+ readonly #view: WrapperView;
89
+ #componentData: HeadersViewComponentData;
65
90
 
66
- constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
91
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode, view: WrapperView = HEADERS_VIEW_DEFAULT_VIEW) {
67
92
  super({
68
93
  title: i18n.i18n.lockedString('HeadersView'),
69
94
  viewId: 'headers-view',
70
95
  jslog: `${VisualLogging.pane('headers-view')}`,
71
96
  });
97
+ this.#view = view;
72
98
  this.#uiSourceCode = uiSourceCode;
73
- this.#uiSourceCode.addEventListener(
74
- Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged, this);
75
- this.#uiSourceCode.addEventListener(
76
- Workspace.UISourceCode.Events.WorkingCopyCommitted, this.#onWorkingCopyCommitted, this);
77
- this.element.appendChild(this.#headersViewComponent);
99
+ this.#componentData = {
100
+ headerOverrides: [],
101
+ uiSourceCode: this.#uiSourceCode,
102
+ parsingError: false,
103
+ };
104
+ this.#uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged,
105
+ this);
106
+ this.#uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted,
107
+ this.#onWorkingCopyCommitted, this);
108
+ this.performUpdate();
78
109
  void this.#setInitialData();
79
110
  }
80
111
 
112
+ override performUpdate(): void {
113
+ const that = this;
114
+ const output: WrapperViewOutput = {
115
+ set component(value: HeadersViewComponent|undefined) {
116
+ if (value) {
117
+ that.#headersViewComponent = value;
118
+ }
119
+ },
120
+ };
121
+ this.#view({data: this.#componentData}, output, this.contentElement);
122
+ }
123
+
81
124
  async #setInitialData(): Promise<void> {
82
125
  const contentDataOrError = await this.#uiSourceCode.requestContentData();
83
126
  this.#setComponentData(TextUtils.ContentData.ContentData.textOr(contentDataOrError, ''));
@@ -97,11 +140,12 @@ export class HeadersView extends UI.View.SimpleView {
97
140
  parsingError = true;
98
141
  }
99
142
 
100
- this.#headersViewComponent.data = {
143
+ this.#componentData = {
101
144
  headerOverrides,
102
145
  uiSourceCode: this.#uiSourceCode,
103
146
  parsingError,
104
147
  };
148
+ this.performUpdate();
105
149
  }
106
150
 
107
151
  #onWorkingCopyChanged(): void {
@@ -117,10 +161,10 @@ export class HeadersView extends UI.View.SimpleView {
117
161
  }
118
162
 
119
163
  dispose(): void {
120
- this.#uiSourceCode.removeEventListener(
121
- Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged, this);
122
- this.#uiSourceCode.removeEventListener(
123
- Workspace.UISourceCode.Events.WorkingCopyCommitted, this.#onWorkingCopyCommitted, this);
164
+ this.#uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged,
165
+ this);
166
+ this.#uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted,
167
+ this.#onWorkingCopyCommitted, this);
124
168
  }
125
169
  }
126
170
 
@@ -323,7 +367,7 @@ export class HeadersViewComponent extends HTMLElement {
323
367
  }
324
368
  range.deleteContents();
325
369
 
326
- const textNode = document.createTextNode(text);
370
+ const textNode = new Text(text);
327
371
  range.insertNode(textNode);
328
372
  range.selectNodeContents(textNode);
329
373
  range.collapse(false);
@@ -341,119 +385,42 @@ export class HeadersViewComponent extends HTMLElement {
341
385
  throw new Error('HeadersView render was not scheduled');
342
386
  }
343
387
 
344
- if (this.#parsingError) {
345
- const fileName = this.#uiSourceCode?.name() || '.headers';
346
- // clang-format off
347
- Lit.render(html`
348
- <style>${headersViewStyles}</style>
349
- <div class="center-wrapper">
350
- <div class="centered">
351
- <div class="error-header">${i18nString(UIStrings.errorWhenParsing, {PH1: fileName})}</div>
352
- <div class="error-body">${i18nString(UIStrings.parsingErrorExplainer, {PH1: fileName})}</div>
353
- </div>
354
- </div>
355
- `, this.#shadow, {host: this});
356
- // clang-format on
357
- return;
358
- }
359
-
360
- // clang-format off
361
- Lit.render(html`
362
- <style>${headersViewStyles}</style>
363
- ${this.#headerOverrides.map((headerOverride, blockIndex) =>
364
- html`
365
- ${this.#renderApplyToRow(headerOverride.applyTo, blockIndex)}
366
- ${headerOverride.headers.map((header, headerIndex) =>
367
- html`
368
- ${this.#renderHeaderRow(header, blockIndex, headerIndex)}
369
- `,
370
- )}
371
- `,
372
- )}
373
- <devtools-button
374
- .variant=${Buttons.Button.Variant.OUTLINED}
375
- .jslogContext=${'headers-view.add-override-rule'}
376
- class="add-block">
377
- ${i18nString(UIStrings.addOverrideRule)}
378
- </devtools-button>
379
- <div class="learn-more-row">
380
- <devtools-link
381
- href="https://goo.gle/devtools-override"
382
- class="link"
383
- jslogContext=${'learn-more'}>${i18nString(UIStrings.learnMore)}</devtools-link>
384
- </div>
385
- `, this.#shadow, {host: this});
386
- // clang-format on
388
+ const output: ComponentViewOutput = {};
389
+ DEFAULT_VIEW(
390
+ {
391
+ headerOverrides: this.#headerOverrides,
392
+ parsingError: this.#parsingError,
393
+ fileName: this.#uiSourceCode?.name() || '.headers',
394
+ isDeletable: (blockIndex: number, headerIndex: number) => this.#isDeletable(blockIndex, headerIndex),
395
+ },
396
+ output,
397
+ this.#shadow,
398
+ );
387
399
 
388
400
  if (this.#focusElement) {
389
- let focusElement: Element|null = null;
390
- if (this.#focusElement.headerIndex) {
391
- focusElement = this.#shadow.querySelector(`[data-block-index="${
392
- this.#focusElement.blockIndex}"][data-header-index="${this.#focusElement.headerIndex}"] .header-name`);
393
- } else {
394
- focusElement = this.#shadow.querySelector(`[data-block-index="${this.#focusElement.blockIndex}"] .apply-to`);
395
- }
396
- if (focusElement) {
397
- (focusElement as HTMLElement).focus();
398
- }
401
+ output.focusElement?.(this.#focusElement.blockIndex, this.#focusElement.headerIndex);
399
402
  this.#focusElement = null;
400
403
  }
401
404
  }
405
+ }
402
406
 
403
- #renderApplyToRow(pattern: string, blockIndex: number): Lit.TemplateResult {
404
- // clang-format off
405
- return html`
406
- <div class="row" data-block-index=${blockIndex}
407
- jslog=${VisualLogging.treeItem(pattern === '*' ? pattern : undefined).track({resize: true})}>
408
- <div>${i18n.i18n.lockedString('Apply to')}</div>
409
- <div class="separator">:</div>
410
- ${this.#renderEditable(pattern, 'apply-to')}
411
- <devtools-button
412
- title=${i18nString(UIStrings.removeBlock)}
413
- .size=${Buttons.Button.Size.SMALL}
414
- .iconName=${'bin'}
415
- .iconWidth=${'14px'}
416
- .iconHeight=${'14px'}
417
- .variant=${Buttons.Button.Variant.ICON}
418
- .jslogContext=${'headers-view.remove-apply-to-section'}
419
- class="remove-block inline-button"
420
- ></devtools-button>
421
- </div>
422
- `;
423
- // clang-format on
424
- }
407
+ export interface ComponentViewInput {
408
+ headerOverrides: Persistence.NetworkPersistenceManager.HeaderOverride[];
409
+ parsingError: boolean;
410
+ fileName: string;
411
+ isDeletable: (blockIndex: number, headerIndex: number) => boolean;
412
+ }
425
413
 
426
- #renderHeaderRow(header: Protocol.Fetch.HeaderEntry, blockIndex: number, headerIndex: number): Lit.TemplateResult {
427
- // clang-format off
428
- return html`
429
- <div class="row padded" data-block-index=${blockIndex} data-header-index=${headerIndex}
430
- jslog=${VisualLogging.treeItem(header.name).parent('headers-editor-row-parent').track({resize: true})}>
431
- ${this.#renderEditable(header.name, 'header-name red', true)}
432
- <div class="separator">:</div>
433
- ${this.#renderEditable(header.value, 'header-value')}
434
- <devtools-button
435
- title=${i18nString(UIStrings.addHeader)}
436
- .size=${Buttons.Button.Size.SMALL}
437
- .iconName=${'plus'}
438
- .variant=${Buttons.Button.Variant.ICON}
439
- .jslogContext=${'headers-view.add-header'}
440
- class="add-header inline-button"
441
- ></devtools-button>
442
- <devtools-button
443
- title=${i18nString(UIStrings.removeHeader)}
444
- .size=${Buttons.Button.Size.SMALL}
445
- .iconName=${'bin'}
446
- .variant=${Buttons.Button.Variant.ICON}
447
- ?hidden=${!this.#isDeletable(blockIndex, headerIndex)}
448
- .jslogContext=${'headers-view.remove-header'}
449
- class="remove-header inline-button"
450
- ></devtools-button>
451
- </div>
452
- `;
453
- // clang-format on
454
- }
414
+ export interface ComponentViewOutput {
415
+ focusElement?: (blockIndex: number, headerIndex?: number) => void;
416
+ }
455
417
 
456
- #renderEditable(value: string, className?: string, isKey?: boolean): Lit.TemplateResult {
418
+ export const DEFAULT_VIEW = (
419
+ input: ComponentViewInput,
420
+ output: ComponentViewOutput,
421
+ target: HTMLElement|DocumentFragment,
422
+ ): void => {
423
+ const renderEditable = (value: string, className?: string, isKey?: boolean): Lit.TemplateResult => {
457
424
  // This uses Lit's `live`-directive, so that when checking whether to
458
425
  // update during re-render, `value` is compared against the actual live DOM
459
426
  // value of the contenteditable element and not the potentially outdated
@@ -466,8 +433,111 @@ export class HeadersViewComponent extends HTMLElement {
466
433
  tabindex="0"
467
434
  .innerText=${Lit.Directives.live(value)}></span>`;
468
435
  // clang-format on
469
- }
470
- }
436
+ };
437
+
438
+ const renderApplyToRow = (pattern: string, blockIndex: number): Lit.TemplateResult => {
439
+ // clang-format off
440
+ return html`
441
+ <div class="row" data-block-index=${blockIndex}
442
+ jslog=${VisualLogging.treeItem(pattern === '*' ? pattern : undefined).track({resize: true})}>
443
+ <div>${i18n.i18n.lockedString('Apply to')}</div>
444
+ <div class="separator">:</div>
445
+ ${renderEditable(pattern, 'apply-to')}
446
+ <devtools-button
447
+ title=${i18nString(UIStrings.removeBlock)}
448
+ .size=${Buttons.Button.Size.SMALL}
449
+ .iconName=${'bin'}
450
+ .iconWidth=${'14px'}
451
+ .iconHeight=${'14px'}
452
+ .variant=${Buttons.Button.Variant.ICON}
453
+ .jslogContext=${'headers-view.remove-apply-to-section'}
454
+ class="remove-block inline-button"
455
+ ></devtools-button>
456
+ </div>
457
+ `;
458
+ // clang-format on
459
+ };
460
+
461
+ const renderHeaderRow =
462
+ (header: Protocol.Fetch.HeaderEntry, blockIndex: number, headerIndex: number): Lit.TemplateResult => {
463
+ // clang-format off
464
+ return html`
465
+ <div class="row padded" data-block-index=${blockIndex} data-header-index=${headerIndex}
466
+ jslog=${VisualLogging.treeItem(header.name).parent('headers-editor-row-parent').track({resize: true})}>
467
+ ${renderEditable(header.name, 'header-name red', true)}
468
+ <div class="separator">:</div>
469
+ ${renderEditable(header.value, 'header-value')}
470
+ <devtools-button
471
+ title=${i18nString(UIStrings.addHeader)}
472
+ .size=${Buttons.Button.Size.SMALL}
473
+ .iconName=${'plus'}
474
+ .variant=${Buttons.Button.Variant.ICON}
475
+ .jslogContext=${'headers-view.add-header'}
476
+ class="add-header inline-button"
477
+ ></devtools-button>
478
+ <devtools-button
479
+ title=${i18nString(UIStrings.removeHeader)}
480
+ .size=${Buttons.Button.Size.SMALL}
481
+ .iconName=${'bin'}
482
+ .variant=${Buttons.Button.Variant.ICON}
483
+ ?hidden=${!input.isDeletable(blockIndex, headerIndex)}
484
+ .jslogContext=${'headers-view.remove-header'}
485
+ class="remove-header inline-button"
486
+ ></devtools-button>
487
+ </div>
488
+ `;
489
+ // clang-format on
490
+ };
491
+
492
+ // clang-format off
493
+ Lit.render(
494
+ input.parsingError
495
+ ? html`
496
+ <style>${headersViewStyles}</style>
497
+ <div class="center-wrapper">
498
+ <div class="centered">
499
+ <div class="error-header">${i18nString(UIStrings.errorWhenParsing, {PH1: input.fileName})}</div>
500
+ <div class="error-body">${i18nString(UIStrings.parsingErrorExplainer, {PH1: input.fileName})}</div>
501
+ </div>
502
+ </div>
503
+ `
504
+ : html`
505
+ <style>${headersViewStyles}</style>
506
+ ${input.headerOverrides.map((headerOverride, blockIndex) =>
507
+ html`
508
+ ${renderApplyToRow(headerOverride.applyTo, blockIndex)}
509
+ ${headerOverride.headers.map((header, headerIndex) =>
510
+ html`
511
+ ${renderHeaderRow(header, blockIndex, headerIndex)}
512
+ `,
513
+ )}
514
+ `,
515
+ )}
516
+ <devtools-button
517
+ .variant=${Buttons.Button.Variant.OUTLINED}
518
+ .jslogContext=${'headers-view.add-override-rule'}
519
+ class="add-block">
520
+ ${i18nString(UIStrings.addOverrideRule)}
521
+ </devtools-button>
522
+ <div class="learn-more-row">
523
+ <devtools-link
524
+ href="https://goo.gle/devtools-override"
525
+ class="link"
526
+ jslogContext=${'learn-more'}>${i18nString(UIStrings.learnMore)}</devtools-link>
527
+ </div>
528
+ `,
529
+ target);
530
+ // clang-format on
531
+
532
+ output.focusElement = (blockIndex: number, headerIndex?: number) => {
533
+ const focusElement = headerIndex !== undefined ?
534
+ target.querySelector(`[data-block-index="${blockIndex}"][data-header-index="${headerIndex}"] .header-name`) :
535
+ target.querySelector(`[data-block-index="${blockIndex}"] .apply-to`);
536
+ if (focusElement) {
537
+ (focusElement as HTMLElement).focus();
538
+ }
539
+ };
540
+ };
471
541
 
472
542
  VisualLogging.registerParentProvider('headers-editor-row-parent', (e: Element) => {
473
543
  while (e.previousElementSibling?.classList?.contains('padded')) {
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: Internal
3
3
  Version: N/A
4
- Revision: d45ba94c77a2835c4097934e46ff30d9b7615fc0
4
+ Revision: d4131488cec036cb5a8b1c69a9c252d54b540f29
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: 25.11.0
4
+ Version: 25.12.0
5
5
  License: Apache-2.0
6
6
  License File: LICENSE
7
- Revision: 043cd46e594b39ea77343e221a59724183448059
7
+ Revision: 15684eb7f1adf98c1c0c4a5d23a154b7995e947e
8
8
  Security Critical: no
9
9
  Shipped: yes
10
10
  Update Mechanism: Autoroll
@@ -8392,6 +8392,11 @@ export declare const PredefinedNetworkConditions: Readonly<{
8392
8392
  export declare type Predicate<From, To extends From = From> =
8393
8393
  ((value: From) => value is To) | ((value: From) => Awaitable<boolean>);
8394
8394
 
8395
+ declare interface ProcessExitEmitter {
8396
+ once(event: 'exit', listener: () => void): void;
8397
+ off(event: 'exit', listener: () => void): void;
8398
+ }
8399
+
8395
8400
  export {Protocol};
8396
8401
 
8397
8402
  /**