chrome-devtools-frontend 1.0.1702515 → 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 (84) hide show
  1. package/AUTHORS +1 -0
  2. package/front_end/core/common/ParsedURL.ts +59 -1
  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/core/text_utils/Markdown.ts +73 -0
  9. package/front_end/core/text_utils/text_utils.ts +2 -0
  10. package/front_end/entrypoints/main/MainImpl.ts +3 -3
  11. package/front_end/generated/InspectorBackendCommands.ts +3 -1
  12. package/front_end/generated/protocol-mapping.d.ts +8 -0
  13. package/front_end/generated/protocol-proxy-api.d.ts +6 -0
  14. package/front_end/generated/protocol.ts +22 -0
  15. package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
  16. package/front_end/models/comment_manager/CD4ABridge.ts +5 -0
  17. package/front_end/models/har/HARFormat.ts +7 -2
  18. package/front_end/models/issues_manager/MarkdownIssueDescription.ts +4 -47
  19. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +1 -1
  20. package/front_end/models/source_map_scopes/NamesResolver.ts +13 -5
  21. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingListView.ts +33 -1
  22. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +4 -12
  23. package/front_end/panels/application/ApplicationPanelSidebar.ts +58 -60
  24. package/front_end/panels/application/BackForwardCacheTreeElement.ts +1 -1
  25. package/front_end/panels/application/FrameDetailsView.ts +64 -82
  26. package/front_end/panels/application/OpenedWindowDetailsView.ts +20 -21
  27. package/front_end/panels/application/PreloadingTreeElement.ts +3 -3
  28. package/front_end/panels/common/CommentsOverlayWidget.ts +145 -72
  29. package/front_end/panels/common/CommentsStatusBarPill.ts +40 -7
  30. package/front_end/panels/common/commentsOverlay.css +34 -23
  31. package/front_end/panels/common/commentsStatusBarPill.css +13 -0
  32. package/front_end/panels/elements/DOMTreeWidget.ts +29 -10
  33. package/front_end/panels/issues/IssueView.ts +5 -1
  34. package/front_end/panels/network/RequestPayloadView.ts +7 -2
  35. package/front_end/panels/network/ShowMoreDetailsWidget.ts +12 -9
  36. package/front_end/panels/sources/DebuggerPlugin.ts +49 -16
  37. package/front_end/panels/sources/SourcesPanel.ts +1 -1
  38. package/front_end/panels/sources/SourcesView.ts +119 -148
  39. package/front_end/panels/sources/TabbedEditorContainer.ts +263 -207
  40. package/front_end/panels/sources/components/HeadersView.ts +193 -123
  41. package/front_end/third_party/chromium/README.chromium +1 -1
  42. package/front_end/third_party/puppeteer/README.chromium +2 -2
  43. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +5 -0
  44. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +24 -32
  45. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts +1 -1
  46. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.d.ts.map +1 -1
  47. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js +15 -1
  48. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/ElementHandle.js.map +1 -1
  49. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +8 -1
  50. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
  51. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +0 -8
  52. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
  53. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +0 -24
  54. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
  55. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts +12 -0
  56. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  57. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +79 -17
  58. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
  59. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js.map +1 -1
  61. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  62. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  63. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  64. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  65. package/front_end/third_party/puppeteer/package/lib/types.d.ts +5 -0
  66. package/front_end/third_party/puppeteer/package/package.json +4 -4
  67. package/front_end/third_party/puppeteer/package/src/api/ElementHandle.ts +15 -2
  68. package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +10 -1
  69. package/front_end/third_party/puppeteer/package/src/common/Debug.ts +0 -27
  70. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +96 -17
  71. package/front_end/third_party/puppeteer/package/src/node-env-setup.ts +1 -1
  72. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  73. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  74. package/front_end/ui/comments/CommentAnchorResolver.ts +60 -22
  75. package/front_end/ui/comments/CommentOverlayManager.ts +78 -25
  76. package/front_end/ui/components/markdown_view/MarkdownPlaceholderLitRenderer.ts +7 -65
  77. package/front_end/ui/legacy/TabbedPane.ts +51 -40
  78. package/front_end/ui/legacy/components/data_grid/DataGridExporter.ts +7 -13
  79. package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +51 -57
  80. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +342 -373
  81. package/front_end/ui/legacy/components/source_frame/ImageView.ts +101 -42
  82. package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -2
  83. package/front_end/ui/visual_logging/KnownContextValues.ts +8 -0
  84. package/package.json +2 -1
