chrome-devtools-frontend 1.0.1515446 → 1.0.1515796

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 (95) hide show
  1. package/front_end/entrypoints/main/main-meta.ts +2 -2
  2. package/front_end/generated/InspectorBackendCommands.js +4 -4
  3. package/front_end/generated/SupportedCSSProperties.js +12 -0
  4. package/front_end/generated/protocol.ts +10 -1
  5. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +64 -0
  6. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +78 -58
  7. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +123 -55
  8. package/front_end/models/javascript_metadata/NativeFunctions.js +7 -7
  9. package/front_end/models/text_utils/TextUtils.ts +26 -0
  10. package/front_end/models/trace/Processor.ts +1 -1
  11. package/front_end/models/trace/insights/DocumentLatency.ts +9 -7
  12. package/front_end/models/trace/types/Configuration.ts +12 -0
  13. package/front_end/panels/application/components/BackForwardCacheStrings.ts +8 -2
  14. package/front_end/panels/common/BadgeNotification.ts +10 -8
  15. package/front_end/panels/common/GdpSignUpDialog.ts +24 -11
  16. package/front_end/panels/common/gdpSignUpDialog.css +4 -0
  17. package/front_end/panels/search/SearchView.ts +195 -135
  18. package/front_end/panels/settings/components/SyncSection.ts +58 -9
  19. package/front_end/panels/settings/components/syncSection.css +6 -0
  20. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +1 -4
  21. package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
  22. package/front_end/third_party/chromium/README.chromium +1 -1
  23. package/front_end/third_party/puppeteer/README.chromium +2 -2
  24. package/front_end/third_party/puppeteer/package/README.md +6 -3
  25. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts +1 -1
  26. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +11 -1
  27. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  28. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js +2 -2
  29. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  30. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +5 -1
  31. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
  32. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +30 -8
  33. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
  34. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  35. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +1 -3
  36. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  37. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  38. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts +1 -1
  39. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  40. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +8 -2
  41. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  42. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +5 -1
  43. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  44. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +8 -2
  45. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  46. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  47. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  48. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  49. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  50. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +5 -0
  51. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  52. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  53. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +12 -2
  54. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +22 -8
  55. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +1 -1
  56. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +11 -1
  57. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  58. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js +2 -2
  59. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +5 -1
  61. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
  62. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +30 -8
  63. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
  64. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  65. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +1 -3
  66. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  67. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts +1 -1
  68. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +8 -2
  70. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  71. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +5 -1
  72. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  73. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +8 -2
  74. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  76. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  77. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  78. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +5 -0
  79. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  80. package/front_end/third_party/puppeteer/package/lib/types.d.ts +12 -2
  81. package/front_end/third_party/puppeteer/package/package.json +4 -4
  82. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +1 -1
  83. package/front_end/third_party/puppeteer/package/src/api/Page.ts +13 -2
  84. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +50 -8
  85. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +0 -1
  86. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +8 -1
  87. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +21 -5
  88. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  89. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +12 -0
  90. package/front_end/ui/components/text_editor/config.ts +66 -16
  91. package/front_end/ui/legacy/ProgressIndicator.ts +4 -5
  92. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +4 -2
  93. package/front_end/ui/visual_logging/Debugging.ts +24 -12
  94. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  95. package/package.json +3 -3
