chrome-devtools-frontend 1.0.1515446 → 1.0.1515988

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 (215) hide show
  1. package/docs/contributing/infrastructure.md +131 -82
  2. package/front_end/Tests.js +3 -29
  3. package/front_end/core/common/Progress.ts +73 -55
  4. package/front_end/core/host/UserMetrics.ts +0 -1
  5. package/front_end/core/protocol_client/InspectorBackend.ts +2 -0
  6. package/front_end/core/root/Runtime.ts +0 -1
  7. package/front_end/core/sdk/CSSMatchedStyles.ts +12 -10
  8. package/front_end/core/sdk/CSSModel.ts +1 -31
  9. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +27 -7
  10. package/front_end/core/sdk/DebuggerModel.ts +1 -31
  11. package/front_end/core/sdk/EnhancedTracesParser.ts +81 -50
  12. package/front_end/core/sdk/NetworkManager.ts +1 -31
  13. package/front_end/core/sdk/NetworkRequest.ts +1 -31
  14. package/front_end/core/sdk/RehydratingConnection.snapshot.txt +1003 -0
  15. package/front_end/core/sdk/RehydratingConnection.ts +13 -18
  16. package/front_end/core/sdk/RehydratingObject.ts +8 -31
  17. package/front_end/core/sdk/RemoteObject.ts +1 -31
  18. package/front_end/core/sdk/ResourceTreeModel.ts +1 -31
  19. package/front_end/core/sdk/RuntimeModel.ts +1 -31
  20. package/front_end/core/sdk/ServiceWorkerManager.ts +1 -31
  21. package/front_end/core/sdk/SourceMap.ts +1 -31
  22. package/front_end/core/sdk/TraceObject.ts +8 -3
  23. package/front_end/entrypoints/main/MainImpl.ts +0 -2
  24. package/front_end/entrypoints/main/main-meta.ts +2 -2
  25. package/front_end/generated/InspectorBackendCommands.js +4 -4
  26. package/front_end/generated/SupportedCSSProperties.js +12 -0
  27. package/front_end/generated/protocol.ts +10 -1
  28. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -3
  29. package/front_end/models/ai_assistance/ConversationHandler.ts +4 -6
  30. package/front_end/models/ai_assistance/agents/AiAgent.ts +4 -1
  31. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +107 -72
  32. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +2 -2
  33. package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -2
  34. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +178 -85
  35. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +308 -218
  36. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +161 -97
  37. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +78 -58
  38. package/front_end/models/ai_assistance/data_formatters/UnitFormatters.ts +10 -1
  39. package/front_end/models/ai_assistance/performance/AIContext.ts +19 -21
  40. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +123 -55
  41. package/front_end/models/bindings/ContentProviderBasedProject.ts +6 -4
  42. package/front_end/models/breakpoints/BreakpointManager.ts +3 -3
  43. package/front_end/models/har/Writer.ts +11 -11
  44. package/front_end/models/javascript_metadata/NativeFunctions.js +7 -7
  45. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +3 -3
  46. package/front_end/models/persistence/IsolatedFileSystem.ts +4 -4
  47. package/front_end/models/persistence/IsolatedFileSystemManager.ts +7 -7
  48. package/front_end/models/persistence/PersistenceImpl.ts +8 -8
  49. package/front_end/models/persistence/PlatformFileSystem.ts +1 -1
  50. package/front_end/models/text_utils/TextUtils.ts +26 -0
  51. package/front_end/models/trace/ModelImpl.ts +2 -16
  52. package/front_end/models/trace/Processor.ts +14 -8
  53. package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +4 -4
  54. package/front_end/models/trace/handlers/FramesHandler.ts +2 -2
  55. package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +7 -10
  56. package/front_end/models/trace/handlers/MetaHandler.ts +11 -9
  57. package/front_end/models/trace/handlers/ScreenshotsHandler.ts +1 -1
  58. package/front_end/models/trace/handlers/ScriptsHandler.ts +5 -5
  59. package/front_end/models/trace/handlers/UserInteractionsHandler.ts +2 -14
  60. package/front_end/models/trace/handlers/UserTimingsHandler.ts +3 -4
  61. package/front_end/models/trace/insights/CLSCulprits.ts +1 -1
  62. package/front_end/models/trace/insights/DocumentLatency.ts +8 -7
  63. package/front_end/models/trace/insights/DuplicatedJavaScript.ts +1 -1
  64. package/front_end/models/trace/insights/INPBreakdown.ts +1 -1
  65. package/front_end/models/trace/insights/ImageDelivery.ts +1 -1
  66. package/front_end/models/trace/insights/LCPBreakdown.ts +1 -1
  67. package/front_end/models/trace/insights/LCPDiscovery.ts +1 -1
  68. package/front_end/models/trace/insights/ModernHTTP.ts +1 -1
  69. package/front_end/models/trace/insights/NetworkDependencyTree.ts +1 -1
  70. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  71. package/front_end/models/trace/insights/types.ts +2 -0
  72. package/front_end/models/trace/types/Configuration.ts +12 -0
  73. package/front_end/models/trace/types/TraceEvents.ts +41 -64
  74. package/front_end/models/trace_source_maps_resolver/trace_source_maps_resolver.ts +1 -1
  75. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +21 -99
  76. package/front_end/panels/application/ServiceWorkersView.ts +0 -1
  77. package/front_end/panels/application/components/BackForwardCacheStrings.ts +8 -2
  78. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -3
  79. package/front_end/panels/common/BadgeNotification.ts +10 -8
  80. package/front_end/panels/common/GdpSignUpDialog.ts +30 -14
  81. package/front_end/panels/common/gdpSignUpDialog.css +4 -0
  82. package/front_end/panels/console/ConsoleView.ts +23 -28
  83. package/front_end/panels/console/ConsoleViewport.ts +2 -2
  84. package/front_end/panels/console/consoleView.css +11 -1
  85. package/front_end/panels/coverage/CoverageView.ts +2 -2
  86. package/front_end/panels/elements/ElementsTreeOutline.ts +2 -2
  87. package/front_end/panels/elements/StyleEditorWidget.ts +8 -19
  88. package/front_end/panels/elements/StylePropertyTreeElement.ts +39 -25
  89. package/front_end/panels/elements/StylesSidebarPane.ts +2 -2
  90. package/front_end/panels/elements/stylePropertiesTreeOutline.css +4 -3
  91. package/front_end/panels/layer_viewer/Layers3DView.ts +2 -2
  92. package/front_end/panels/layers/LayerTreeModel.ts +3 -3
  93. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +4 -4
  94. package/front_end/panels/network/NetworkLogView.ts +1 -1
  95. package/front_end/panels/network/NetworkLogViewColumns.ts +3 -3
  96. package/front_end/panels/network/NetworkSearchScope.ts +6 -6
  97. package/front_end/panels/search/SearchView.ts +220 -159
  98. package/front_end/panels/settings/components/SyncSection.ts +64 -10
  99. package/front_end/panels/settings/components/syncSection.css +6 -0
  100. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +1 -4
  101. package/front_end/panels/sources/SourcesSearchScope.ts +4 -4
  102. package/front_end/panels/sources/TabbedEditorContainer.ts +5 -5
  103. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +10 -5
  104. package/front_end/panels/timeline/TimelineFlameChartView.ts +18 -15
  105. package/front_end/panels/timeline/TimelinePanel.ts +41 -22
  106. package/front_end/panels/timeline/TracingLayerTree.ts +4 -5
  107. package/front_end/panels/timeline/components/ExportTraceOptions.ts +37 -22
  108. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +17 -7
  109. package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
  110. package/front_end/third_party/axe-core/README.chromium +1 -0
  111. package/front_end/third_party/chromium/README.chromium +1 -1
  112. package/front_end/third_party/codemirror/README.chromium +1 -0
  113. package/front_end/third_party/codemirror.next/README.chromium +1 -0
  114. package/front_end/third_party/csp_evaluator/README.chromium +1 -0
  115. package/front_end/third_party/diff/README.chromium +1 -0
  116. package/front_end/third_party/i18n/README.chromium +1 -0
  117. package/front_end/third_party/intl-messageformat/README.chromium +1 -0
  118. package/front_end/third_party/json5/README.chromium +1 -0
  119. package/front_end/third_party/legacy-javascript/README.chromium +1 -0
  120. package/front_end/third_party/lighthouse/README.chromium +1 -0
  121. package/front_end/third_party/lit/README.chromium +1 -0
  122. package/front_end/third_party/marked/README.chromium +1 -0
  123. package/front_end/third_party/puppeteer/README.chromium +2 -2
  124. package/front_end/third_party/puppeteer/package/README.md +6 -3
  125. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +11 -1
  127. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js +2 -2
  129. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +5 -1
  131. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +30 -8
  133. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  135. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +1 -3
  136. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  137. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  138. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts +1 -1
  139. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  140. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +8 -2
  141. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  142. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +5 -1
  143. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +8 -2
  145. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  146. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  147. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  148. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  150. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +5 -0
  151. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  152. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  153. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +12 -2
  154. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +22 -8
  155. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +1 -1
  156. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +11 -1
  157. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  158. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js +2 -2
  159. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  160. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +5 -1
  161. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
  162. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +30 -8
  163. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
  164. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  165. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +1 -3
  166. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  167. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts +1 -1
  168. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  169. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +8 -2
  170. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  171. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +5 -1
  172. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  173. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +8 -2
  174. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  175. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  176. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  177. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  178. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +5 -0
  179. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  180. package/front_end/third_party/puppeteer/package/lib/types.d.ts +12 -2
  181. package/front_end/third_party/puppeteer/package/package.json +4 -4
  182. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +1 -1
  183. package/front_end/third_party/puppeteer/package/src/api/Page.ts +13 -2
  184. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +50 -8
  185. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +0 -1
  186. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +8 -1
  187. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +21 -5
  188. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  189. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +12 -0
  190. package/front_end/third_party/puppeteer-replay/README.chromium +1 -0
  191. package/front_end/third_party/third-party-web/README.chromium +1 -0
  192. package/front_end/third_party/vscode.web-custom-data/README.chromium +1 -0
  193. package/front_end/third_party/wasmparser/README.chromium +1 -0
  194. package/front_end/third_party/web-vitals/README.chromium +1 -0
  195. package/front_end/ui/components/text_editor/config.ts +66 -16
  196. package/front_end/ui/components/tooltips/Tooltip.ts +17 -1
  197. package/front_end/ui/legacy/ContextMenu.ts +2 -2
  198. package/front_end/ui/legacy/GlassPane.ts +7 -3
  199. package/front_end/ui/legacy/ProgressIndicator.ts +33 -21
  200. package/front_end/ui/legacy/TabbedPane.ts +2 -2
  201. package/front_end/ui/legacy/Treeoutline.ts +10 -5
  202. package/front_end/ui/legacy/UIUtils.ts +42 -10
  203. package/front_end/ui/legacy/components/color_picker/Spectrum.ts +14 -14
  204. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +6 -6
  205. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +4 -2
  206. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +3 -29
  207. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +14 -14
  208. package/front_end/ui/visual_logging/Debugging.ts +24 -12
  209. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  210. package/inspector_overlay/highlight_common.ts +1 -27
  211. package/inspector_overlay/highlight_grid_common.ts +1 -27
  212. package/inspector_overlay/tool_highlight.ts +1 -27
  213. package/inspector_overlay/tool_persistent.ts +1 -27
  214. package/inspector_overlay/tool_source_order.ts +1 -27
  215. package/package.json +3 -3
