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.
- package/front_end/entrypoints/main/main-meta.ts +2 -2
- package/front_end/generated/InspectorBackendCommands.js +4 -4
- package/front_end/generated/SupportedCSSProperties.js +12 -0
- package/front_end/generated/protocol.ts +10 -1
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +64 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +78 -58
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +123 -55
- package/front_end/models/javascript_metadata/NativeFunctions.js +7 -7
- package/front_end/models/text_utils/TextUtils.ts +26 -0
- package/front_end/models/trace/Processor.ts +1 -1
- package/front_end/models/trace/insights/DocumentLatency.ts +9 -7
- package/front_end/models/trace/types/Configuration.ts +12 -0
- package/front_end/panels/application/components/BackForwardCacheStrings.ts +8 -2
- package/front_end/panels/common/BadgeNotification.ts +10 -8
- package/front_end/panels/common/GdpSignUpDialog.ts +24 -11
- package/front_end/panels/common/gdpSignUpDialog.css +4 -0
- package/front_end/panels/search/SearchView.ts +195 -135
- package/front_end/panels/settings/components/SyncSection.ts +58 -9
- package/front_end/panels/settings/components/syncSection.css +6 -0
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +1 -4
- package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/README.md +6 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +11 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +30 -8
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +1 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +5 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +12 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +22 -8
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +11 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +30 -8
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +1 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +5 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +12 -2
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/Browser.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +13 -2
- package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +50 -8
- package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +0 -1
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +8 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +21 -5
- package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +12 -0
- package/front_end/ui/components/text_editor/config.ts +66 -16
- package/front_end/ui/legacy/ProgressIndicator.ts +4 -5
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +4 -2
- package/front_end/ui/visual_logging/Debugging.ts +24 -12
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- 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
|
-
|
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
|
-
|
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
|
-
|
177
|
+
(metadata || platform)
|
154
178
|
) {
|
155
179
|
return await this._client().send('Network.setUserAgentOverride', {
|
156
180
|
userAgent: userAgent,
|
157
|
-
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
|
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(
|
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(
|
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
|
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
|
-
|
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
|
-
|
754
|
-
|
755
|
-
|
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> {
|
@@ -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 (
|
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
|
-
|
573
|
-
|
574
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
788
|
+
pendingEventExpectation = {expectedEvents, success, fail, unmatchedEvents: []};
|
789
789
|
checkPendingEventExpectation();
|
790
790
|
|
791
791
|
const timeout = setTimeout(() => {
|
792
792
|
if (pendingEventExpectation?.missingEvents) {
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
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.
|
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
|
830
|
-
if ('impressions' in
|
831
|
-
|
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.
|
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 {
|
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.
|
105
|
+
"version": "1.0.1515796"
|
106
106
|
}
|