@@ -1655,12 +1655,23 @@ export abstract class Page extends EventEmitter<PageEvents> {
1655
1655
  * @param userAgentData - Specific user agent client hint data to use in this
1656
1656
  * page
1657
1657
  * @returns Promise which resolves when the user agent is set.
1658
+ * @deprecated Use {@link Page.(setUserAgent:2) } instead.
1658
1659
  */
1659
1660
  abstract setUserAgent(
1660
1661
  userAgent: string,
1661
1662
  userAgentMetadata?: Protocol.Emulation.UserAgentMetadata,
1662
1663
  ): Promise<void>;
1663
1664
 
1665
+ /**
1666
+ * @param options - Object containing user agent and optional user agent metadata
1667
+ * @returns Promise which resolves when the user agent is set.
1668
+ */
1669
+ abstract setUserAgent(options: {
1670
+ userAgent?: string;
1671
+ userAgentMetadata?: Protocol.Emulation.UserAgentMetadata;
1672
+ platform?: string;
1673
+ }): Promise<void>;
1674
+
1664
1675
  /**
1665
1676
  * Object containing metrics as key/value pairs.
1666
1677
  *
@@ -2014,7 +2025,7 @@ export abstract class Page extends EventEmitter<PageEvents> {
2014
2025
  *
2015
2026
  * @remarks
2016
2027
  * This method is a shortcut for calling two methods:
2017
- * {@link Page.setUserAgent} and {@link Page.setViewport}.
2028
+ * {@link Page.(setUserAgent:2) } and {@link Page.setViewport}.
2018
2029
  *
2019
2030
  * This method will resize the page. A lot of websites don't expect phones to
2020
2031
  * change size, so you should emulate before navigating to the page.
@@ -2037,7 +2048,7 @@ export abstract class Page extends EventEmitter<PageEvents> {
2037
2048
  */
2038
2049
  async emulate(device: Device): Promise<void> {
2039
2050
  await Promise.all([
2040
- this.setUserAgent(device.userAgent),
2051
+ this.setUserAgent({userAgent: device.userAgent}),
2041
2052
  this.setViewport(device.viewport),
2042
2053
  ]);
2043
2054
  }
@@ -141,20 +141,45 @@ export class BidiPage extends Page {
141
141
  #userAgentInterception?: string;
142
142
  #userAgentPreloadScript?: string;
143
143
  override async setUserAgent(
144
- userAgent: string,
144
+ userAgentOrOptions:
145
+ | string
146
+ | {
147
+ userAgent?: string;
148
+ userAgentMetadata?: Protocol.Emulation.UserAgentMetadata;
149
+ platform?: string;
150
+ },
145
151
  userAgentMetadata?: Protocol.Emulation.UserAgentMetadata,
146
152
  ): Promise<void> {
147
- if (!this.#browserContext.browser().cdpSupported && userAgentMetadata) {
153
+ let userAgent: string;
154
+ let metadata: Protocol.Emulation.UserAgentMetadata | undefined;
155
+ let platform: string | undefined;
156
+
157
+ if (typeof userAgentOrOptions === 'string') {
158
+ userAgent = userAgentOrOptions;
159
+ metadata = userAgentMetadata;
160
+ } else {
161
+ userAgent =
162
+ userAgentOrOptions.userAgent ??
163
+ (await this.#browserContext.browser().userAgent());
164
+ metadata = userAgentOrOptions.userAgentMetadata;
165
+ platform = userAgentOrOptions.platform;
166
+ }
167
+
168
+ if (
169
+ !this.#browserContext.browser().cdpSupported &&
170
+ (metadata || platform)
171
+ ) {
148
172
  throw new UnsupportedOperation(
149
- 'Current Browser does not support `userAgentMetadata`',
173
+ 'Current Browser does not support `userAgentMetadata` or `platform`',
150
174
  );
151
175
  } else if (
152
176
  this.#browserContext.browser().cdpSupported &&
153
- userAgentMetadata
177
+ (metadata || platform)
154
178
  ) {
155
179
  return await this._client().send('Network.setUserAgentOverride', {
156
180
  userAgent: userAgent,
157
- userAgentMetadata: userAgentMetadata,
181
+ userAgentMetadata: metadata,
182
+ platform: platform,
158
183
  });
159
184
  }
160
185
  const enable = userAgent !== '';
@@ -172,11 +197,20 @@ export class BidiPage extends Page {
172
197
  enable,
173
198
  );
174
199
 
175
- const changeUserAgent = (userAgent: string) => {
200
+ const overrideNavigatorProperties = (
201
+ userAgent: string,
202
+ platform: string | undefined,
203
+ ) => {
176
204
  Object.defineProperty(navigator, 'userAgent', {
177
205
  value: userAgent,
178
206
  configurable: true,
179
207
  });
208
+ if (platform) {
209
+ Object.defineProperty(navigator, 'platform', {
210
+ value: platform,
211
+ configurable: true,
212
+ });
213
+ }
180
214
  };
181
215
 
182
216
  const frames = [this.#frame];
@@ -191,12 +225,20 @@ export class BidiPage extends Page {
191
225
  }
192
226
  const [evaluateToken] = await Promise.all([
193
227
  enable
194
- ? this.evaluateOnNewDocument(changeUserAgent, userAgent)
228
+ ? this.evaluateOnNewDocument(
229
+ overrideNavigatorProperties,
230
+ userAgent,
231
+ platform || undefined,
232
+ )
195
233
  : undefined,
196
234
  // When we disable the UserAgent we want to
197
235
  // evaluate the original value in all Browsing Contexts
198
236
  ...frames.map(frame => {
199
- return frame.evaluate(changeUserAgent, userAgent);
237
+ return frame.evaluate(
238
+ overrideNavigatorProperties,
239
+ userAgent,
240
+ platform || undefined,
241
+ );
200
242
  }),
201
243
  ]);
202
244
  this.#userAgentPreloadScript = evaluateToken?.identifier;
@@ -713,7 +713,6 @@ export class BrowsingContext extends EventEmitter<{
713
713
 
714
714
  async setJavaScriptEnabled(enabled: boolean): Promise<void> {
715
715
  await this.userContext.browser.session.send(
716
- // @ts-expect-error missing types
717
716
  'emulation.setScriptingEnabled',
718
717
  {
719
718
  // Enabled `null` means `default`, `false` means `disabled`.
@@ -77,11 +77,12 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
77
77
  #credentials: Credentials | null = null;
78
78
  #attemptedAuthentications = new Set<string>();
79
79
  #userRequestInterceptionEnabled = false;
80
- #protocolRequestInterceptionEnabled = false;
80
+ #protocolRequestInterceptionEnabled?: boolean;
81
81
  #userCacheDisabled?: boolean;
82
82
  #emulatedNetworkConditions?: InternalNetworkConditions;
83
83
  #userAgent?: string;
84
84
  #userAgentMetadata?: Protocol.Emulation.UserAgentMetadata;
85
+ #platform?: string;
85
86
 
86
87
  readonly #handlers = [
87
88
  ['Fetch.requestPaused', this.#onRequestPaused],
@@ -265,9 +266,11 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
265
266
  async setUserAgent(
266
267
  userAgent: string,
267
268
  userAgentMetadata?: Protocol.Emulation.UserAgentMetadata,
269
+ platform?: string,
268
270
  ): Promise<void> {
269
271
  this.#userAgent = userAgent;
270
272
  this.#userAgentMetadata = userAgentMetadata;
273
+ this.#platform = platform;
271
274
  await this.#applyToAllClients(this.#applyUserAgent.bind(this));
272
275
  }
273
276
 
@@ -279,6 +282,7 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
279
282
  await client.send('Network.setUserAgentOverride', {
280
283
  userAgent: this.#userAgent,
281
284
  userAgentMetadata: this.#userAgentMetadata,
285
+ platform: this.#platform,
282
286
  });
283
287
  } catch (error) {
284
288
  if (this.#canIgnoreError(error)) {
@@ -306,6 +310,9 @@ export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
306
310
  }
307
311
 
308
312
  async #applyProtocolRequestInterception(client: CDPSession): Promise<void> {
313
+ if (this.#protocolRequestInterceptionEnabled === undefined) {
314
+ return;
315
+ }
309
316
  if (this.#userCacheDisabled === undefined) {
310
317
  this.#userCacheDisabled = false;
311
318
  }
@@ -747,13 +747,29 @@ export class CdpPage extends Page {
747
747
  }
748
748
 
749
749
  override async setUserAgent(
750
- userAgent: string,
750
+ userAgentOrOptions:
751
+ | string
752
+ | {
753
+ userAgent?: string;
754
+ userAgentMetadata?: Protocol.Emulation.UserAgentMetadata;
755
+ platform?: string;
756
+ },
751
757
  userAgentMetadata?: Protocol.Emulation.UserAgentMetadata,
752
758
  ): Promise<void> {
753
- return await this.#frameManager.networkManager.setUserAgent(
754
- userAgent,
755
- userAgentMetadata,
756
- );
759
+ if (typeof userAgentOrOptions === 'string') {
760
+ return await this.#frameManager.networkManager.setUserAgent(
761
+ userAgentOrOptions,
762
+ userAgentMetadata,
763
+ );
764
+ } else {
765
+ const userAgent =
766
+ userAgentOrOptions.userAgent ?? (await this.browser().userAgent());
767
+ return await this.#frameManager.networkManager.setUserAgent(
768
+ userAgent,
769
+ userAgentOrOptions.userAgentMetadata,
770
+ userAgentOrOptions.platform,
771
+ );
772
+ }
757
773
  }
758
774
 
759
775
  override async metrics(): Promise<Metrics> {
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * @internal
3
3
  */
4
- export const packageVersion = '24.20.0';
4
+ export const packageVersion = '24.21.0';
@@ -181,6 +181,7 @@ export abstract class BrowserLauncher {
181
181
  slowMo,
182
182
  });
183
183
  }
184
+
184
185
  if (protocol === 'webDriverBiDi') {
185
186
  browser = await this.createBiDiOverCdpBrowser(
186
187
  browserProcess,
@@ -210,6 +211,17 @@ export abstract class BrowserLauncher {
210
211
  }
211
212
  } catch (error) {
212
213
  void browserCloseCallback();
214
+ if (
215
+ browserProcess.getRecentLogs().some(line => {
216
+ return line.includes(
217
+ 'Failed to create a ProcessSingleton for your profile directory',
218
+ );
219
+ })
220
+ ) {
221
+ throw new Error(
222
+ `The browser is already running for ${launchArgs.userDataDir}. Use a different \`userDataDir\` or stop the running browser first.`,
223
+ );
224
+ }
213
225
  if (error instanceof BrowsersTimeoutError) {
214
226
  throw new TimeoutError(error.message);
215
227
  }
@@ -132,7 +132,6 @@ function moveCompletionSelectionIfNotConservative(
132
132
  if (CM.completionStatus(view.state) !== 'active') {
133
133
  return false;
134
134
  }
135
- view.dispatch({effects: setAiAutoCompleteSuggestion.of(null)});
136
135
  if (view.state.field(conservativeCompletion, false)) {
137
136
  view.dispatch({effects: disableConservativeCompletion.of(null)});
138
137
  announceSelectedCompletionInfo(view);
@@ -149,7 +148,6 @@ function moveCompletionSelectionBackwardWrapper(): ((view: CM.EditorView) => boo
149
148
  if (CM.completionStatus(view.state) !== 'active') {
150
149
  return false;
151
150
  }
152
- view.dispatch({effects: setAiAutoCompleteSuggestion.of(null)});
153
151
  CM.moveCompletionSelection(false)(view);
154
152
  announceSelectedCompletionInfo(view);
155
153
  return true;
@@ -523,11 +521,11 @@ export const aiAutoCompleteSuggestionState = CM.StateField.define<ActiveSuggesti
523
521
  const {head} = tr.state.selection.main;
524
522
 
525
523
  // If a change happened before the position from which suggestion was generated, set to null.
526
- if (tr.changes.touchesRange(0, from - 1) || head < from) {
524
+ if (head < from) {
527
525
  return null;
528
526
  }
529
527
 
530
- // Check if what's typed is a prefix of the suggestion.
528
+ // Check if what's typed after the AI suggestion is a prefix of the AI suggestion.
531
529
  const typedText = tr.state.doc.sliceString(from, head);
532
530
  return value.text.startsWith(typedText) ? value : null;
533
531
  },
@@ -539,6 +537,11 @@ export function hasActiveAiSuggestion(state: CM.EditorState): boolean {
539
537
 
540
538
  export function acceptAiAutoCompleteSuggestion(view: CM.EditorView):
541
539
  {accepted: boolean, suggestion?: ActiveSuggestion} {
540
+ const selectedCompletion = CM.selectedCompletion(view.state);
541
+ if (selectedCompletion) {
542
+ return {accepted: false};
543
+ }
544
+
542
545
  const suggestion = view.state.field(aiAutoCompleteSuggestionState);
543
546
  if (!suggestion) {
544
547
  return {accepted: false};
@@ -568,23 +571,70 @@ export const aiAutoCompleteSuggestion: CM.Extension = [
568
571
  decorations: CM.DecorationSet = CM.Decoration.none;
569
572
 
570
573
  update(update: CM.ViewUpdate): void {
574
+ // Hide decorations if there is no active AI suggestion.
571
575
  const activeSuggestion = update.state.field(aiAutoCompleteSuggestionState);
572
- const {head, empty} = update.state.selection.main;
573
- let hint = '';
574
- if (activeSuggestion && empty && head >= activeSuggestion.from) {
575
- const {text, from} = activeSuggestion;
576
- const typedText = update.state.doc.sliceString(from, head);
577
- if (text.startsWith(typedText)) {
578
- hint = text.slice(typedText.length);
579
- }
576
+ if (!activeSuggestion) {
577
+ this.decorations = CM.Decoration.none;
578
+ return;
580
579
  }
581
580
 
582
- if (!hint) {
581
+ // Hide AI suggestion while the user is interacting with the traditional
582
+ // autocomplete menu to avoid conflicting suggestions.
583
+ if (CM.completionStatus(update.view.state) === 'pending') {
583
584
  this.decorations = CM.Decoration.none;
584
- } else {
585
- this.decorations =
586
- CM.Decoration.set([CM.Decoration.widget({widget: new CompletionHint(hint), side: 1}).range(head)]);
585
+ return;
587
586
  }
587
+
588
+ // Hide AI suggestion if the user has selected an item from the
589
+ // traditional autocomplete menu that is not the first one.
590
+ const selectedCompletionIndex = CM.selectedCompletionIndex(update.state);
591
+ if (selectedCompletionIndex && selectedCompletionIndex > 0) {
592
+ this.decorations = CM.Decoration.none;
593
+ return;
594
+ }
595
+
596
+ const {head} = update.state.selection.main;
597
+ const selectedCompletion = CM.selectedCompletion(update.state);
598
+ const additionallyTypedText = update.state.doc.sliceString(activeSuggestion.from, head);
599
+ // The user might have typed text after the suggestion is triggered.
600
+ // If the suggestion no longer starts with the typed text, hide it.
601
+ if (!activeSuggestion.text.startsWith(additionallyTypedText)) {
602
+ this.decorations = CM.Decoration.none;
603
+ return;
604
+ }
605
+
606
+ let ghostText = activeSuggestion.text.slice(additionallyTypedText.length);
607
+ if (selectedCompletion) {
608
+ // If the user typed the full selected completion, then we don't check for overlap.
609
+ // (e.g. the user wrote `flex`, traditional suggestion is `flex` and the AI autocompletion is
610
+ // `;\njustify-content: center`. Then, we want to show the AI completion)
611
+ const endsWithCompleteSelectedCompletion =
612
+ update.state.doc.sliceString(head - selectedCompletion.label.length, head) === selectedCompletion.label;
613
+ // If a traditional autocomplete menu is shown, the AI suggestion is only
614
+ // shown if it builds upon the currently selected item. If there is no
615
+ // overlap, we hide the AI suggestion. For example, for the text `console`
616
+ // if the traditional autocomplete suggests `log` and the AI
617
+ // suggests `warn`, there is no overlap and the AI suggestion is hidden.
618
+ if (!endsWithCompleteSelectedCompletion &&
619
+ !TextUtils.TextUtils.getOverlap(selectedCompletion.label, ghostText)) {
620
+ this.decorations = CM.Decoration.none;
621
+ return;
622
+ }
623
+ }
624
+
625
+ // When `conservativeCompletion` is disabled in Console, the editor shows a ghost
626
+ // text for the first item in the traditional autocomplete menu and this ghost text
627
+ // is reflected in `currentHint`. In this case, we need to remove
628
+ // the overlapping part from our AI suggestion's ghost text to avoid
629
+ // showing a double suggestion.
630
+ const currentMenuHint = update.view.plugin(showCompletionHint)?.currentHint;
631
+ const conservativeCompletionEnabled = update.state.field(conservativeCompletion, false);
632
+ if (!conservativeCompletionEnabled && currentMenuHint) {
633
+ ghostText = ghostText.slice(currentMenuHint.length);
634
+ }
635
+
636
+ this.decorations =
637
+ CM.Decoration.set([CM.Decoration.widget({widget: new CompletionHint(ghostText), side: 1}).range(head)]);
588
638
  }
589
639
  },
590
640
  {decorations: p => p.decorations}),
@@ -12,7 +12,7 @@ export class ProgressIndicator extends HTMLElement implements Common.Progress.Pr
12
12
  readonly #contentElement: Element;
13
13
  #labelElement: Element;
14
14
  #progressElement: HTMLProgressElement;
15
- readonly #stopButton?: Element;
15
+ #stopButton?: Element;
16
16
  #isCanceled = false;
17
17
  #worked = 0;
18
18
  #isDone = false;
@@ -25,7 +25,10 @@ export class ProgressIndicator extends HTMLElement implements Common.Progress.Pr
25
25
  this.#labelElement = this.#contentElement.createChild('div', 'title');
26
26
  this.#progressElement = this.#contentElement.createChild('progress');
27
27
  this.#progressElement.value = 0;
28
+ }
28
29
 
30
+ connectedCallback(): void {
31
+ this.classList.add('progress-indicator');
29
32
  // By default we show the stop button, but this can be controlled by
30
33
  // using the 'no-stop-button' attribute on the element.
31
34
  if (!this.hasAttribute('no-stop-button')) {
@@ -34,10 +37,6 @@ export class ProgressIndicator extends HTMLElement implements Common.Progress.Pr
34
37
  }
35
38
  }
36
39
 
37
- connectedCallback(): void {
38
- this.classList.add('progress-indicator');
39
- }
40
-
41
40
  done(): void {
42
41
  if (this.#isDone) {
43
42
  return;
@@ -399,7 +399,7 @@ class DataGridElementNode extends SortableDataGridNode<DataGridElementNode> {
399
399
  const cell = cells[i];
400
400
  const column = this.#dataGridElement.columns[i];
401
401
  if (column.dataType === DataType.BOOLEAN) {
402
- this.data[column.id] = hasBooleanAttribute(cell, 'data-value');
402
+ this.data[column.id] = hasBooleanAttribute(cell, 'data-value') || cell.textContent === 'true';
403
403
  } else {
404
404
  this.data[column.id] = cell.dataset.value ?? cell.textContent ?? '';
405
405
  }
@@ -472,7 +472,9 @@ class DataGridElementNode extends SortableDataGridNode<DataGridElementNode> {
472
472
  override createCell(columnId: string): HTMLElement {
473
473
  const index = this.#dataGridElement.columns.findIndex(({id}) => id === columnId);
474
474
  if (this.#dataGridElement.columns[index].dataType === DataType.BOOLEAN) {
475
- return super.createCell(columnId);
475
+ const cell = super.createCell(columnId);
476
+ cell.setAttribute('part', `${columnId}-column`);
477
+ return cell;
476
478
  }
477
479
  const cell = this.createTD(columnId);
478
480
  cell.setAttribute('part', `${columnId}-column`);
@@ -731,7 +731,7 @@ function compareVeEvents(actual: TestLogEntry, expected: TestLogEntry): boolean
731
731
  interface PendingEventExpectation {
732
732
  expectedEvents: TestLogEntry[];
733
733
  missingEvents?: TestLogEntry[];
734
- unmatchingEvents: TestLogEntry[];
734
+ unmatchedEvents: TestLogEntry[];
735
735
  success: () => void;
736
736
  fail: (arg0: Error) => void;
737
737
  }
@@ -785,20 +785,33 @@ export async function expectVeEvents(expectedEvents: TestLogEntry[]): Promise<vo
785
785
  throw new Error('VE events expectation already set. Cannot set another one until the previous is resolved');
786
786
  }
787
787
  const {promise, resolve: success, reject: fail} = Promise.withResolvers<void>();
788
- pendingEventExpectation = {expectedEvents, success, fail, unmatchingEvents: []};
788
+ pendingEventExpectation = {expectedEvents, success, fail, unmatchedEvents: []};
789
789
  checkPendingEventExpectation();
790
790
 
791
791
  const timeout = setTimeout(() => {
792
792
  if (pendingEventExpectation?.missingEvents) {
793
- pendingEventExpectation.fail(new Error(
794
- '\nMissing VE Events:\n' + formatVeEvents(pendingEventExpectation.missingEvents) +
795
- '\nUnmatched VE Events:\n' + formatVeEvents(pendingEventExpectation.unmatchingEvents) + '\nAll events:\n' +
796
- JSON.stringify(veDebugEventsLog, null, 2)));
793
+ const allLogs = veDebugEventsLog.filter(ve => {
794
+ if ('interaction' in ve) {
795
+ // Very noisy in the error and not providing context
796
+ return ve.interaction !== 'SettingAccess';
797
+ }
798
+
799
+ return true;
800
+ });
801
+ pendingEventExpectation.fail(new Error(`
802
+ Missing VE Events:
803
+ ${formatVeEvents(pendingEventExpectation.missingEvents)}
804
+ Unmatched VE Events:
805
+ ${formatVeEvents(pendingEventExpectation.unmatchedEvents)}
806
+ All events:
807
+ ${JSON.stringify(allLogs, null, 2)}
808
+ `));
797
809
  }
798
810
  }, EVENT_EXPECTATION_TIMEOUT);
799
811
 
800
812
  return await promise.finally(() => {
801
813
  clearTimeout(timeout);
814
+ pendingEventExpectation = null;
802
815
  });
803
816
  }
804
817
 
@@ -811,7 +824,7 @@ function checkPendingEventExpectation(): void {
811
824
  const actualEvents = [...veDebugEventsLog] as TestLogEntry[];
812
825
  let partialMatch = false;
813
826
  const matchedImpressions = new Set<string>();
814
- pendingEventExpectation.unmatchingEvents = [];
827
+ pendingEventExpectation.unmatchedEvents = [];
815
828
  for (let i = 0; i < pendingEventExpectation.expectedEvents.length; ++i) {
816
829
  const expectedEvent = pendingEventExpectation.expectedEvents[i];
817
830
  while (true) {
@@ -826,9 +839,9 @@ function checkPendingEventExpectation(): void {
826
839
  }
827
840
  if (!compareVeEvents(actualEvents[i], expectedEvent)) {
828
841
  if (partialMatch) {
829
- const unmatching = {...actualEvents[i]};
830
- if ('impressions' in unmatching && 'impressions' in expectedEvent) {
831
- unmatching.impressions = unmatching.impressions.filter(impression => {
842
+ const unmatched = {...actualEvents[i]};
843
+ if ('impressions' in unmatched && 'impressions' in expectedEvent) {
844
+ unmatched.impressions = unmatched.impressions.filter(impression => {
832
845
  const matched = expectedEvent.impressions.includes(impression);
833
846
  if (matched) {
834
847
  matchedImpressions.add(impression);
@@ -836,7 +849,7 @@ function checkPendingEventExpectation(): void {
836
849
  return !matched;
837
850
  });
838
851
  }
839
- pendingEventExpectation.unmatchingEvents.push(unmatching);
852
+ pendingEventExpectation.unmatchedEvents.push(unmatched);
840
853
  }
841
854
  actualEvents.splice(i, 1);
842
855
  } else {
@@ -847,7 +860,6 @@ function checkPendingEventExpectation(): void {
847
860
  }
848
861
  numMatchedEvents = veDebugEventsLog.length - actualEvents.length + pendingEventExpectation.expectedEvents.length;
849
862
  pendingEventExpectation.success();
850
- pendingEventExpectation = null;
851
863
  }
852
864
 
853
865
  function getUnmatchedVeEvents(): string {
@@ -2739,6 +2739,7 @@ export const knownContextValues = new Set([
2739
2739
  'overscroll-behavior-inline',
2740
2740
  'overscroll-behavior-x',
2741
2741
  'overscroll-behavior-y',
2742
+ 'overscroll-position',
2742
2743
  'p3',
2743
2744
  'pa',
2744
2745
  'packetLoss',
package/package.json CHANGED
@@ -23,8 +23,8 @@
23
23
  "collect-strings": "vpython3 third_party/node/node.py --output third_party/i18n/collect-strings.js front_end",
24
24
  "components-server": "vpython3 third_party/node/node.py --output scripts/component_server/server.js",
25
25
  "debug-webtest": "vpython3 third_party/node/node.py --output scripts/npm_test.js --debug-devtools",
26
- "generate-protocol-resources": "scripts/deps/generate_protocol_resources.py && git cl format --js",
27
- "install-deps": "scripts/deps/manage_node_deps.py",
26
+ "generate-protocol-resources": "vpython3 scripts/deps/generate_protocol_resources.py && git cl format --js",
27
+ "install-deps": "vpython3 scripts/deps/manage_node_deps.py",
28
28
  "lint": "vpython3 third_party/node/node.py --output --experimental-strip-types --no-warnings=ExperimentalWarning scripts/test/run_lint_check.mjs",
29
29
  "prebuild": "gn gen out/Default",
30
30
  "rdb": "rdb stream -new -realm chromium:public --",
@@ -102,5 +102,5 @@
102
102
  "@eslint/core": "0.15.1"
103
103
  }
104
104
  },
105
- "version": "1.0.1515446"
105
+ "version": "1.0.1515796"
106
106
  }