@@ -108,67 +108,52 @@ const str_ = i18n.i18n.registerUIStrings('panels/search/SearchView.ts', UIString
108
108
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
109
109
  const {ref} = Directives;
110
110
 
111
- export class SearchView extends UI.Widget.VBox {
112
- #focusOnShow: boolean;
113
- #isIndexing: boolean;
114
- #searchId: number;
115
- #searchMatchesCount: number;
116
- #searchResultsCount: number;
117
- #nonEmptySearchResultsCount: number;
118
- #searchingView: UI.Widget.Widget|null;
119
- #notFoundView: UI.Widget.Widget|null;
120
- #searchConfig: Workspace.SearchConfig.SearchConfig|null;
121
- #pendingSearchConfig: Workspace.SearchConfig.SearchConfig|null;
122
- #searchResultsPane: SearchResultsPane|null;
123
- #progressIndicator: UI.ProgressIndicator.ProgressIndicator|null;
124
- #visiblePane: UI.Widget.Widget|null;
125
- #searchResultsElement!: HTMLElement;
126
- #searchInputElement!: HTMLInputElement;
127
- #matchCaseButton!: Buttons.Button.Button;
128
- #regexButton!: Buttons.Button.Button;
129
- #searchMessageElement!: HTMLElement;
130
- #searchProgressPlaceholderElement!: HTMLElement;
131
- #searchResultsMessageElement!: HTMLElement;
132
- readonly #advancedSearchConfig: Common.Settings.Setting<{
133
- query: string,
134
- ignoreCase: boolean,
135
- isRegex: boolean,
136
- }>;
137
- #searchScope: SearchScope|null;
138
-
139
- // We throttle adding search results, otherwise we trigger DOM layout for each
140
- // result added.
141
- #throttler: Common.Throttler.Throttler;
142
- #pendingSearchResults: SearchResult[] = [];
143
- #emptyStartView: UI.EmptyWidget.EmptyWidget;
144
-
145
- constructor(settingKey: string, throttler: Common.Throttler.Throttler) {
146
- super({
147
- jslog: `${VisualLogging.panel('search').track({resize: true})}`,
148
- useShadowDom: true,
149
- });
150
- this.setMinimumSize(0, 40);
111
+ interface SearchViewInput {
112
+ query: string;
113
+ focusSearchInput: boolean;
114
+ matchCase: boolean;
115
+ isRegex: boolean;
116
+ searchMessage: string;
117
+ searchResultsMessage: string;
118
+ progress: Common.Progress.Progress|null;
119
+ onQueryChange: (query: string) => void;
120
+ onQueryKeyDown: (evt: KeyboardEvent) => void;
121
+ onPanelKeyDown: (evt: KeyboardEvent) => void;
122
+ onClearSearchInput: () => void;
123
+ onToggleRegex: () => void;
124
+ onToggleMatchCase: () => void;
125
+ onRefresh: () => void;
126
+ onClearSearch: () => void;
127
+ }
151
128
 
152
- this.#focusOnShow = false;
153
- this.#isIndexing = false;
154
- this.#searchId = 1;
155
- this.#searchMatchesCount = 0;
156
- this.#searchResultsCount = 0;
157
- this.#nonEmptySearchResultsCount = 0;
158
- this.#searchingView = null;
159
- this.#notFoundView = null;
160
- this.#searchConfig = null;
161
- this.#pendingSearchConfig = null;
162
- this.#searchResultsPane = null;
163
- this.#progressIndicator = null;
164
- this.#visiblePane = null;
165
- this.#throttler = throttler;
129
+ interface SearchViewOutput {
130
+ searchResultsElement?: HTMLElement;
131
+ }
166
132
 
167
- // clang-format off
168
- /* eslint-disable-next-line rulesdir/no-lit-render-outside-of-view */
169
- render(html`
133
+ type View = (input: SearchViewInput, output: SearchViewOutput, target: HTMLElement) => void;
134
+
135
+ export const DEFAULT_VIEW: View = (input, output, target) => {
136
+ const {
137
+ query,
138
+ focusSearchInput,
139
+ matchCase,
140
+ isRegex,
141
+ searchMessage,
142
+ searchResultsMessage,
143
+ progress,
144
+ onQueryChange,
145
+ onQueryKeyDown,
146
+ onPanelKeyDown,
147
+ onClearSearchInput,
148
+ onToggleRegex,
149
+ onToggleMatchCase,
150
+ onRefresh,
151
+ onClearSearch,
152
+ } = input;
153
+ // clang-format off
154
+ render(html`
170
155
  <style>${searchViewStyles}</style>
171
- <div class="search-drawer-header" @keydown=${this.#onPanelKeyDown}>
156
+ <div class="search-drawer-header" @keydown=${onPanelKeyDown}>
172
157
  <div class="search-container">
173
158
  <div class="toolbar-item-search">
174
159
  <devtools-icon name="search"></devtools-icon>
@@ -179,10 +164,17 @@ export class SearchView extends UI.Widget.VBox {
179
164
  change: true, keydown: 'ArrowUp|ArrowDown|Enter'})}
180
165
  aria-label=${i18nString(UIStrings.find)}
181
166
  size="100" results="0"
182
- @keydown=${this.#onQueryKeyDown}
183
- ${ref(e => {this.#searchInputElement = e as HTMLInputElement;})}>
167
+ .value=${query}
168
+ @keydown=${onQueryKeyDown}
169
+ @input=${(e: Event) => onQueryChange((e.target as HTMLInputElement).value)}
170
+ ${ref(e => {
171
+ if (e instanceof HTMLInputElement && focusSearchInput) {
172
+ e.focus();
173
+ e.select();
174
+ }
175
+ })}>
184
176
  <devtools-button class="clear-button" tabindex="-1"
185
- @click=${this.#onClearSearchInput}
177
+ @click=${onClearSearchInput}
186
178
  .data=${{
187
179
  variant: Buttons.Button.Variant.ICON,
188
180
  iconName: 'cross-circle-filled',
@@ -191,40 +183,40 @@ export class SearchView extends UI.Widget.VBox {
191
183
  title: i18nString(UIStrings.clearInput),
192
184
  } as Buttons.Button.ButtonData}
193
185
  ></devtools-button>
194
- <devtools-button @click=${this.#onToggleRegex} .data=${{
186
+ <devtools-button @click=${onToggleRegex} .data=${{
195
187
  variant: Buttons.Button.Variant.ICON_TOGGLE,
196
188
  iconName: 'regular-expression',
197
189
  toggledIconName: 'regular-expression',
198
190
  toggleType: Buttons.Button.ToggleType.PRIMARY,
199
191
  size: Buttons.Button.Size.SMALL,
200
- toggled: false,
201
- title: i18nString(UIStrings.enableRegularExpression),
192
+ toggled: isRegex,
193
+ title: isRegex ? i18nString(UIStrings.disableRegularExpression) : i18nString(UIStrings.enableRegularExpression),
202
194
  jslogContext: 'regular-expression',
203
195
  } as Buttons.Button.ButtonData}
204
- ${ref(e => {this.#regexButton = e as Buttons.Button.Button;})}
196
+ class="regex-button"
205
197
  ></devtools-button>
206
- <devtools-button @click=${this.#onToggleMatchCase} .data=${{
198
+ <devtools-button @click=${onToggleMatchCase} .data=${{
207
199
  variant: Buttons.Button.Variant.ICON_TOGGLE,
208
200
  iconName: 'match-case',
209
201
  toggledIconName: 'match-case',
210
202
  toggleType: Buttons.Button.ToggleType.PRIMARY,
211
203
  size: Buttons.Button.Size.SMALL,
212
- toggled: false,
213
- title: i18nString(UIStrings.enableCaseSensitive),
204
+ toggled: matchCase,
205
+ title: matchCase ? i18nString(UIStrings.disableCaseSensitive) : i18nString(UIStrings.enableCaseSensitive),
214
206
  jslogContext: 'match-case',
215
207
  } as Buttons.Button.ButtonData}
216
- ${ref(e => {this.#matchCaseButton = e as Buttons.Button.Button;})}
208
+ class="match-case-button"
217
209
  ></devtools-button>
218
210
  </div>
219
211
  </div>
220
212
  <devtools-toolbar class="search-toolbar" jslog=${VisualLogging.toolbar()}>
221
- <devtools-button title=${i18nString(UIStrings.refresh)} @click=${this.#onRefresh}
213
+ <devtools-button title=${i18nString(UIStrings.refresh)} @click=${onRefresh}
222
214
  .data=${{
223
215
  variant: Buttons.Button.Variant.TOOLBAR,
224
216
  iconName: 'refresh',
225
217
  jslogContext: 'search.refresh',
226
218
  } as Buttons.Button.ButtonData}></devtools-button>
227
- <devtools-button title=${i18nString(UIStrings.clear)} @click=${this.#onClearSearch}
219
+ <devtools-button title=${i18nString(UIStrings.clear)} @click=${onClearSearch}
228
220
  .data=${{
229
221
  variant: Buttons.Button.Variant.TOOLBAR,
230
222
  iconName: 'clear',
@@ -232,22 +224,86 @@ export class SearchView extends UI.Widget.VBox {
232
224
  } as Buttons.Button.ButtonData}></devtools-button>
233
225
  </devtools-toolbar>
234
226
  </div>
235
- <div class="search-results" @keydown=${this.#onPanelKeyDown}
236
- ${ref(e => {this.#searchResultsElement = e as HTMLElement;})}>
227
+ <div class="search-results" @keydown=${onPanelKeyDown}
228
+ ${ref(e => {output.searchResultsElement = e as HTMLElement;})}>
237
229
  </div>
238
- <div class="search-toolbar-summary" @keydown=${this.#onPanelKeyDown}>
239
- <div class="search-message" ${ref(e => {this.#searchMessageElement = e as HTMLElement;})}></div>
240
- <div class="flex-centered" ${ref(e => {this.#searchProgressPlaceholderElement = e as HTMLElement;})}>
230
+ <div class="search-toolbar-summary" @keydown=${onPanelKeyDown}>
231
+ <div class="search-message">${searchMessage}</div>
232
+ <div class="flex-centered">
233
+ ${progress ? html`
234
+ <devtools-progress .title=${progress.title ?? ''}
235
+ .worked=${progress.worked} .totalWork=${progress.totalWork}>
236
+ </devtools-progress>` : ''}
241
237
  </div>
242
- <div class="search-message" ${ref(e => {this.#searchResultsMessageElement = e as HTMLElement;})}>
243
- </div>
244
- </div>`, this.contentElement, {host: this});
245
- // clang-format on
238
+ <div class="search-message">${searchResultsMessage}</div>
239
+ </div>`, target);
240
+ // clang-format on
241
+ };
242
+
243
+ export class SearchView extends UI.Widget.VBox {
244
+ readonly #view: View;
245
+ #focusSearchInput: boolean;
246
+ #isIndexing: boolean;
247
+ #searchId: number;
248
+ #searchMatchesCount: number;
249
+ #searchResultsCount: number;
250
+ #nonEmptySearchResultsCount: number;
251
+ #searchingView: UI.Widget.Widget|null;
252
+ #notFoundView: UI.Widget.Widget|null;
253
+ #searchConfig: Workspace.SearchConfig.SearchConfig|null;
254
+ #pendingSearchConfig: Workspace.SearchConfig.SearchConfig|null;
255
+ #searchResultsPane: SearchResultsPane|null;
256
+ #progress: Common.Progress.Progress|null;
257
+ #visiblePane: UI.Widget.Widget|null;
258
+ #searchResultsElement!: HTMLElement;
259
+ #query: string;
260
+ #matchCase = false;
261
+ #isRegex = false;
262
+ #searchMessage = '';
263
+ #searchResultsMessage = '';
264
+ readonly #advancedSearchConfig: Common.Settings.Setting<{
265
+ query: string,
266
+ ignoreCase: boolean,
267
+ isRegex: boolean,
268
+ }>;
269
+ #searchScope: SearchScope|null;
270
+
271
+ // We throttle adding search results, otherwise we trigger DOM layout for each
272
+ // result added.
273
+ #throttler: Common.Throttler.Throttler;
274
+ #pendingSearchResults: SearchResult[] = [];
275
+ #emptyStartView: UI.EmptyWidget.EmptyWidget;
276
+
277
+ constructor(settingKey: string, throttler: Common.Throttler.Throttler, view = DEFAULT_VIEW) {
278
+ super({
279
+ jslog: `${VisualLogging.panel('search').track({resize: true})}`,
280
+ useShadowDom: true,
281
+ });
282
+ this.#view = view;
283
+ this.setMinimumSize(0, 40);
284
+
285
+ this.#focusSearchInput = false;
286
+ this.#isIndexing = false;
287
+ this.#searchId = 1;
288
+ this.#query = '';
289
+ this.#searchMatchesCount = 0;
290
+ this.#searchResultsCount = 0;
291
+ this.#nonEmptySearchResultsCount = 0;
292
+ this.#searchingView = null;
293
+ this.#notFoundView = null;
294
+ this.#searchConfig = null;
295
+ this.#pendingSearchConfig = null;
296
+ this.#searchResultsPane = null;
297
+ this.#progress = null;
298
+ this.#visiblePane = null;
299
+ this.#throttler = throttler;
246
300
 
247
301
  this.#advancedSearchConfig = Common.Settings.Settings.instance().createLocalSetting(
248
302
  settingKey + '-search-config', new Workspace.SearchConfig.SearchConfig('', true, false).toPlainObject());
249
303
 
304
+ this.performUpdate();
250
305
  this.#load();
306
+ this.performUpdate();
251
307
  this.#searchScope = null;
252
308
 
253
309
  this.#emptyStartView = new UI.EmptyWidget.EmptyWidget(
@@ -257,28 +313,52 @@ export class SearchView extends UI.Widget.VBox {
257
313
  this.#showPane(this.#emptyStartView);
258
314
  }
259
315
 
316
+ override performUpdate(): void {
317
+ const input: SearchViewInput = {
318
+ query: this.#query,
319
+ focusSearchInput: this.#focusSearchInput,
320
+ matchCase: this.#matchCase,
321
+ isRegex: this.#isRegex,
322
+ searchMessage: this.#searchMessage,
323
+ searchResultsMessage: this.#searchResultsMessage,
324
+ progress: this.#progress,
325
+ onQueryChange: (query: string) => {
326
+ this.#query = query;
327
+ },
328
+ onQueryKeyDown: this.#onQueryKeyDown.bind(this),
329
+ onPanelKeyDown: this.#onPanelKeyDown.bind(this),
330
+ onClearSearchInput: this.#onClearSearchInput.bind(this),
331
+ onToggleRegex: this.#onToggleRegex.bind(this),
332
+ onToggleMatchCase: this.#onToggleMatchCase.bind(this),
333
+ onRefresh: this.#onRefresh.bind(this),
334
+ onClearSearch: this.#onClearSearch.bind(this),
335
+ };
336
+ const output: SearchViewOutput = {};
337
+ this.#view(input, output, this.contentElement);
338
+ this.#focusSearchInput = false;
339
+ if (output.searchResultsElement) {
340
+ this.#searchResultsElement = output.searchResultsElement;
341
+ }
342
+ }
343
+
260
344
  #onToggleRegex(): void {
261
- this.#regexButton.title = this.#regexButton.toggled ? i18nString(UIStrings.disableRegularExpression) :
262
- i18nString(UIStrings.enableRegularExpression);
345
+ this.#isRegex = !this.#isRegex;
346
+ this.performUpdate();
263
347
  }
264
348
 
265
349
  #onToggleMatchCase(): void {
266
- this.#matchCaseButton.title = this.#matchCaseButton.toggled ? i18nString(UIStrings.disableCaseSensitive) :
267
- i18nString(UIStrings.enableCaseSensitive);
350
+ this.#matchCase = !this.#matchCase;
351
+ this.performUpdate();
268
352
  }
269
353
 
270
354
  #buildSearchConfig(): Workspace.SearchConfig.SearchConfig {
271
- return new Workspace.SearchConfig.SearchConfig(
272
- this.#searchInputElement.value, !this.#matchCaseButton.toggled, this.#regexButton.toggled);
355
+ return new Workspace.SearchConfig.SearchConfig(this.#query, !this.#matchCase, this.#isRegex);
273
356
  }
274
357
 
275
358
  toggle(queryCandidate: string, searchImmediately?: boolean): void {
276
- this.#searchInputElement.value = queryCandidate;
277
- if (this.isShowing()) {
278
- this.focus();
279
- } else {
280
- this.#focusOnShow = true;
281
- }
359
+ this.#query = queryCandidate;
360
+ this.requestUpdate();
361
+ this.focus();
282
362
 
283
363
  this.#initScope();
284
364
  if (searchImmediately) {
@@ -296,61 +376,54 @@ export class SearchView extends UI.Widget.VBox {
296
376
  this.#searchScope = this.createScope();
297
377
  }
298
378
 
299
- override wasShown(): void {
300
- super.wasShown();
301
- if (this.#focusOnShow) {
302
- this.focus();
303
- this.#focusOnShow = false;
304
- }
305
- }
306
-
307
379
  #onIndexingFinished(): void {
308
- if (!this.#progressIndicator) {
380
+ if (!this.#progress) {
309
381
  return;
310
382
  }
311
383
 
312
- const finished = !this.#progressIndicator.isCanceled();
313
- this.#progressIndicator.done();
314
- this.#progressIndicator = null;
384
+ const finished = !this.#progress.canceled;
385
+ this.#progress = null;
315
386
  this.#isIndexing = false;
316
- this.#searchMessageElement.textContent = finished ? '' : i18nString(UIStrings.indexingInterrupted);
387
+ this.#searchMessage = finished ? '' : i18nString(UIStrings.indexingInterrupted);
317
388
  if (!finished) {
318
389
  this.#pendingSearchConfig = null;
319
390
  }
391
+ this.performUpdate();
320
392
  if (!this.#pendingSearchConfig) {
321
393
  return;
322
394
  }
323
395
  const searchConfig = this.#pendingSearchConfig;
324
396
  this.#pendingSearchConfig = null;
325
- this.#innerStartSearch(searchConfig);
397
+ this.#startSearch(searchConfig);
326
398
  }
327
399
 
328
400
  #startIndexing(): void {
329
401
  this.#isIndexing = true;
330
- if (this.#progressIndicator) {
331
- this.#progressIndicator.done();
402
+ if (this.#progress) {
403
+ this.#progress.done = true;
332
404
  }
333
- this.#progressIndicator = document.createElement('devtools-progress');
334
- this.#searchMessageElement.textContent = i18nString(UIStrings.indexing);
335
- this.#searchProgressPlaceholderElement.appendChild(this.#progressIndicator);
405
+ this.#progress = new Common.Progress.ProgressProxy(
406
+ new Common.Progress.Progress(), this.#onIndexingFinished.bind(this), this.requestUpdate.bind(this));
407
+ this.#searchMessage = i18nString(UIStrings.indexing);
408
+ this.performUpdate();
336
409
  if (this.#searchScope) {
337
- this.#searchScope.performIndexing(
338
- new Common.Progress.ProgressProxy(this.#progressIndicator, this.#onIndexingFinished.bind(this)));
410
+ this.#searchScope.performIndexing(this.#progress);
339
411
  }
340
412
  }
341
413
 
342
414
  #onClearSearchInput(): void {
343
- this.#searchInputElement.value = '';
415
+ this.#query = '';
416
+ this.requestUpdate();
344
417
  this.#save();
345
418
  this.focus();
346
419
  this.#showPane(this.#emptyStartView);
347
420
  }
348
421
 
349
422
  #onSearchResult(searchId: number, searchResult: SearchResult): void {
350
- if (searchId !== this.#searchId || !this.#progressIndicator) {
423
+ if (searchId !== this.#searchId || !this.#progress) {
351
424
  return;
352
425
  }
353
- if (this.#progressIndicator?.isCanceled()) {
426
+ if (this.#progress?.canceled) {
354
427
  this.#onIndexingFinished();
355
428
  return;
356
429
  }
@@ -377,28 +450,29 @@ export class SearchView extends UI.Widget.VBox {
377
450
  }
378
451
 
379
452
  #onSearchFinished(searchId: number, finished: boolean): void {
380
- if (searchId !== this.#searchId || !this.#progressIndicator) {
453
+ if (searchId !== this.#searchId || !this.#progress) {
381
454
  return;
382
455
  }
383
456
  if (!this.#searchResultsPane) {
384
457
  this.#nothingFound();
385
458
  }
459
+ this.#progress = null;
386
460
  this.#searchFinished(finished);
387
461
  this.#searchConfig = null;
388
- UI.ARIAUtils.LiveAnnouncer.alert(
389
- this.#searchMessageElement.textContent + ' ' + this.#searchResultsMessageElement.textContent);
462
+ UI.ARIAUtils.LiveAnnouncer.alert(this.#searchMessage + ' ' + this.#searchResultsMessage);
390
463
  }
391
464
 
392
- #innerStartSearch(searchConfig: Workspace.SearchConfig.SearchConfig): void {
465
+ #startSearch(searchConfig: Workspace.SearchConfig.SearchConfig): void {
393
466
  this.#searchConfig = searchConfig;
394
- if (this.#progressIndicator) {
395
- this.#progressIndicator.done();
467
+ if (this.#progress) {
468
+ this.#progress.done = true;
396
469
  }
397
- this.#progressIndicator = document.createElement('devtools-progress');
398
- this.#searchStarted(this.#progressIndicator);
470
+ this.#progress =
471
+ new Common.Progress.ProgressProxy(new Common.Progress.Progress(), undefined, this.requestUpdate.bind(this));
472
+ this.#searchStarted();
399
473
  if (this.#searchScope) {
400
474
  void this.#searchScope.performSearch(
401
- searchConfig, this.#progressIndicator, this.#onSearchResult.bind(this, this.#searchId),
475
+ searchConfig, this.#progress, this.#onSearchResult.bind(this, this.#searchId),
402
476
  this.#onSearchFinished.bind(this, this.#searchId));
403
477
  }
404
478
  }
@@ -407,13 +481,14 @@ export class SearchView extends UI.Widget.VBox {
407
481
  this.#stopSearch();
408
482
  this.#showPane(null);
409
483
  this.#searchResultsPane = null;
410
- this.#searchMessageElement.textContent = '';
411
- this.#searchResultsMessageElement.textContent = '';
484
+ this.#searchMessage = '';
485
+ this.#searchResultsMessage = '';
486
+ this.performUpdate();
412
487
  }
413
488
 
414
489
  #stopSearch(): void {
415
- if (this.#progressIndicator && !this.#isIndexing) {
416
- this.#progressIndicator.cancel();
490
+ if (this.#progress && !this.#isIndexing) {
491
+ this.#progress.canceled = true;
417
492
  }
418
493
  if (this.#searchScope) {
419
494
  this.#searchScope.stopSearch();
@@ -421,7 +496,7 @@ export class SearchView extends UI.Widget.VBox {
421
496
  this.#searchConfig = null;
422
497
  }
423
498
 
424
- #searchStarted(progressIndicator: UI.ProgressIndicator.ProgressIndicator): void {
499
+ #searchStarted(): void {
425
500
  this.#searchMatchesCount = 0;
426
501
  this.#searchResultsCount = 0;
427
502
  this.#nonEmptySearchResultsCount = 0;
@@ -429,26 +504,26 @@ export class SearchView extends UI.Widget.VBox {
429
504
  this.#searchingView = new UI.EmptyWidget.EmptyWidget(i18nString(UIStrings.searching), '');
430
505
  }
431
506
  this.#showPane(this.#searchingView);
432
- this.#searchMessageElement.textContent = i18nString(UIStrings.searching);
433
- this.#searchProgressPlaceholderElement.appendChild(progressIndicator);
507
+ this.#searchMessage = i18nString(UIStrings.searching);
508
+ this.performUpdate();
434
509
  this.#updateSearchResultsMessage();
435
510
  }
436
511
 
437
512
  #updateSearchResultsMessage(): void {
438
513
  if (this.#searchMatchesCount && this.#searchResultsCount) {
439
514
  if (this.#searchMatchesCount === 1 && this.#nonEmptySearchResultsCount === 1) {
440
- this.#searchResultsMessageElement.textContent = i18nString(UIStrings.foundMatchingLineInFile);
515
+ this.#searchResultsMessage = i18nString(UIStrings.foundMatchingLineInFile);
441
516
  } else if (this.#searchMatchesCount > 1 && this.#nonEmptySearchResultsCount === 1) {
442
- this.#searchResultsMessageElement.textContent =
443
- i18nString(UIStrings.foundDMatchingLinesInFile, {PH1: this.#searchMatchesCount});
517
+ this.#searchResultsMessage = i18nString(UIStrings.foundDMatchingLinesInFile, {PH1: this.#searchMatchesCount});
444
518
  } else {
445
- this.#searchResultsMessageElement.textContent = i18nString(
519
+ this.#searchResultsMessage = i18nString(
446
520
  UIStrings.foundDMatchingLinesInDFiles,
447
521
  {PH1: this.#searchMatchesCount, PH2: this.#nonEmptySearchResultsCount});
448
522
  }
449
523
  } else {
450
- this.#searchResultsMessageElement.textContent = '';
524
+ this.#searchResultsMessage = '';
451
525
  }
526
+ this.performUpdate();
452
527
  }
453
528
 
454
529
  #showPane(panel: UI.Widget.Widget|null): void {
@@ -480,13 +555,13 @@ export class SearchView extends UI.Widget.VBox {
480
555
  }
481
556
 
482
557
  #searchFinished(finished: boolean): void {
483
- this.#searchMessageElement.textContent =
484
- finished ? i18nString(UIStrings.searchFinished) : i18nString(UIStrings.searchInterrupted);
558
+ this.#searchMessage = finished ? i18nString(UIStrings.searchFinished) : i18nString(UIStrings.searchInterrupted);
559
+ this.performUpdate();
485
560
  }
486
561
 
487
562
  override focus(): void {
488
- this.#searchInputElement.focus();
489
- this.#searchInputElement.select();
563
+ this.#focusSearchInput = true;
564
+ this.requestUpdate();
490
565
  }
491
566
 
492
567
  override willHide(): void {
@@ -550,13 +625,11 @@ export class SearchView extends UI.Widget.VBox {
550
625
 
551
626
  #load(): void {
552
627
  const searchConfig = Workspace.SearchConfig.SearchConfig.fromPlainObject(this.#advancedSearchConfig.get());
553
- this.#searchInputElement.value = searchConfig.query();
554
-
555
- this.#matchCaseButton.toggled = !searchConfig.ignoreCase();
556
- this.#onToggleMatchCase();
628
+ this.#query = searchConfig.query();
557
629
 
558
- this.#regexButton.toggled = searchConfig.isRegex();
559
- this.#onToggleRegex();
630
+ this.#matchCase = !searchConfig.ignoreCase();
631
+ this.#isRegex = searchConfig.isRegex();
632
+ this.requestUpdate();
560
633
  }
561
634
 
562
635
  #onRefresh(): void {
@@ -581,16 +654,4 @@ export class SearchView extends UI.Widget.VBox {
581
654
  get throttlerForTest(): Common.Throttler.Throttler {
582
655
  return this.#throttler;
583
656
  }
584
-
585
- get search(): HTMLInputElement {
586
- return this.#searchInputElement;
587
- }
588
-
589
- get matchCaseButton(): Buttons.Button.Button {
590
- return this.#matchCaseButton;
591
- }
592
-
593
- get regexButton(): Buttons.Button.Button {
594
- return this.#regexButton;
595
- }
596
657
  }