@@ -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 {
@@ -1,7 +1,6 @@
1
1
  // Copyright 2014 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
4
 
6
5
  import '../../ui/legacy/legacy.js';
7
6
 
@@ -13,17 +12,17 @@ import * as SDK from '../../core/sdk/sdk.js';
13
12
  import * as Bindings from '../../models/bindings/bindings.js';
14
13
  import * as Persistence from '../../models/persistence/persistence.js';
15
14
  import * as Workspace from '../../models/workspace/workspace.js';
15
+ 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, 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';
23
23
  import sourcesViewStyles from './sourcesView.css.js';
24
24
  import {
25
25
  type EditorSelectedEvent,
26
- Events as TabbedEditorContainerEvents,
27
26
  type SerializedHistoryItem,
28
27
  TabbedEditorContainer,
29
28
  } from './TabbedEditorContainer.js';
@@ -76,14 +75,24 @@ export interface ViewInput {
76
75
  searchProvider: UI.SearchableView.Searchable;
77
76
  replaceProvider: UI.SearchableView.Replaceable;
78
77
  searchableViewId: string;
79
- scriptViewToolbarItems: UI.Toolbar.ToolbarItem[];
80
- bottomToolbarItems: UI.Toolbar.ToolbarItem[];
78
+ scriptViewToolbarItems: UI.Toolbar.ToolbarItem[]|LitTemplate;
79
+ isNavigatorSidebarOpen: boolean;
80
+ isDebuggerSidebarOpen: boolean;
81
+ isDebuggerSidebarButtonEnabled: boolean;
82
+ isVertical: boolean;
83
+ isInWrapper: boolean;
84
+ isTraceApp: boolean;
85
+ onToggleNavigatorSidebar?: () => void;
86
+ onToggleDebuggerSidebar?: () => void;
87
+ breakpointsActive: boolean;
88
+ uiSourceCodes: ReadonlySet<Workspace.UISourceCode.UISourceCode>;
81
89
  historyManager: EditingLocationHistoryManager;
82
90
  previouslyViewedFilesSetting: Common.Settings.Setting<SerializedHistoryItem[]>;
91
+ onEditorSelected: (event: EditorSelectedEvent) => void;
92
+ onEditorClosed: (uiSourceCode: Workspace.UISourceCode.UISourceCode) => void;
83
93
  }
84
94
 
85
95
  export interface ViewOutput {
86
- scriptViewToolbar?: UI.Toolbar.Toolbar;
87
96
  editorContainer?: TabbedEditorContainer;
88
97
  searchableView?: UI.SearchableView.SearchableView;
89
98
  }
@@ -91,8 +100,52 @@ export interface ViewOutput {
91
100
  export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
92
101
 
93
102
  export const DEFAULT_VIEW: View = (input, output, target): void => {
103
+ const renderNavigatorToggleButton = (): LitTemplate => {
104
+ const navHidden = !input.isNavigatorSidebarOpen;
105
+ const title = navHidden ? i18nString(UIStrings.showNavigator) : i18nString(UIStrings.hideNavigator);
106
+ // clang-format off
107
+ return html`
108
+ <devtools-button
109
+ class="toolbar-button"
110
+ title=${title}
111
+ aria-label=${title}
112
+ .iconName=${navHidden ? 'left-panel-open' : 'left-panel-close'}
113
+ .variant=${Buttons.Button.Variant.TOOLBAR}
114
+ jslog=${VisualLogging.toggleSubpane().track({click: true}).context('navigator')}
115
+ @click=${() => input.onToggleNavigatorSidebar?.()}
116
+ ></devtools-button>`;
117
+ // clang-format on
118
+ };
119
+
120
+ const renderDebuggerToggleButton = (): LitTemplate => {
121
+ const debuggerHidden = !input.isDebuggerSidebarOpen;
122
+ const title = debuggerHidden ? i18nString(UIStrings.showDebugger) : i18nString(UIStrings.hideDebugger);
123
+ const glyph = debuggerHidden ? (input.isVertical ? 'right-panel-open' : 'bottom-panel-open') :
124
+ (input.isVertical ? 'right-panel-close' : 'bottom-panel-close');
125
+ // clang-format off
126
+ return html`
127
+ <devtools-button
128
+ class="toolbar-button"
129
+ title=${title}
130
+ aria-label=${title}
131
+ .iconName=${glyph}
132
+ .variant=${Buttons.Button.Variant.TOOLBAR}
133
+ ?disabled=${!input.isDebuggerSidebarButtonEnabled}
134
+ jslog=${VisualLogging.toggleSubpane().track({click: true}).context('debugger')}
135
+ @click=${() => input.onToggleDebuggerSidebar?.()}
136
+ ></devtools-button>`;
137
+ // clang-format on
138
+ };
139
+
140
+ const leftToolbarItems: LitTemplate[] = !input.isInWrapper ? [renderNavigatorToggleButton()] : [];
141
+ const rightToolbarItems: LitTemplate[] =
142
+ (!input.isInWrapper && !input.isTraceApp && input.isVertical) ? [renderDebuggerToggleButton()] : [];
143
+ const bottomToolbarContent: LitTemplate =
144
+ (!input.isInWrapper && !input.isTraceApp && !input.isVertical) ? renderDebuggerToggleButton() : nothing;
145
+
94
146
  // clang-format off
95
147
  render(html`
148
+ <style>${sourcesViewStyles}</style>
96
149
  <devtools-widget class="vbox flex-auto"
97
150
  ${widget(element => {
98
151
  const searchableView = new UI.SearchableView.SearchableView(input.searchProvider, input.replaceProvider, input.searchableViewId, element);
@@ -101,19 +154,35 @@ export const DEFAULT_VIEW: View = (input, output, target): void => {
101
154
  })}
102
155
  ${widgetRef(UI.SearchableView.SearchableView, e => { output.searchableView = e; })}
103
156
  >
104
- <devtools-widget class="vbox flex-auto"
105
- ${widget(TabbedEditorContainer, {historyManager: input.historyManager, previouslyViewedFilesSetting: input.previouslyViewedFilesSetting})}
157
+ <devtools-widget class="vbox flex-auto ${input.breakpointsActive ? '' : 'breakpoints-deactivated'}"
158
+ ${widget(TabbedEditorContainer, {
159
+ historyManager: input.historyManager,
160
+ previouslyViewedFilesSetting: input.previouslyViewedFilesSetting,
161
+ leftToolbarItems,
162
+ rightToolbarItems,
163
+ uiSourceCodes: input.uiSourceCodes,
164
+ onEditorSelected: input.onEditorSelected,
165
+ onEditorClosed: input.onEditorClosed,
166
+ })}
106
167
  ${widgetRef(TabbedEditorContainer, e => { output.editorContainer = e; })}>
107
168
  </devtools-widget>
108
169
  </devtools-widget>
109
170
  <div class="sources-toolbar" jslog=${VisualLogging.toolbar('bottom')}>
110
- <devtools-toolbar class="script-view-toolbar" style="flex: auto;" ${Directives.ref(el => { output.scriptViewToolbar = el as UI.Toolbar.Toolbar; })}>
111
- ${input.scriptViewToolbarItems.map(item => item.element)}
171
+ <devtools-toolbar class="script-view-toolbar" style="flex: auto;">
172
+ ${Array.isArray(input.scriptViewToolbarItems)
173
+ ? input.scriptViewToolbarItems.map(item => item.element)
174
+ : input.scriptViewToolbarItems}
112
175
  </devtools-toolbar>
113
176
  <devtools-toolbar class="bottom-toolbar">
114
- ${input.bottomToolbarItems.map(item => item.element)}
177
+ ${bottomToolbarContent}
115
178
  </devtools-toolbar>
116
- </div>`, target);
179
+ </div>`, target, {
180
+ container: {
181
+ attributes: {
182
+ id: 'sources-panel-sources-view',
183
+ },
184
+ },
185
+ });
117
186
  // clang-format on
118
187
  };
119
188
 
@@ -128,38 +197,32 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
128
197
  editorContainer?: TabbedEditorContainer;
129
198
  #uiSourceCodes = new Set<Workspace.UISourceCode.UISourceCode>();
130
199
  private readonly historyManager: EditingLocationHistoryManager;
131
- #scriptViewToolbar?: UI.Toolbar.Toolbar;
132
- #scriptViewToolbarItems: UI.Toolbar.ToolbarItem[] = [];
133
- #bottomToolbarItems: UI.Toolbar.ToolbarItem[] = [];
200
+ #scriptViewToolbarItems: UI.Toolbar.ToolbarItem[]|LitTemplate = [];
134
201
  private toolbarChangedListener: Common.EventTarget.EventDescriptor|null;
135
202
  private searchView?: UISourceCodeFrame;
136
203
  private searchConfig?: UI.SearchableView.SearchConfig;
137
- #view: View = DEFAULT_VIEW;
204
+ readonly #view: View;
138
205
 
139
- #toggleNavigatorSidebarButton: UI.Toolbar.ToolbarButton;
140
- #toggleDebuggerSidebarButton: UI.Toolbar.ToolbarButton;
141
206
  #onToggleNavigatorSidebar?: () => void;
142
207
  #onToggleDebuggerSidebar?: () => void;
143
208
  #isNavigatorSidebarOpen = false;
144
209
  #isDebuggerSidebarOpen = false;
210
+ #isDebuggerSidebarButtonEnabled = true;
145
211
  #navigatorSidebarInitialized = false;
146
212
  #debuggerSidebarInitialized = false;
147
213
  #isVertical = false;
148
- #leftToolbarItems?: UI.Toolbar.ToolbarItem[];
149
- #rightToolbarItems?: UI.Toolbar.ToolbarItem[];
150
- #breakpointsActive?: boolean;
214
+ #isInWrapper = true;
215
+ #breakpointsActive = true;
151
216
  #editorContainerPromise: Promise<TabbedEditorContainer>;
152
217
  #editorContainerResolve!: (container: TabbedEditorContainer) => void;
153
218
  readonly previouslyViewedFilesSetting: Common.Settings.Setting<SerializedHistoryItem[]>;
154
219
 
155
- constructor() {
156
- super({jslog: `${VisualLogging.pane('editor').track({keydown: 'Escape'})}`});
220
+ constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
221
+ super(element, {jslog: `${VisualLogging.pane('editor').track({keydown: 'Escape'})}`});
222
+ this.#view = view;
157
223
  this.#editorContainerPromise = new Promise(resolve => {
158
224
  this.#editorContainerResolve = resolve;
159
225
  });
160
- this.registerRequiredCSS(sourcesViewStyles);
161
-
162
- this.element.id = 'sources-panel-sources-view';
163
226
  this.setMinimumAndPreferredSizes(88, 52, 150, 100);
164
227
 
165
228
  const workspace = Workspace.Workspace.WorkspaceImpl.instance();
@@ -168,22 +231,6 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
168
231
 
169
232
  this.toolbarChangedListener = null;
170
233
 
171
- this.#toggleNavigatorSidebarButton =
172
- new UI.Toolbar.ToolbarButton(i18nString(UIStrings.showNavigator), 'left-panel-open');
173
- this.#toggleNavigatorSidebarButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {
174
- this.#onToggleNavigatorSidebar?.();
175
- });
176
- this.#toggleNavigatorSidebarButton.element.setAttribute(
177
- 'jslog', `${VisualLogging.toggleSubpane().track({click: true}).context('navigator')}`);
178
-
179
- this.#toggleDebuggerSidebarButton =
180
- new UI.Toolbar.ToolbarButton(i18nString(UIStrings.showDebugger), 'right-panel-open');
181
- this.#toggleDebuggerSidebarButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {
182
- this.#onToggleDebuggerSidebar?.();
183
- });
184
- this.#toggleDebuggerSidebarButton.element.setAttribute(
185
- 'jslog', `${VisualLogging.toggleSubpane().track({click: true}).context('debugger')}`);
186
-
187
234
  this.previouslyViewedFilesSetting =
188
235
  Common.Settings.Settings.instance().createLocalSetting('previously-viewed-files', []);
189
236
  this.requestUpdate();
@@ -235,16 +282,24 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
235
282
  replaceProvider: this,
236
283
  searchableViewId: 'sources-view-search-config',
237
284
  scriptViewToolbarItems: this.#scriptViewToolbarItems,
238
- bottomToolbarItems: this.#bottomToolbarItems,
285
+ isNavigatorSidebarOpen: this.#isNavigatorSidebarOpen,
286
+ isDebuggerSidebarOpen: this.#isDebuggerSidebarOpen,
287
+ isDebuggerSidebarButtonEnabled: this.#isDebuggerSidebarButtonEnabled,
288
+ isVertical: this.#isVertical,
289
+ isInWrapper: this.#isInWrapper,
290
+ isTraceApp: Root.Runtime.Runtime.isTraceApp(),
291
+ onToggleNavigatorSidebar: this.#onToggleNavigatorSidebar,
292
+ onToggleDebuggerSidebar: this.#onToggleDebuggerSidebar,
293
+ breakpointsActive: this.#breakpointsActive,
294
+ uiSourceCodes: new Set(this.#uiSourceCodes),
239
295
  historyManager: this.historyManager,
240
296
  previouslyViewedFilesSetting: this.previouslyViewedFilesSetting,
297
+ onEditorSelected: this.editorSelected.bind(this),
298
+ onEditorClosed: this.editorClosed.bind(this),
241
299
  };
242
300
 
243
301
  const that = this;
244
302
  const output: ViewOutput = {
245
- set scriptViewToolbar(value: UI.Toolbar.Toolbar) {
246
- that.#scriptViewToolbar = value;
247
- },
248
303
  set editorContainer(value: TabbedEditorContainer) {
249
304
  that.setEditorContainer(value);
250
305
  },
@@ -265,36 +320,9 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
265
320
  if (this.editorContainer === editorContainer) {
266
321
  return;
267
322
  }
268
- if (this.editorContainer) {
269
- this.editorContainer.removeEventListener(TabbedEditorContainerEvents.EDITOR_SELECTED, this.editorSelected, this);
270
- this.editorContainer.removeEventListener(TabbedEditorContainerEvents.EDITOR_CLOSED, this.editorClosed, this);
271
- }
272
323
  this.editorContainer = editorContainer;
273
324
  if (this.editorContainer) {
274
- if (this.#leftToolbarItems) {
275
- this.editorContainer.leftToolbar().removeToolbarItems();
276
- for (const item of this.#leftToolbarItems) {
277
- this.editorContainer.leftToolbar().appendToolbarItem(item);
278
- }
279
- }
280
- if (this.#rightToolbarItems) {
281
- this.editorContainer.rightToolbar().removeToolbarItems();
282
- for (const item of this.#rightToolbarItems) {
283
- this.editorContainer.rightToolbar().appendToolbarItem(item);
284
- }
285
- }
286
- if (this.#breakpointsActive !== undefined) {
287
- this.editorContainer.element.classList.toggle('breakpoints-deactivated', !this.#breakpointsActive);
288
- }
289
-
290
325
  this.#editorContainerResolve(editorContainer);
291
- this.editorContainer.addEventListener(TabbedEditorContainerEvents.EDITOR_SELECTED, this.editorSelected, this);
292
- this.editorContainer.addEventListener(TabbedEditorContainerEvents.EDITOR_CLOSED, this.editorClosed, this);
293
- UI.UIUtils.startBatchUpdate();
294
- for (const uiSourceCode of this.#uiSourceCodes) {
295
- this.editorContainer.addUISourceCode(uiSourceCode);
296
- }
297
- UI.UIUtils.endBatchUpdate();
298
326
  }
299
327
  }
300
328
 
@@ -313,10 +341,12 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
313
341
 
314
342
  set onToggleNavigatorSidebar(callback: () => void) {
315
343
  this.#onToggleNavigatorSidebar = callback;
344
+ this.requestUpdate();
316
345
  }
317
346
 
318
347
  set onToggleDebuggerSidebar(callback: () => void) {
319
348
  this.#onToggleDebuggerSidebar = callback;
349
+ this.requestUpdate();
320
350
  }
321
351
 
322
352
  set isNavigatorSidebarOpen(isOpen: boolean) {
@@ -326,7 +356,7 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
326
356
  return;
327
357
  }
328
358
  this.#isNavigatorSidebarOpen = isOpen;
329
- this.#updateNavigatorSidebarButton();
359
+ this.requestUpdate();
330
360
  if (isInitialized) {
331
361
  UI.ARIAUtils.LiveAnnouncer.alert(isOpen ? i18nString(UIStrings.navigatorShown) :
332
362
  i18nString(UIStrings.navigatorHidden));
@@ -340,73 +370,21 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
340
370
  return;
341
371
  }
342
372
  this.#isDebuggerSidebarOpen = isOpen;
343
- this.#updateDebuggerSidebarButton();
373
+ this.requestUpdate();
344
374
  if (isInitialized) {
345
375
  UI.ARIAUtils.LiveAnnouncer.alert(isOpen ? i18nString(UIStrings.debuggerShown) :
346
376
  i18nString(UIStrings.debuggerHidden));
347
377
  }
348
378
  }
349
379
 
350
- #updateNavigatorSidebarButton(): void {
351
- const navHidden = !this.#isNavigatorSidebarOpen;
352
- this.#toggleNavigatorSidebarButton.setGlyph(navHidden ? 'left-panel-open' : 'left-panel-close');
353
- this.#toggleNavigatorSidebarButton.setTitle(navHidden ? i18nString(UIStrings.showNavigator) :
354
- i18nString(UIStrings.hideNavigator));
355
- }
356
-
357
- #updateDebuggerSidebarButton(): void {
358
- const debuggerHidden = !this.#isDebuggerSidebarOpen;
359
- const debuggerGlyph = debuggerHidden ? (this.#isVertical ? 'right-panel-open' : 'bottom-panel-open') :
360
- (this.#isVertical ? 'right-panel-close' : 'bottom-panel-close');
361
- this.#toggleDebuggerSidebarButton.setGlyph(debuggerGlyph);
362
- this.#toggleDebuggerSidebarButton.setTitle(debuggerHidden ? i18nString(UIStrings.showDebugger) :
363
- i18nString(UIStrings.hideDebugger));
364
- }
365
-
366
380
  toggleDebuggerSidebarButtonEnabled(enabled: boolean): void {
367
- this.#toggleDebuggerSidebarButton.setEnabled(enabled);
381
+ this.#isDebuggerSidebarButtonEnabled = enabled;
382
+ this.requestUpdate();
368
383
  }
369
384
 
370
- setLayoutMode(splitWidget: UI.SplitWidget.SplitWidget, isVertical: boolean, isInWrapper: boolean): void {
371
- this.#bottomToolbarItems = [];
372
-
373
- if (isVertical || isInWrapper) {
374
- if (this.#scriptViewToolbar) {
375
- splitWidget.uninstallResizer(this.#scriptViewToolbar);
376
- }
377
- } else if (this.#scriptViewToolbar) {
378
- splitWidget.installResizer(this.#scriptViewToolbar);
379
- }
380
-
385
+ setLayoutMode(isVertical: boolean, isInWrapper: boolean): void {
381
386
  this.#isVertical = isVertical;
382
- this.#updateNavigatorSidebarButton();
383
- this.#updateDebuggerSidebarButton();
384
-
385
- const leftItems: UI.Toolbar.ToolbarItem[] = [];
386
- const rightItems: UI.Toolbar.ToolbarItem[] = [];
387
-
388
- if (!isInWrapper) {
389
- leftItems.push(this.#toggleNavigatorSidebarButton);
390
- if (!Root.Runtime.Runtime.isTraceApp()) {
391
- if (isVertical) {
392
- rightItems.push(this.#toggleDebuggerSidebarButton);
393
- } else {
394
- this.#bottomToolbarItems.push(this.#toggleDebuggerSidebarButton);
395
- }
396
- }
397
- }
398
-
399
- this.#leftToolbarItems = leftItems;
400
- this.#rightToolbarItems = rightItems;
401
-
402
- if (this.editorContainer) {
403
- const editorContainer = this.editorContainer;
404
- editorContainer.leftToolbar().removeToolbarItems();
405
- leftItems.forEach(item => editorContainer.leftToolbar().appendToolbarItem(item));
406
-
407
- editorContainer.rightToolbar().removeToolbarItems();
408
- rightItems.forEach(item => editorContainer.rightToolbar().appendToolbarItem(item));
409
- }
387
+ this.#isInWrapper = isInWrapper;
410
388
  this.requestUpdate();
411
389
  }
412
390
 
@@ -500,7 +478,7 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
500
478
  }
501
479
  }
502
480
  this.#uiSourceCodes.add(uiSourceCode);
503
- this.editorContainer?.addUISourceCode(uiSourceCode);
481
+ this.requestUpdate();
504
482
  }
505
483
 
506
484
  private uiSourceCodeRemoved(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.UISourceCode>): void {
@@ -510,10 +488,10 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
510
488
 
511
489
  private removeUISourceCodes(uiSourceCodes: Workspace.UISourceCode.UISourceCode[]): void {
512
490
  uiSourceCodes.forEach(ui => this.#uiSourceCodes.delete(ui));
513
- this.editorContainer?.removeUISourceCodes(uiSourceCodes);
514
491
  for (let i = 0; i < uiSourceCodes.length; ++i) {
515
492
  this.historyManager.removeHistoryForSourceCode(uiSourceCodes[i]);
516
493
  }
494
+ this.requestUpdate();
517
495
  }
518
496
 
519
497
  private projectRemoved(event: Common.EventTarget.EventTargetEvent<Workspace.Workspace.Project>): void {
@@ -526,17 +504,12 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
526
504
  const view = this.visibleView();
527
505
  if (view instanceof UI.View.SimpleView) {
528
506
  void view.toolbarItems().then(items => {
529
- if (Array.isArray(items)) {
530
- this.#scriptViewToolbarItems = items;
531
- } else {
532
- const wrapper = document.createElement('div');
533
- wrapper.style.display = 'contents';
534
- // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
535
- render(items, wrapper);
536
- this.#scriptViewToolbarItems = [new UI.Toolbar.ToolbarItem(wrapper)];
537
- }
507
+ this.#scriptViewToolbarItems = items;
538
508
  this.requestUpdate();
539
509
  });
510
+ } else {
511
+ this.#scriptViewToolbarItems = [];
512
+ this.requestUpdate();
540
513
  }
541
514
  }
542
515
 
@@ -570,8 +543,7 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
570
543
  return this.editorContainer?.getCreatedSourceView(uiSourceCode);
571
544
  }
572
545
 
573
- private editorClosed(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.UISourceCode>): void {
574
- const uiSourceCode = event.data;
546
+ private editorClosed(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
575
547
  this.historyManager.removeHistoryForSourceCode(uiSourceCode);
576
548
 
577
549
  let wasSelected = false;
@@ -591,12 +563,12 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
591
563
  this.dispatchEventToListeners(Events.EDITOR_CLOSED, data);
592
564
  }
593
565
 
594
- private editorSelected(event: Common.EventTarget.EventTargetEvent<EditorSelectedEvent>): void {
595
- const previousSourceFrame = event.data.previousView instanceof UISourceCodeFrame ? event.data.previousView : null;
566
+ private editorSelected(event: EditorSelectedEvent): void {
567
+ const previousSourceFrame = event.previousView instanceof UISourceCodeFrame ? event.previousView : null;
596
568
  if (previousSourceFrame) {
597
569
  previousSourceFrame.setSearchableView(null);
598
570
  }
599
- const currentSourceFrame = event.data.currentView instanceof UISourceCodeFrame ? event.data.currentView : null;
571
+ const currentSourceFrame = event.currentView instanceof UISourceCodeFrame ? event.currentView : null;
600
572
  if (currentSourceFrame) {
601
573
  currentSourceFrame.setSearchableView(this.searchableView());
602
574
  }
@@ -738,7 +710,6 @@ export class SourcesView extends SourcesViewBase implements UI.SearchableView.Se
738
710
 
739
711
  toggleBreakpointsActiveState(active: boolean): void {
740
712
  this.#breakpointsActive = active;
741
- this.editorContainer?.element.classList.toggle('breakpoints-deactivated', !active);
742
713
  this.requestUpdate();
743
714
  }
744
715
  }