chrome-devtools-frontend 1.0.1592129 → 1.0.1592362
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/core/host/UserMetrics.ts +2 -1
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +1 -0
- package/front_end/core/sdk/EmulationModel.ts +41 -1
- package/front_end/entrypoints/main/MainImpl.ts +8 -0
- package/front_end/generated/InspectorBackendCommands.ts +1 -0
- package/front_end/generated/protocol-mapping.d.ts +6 -0
- package/front_end/generated/protocol-proxy-api.d.ts +7 -0
- package/front_end/generated/protocol.ts +16 -0
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +379 -25
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgentOverlay.ts +87 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +8 -8
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +65 -44
- package/front_end/models/computed_style/ComputedStyleModel.ts +40 -6
- package/front_end/models/emulation/DeviceModeModel.ts +47 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -2
- package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +55 -1
- package/front_end/panels/application/CookieItemsView.ts +194 -134
- package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +1 -1
- package/front_end/panels/application/StorageItemsToolbar.ts +25 -2
- package/front_end/panels/application/cookieItemsView.css +28 -26
- package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
- package/front_end/panels/elements/ComputedStyleWidget.ts +11 -25
- package/front_end/panels/elements/ElementsPanel.ts +26 -3
- package/front_end/panels/elements/StylePropertyTreeElement.ts +33 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +148 -1
- package/front_end/panels/elements/elements-meta.ts +3 -5
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +6 -0
- package/front_end/panels/emulation/DeviceModeToolbar.ts +25 -0
- package/front_end/panels/timeline/components/metricCard.css +0 -4
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +13 -2
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +44 -24
- package/front_end/ui/visual_logging/Debugging.ts +4 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
|
@@ -385,6 +385,9 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
|
|
|
385
385
|
const matchedCascade = await this.#computedStyleModel.fetchMatchedCascade();
|
|
386
386
|
this.#computedStyleWidget.nodeStyle = computedStyle;
|
|
387
387
|
this.#computedStyleWidget.matchedStyles = matchedCascade;
|
|
388
|
+
if (matchedCascade) {
|
|
389
|
+
this.#computedStyleWidget.propertyTraces = this.#computedStyleModel.computePropertyTraces(matchedCascade);
|
|
390
|
+
}
|
|
388
391
|
}
|
|
389
392
|
|
|
390
393
|
private handleElementExpanded(): void {
|
|
@@ -1224,6 +1227,10 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
|
|
|
1224
1227
|
this.splitWidget.setSidebarWidget(this.sidebarPaneView.tabbedPane());
|
|
1225
1228
|
}
|
|
1226
1229
|
|
|
1230
|
+
revealComputedStylesPane(): void {
|
|
1231
|
+
this.sidebarPaneView?.tabbedPane().selectTab(SidebarPaneTabId.COMPUTED);
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1227
1234
|
private updateSidebarPosition(): void {
|
|
1228
1235
|
if (this.sidebarPaneView?.tabbedPane().shouldHideOnDetach()) {
|
|
1229
1236
|
return;
|
|
@@ -1471,11 +1478,23 @@ export class ContextMenuProvider implements
|
|
|
1471
1478
|
}
|
|
1472
1479
|
}
|
|
1473
1480
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1481
|
+
/**
|
|
1482
|
+
* Wraps around the Node so we can pass it into the DOMNodeRevealer but
|
|
1483
|
+
* distinguish that we want to reveal the computed styles panel.
|
|
1484
|
+
*/
|
|
1485
|
+
export class NodeComputedStyles {
|
|
1486
|
+
readonly node: SDK.DOMModel.DOMNode;
|
|
1487
|
+
constructor(node: SDK.DOMModel.DOMNode) {
|
|
1488
|
+
this.node = node;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
export class DOMNodeRevealer implements
|
|
1493
|
+
Common.Revealer.Revealer<SDK.DOMModel.DOMNode|SDK.DOMModel.DeferredDOMNode|SDK.RemoteObject.RemoteObject|
|
|
1494
|
+
SDK.DOMModel.AdoptedStyleSheet|NodeComputedStyles> {
|
|
1476
1495
|
reveal(
|
|
1477
1496
|
node: SDK.DOMModel.DOMNode|SDK.DOMModel.DeferredDOMNode|SDK.RemoteObject.RemoteObject|
|
|
1478
|
-
SDK.DOMModel.AdoptedStyleSheet,
|
|
1497
|
+
SDK.DOMModel.AdoptedStyleSheet|NodeComputedStyles,
|
|
1479
1498
|
omitFocus?: boolean): Promise<void> {
|
|
1480
1499
|
const panel = ElementsPanel.instance();
|
|
1481
1500
|
panel.pendingNodeReveal = true;
|
|
@@ -1501,6 +1520,10 @@ export class DOMNodeRevealer implements Common.Revealer.Revealer<
|
|
|
1501
1520
|
onNodeResolved((node));
|
|
1502
1521
|
} else if (node instanceof SDK.DOMModel.DeferredDOMNode) {
|
|
1503
1522
|
(node).resolve(checkDeferredDOMNodeThenReveal);
|
|
1523
|
+
} else if (node instanceof NodeComputedStyles) {
|
|
1524
|
+
const elements = ElementsPanel.instance();
|
|
1525
|
+
elements.revealComputedStylesPane();
|
|
1526
|
+
onNodeResolved(node.node);
|
|
1504
1527
|
} else {
|
|
1505
1528
|
const domModel = node.runtimeModel().target().model(SDK.DOMModel.DOMModel);
|
|
1506
1529
|
if (domModel) {
|
|
@@ -3543,6 +3543,39 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
3543
3543
|
return event.target === this.expandElement;
|
|
3544
3544
|
}
|
|
3545
3545
|
}
|
|
3546
|
+
|
|
3547
|
+
export class GhostStylePropertyTreeElement extends StylePropertyTreeElement {
|
|
3548
|
+
constructor(
|
|
3549
|
+
stylesContainer: StylesContainer, section: StylePropertiesSection,
|
|
3550
|
+
matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, property: SDK.CSSProperty.CSSProperty) {
|
|
3551
|
+
super({
|
|
3552
|
+
stylesContainer,
|
|
3553
|
+
section,
|
|
3554
|
+
matchedStyles,
|
|
3555
|
+
property,
|
|
3556
|
+
isShorthand: false,
|
|
3557
|
+
inherited: false,
|
|
3558
|
+
overloaded: false,
|
|
3559
|
+
newProperty: false,
|
|
3560
|
+
});
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3563
|
+
override onattach(): void {
|
|
3564
|
+
this.listItemElement.classList.add('ghost-row');
|
|
3565
|
+
this.updateTitle();
|
|
3566
|
+
}
|
|
3567
|
+
|
|
3568
|
+
override updateTitle(): void {
|
|
3569
|
+
this.listItemElement.removeChildren();
|
|
3570
|
+
this.nameElement = Renderer.renderNameElement(this.name);
|
|
3571
|
+
this.listItemElement.appendChild(this.nameElement);
|
|
3572
|
+
this.listItemElement.createChild('span', 'styles-name-value-separator').textContent = ': ';
|
|
3573
|
+
this.valueElement = this.listItemElement.createChild('span');
|
|
3574
|
+
this.valueElement.textContent = this.value;
|
|
3575
|
+
this.listItemElement.createChild('span', 'styles-semicolon').textContent = ';';
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
|
|
3546
3579
|
export interface Context {
|
|
3547
3580
|
expanded: boolean;
|
|
3548
3581
|
hasChildren: boolean;
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
|
6
6
|
import * as Host from '../../core/host/host.js';
|
|
7
7
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
8
|
+
import type * as SDK from '../../core/sdk/sdk.js';
|
|
8
9
|
import * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
|
|
9
|
-
import
|
|
10
|
+
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
11
|
+
import * as TextEditor from '../../ui/components/text_editor/text_editor.js';
|
|
10
12
|
|
|
11
13
|
export class StylesAiCodeCompletionProvider {
|
|
12
14
|
#aidaClient: Host.AidaClient.AidaClient = new Host.AidaClient.AidaClient();
|
|
@@ -16,6 +18,11 @@ export class StylesAiCodeCompletionProvider {
|
|
|
16
18
|
|
|
17
19
|
#boundOnUpdateAiCodeCompletionState = this.#updateAiCodeCompletionState.bind(this);
|
|
18
20
|
|
|
21
|
+
#debouncedRequestAidaSuggestion =
|
|
22
|
+
Common.Debouncer.debounce((prefix: string, suffix: string, cursorPositionAtRequest: number) => {
|
|
23
|
+
void this.#requestAidaSuggestion(prefix, suffix, cursorPositionAtRequest);
|
|
24
|
+
}, TextEditor.AiCodeCompletionProvider.AIDA_REQUEST_DEBOUNCE_TIMEOUT_MS);
|
|
25
|
+
|
|
19
26
|
private constructor(aiCodeCompletionConfig: TextEditor.AiCodeCompletionProvider.AiCodeCompletionConfig) {
|
|
20
27
|
const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();
|
|
21
28
|
if (!AiCodeCompletion.AiCodeCompletion.AiCodeCompletion.isAiCodeCompletionStylesEnabled(devtoolsLocale.locale)) {
|
|
@@ -66,4 +73,144 @@ export class StylesAiCodeCompletionProvider {
|
|
|
66
73
|
this.#cleanupAiCodeCompletion();
|
|
67
74
|
}
|
|
68
75
|
}
|
|
76
|
+
|
|
77
|
+
async triggerAiCodeCompletion(
|
|
78
|
+
text: string, cursorPosition: number, isEditingName: boolean, cssProperty: SDK.CSSProperty.CSSProperty,
|
|
79
|
+
cssModel: SDK.CSSModel.CSSModel): Promise<void> {
|
|
80
|
+
const styleSheetId = cssProperty.ownerStyle.styleSheetId;
|
|
81
|
+
if (!styleSheetId) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const header = cssModel.styleSheetHeaderForId(styleSheetId);
|
|
86
|
+
if (!header) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const contentData = await header.requestContentData();
|
|
91
|
+
if (TextUtils.ContentData.ContentData.isError(contentData)) {
|
|
92
|
+
AiCodeCompletion.debugLog('Error while fetching content from stylesheet', contentData.error);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const content = contentData.text;
|
|
97
|
+
const propertyRange = cssProperty.range;
|
|
98
|
+
if (!content || !propertyRange) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const contentText = new TextUtils.Text.Text(content);
|
|
103
|
+
const propertyStartOffset = contentText.offsetFromPosition(propertyRange.startLine, propertyRange.startColumn);
|
|
104
|
+
const propertyEndOffset = contentText.offsetFromPosition(propertyRange.endLine, propertyRange.endColumn);
|
|
105
|
+
let prefix = content.substring(0, propertyStartOffset);
|
|
106
|
+
if (!isEditingName) {
|
|
107
|
+
const nameRange = cssProperty.nameRange();
|
|
108
|
+
if (nameRange) {
|
|
109
|
+
const nameEndOffset = contentText.offsetFromPosition(nameRange.endLine, nameRange.endColumn);
|
|
110
|
+
prefix = prefix + content.substring(propertyStartOffset, nameEndOffset) + ': ';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
prefix = prefix + text;
|
|
114
|
+
const suffix = content.substring(propertyEndOffset);
|
|
115
|
+
// TODO(b/476098133): Consider adjusting cursor position
|
|
116
|
+
this.#debouncedRequestAidaSuggestion(prefix, suffix, cursorPosition);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async #requestAidaSuggestion(prefix: string, suffix: string, cursorPositionAtRequest: number): Promise<void> {
|
|
120
|
+
if (!this.#aiCodeCompletion) {
|
|
121
|
+
AiCodeCompletion.debugLog('Ai Code Completion is not initialized');
|
|
122
|
+
this.#aiCodeCompletionConfig?.onResponseReceived();
|
|
123
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeCompletionError);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const startTime = performance.now();
|
|
128
|
+
this.#aiCodeCompletionConfig?.onRequestTriggered();
|
|
129
|
+
// Registering AiCodeCompletionRequestTriggered metric even if the request is served from cache
|
|
130
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeCompletionRequestTriggered);
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const completionResponse = await this.#aiCodeCompletion.completeCode(
|
|
134
|
+
prefix, suffix, cursorPositionAtRequest, Host.AidaClient.AidaInferenceLanguage.CSS);
|
|
135
|
+
this.#aiCodeCompletionConfig?.onResponseReceived();
|
|
136
|
+
if (!completionResponse) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const {response, fromCache} = completionResponse;
|
|
141
|
+
if (!response) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const sampleResponse = await this.#generateSampleForRequest(response, prefix, suffix);
|
|
146
|
+
if (!sampleResponse) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (fromCache) {
|
|
150
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeCompletionResponseServedFromCache);
|
|
151
|
+
}
|
|
152
|
+
this.#aiCodeCompletionConfig?.setAiAutoCompletion?.({
|
|
153
|
+
text: sampleResponse.suggestionText,
|
|
154
|
+
from: cursorPositionAtRequest,
|
|
155
|
+
rpcGlobalId: sampleResponse.rpcGlobalId,
|
|
156
|
+
sampleId: sampleResponse.sampleId,
|
|
157
|
+
startTime,
|
|
158
|
+
clearCachedRequest: this.clearCache.bind(this),
|
|
159
|
+
onImpression: this.#aiCodeCompletion?.registerUserImpression.bind(this.#aiCodeCompletion),
|
|
160
|
+
});
|
|
161
|
+
} catch (e) {
|
|
162
|
+
AiCodeCompletion.debugLog('Error while fetching code completion suggestions from AIDA', e);
|
|
163
|
+
this.#aiCodeCompletionConfig?.onResponseReceived();
|
|
164
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeCompletionError);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async #generateSampleForRequest(response: Host.AidaClient.CompletionResponse, prefix: string, suffix?: string):
|
|
169
|
+
Promise<{
|
|
170
|
+
suggestionText: string,
|
|
171
|
+
citations: Host.AidaClient.Citation[],
|
|
172
|
+
rpcGlobalId?: Host.AidaClient.RpcGlobalId,
|
|
173
|
+
sampleId?: number,
|
|
174
|
+
}|null> {
|
|
175
|
+
const suggestionSample = this.#pickSampleFromResponse(response);
|
|
176
|
+
if (!suggestionSample) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const shouldBlock =
|
|
181
|
+
suggestionSample.attributionMetadata?.attributionAction === Host.AidaClient.RecitationAction.BLOCK;
|
|
182
|
+
if (shouldBlock) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const suggestionText = TextEditor.AiCodeCompletionProvider.AiCodeCompletionProvider.trimSuggestionOverlap(
|
|
187
|
+
suggestionSample.generationString, suffix);
|
|
188
|
+
if (suggestionText.length === 0) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
suggestionText,
|
|
194
|
+
sampleId: suggestionSample.sampleId,
|
|
195
|
+
citations: suggestionSample.attributionMetadata?.citations ?? [],
|
|
196
|
+
rpcGlobalId: response.metadata.rpcGlobalId,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
#pickSampleFromResponse(response: Host.AidaClient.CompletionResponse): Host.AidaClient.GenerationSample|null {
|
|
201
|
+
if (!response.generatedSamples.length) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const completionHint = this.#aiCodeCompletionConfig?.getCompletionHint?.();
|
|
206
|
+
if (!completionHint) {
|
|
207
|
+
return response.generatedSamples[0];
|
|
208
|
+
}
|
|
209
|
+
return response.generatedSamples.find(sample => sample.generationString.startsWith(completionHint)) ??
|
|
210
|
+
response.generatedSamples[0];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
clearCache(): void {
|
|
214
|
+
this.#aiCodeCompletion?.clearCachedRequest();
|
|
215
|
+
}
|
|
69
216
|
}
|
|
@@ -8,7 +8,7 @@ import * as Root from '../../core/root/root.js';
|
|
|
8
8
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
9
9
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import * as Elements from './elements.js';
|
|
12
12
|
|
|
13
13
|
const UIStrings = {
|
|
14
14
|
/**
|
|
@@ -614,10 +614,8 @@ UI.ViewManager.registerLocationResolver({
|
|
|
614
614
|
Common.Revealer.registerRevealer({
|
|
615
615
|
contextTypes() {
|
|
616
616
|
return [
|
|
617
|
-
SDK.DOMModel.DOMNode,
|
|
618
|
-
|
|
619
|
-
SDK.RemoteObject.RemoteObject,
|
|
620
|
-
SDK.DOMModel.AdoptedStyleSheet,
|
|
617
|
+
SDK.DOMModel.DOMNode, SDK.DOMModel.DeferredDOMNode, SDK.RemoteObject.RemoteObject, SDK.DOMModel.AdoptedStyleSheet,
|
|
618
|
+
Elements.ElementsPanel.NodeComputedStyles
|
|
621
619
|
];
|
|
622
620
|
},
|
|
623
621
|
destination: Common.Revealer.RevealerDestination.ELEMENTS_PANEL,
|
|
@@ -163,6 +163,11 @@ const UIStrings = {
|
|
|
163
163
|
* @description Tooltip of the rotate/screen orientation button.
|
|
164
164
|
*/
|
|
165
165
|
screenOrientationOptions: 'Screen orientation options',
|
|
166
|
+
/**
|
|
167
|
+
* @description Tooltip shown on the rotate button when screen orientation is locked by the page
|
|
168
|
+
* via screen.orientation.lock().
|
|
169
|
+
*/
|
|
170
|
+
screenOrientationLocked: 'Screen orientation is locked by the page',
|
|
166
171
|
/**
|
|
167
172
|
* @description Tooltip for a button which turns on/off dual-screen mode, which emulates devices
|
|
168
173
|
* like tablets which have two screens.
|
|
@@ -617,6 +622,9 @@ export class DeviceModeToolbar {
|
|
|
617
622
|
private modeMenuClicked(event: {
|
|
618
623
|
data: Event,
|
|
619
624
|
}): void {
|
|
625
|
+
if (this.model.isScreenOrientationLocked()) {
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
620
628
|
const device = this.model.device();
|
|
621
629
|
const model = this.model;
|
|
622
630
|
const autoAdjustScaleSetting = this.autoAdjustScaleSetting;
|
|
@@ -804,6 +812,23 @@ export class DeviceModeToolbar {
|
|
|
804
812
|
}
|
|
805
813
|
this.persistenceSetting.set(value);
|
|
806
814
|
}
|
|
815
|
+
|
|
816
|
+
// When screen orientation is locked by the page (via screen.orientation.lock()),
|
|
817
|
+
// disable the rotate button to prevent user-initiated rotation.
|
|
818
|
+
// When unlocked, restore the button to its normal state.
|
|
819
|
+
if (this.model.isScreenOrientationLocked()) {
|
|
820
|
+
this.modeButton.setEnabled(false);
|
|
821
|
+
setTitleForButton(this.modeButton, i18nString(UIStrings.screenOrientationLocked));
|
|
822
|
+
} else if (this.cachedModelDevice) {
|
|
823
|
+
const modeCount = this.cachedModelDevice.modes.length;
|
|
824
|
+
this.modeButton.setEnabled(modeCount >= 2);
|
|
825
|
+
setTitleForButton(
|
|
826
|
+
this.modeButton,
|
|
827
|
+
modeCount === 2 ? i18nString(UIStrings.rotate) : i18nString(UIStrings.screenOrientationOptions));
|
|
828
|
+
} else if (this.model.type() === EmulationModel.DeviceModeModel.Type.Responsive) {
|
|
829
|
+
this.modeButton.setEnabled(true);
|
|
830
|
+
setTitleForButton(this.modeButton, i18nString(UIStrings.rotate));
|
|
831
|
+
}
|
|
807
832
|
}
|
|
808
833
|
|
|
809
834
|
restore(): void {
|
|
@@ -56,6 +56,17 @@ export interface AiCodeCompletionConfig {
|
|
|
56
56
|
onRequestTriggered: () => void;
|
|
57
57
|
onResponseReceived: () => void;
|
|
58
58
|
panel: AiCodeCompletion.AiCodeCompletion.ContextFlavor;
|
|
59
|
+
getCompletionHint?: () => string | null;
|
|
60
|
+
getCurrentText?: () => string;
|
|
61
|
+
setAiAutoCompletion?: (args: {
|
|
62
|
+
text: string,
|
|
63
|
+
from: number,
|
|
64
|
+
startTime: number,
|
|
65
|
+
onImpression: (rpcGlobalId: Host.AidaClient.RpcGlobalId, latency: number, sampleId?: number) => void,
|
|
66
|
+
clearCachedRequest: () => void,
|
|
67
|
+
rpcGlobalId?: Host.AidaClient.RpcGlobalId,
|
|
68
|
+
sampleId?: number,
|
|
69
|
+
}|null) => void;
|
|
59
70
|
}
|
|
60
71
|
|
|
61
72
|
export const DELAY_BEFORE_SHOWING_RESPONSE_MS = 500;
|
|
@@ -401,7 +412,7 @@ export class AiCodeCompletionProvider {
|
|
|
401
412
|
return null;
|
|
402
413
|
}
|
|
403
414
|
|
|
404
|
-
const suggestionText =
|
|
415
|
+
const suggestionText = AiCodeCompletionProvider.trimSuggestionOverlap(suggestionSample.generationString, suffix);
|
|
405
416
|
if (suggestionText.length === 0) {
|
|
406
417
|
return null;
|
|
407
418
|
}
|
|
@@ -442,7 +453,7 @@ export class AiCodeCompletionProvider {
|
|
|
442
453
|
/**
|
|
443
454
|
* Removes the end of a suggestion if it overlaps with the start of the suffix.
|
|
444
455
|
*/
|
|
445
|
-
|
|
456
|
+
static trimSuggestionOverlap(generationString: string, suffix?: string): string {
|
|
446
457
|
if (!suffix) {
|
|
447
458
|
return generationString;
|
|
448
459
|
}
|
|
@@ -183,26 +183,26 @@ export interface CookiesTableData {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
export class CookiesTable extends UI.Widget.VBox {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
#saveCallback?: ((arg0: SDK.Cookie.Cookie, arg1: SDK.Cookie.Cookie|null) => Promise<boolean>);
|
|
187
|
+
#refreshCallback?: (() => void);
|
|
188
|
+
#selectedCallback?: ((arg0: SDK.Cookie.Cookie|null) => void);
|
|
189
|
+
#deleteCallback?: ((arg0: SDK.Cookie.Cookie, arg1: () => void) => void);
|
|
190
190
|
private lastEditedColumnId: string|null;
|
|
191
191
|
private data: CookieData[] = [];
|
|
192
192
|
private cookies: SDK.Cookie.Cookie[] = [];
|
|
193
|
-
|
|
193
|
+
#cookieDomain: string;
|
|
194
194
|
private cookieToBlockedReasons: ReadonlyMap<SDK.Cookie.Cookie, SDK.CookieModel.BlockedReason[]>|null;
|
|
195
195
|
private cookieToExemptionReason: ReadonlyMap<SDK.Cookie.Cookie, SDK.CookieModel.ExemptionReason>|null;
|
|
196
196
|
private readonly view: ViewFunction;
|
|
197
197
|
private selectedKey?: string;
|
|
198
|
-
|
|
198
|
+
#editable: boolean;
|
|
199
199
|
private renderInline: boolean;
|
|
200
200
|
private readonly schemeBindingEnabled: boolean;
|
|
201
201
|
private readonly portBindingEnabled: boolean;
|
|
202
202
|
constructor(
|
|
203
203
|
element?: HTMLElement, renderInline?: boolean,
|
|
204
204
|
saveCallback?: ((arg0: SDK.Cookie.Cookie, arg1: SDK.Cookie.Cookie|null) => Promise<boolean>),
|
|
205
|
-
refreshCallback?: (() => void), selectedCallback?: (() => void),
|
|
205
|
+
refreshCallback?: (() => void), selectedCallback?: ((arg0: SDK.Cookie.Cookie|null) => void),
|
|
206
206
|
deleteCallback?: ((arg0: SDK.Cookie.Cookie, arg1: () => void) => void), view?: ViewFunction) {
|
|
207
207
|
super(element);
|
|
208
208
|
if (!view) {
|
|
@@ -302,11 +302,11 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
302
302
|
|
|
303
303
|
this.element.classList.add('cookies-table');
|
|
304
304
|
|
|
305
|
-
this
|
|
306
|
-
this
|
|
307
|
-
this
|
|
305
|
+
this.#saveCallback = saveCallback;
|
|
306
|
+
this.#refreshCallback = refreshCallback;
|
|
307
|
+
this.#deleteCallback = deleteCallback;
|
|
308
308
|
|
|
309
|
-
this
|
|
309
|
+
this.#editable = Boolean(saveCallback);
|
|
310
310
|
const {devToolsEnableOriginBoundCookies} = Root.Runtime.hostConfig;
|
|
311
311
|
|
|
312
312
|
this.schemeBindingEnabled = Boolean(devToolsEnableOriginBoundCookies?.schemeBindingEnabled);
|
|
@@ -316,13 +316,13 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
316
316
|
|
|
317
317
|
this.renderInline = Boolean(renderInline);
|
|
318
318
|
|
|
319
|
-
this
|
|
319
|
+
this.#selectedCallback = selectedCallback;
|
|
320
320
|
|
|
321
321
|
this.lastEditedColumnId = null;
|
|
322
322
|
|
|
323
323
|
this.data = [];
|
|
324
324
|
|
|
325
|
-
this
|
|
325
|
+
this.#cookieDomain = '';
|
|
326
326
|
|
|
327
327
|
this.cookieToBlockedReasons = null;
|
|
328
328
|
|
|
@@ -335,6 +335,26 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
335
335
|
this.setCookies(data.cookies, data.cookieToBlockedReasons, data.cookieToExemptionReason);
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
+
set saveCallback(callback: (arg0: SDK.Cookie.Cookie, arg1: SDK.Cookie.Cookie|null) => Promise<boolean>) {
|
|
339
|
+
this.#saveCallback = callback;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
set refreshCallback(callback: () => void) {
|
|
343
|
+
this.#refreshCallback = callback;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
set selectedCallback(callback: (arg0: SDK.Cookie.Cookie|null) => void) {
|
|
347
|
+
this.#selectedCallback = callback;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
set deleteCallback(callback: (arg0: SDK.Cookie.Cookie, arg1: () => void) => void) {
|
|
351
|
+
this.#deleteCallback = callback;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
set editable(value: boolean) {
|
|
355
|
+
this.#editable = value;
|
|
356
|
+
}
|
|
357
|
+
|
|
338
358
|
set inline(value: boolean) {
|
|
339
359
|
this.renderInline = value;
|
|
340
360
|
this.requestUpdate();
|
|
@@ -357,8 +377,8 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
357
377
|
this.requestUpdate();
|
|
358
378
|
}
|
|
359
379
|
|
|
360
|
-
|
|
361
|
-
this
|
|
380
|
+
set cookieDomain(cookieDomain: string) {
|
|
381
|
+
this.#cookieDomain = cookieDomain;
|
|
362
382
|
}
|
|
363
383
|
|
|
364
384
|
selectedCookie(): SDK.Cookie.Cookie|null {
|
|
@@ -374,7 +394,7 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
374
394
|
const input: ViewInput = {
|
|
375
395
|
data: this.data,
|
|
376
396
|
selectedKey: this.selectedKey,
|
|
377
|
-
editable: this
|
|
397
|
+
editable: this.#editable,
|
|
378
398
|
renderInline: this.renderInline,
|
|
379
399
|
schemeBindingEnabled: this.schemeBindingEnabled,
|
|
380
400
|
portBindingEnabled: this.portBindingEnabled,
|
|
@@ -391,13 +411,13 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
391
411
|
|
|
392
412
|
private onSelect(key: string|undefined): void {
|
|
393
413
|
this.selectedKey = key;
|
|
394
|
-
this
|
|
414
|
+
this.#selectedCallback?.(this.selectedCookie());
|
|
395
415
|
}
|
|
396
416
|
|
|
397
417
|
private onDeleteCookie(data: CookieData): void {
|
|
398
418
|
const cookie = this.cookies.find(cookie => cookie.key() === data.key);
|
|
399
|
-
if (cookie && this
|
|
400
|
-
this
|
|
419
|
+
if (cookie && this.#deleteCallback) {
|
|
420
|
+
this.#deleteCallback(cookie, () => this.refresh());
|
|
401
421
|
}
|
|
402
422
|
}
|
|
403
423
|
|
|
@@ -434,7 +454,7 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
434
454
|
data[SDK.Cookie.Attribute.VALUE] = '';
|
|
435
455
|
}
|
|
436
456
|
if (data[SDK.Cookie.Attribute.DOMAIN] === undefined) {
|
|
437
|
-
data[SDK.Cookie.Attribute.DOMAIN] = this
|
|
457
|
+
data[SDK.Cookie.Attribute.DOMAIN] = this.#cookieDomain;
|
|
438
458
|
}
|
|
439
459
|
if (data[SDK.Cookie.Attribute.PATH] === undefined) {
|
|
440
460
|
data[SDK.Cookie.Attribute.PATH] = '/';
|
|
@@ -448,11 +468,11 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
448
468
|
}
|
|
449
469
|
|
|
450
470
|
private saveCookie(newCookieData: CookieData, oldCookie?: SDK.Cookie.Cookie): void {
|
|
451
|
-
if (!this
|
|
471
|
+
if (!this.#saveCallback) {
|
|
452
472
|
return;
|
|
453
473
|
}
|
|
454
474
|
const newCookie = this.createCookieFromData(newCookieData);
|
|
455
|
-
void this
|
|
475
|
+
void this.#saveCallback(newCookie, oldCookie ?? null).then(success => {
|
|
456
476
|
if (!success) {
|
|
457
477
|
newCookieData.dirty = true;
|
|
458
478
|
}
|
|
@@ -591,8 +611,8 @@ export class CookiesTable extends UI.Widget.VBox {
|
|
|
591
611
|
}
|
|
592
612
|
|
|
593
613
|
private refresh(): void {
|
|
594
|
-
if (this
|
|
595
|
-
this
|
|
614
|
+
if (this.#refreshCallback) {
|
|
615
|
+
this.#refreshCallback();
|
|
596
616
|
}
|
|
597
617
|
}
|
|
598
618
|
|
|
@@ -878,6 +878,10 @@ function checkPendingEventExpectation(): void {
|
|
|
878
878
|
}
|
|
879
879
|
if (!found) {
|
|
880
880
|
processMissingEvents(pendingEventExpectation, expectedEventIndex, matchedImpressions);
|
|
881
|
+
if (!pendingEventExpectation.missingEvents?.length) {
|
|
882
|
+
numMatchedEvents = actualEventIndex;
|
|
883
|
+
pendingEventExpectation.success();
|
|
884
|
+
}
|
|
881
885
|
return;
|
|
882
886
|
}
|
|
883
887
|
}
|
package/package.json
CHANGED