chrome-devtools-frontend 1.0.1621064 → 1.0.1621678
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/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +1 -1
- package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +31 -20
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +5 -1
- package/front_end/models/bindings/SymbolizedError.ts +18 -1
- package/front_end/models/issues_manager/GenericIssue.ts +50 -1
- package/front_end/models/issues_manager/descriptions/genericFormModelContextMissingToolDescription.md +5 -0
- package/front_end/models/issues_manager/descriptions/genericFormModelContextMissingToolName.md +5 -0
- package/front_end/models/issues_manager/descriptions/genericFormModelContextParameterMissingName.md +5 -0
- package/front_end/models/issues_manager/descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
- package/front_end/models/issues_manager/descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
- package/front_end/models/trace/insights/Common.ts +4 -0
- package/front_end/models/trace/insights/types.ts +1 -1
- package/front_end/models/web_mcp/WebMCPModel.ts +11 -1
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +31 -1
- package/front_end/panels/application/WebMCPView.ts +16 -7
- package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +0 -1
- package/front_end/panels/elements/ElementsTreeElement.ts +53 -61
- package/front_end/panels/elements/PropertiesWidget.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/text_editor/TextEditor.ts +1 -3
- package/front_end/ui/legacy/Treeoutline.ts +5 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/package.json +1 -1
|
@@ -349,7 +349,7 @@ inspectorBackend.registerCommand("CrashReportContext.getEntries", [], ["entries"
|
|
|
349
349
|
inspectorBackend.registerType("CrashReportContext.CrashReportContextEntry", [{"name": "key", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "value", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "frameId", "type": "string", "optional": false, "description": "The ID of the frame where the key-value pair was set.", "typeRef": "Page.FrameId"}]);
|
|
350
350
|
|
|
351
351
|
// DOM.
|
|
352
|
-
inspectorBackend.registerEnum("DOM.PseudoType", {FirstLine: "first-line", FirstLetter: "first-letter", Checkmark: "checkmark", Before: "before", After: "after", ExpandIcon: "expand-icon", PickerIcon: "picker-icon",
|
|
352
|
+
inspectorBackend.registerEnum("DOM.PseudoType", {FirstLine: "first-line", FirstLetter: "first-letter", Checkmark: "checkmark", Before: "before", After: "after", ExpandIcon: "expand-icon", PickerIcon: "picker-icon", InterestButton: "interest-button", Marker: "marker", Backdrop: "backdrop", Column: "column", Selection: "selection", SearchText: "search-text", TargetText: "target-text", SpellingError: "spelling-error", GrammarError: "grammar-error", Highlight: "highlight", FirstLineInherited: "first-line-inherited", ScrollMarker: "scroll-marker", ScrollMarkerGroup: "scroll-marker-group", ScrollButton: "scroll-button", Scrollbar: "scrollbar", ScrollbarThumb: "scrollbar-thumb", ScrollbarButton: "scrollbar-button", ScrollbarTrack: "scrollbar-track", ScrollbarTrackPiece: "scrollbar-track-piece", ScrollbarCorner: "scrollbar-corner", Resizer: "resizer", InputListButton: "input-list-button", ViewTransition: "view-transition", ViewTransitionGroup: "view-transition-group", ViewTransitionImagePair: "view-transition-image-pair", ViewTransitionGroupChildren: "view-transition-group-children", ViewTransitionOld: "view-transition-old", ViewTransitionNew: "view-transition-new", Placeholder: "placeholder", FileSelectorButton: "file-selector-button", DetailsContent: "details-content", Picker: "picker", PermissionIcon: "permission-icon", OverscrollAreaParent: "overscroll-area-parent"});
|
|
353
353
|
inspectorBackend.registerEnum("DOM.ShadowRootType", {UserAgent: "user-agent", Open: "open", Closed: "closed"});
|
|
354
354
|
inspectorBackend.registerEnum("DOM.CompatibilityMode", {QuirksMode: "QuirksMode", LimitedQuirksMode: "LimitedQuirksMode", NoQuirksMode: "NoQuirksMode"});
|
|
355
355
|
inspectorBackend.registerEnum("DOM.PhysicalAxes", {Horizontal: "Horizontal", Vertical: "Vertical", Both: "Both"});
|
|
@@ -4604,7 +4604,7 @@ export namespace DOM {
|
|
|
4604
4604
|
After = 'after',
|
|
4605
4605
|
ExpandIcon = 'expand-icon',
|
|
4606
4606
|
PickerIcon = 'picker-icon',
|
|
4607
|
-
|
|
4607
|
+
InterestButton = 'interest-button',
|
|
4608
4608
|
Marker = 'marker',
|
|
4609
4609
|
Backdrop = 'backdrop',
|
|
4610
4610
|
Column = 'column',
|
|
@@ -251,7 +251,7 @@ export interface PerformanceTraceAiWidget {
|
|
|
251
251
|
export interface PerfInsightAiWidget {
|
|
252
252
|
name: 'PERF_INSIGHT';
|
|
253
253
|
data: {
|
|
254
|
-
insight:
|
|
254
|
+
insight: Trace.Insights.Types.InsightKeys,
|
|
255
255
|
insightData: Trace.Insights.Types.InsightModel,
|
|
256
256
|
};
|
|
257
257
|
}
|
|
@@ -222,6 +222,12 @@ enum ScorePriority {
|
|
|
222
222
|
DEFAULT = 1,
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
+
// TODO(crbug.com/503296282): Remove this when we add support for all insights
|
|
226
|
+
const SUPPORTED_INSIGHT_WIDGETS = new Set<Trace.Insights.Types.InsightKeys>([
|
|
227
|
+
Trace.Insights.Types.InsightKeys.LCP_BREAKDOWN,
|
|
228
|
+
Trace.Insights.Types.InsightKeys.RENDER_BLOCKING,
|
|
229
|
+
]);
|
|
230
|
+
|
|
225
231
|
export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
226
232
|
static fromParsedTrace(parsedTrace: Trace.TraceModel.ParsedTrace): PerformanceTraceContext {
|
|
227
233
|
return new PerformanceTraceContext(AgentFocus.fromParsedTrace(parsedTrace));
|
|
@@ -334,8 +340,8 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
|
334
340
|
const failingInsightSuggestions =
|
|
335
341
|
Object.values(insightSet.model)
|
|
336
342
|
.filter(model => {
|
|
337
|
-
return model.state !== 'pass' &&
|
|
338
|
-
!poorMetrics.has(model.insightKey
|
|
343
|
+
return model.state !== 'pass' && Trace.Insights.Common.isInsightKey(model.insightKey) &&
|
|
344
|
+
!poorMetrics.has(model.insightKey);
|
|
339
345
|
})
|
|
340
346
|
.map(model => new PerformanceInsightFormatter(focus, model).getSuggestions().at(-1))
|
|
341
347
|
.filter((suggestion): suggestion is ConversationSuggestion => !!suggestion)
|
|
@@ -536,15 +542,18 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
536
542
|
return widgets;
|
|
537
543
|
}
|
|
538
544
|
|
|
539
|
-
// Case 2:
|
|
540
|
-
if (focus.insight
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
545
|
+
// Case 2: Insight -> PERF_INSIGHT widget
|
|
546
|
+
if (focus.insight) {
|
|
547
|
+
const insightKey = focus.insight.insightKey;
|
|
548
|
+
if (Trace.Insights.Common.isInsightKey(insightKey) && SUPPORTED_INSIGHT_WIDGETS.has(insightKey)) {
|
|
549
|
+
widgets.push({
|
|
550
|
+
name: 'PERF_INSIGHT',
|
|
551
|
+
data: {
|
|
552
|
+
insight: insightKey,
|
|
553
|
+
insightData: focus.insight,
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
}
|
|
548
557
|
}
|
|
549
558
|
|
|
550
559
|
// Case 3: Whole Trace or insight other than LCP -> CWV widget
|
|
@@ -1006,15 +1015,17 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1006
1015
|
}
|
|
1007
1016
|
}
|
|
1008
1017
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
const insightKey = params.insightName;
|
|
1021
|
+
if (Trace.Insights.Common.isInsightKey(insightKey) && SUPPORTED_INSIGHT_WIDGETS.has(insightKey)) {
|
|
1022
|
+
widgets.push({
|
|
1023
|
+
name: 'PERF_INSIGHT',
|
|
1024
|
+
data: {
|
|
1025
|
+
insight: insightKey,
|
|
1026
|
+
insightData: insight as Trace.Insights.Types.InsightModel,
|
|
1027
|
+
},
|
|
1028
|
+
});
|
|
1018
1029
|
}
|
|
1019
1030
|
|
|
1020
1031
|
const key = `getInsightDetails('${params.insightSetId}', '${params.insightName}')`;
|
|
@@ -21,10 +21,11 @@ import {NetworkProject} from './NetworkProject.js';
|
|
|
21
21
|
import type {ResourceMapping} from './ResourceMapping.js';
|
|
22
22
|
import {type ResourceScriptFile, ResourceScriptMapping} from './ResourceScriptMapping.js';
|
|
23
23
|
import {
|
|
24
|
+
isErrorLike,
|
|
24
25
|
type SymbolizedError,
|
|
25
26
|
SymbolizedErrorObject,
|
|
26
27
|
SymbolizedSyntaxError,
|
|
27
|
-
UnparsableError
|
|
28
|
+
UnparsableError,
|
|
28
29
|
} from './SymbolizedError.js';
|
|
29
30
|
|
|
30
31
|
export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObserver<SDK.DebuggerModel.DebuggerModel> {
|
|
@@ -247,6 +248,9 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
|
|
|
247
248
|
}
|
|
248
249
|
} else if (remoteObject.type === 'string') {
|
|
249
250
|
errorStack = remoteObject.description || '';
|
|
251
|
+
if (!isErrorLike(errorStack)) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
250
254
|
} else {
|
|
251
255
|
return null;
|
|
252
256
|
}
|
|
@@ -11,6 +11,10 @@ import type * as Workspace from '../workspace/workspace.js';
|
|
|
11
11
|
import type {DebuggerWorkspaceBinding} from './DebuggerWorkspaceBinding.js';
|
|
12
12
|
import {type LiveLocation, LiveLocationPool} from './LiveLocation.js';
|
|
13
13
|
|
|
14
|
+
export function isErrorLike(stack: string): boolean {
|
|
15
|
+
return /\n\s*at\s/.test(stack) || stack.startsWith('SyntaxError:');
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
export type SymbolizedError = SymbolizedErrorObject|SymbolizedSyntaxError|UnparsableError;
|
|
15
19
|
|
|
16
20
|
export class UnparsableError extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
@@ -21,6 +25,19 @@ export class UnparsableError extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
21
25
|
super();
|
|
22
26
|
this.errorStack = errorStack;
|
|
23
27
|
this.cause = cause;
|
|
28
|
+
|
|
29
|
+
this.cause?.addEventListener(Events.UPDATED, this.#fireUpdated, this);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dispose(): void {
|
|
33
|
+
this.cause?.removeEventListener(Events.UPDATED, this.#fireUpdated, this);
|
|
34
|
+
if (this.cause instanceof SymbolizedErrorObject || this.cause instanceof UnparsableError) {
|
|
35
|
+
this.cause.dispose();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#fireUpdated(): void {
|
|
40
|
+
this.dispatchEventToListeners(Events.UPDATED);
|
|
24
41
|
}
|
|
25
42
|
}
|
|
26
43
|
|
|
@@ -42,7 +59,7 @@ export class SymbolizedErrorObject extends Common.ObjectWrapper.ObjectWrapper<Ev
|
|
|
42
59
|
dispose(): void {
|
|
43
60
|
this.stackTrace.removeEventListener(StackTrace.StackTrace.Events.UPDATED, this.#fireUpdated, this);
|
|
44
61
|
this.cause?.removeEventListener(Events.UPDATED, this.#fireUpdated, this);
|
|
45
|
-
if (this.cause instanceof SymbolizedErrorObject) {
|
|
62
|
+
if (this.cause instanceof SymbolizedErrorObject || this.cause instanceof UnparsableError) {
|
|
46
63
|
this.cause.dispose();
|
|
47
64
|
}
|
|
48
65
|
}
|
|
@@ -193,6 +193,31 @@ export const genericNavigationEntryMarkedSkippable = {
|
|
|
193
193
|
}],
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
+
export const genericFormModelContextMissingToolName = {
|
|
197
|
+
file: 'genericFormModelContextMissingToolName.md',
|
|
198
|
+
links: [],
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const genericFormModelContextMissingToolDescription = {
|
|
202
|
+
file: 'genericFormModelContextMissingToolDescription.md',
|
|
203
|
+
links: [],
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export const genericFormModelContextParameterMissingTitleAndDescription = {
|
|
207
|
+
file: 'genericFormModelContextParameterMissingTitleAndDescription.md',
|
|
208
|
+
links: [],
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export const genericFormModelContextRequiredParameterMissingName = {
|
|
212
|
+
file: 'genericFormModelContextRequiredParameterMissingName.md',
|
|
213
|
+
links: [],
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export const genericFormModelContextParameterMissingName = {
|
|
217
|
+
file: 'genericFormModelContextParameterMissingName.md',
|
|
218
|
+
links: [],
|
|
219
|
+
};
|
|
220
|
+
|
|
196
221
|
const issueDescriptions = new Map<Protocol.Audits.GenericIssueErrorType, LazyMarkdownIssueDescription>([
|
|
197
222
|
[Protocol.Audits.GenericIssueErrorType.FormLabelForNameError, genericFormLabelForNameError],
|
|
198
223
|
[Protocol.Audits.GenericIssueErrorType.FormInputWithNoLabelError, genericFormInputWithNoLabelError],
|
|
@@ -233,6 +258,26 @@ const issueDescriptions = new Map<Protocol.Audits.GenericIssueErrorType, LazyMar
|
|
|
233
258
|
Protocol.Audits.GenericIssueErrorType.NavigationEntryMarkedSkippable,
|
|
234
259
|
genericNavigationEntryMarkedSkippable,
|
|
235
260
|
],
|
|
261
|
+
[
|
|
262
|
+
Protocol.Audits.GenericIssueErrorType.FormModelContextMissingToolName,
|
|
263
|
+
genericFormModelContextMissingToolName,
|
|
264
|
+
],
|
|
265
|
+
[
|
|
266
|
+
Protocol.Audits.GenericIssueErrorType.FormModelContextMissingToolDescription,
|
|
267
|
+
genericFormModelContextMissingToolDescription,
|
|
268
|
+
],
|
|
269
|
+
[
|
|
270
|
+
Protocol.Audits.GenericIssueErrorType.FormModelContextParameterMissingTitleAndDescription,
|
|
271
|
+
genericFormModelContextParameterMissingTitleAndDescription,
|
|
272
|
+
],
|
|
273
|
+
[
|
|
274
|
+
Protocol.Audits.GenericIssueErrorType.FormModelContextRequiredParameterMissingName,
|
|
275
|
+
genericFormModelContextRequiredParameterMissingName,
|
|
276
|
+
],
|
|
277
|
+
[
|
|
278
|
+
Protocol.Audits.GenericIssueErrorType.FormModelContextParameterMissingName,
|
|
279
|
+
genericFormModelContextParameterMissingName,
|
|
280
|
+
],
|
|
236
281
|
]);
|
|
237
282
|
|
|
238
283
|
const issueTypes = new Map<Protocol.Audits.GenericIssueErrorType, IssueKind>([
|
|
@@ -249,5 +294,9 @@ const issueTypes = new Map<Protocol.Audits.GenericIssueErrorType, IssueKind>([
|
|
|
249
294
|
[Protocol.Audits.GenericIssueErrorType.FormLabelForMatchesNonExistingIdError, IssueKind.PAGE_ERROR],
|
|
250
295
|
[Protocol.Audits.GenericIssueErrorType.FormLabelHasNeitherForNorNestedInputError, IssueKind.IMPROVEMENT],
|
|
251
296
|
[Protocol.Audits.GenericIssueErrorType.FormInputHasWrongButWellIntendedAutocompleteValueError, IssueKind.IMPROVEMENT],
|
|
252
|
-
|
|
297
|
+
[Protocol.Audits.GenericIssueErrorType.FormModelContextMissingToolName, IssueKind.PAGE_ERROR],
|
|
298
|
+
[Protocol.Audits.GenericIssueErrorType.FormModelContextMissingToolDescription, IssueKind.PAGE_ERROR],
|
|
299
|
+
[Protocol.Audits.GenericIssueErrorType.FormModelContextParameterMissingTitleAndDescription, IssueKind.PAGE_ERROR],
|
|
300
|
+
[Protocol.Audits.GenericIssueErrorType.FormModelContextRequiredParameterMissingName, IssueKind.PAGE_ERROR],
|
|
301
|
+
[Protocol.Audits.GenericIssueErrorType.FormModelContextParameterMissingName, IssueKind.PAGE_ERROR],
|
|
253
302
|
]);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Missing tool description for a WebMCP declarative tool definition
|
|
2
|
+
|
|
3
|
+
This form is intended to be used as a WebMCP declarative tool definition, but it lacks a description explaining what the tool does. Descriptions are critical for AI models to decide when to use a given tool.
|
|
4
|
+
|
|
5
|
+
To fix this issue, provide a tool description via the `tooldescription` attribute.
|
package/front_end/models/issues_manager/descriptions/genericFormModelContextMissingToolName.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Missing tool name for a WebMCP declarative tool definition
|
|
2
|
+
|
|
3
|
+
This form is intended to be used as a WebMCP declarative tool definition, but it does not specify a name. A tool name is required for an AI model to correctly identify and invoke the tool.
|
|
4
|
+
|
|
5
|
+
To fix this issue, provide a tool name via the `toolname` attribute.
|
package/front_end/models/issues_manager/descriptions/genericFormModelContextParameterMissingName.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Parameter missing name for a WebMCP declarative tool definition
|
|
2
|
+
|
|
3
|
+
An input element within this form lacks a `name` attribute. Without a name, the AI model cannot format the parameter payload correctly when invoking the tool.
|
|
4
|
+
|
|
5
|
+
To fix this issue, ensure form parameters have a `name` attribute.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Missing parameter title and description for a WebMCP declarative tool definition
|
|
2
|
+
|
|
3
|
+
A parameter within this form (such as an `<input>` field) is missing both a title and a description. An AI model needs this metadata to understand what information should be passed to this parameter when invoking the tool.
|
|
4
|
+
|
|
5
|
+
To fix this issue, add a title and description to the form parameter.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Required parameter missing name for a WebMCP declarative tool definition
|
|
2
|
+
|
|
3
|
+
A required input element within this form lacks a `name` attribute. Without a name, the AI model cannot format the parameter payload correctly when invoking the tool.
|
|
4
|
+
|
|
5
|
+
To fix this issue, ensure all required form parameters have a `name` attribute.
|
|
@@ -7639,6 +7639,14 @@ export const NativeFunctions = [
|
|
|
7639
7639
|
name: "Sanitizer",
|
|
7640
7640
|
signatures: [["?configuration"]]
|
|
7641
7641
|
},
|
|
7642
|
+
{
|
|
7643
|
+
name: "allowProcessingInstruction",
|
|
7644
|
+
signatures: [["pi"]]
|
|
7645
|
+
},
|
|
7646
|
+
{
|
|
7647
|
+
name: "removeProcessingInstruction",
|
|
7648
|
+
signatures: [["pi"]]
|
|
7649
|
+
},
|
|
7642
7650
|
{
|
|
7643
7651
|
name: "TaskController",
|
|
7644
7652
|
signatures: [["?init"]]
|
|
@@ -26,6 +26,10 @@ export function getInsight<InsightName extends keyof InsightModels>(
|
|
|
26
26
|
return insightSet.model[insightName];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export function isInsightKey(key: string): key is InsightKeys {
|
|
30
|
+
return Object.values(InsightKeys).includes(key as InsightKeys);
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
export function getLCP(insightSet: InsightSet):
|
|
30
34
|
{value: Types.Timing.Micro, event: Types.Events.AnyLargestContentfulPaintCandidate}|null {
|
|
31
35
|
const insight = getInsight(InsightKeys.LCP_BREAKDOWN, insightSet);
|
|
@@ -145,7 +145,7 @@ export type InsightModelErrors = {
|
|
|
145
145
|
*/
|
|
146
146
|
export type TraceInsightSets = Map<Types.Events.NavigationId, InsightSet>;
|
|
147
147
|
|
|
148
|
-
export
|
|
148
|
+
export enum InsightKeys {
|
|
149
149
|
LCP_BREAKDOWN = 'LCPBreakdown',
|
|
150
150
|
INP_BREAKDOWN = 'INPBreakdown',
|
|
151
151
|
CLS_CULPRITS = 'CLSCulprits',
|
|
@@ -90,6 +90,7 @@ export interface Call {
|
|
|
90
90
|
tool: Tool;
|
|
91
91
|
input: string;
|
|
92
92
|
result?: Result;
|
|
93
|
+
cancel: () => void;
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
export class Tool {
|
|
@@ -244,7 +245,16 @@ export class WebMCPModel extends SDK.SDKModel.SDKModel<EventTypes> implements Pr
|
|
|
244
245
|
if (!tool) {
|
|
245
246
|
return;
|
|
246
247
|
}
|
|
247
|
-
const call: Call = {
|
|
248
|
+
const call: Call = {
|
|
249
|
+
tool,
|
|
250
|
+
input: params.input,
|
|
251
|
+
invocationId: params.invocationId,
|
|
252
|
+
cancel: () => {
|
|
253
|
+
if (call.result === undefined) {
|
|
254
|
+
void this.agent.invoke_cancelInvocation({invocationId: params.invocationId});
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
};
|
|
248
258
|
this.#calls.set(params.invocationId, call);
|
|
249
259
|
this.dispatchEventToListeners(Events.TOOL_INVOKED, call);
|
|
250
260
|
}
|
|
@@ -201,6 +201,10 @@ const UIStringsNotTranslate = {
|
|
|
201
201
|
* @description Accessible label for the reveal button in the LCP breakdown widget.
|
|
202
202
|
*/
|
|
203
203
|
revealLcpBreakdown: 'Reveal LCP breakdown',
|
|
204
|
+
/**
|
|
205
|
+
* @description Accessible label for the reveal button in the render-blocking requests widget.
|
|
206
|
+
*/
|
|
207
|
+
revealRenderBlockingBreakdown: 'Reveal render-blocking requests',
|
|
204
208
|
/**
|
|
205
209
|
* @description Accessible label for the reveal button in the LCP element widget.
|
|
206
210
|
*/
|
|
@@ -221,6 +225,10 @@ const UIStringsNotTranslate = {
|
|
|
221
225
|
* @description Title for the LCP breakdown widget.
|
|
222
226
|
*/
|
|
223
227
|
lcpBreakdown: 'LCP breakdown',
|
|
228
|
+
/**
|
|
229
|
+
* @description Title for the render-blocking requests widget.
|
|
230
|
+
*/
|
|
231
|
+
renderBlockingBreakdown: 'Render-blocking requests',
|
|
224
232
|
/**
|
|
225
233
|
* @description Title for the LCP element widget.
|
|
226
234
|
*/
|
|
@@ -916,7 +924,7 @@ async function makeStylePropertiesWidget(widgetData: StylePropertiesAiWidget): P
|
|
|
916
924
|
|
|
917
925
|
async function makePerfInsightWidget(widgetData: PerfInsightAiWidget): Promise<WidgetMakerResponse|null> {
|
|
918
926
|
switch (widgetData.data.insight) {
|
|
919
|
-
case
|
|
927
|
+
case Trace.Insights.Types.InsightKeys.LCP_BREAKDOWN: {
|
|
920
928
|
const insight = widgetData.data.insightData;
|
|
921
929
|
if (!insight || !Trace.Insights.Models.LCPBreakdown.isLCPBreakdownInsight(insight)) {
|
|
922
930
|
return null;
|
|
@@ -938,6 +946,28 @@ async function makePerfInsightWidget(widgetData: PerfInsightAiWidget): Promise<W
|
|
|
938
946
|
jslogContext: 'lcp-breakdown',
|
|
939
947
|
};
|
|
940
948
|
}
|
|
949
|
+
case Trace.Insights.Types.InsightKeys.RENDER_BLOCKING: {
|
|
950
|
+
const insight = widgetData.data.insightData;
|
|
951
|
+
if (!insight || !Trace.Insights.Models.RenderBlocking.isRenderBlockingInsight(insight)) {
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
// clang-format off
|
|
955
|
+
const renderedWidget = html`<devtools-widget
|
|
956
|
+
class="render-blocking-widget"
|
|
957
|
+
${widget(TimelineInsights.RenderBlocking.RenderBlocking, {
|
|
958
|
+
model: insight,
|
|
959
|
+
minimal: true,
|
|
960
|
+
})}></devtools-widget>`;
|
|
961
|
+
// clang-format on
|
|
962
|
+
|
|
963
|
+
return {
|
|
964
|
+
renderedWidget,
|
|
965
|
+
revealable: new TimelineUtils.Helpers.RevealableInsight(insight),
|
|
966
|
+
accessibleRevealLabel: lockedString(UIStringsNotTranslate.revealRenderBlockingBreakdown),
|
|
967
|
+
title: lockedString(UIStringsNotTranslate.renderBlockingBreakdown),
|
|
968
|
+
jslogContext: 'render-blocking-widget',
|
|
969
|
+
};
|
|
970
|
+
}
|
|
941
971
|
default:
|
|
942
972
|
return null;
|
|
943
973
|
}
|
|
@@ -167,6 +167,10 @@ const UIStrings = {
|
|
|
167
167
|
* @description Context menu action to copy the description of a tool
|
|
168
168
|
*/
|
|
169
169
|
copyDescription: 'Copy description',
|
|
170
|
+
/**
|
|
171
|
+
* @description Context menu action to cancel an in-progress tool call
|
|
172
|
+
*/
|
|
173
|
+
cancelCall: 'Cancel',
|
|
170
174
|
/**
|
|
171
175
|
* @description Text for the header of the tool run section
|
|
172
176
|
*/
|
|
@@ -498,6 +502,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
498
502
|
const payload = parsePayload(call.input);
|
|
499
503
|
input.onRevealTool(call.tool, payload.valueObject as Record<string, unknown> | undefined);
|
|
500
504
|
}, {jslogContext: 'webmcp.edit-and-run', disabled: isUnregistered});
|
|
505
|
+
if (call.result === undefined) {
|
|
506
|
+
contextMenu.defaultSection().appendItem(i18nString(UIStrings.cancelCall), () => {
|
|
507
|
+
call.cancel();
|
|
508
|
+
}, {jslogContext: 'webmcp.cancel-call'});
|
|
509
|
+
}
|
|
501
510
|
}}>
|
|
502
511
|
<td>
|
|
503
512
|
<div class="name-cell">
|
|
@@ -598,11 +607,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
598
607
|
` : html`
|
|
599
608
|
<devtools-list class="square-corners">
|
|
600
609
|
${tools.map(tool => html`
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
610
|
+
<div class=${Directives.classMap({'tool-item': true, selected: tool === input.selectedTool?.tool})}
|
|
611
|
+
@click=${() => input.onToolSelect(tool)}
|
|
612
|
+
@contextmenu=${(e: Event) => onToolContextMenu(e, tool)}>
|
|
613
|
+
<div class="tool-name-container">
|
|
614
|
+
<div class="tool-name source-code">${tool.name}</div>
|
|
606
615
|
<div class="tool-icons">
|
|
607
616
|
${getIconGroupsFromStats(toolStats.stats.get(tool)).map(group => html`
|
|
608
617
|
<icon-button
|
|
@@ -613,8 +622,8 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
613
622
|
} as IconButton.IconButton.IconButtonData}
|
|
614
623
|
@click=${(e: Event) => e.stopPropagation()}></icon-button>`)}
|
|
615
624
|
</div>
|
|
616
|
-
|
|
617
|
-
|
|
625
|
+
</div>
|
|
626
|
+
<div class="tool-description">${tool.description}</div>
|
|
618
627
|
</div>`)}
|
|
619
628
|
</devtools-list>
|
|
620
629
|
`}
|
|
@@ -460,10 +460,14 @@ export interface ViewInput {
|
|
|
460
460
|
descendantDecorations: Decoration[];
|
|
461
461
|
decorationsTooltip: string;
|
|
462
462
|
indent: number;
|
|
463
|
+
|
|
464
|
+
editorState: CodeMirror.EditorState|null;
|
|
465
|
+
editorWidth: number|null;
|
|
463
466
|
}
|
|
464
467
|
|
|
465
468
|
export interface ViewOutput {
|
|
466
469
|
contentElement?: HTMLElement;
|
|
470
|
+
editorRef?: TextEditor.TextEditor.TextEditor;
|
|
467
471
|
}
|
|
468
472
|
|
|
469
473
|
export function adornerRef(): DirectiveResult<typeof Lit.Directives.RefDirective> {
|
|
@@ -936,11 +940,12 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
936
940
|
const gutterContainerClasses = {
|
|
937
941
|
'has-decorations': input.decorations.length || input.descendantDecorations.length,
|
|
938
942
|
'gutter-container': true,
|
|
943
|
+
hidden: Boolean(input.editorState),
|
|
939
944
|
};
|
|
940
945
|
// clang-format off
|
|
941
946
|
render(html`
|
|
942
947
|
<div ${ref(el => { output.contentElement = el as HTMLElement; })}>
|
|
943
|
-
${input.node ? html`<span class="highlight">${renderTitle(
|
|
948
|
+
${input.node ? html`<span class="highlight ${input.editorState ? 'hidden' : ''}">${renderTitle(
|
|
944
949
|
input.node,
|
|
945
950
|
input.isClosingTag,
|
|
946
951
|
input.expanded,
|
|
@@ -951,7 +956,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
951
956
|
input.onExpand,
|
|
952
957
|
)}</span>` : nothing}
|
|
953
958
|
${input.isHovered || input.isSelected ? html`
|
|
954
|
-
<div class="selection fill" style=${`margin-left: ${-input.indent}px`}></div>
|
|
959
|
+
<div class="selection fill ${input.editorState ? 'hidden' : ''}" style=${`margin-left: ${-input.indent}px`}></div>
|
|
955
960
|
` : nothing}
|
|
956
961
|
<div class=${Lit.Directives.classMap(gutterContainerClasses)}
|
|
957
962
|
style="left: ${-input.indent}px"
|
|
@@ -964,7 +969,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
964
969
|
${input.descendantDecorations.map(d => html`<div class="elements-gutter-decoration elements-has-decorated-children" style="--decoration-color: ${d.color}"></div>`)}
|
|
965
970
|
</div>` : nothing}
|
|
966
971
|
</div>
|
|
967
|
-
${hasAdorners ? html`<div class="adorner-container ${
|
|
972
|
+
${hasAdorners ? html`<div class="adorner-container ${(input.editorState) ? 'hidden' : ''}">
|
|
968
973
|
${maybeRenderAdAdorner(input)}
|
|
969
974
|
${input.showViewSourceAdorner ? html`<devtools-adorner
|
|
970
975
|
.name=${ElementsComponents.AdornerManager.RegisteredAdorners.VIEW_SOURCE}
|
|
@@ -1123,10 +1128,10 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1123
1128
|
</devtools-adorner>` : nothing}
|
|
1124
1129
|
</div>`: nothing}
|
|
1125
1130
|
${input.isSelected ? html`
|
|
1126
|
-
<span class="selected-hint" title=${i18nString(UIStrings.useSInTheConsoleToReferToThis, { PH1: '$0' })} aria-hidden="true"></span>
|
|
1131
|
+
<span class="selected-hint ${input.editorState ? 'hidden' : ''}" title=${i18nString(UIStrings.useSInTheConsoleToReferToThis, { PH1: '$0' })} aria-hidden="true"></span>
|
|
1127
1132
|
` : nothing}
|
|
1128
1133
|
${input.showAiButton ? html`
|
|
1129
|
-
<span class="ai-button-container">
|
|
1134
|
+
<span class="ai-button-container ${input.editorState ? 'hidden' : ''}">
|
|
1130
1135
|
<devtools-floating-button
|
|
1131
1136
|
icon-name=${AIAssistance.AiUtils.getIconName()}
|
|
1132
1137
|
title=${input.aiButtonTitle || ''}
|
|
@@ -1136,6 +1141,15 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1136
1141
|
</devtools-floating-button>
|
|
1137
1142
|
</span>
|
|
1138
1143
|
` : nothing}
|
|
1144
|
+
${input.editorState ? html`<div @keydown=${(event: KeyboardEvent) => {
|
|
1145
|
+
if (event.key === 'Escape') {
|
|
1146
|
+
event.consume(true);
|
|
1147
|
+
}
|
|
1148
|
+
}} class="source-code elements-tree-editor" style="width: ${input.editorWidth ?? 0}px;">
|
|
1149
|
+
<devtools-text-editor .state=${input.editorState} ${ref(el => {
|
|
1150
|
+
output.editorRef = el as TextEditor.TextEditor.TextEditor;
|
|
1151
|
+
})}></devtools-text-editor>
|
|
1152
|
+
</div>`: nothing}
|
|
1139
1153
|
</div>
|
|
1140
1154
|
`, target);
|
|
1141
1155
|
// clang-format on
|
|
@@ -1151,7 +1165,9 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1151
1165
|
private inClipboard: boolean;
|
|
1152
1166
|
#hovered: boolean;
|
|
1153
1167
|
private editing: EditorHandles|null;
|
|
1154
|
-
|
|
1168
|
+
#editorRef?: TextEditor.TextEditor.TextEditor;
|
|
1169
|
+
#editorState: CodeMirror.EditorState|null = null;
|
|
1170
|
+
#editorWidth: number|null = null;
|
|
1155
1171
|
expandAllButtonElement: UI.TreeOutline.TreeElement|null;
|
|
1156
1172
|
#elementIssues = new Map<string, IssuesManager.Issue.Issue>();
|
|
1157
1173
|
#nodeElementToIssue = new Map<Element, IssuesManager.Issue.Issue[]>();
|
|
@@ -1288,9 +1304,6 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1288
1304
|
|
|
1289
1305
|
// ClearNode param is used to clean DOM after in-place editing..
|
|
1290
1306
|
performUpdate(clearNode = false): void {
|
|
1291
|
-
if (this.editing) {
|
|
1292
|
-
return;
|
|
1293
|
-
}
|
|
1294
1307
|
const output: ViewOutput = {};
|
|
1295
1308
|
DEFAULT_VIEW(
|
|
1296
1309
|
{
|
|
@@ -1380,10 +1393,13 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1380
1393
|
void action.execute();
|
|
1381
1394
|
}
|
|
1382
1395
|
},
|
|
1396
|
+
editorState: this.#editorState,
|
|
1397
|
+
editorWidth: this.#editorWidth,
|
|
1383
1398
|
},
|
|
1384
1399
|
output, this.listItemElement);
|
|
1385
1400
|
|
|
1386
1401
|
this.#contentElement = output.contentElement;
|
|
1402
|
+
this.#editorRef = output.editorRef;
|
|
1387
1403
|
if (this.#updateRecord) {
|
|
1388
1404
|
this.#updateRecord = null;
|
|
1389
1405
|
}
|
|
@@ -1683,10 +1699,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1683
1699
|
}
|
|
1684
1700
|
}
|
|
1685
1701
|
|
|
1686
|
-
|
|
1687
|
-
if (this.editing) {
|
|
1688
|
-
this.editing.cancel();
|
|
1689
|
-
}
|
|
1702
|
+
clearView(): void {
|
|
1690
1703
|
// Update the element to clean up adorner registrations with the
|
|
1691
1704
|
// ElementsPanel.
|
|
1692
1705
|
// We do not change the ElementsTreeElement state in case the
|
|
@@ -1744,9 +1757,17 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1744
1757
|
descendantDecorations: [],
|
|
1745
1758
|
decorationsTooltip: '',
|
|
1746
1759
|
indent: 0,
|
|
1760
|
+
editorState: null,
|
|
1761
|
+
editorWidth: null,
|
|
1747
1762
|
},
|
|
1748
1763
|
{}, this.listItemElement);
|
|
1764
|
+
}
|
|
1749
1765
|
|
|
1766
|
+
override onunbind(): void {
|
|
1767
|
+
if (this.editing) {
|
|
1768
|
+
this.editing.cancel();
|
|
1769
|
+
}
|
|
1770
|
+
this.clearView();
|
|
1750
1771
|
if (this.treeOutline && this.treeOutline.treeElementByNode.get(this.nodeInternal) === this) {
|
|
1751
1772
|
this.treeOutline.treeElementByNode.delete(this.nodeInternal);
|
|
1752
1773
|
}
|
|
@@ -2553,7 +2574,6 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2553
2574
|
this.editing = {
|
|
2554
2575
|
commit: editorHandles.commit,
|
|
2555
2576
|
cancel: editorHandles.cancel,
|
|
2556
|
-
editor: undefined,
|
|
2557
2577
|
resize: () => {},
|
|
2558
2578
|
};
|
|
2559
2579
|
}
|
|
@@ -2569,31 +2589,13 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2569
2589
|
return;
|
|
2570
2590
|
}
|
|
2571
2591
|
|
|
2572
|
-
const initialValue = convertUnicodeCharsToHTMLEntities(maybeInitialValue).text;
|
|
2573
|
-
this.htmlEditElement = document.createElement('div');
|
|
2574
|
-
this.htmlEditElement.className = 'source-code elements-tree-editor';
|
|
2575
|
-
|
|
2576
|
-
// Hide header items.
|
|
2577
|
-
let child: (ChildNode|null) = this.listItemElement.firstChild;
|
|
2578
|
-
while (child) {
|
|
2579
|
-
if (child instanceof HTMLElement) {
|
|
2580
|
-
child.style.display = 'none';
|
|
2581
|
-
}
|
|
2582
|
-
child = child.nextSibling;
|
|
2583
|
-
}
|
|
2584
2592
|
// Hide children item.
|
|
2585
2593
|
if (this.childrenListElement) {
|
|
2586
2594
|
this.childrenListElement.style.display = 'none';
|
|
2587
2595
|
}
|
|
2596
|
+
const initialValue = convertUnicodeCharsToHTMLEntities(maybeInitialValue).text;
|
|
2588
2597
|
// Append editor.
|
|
2589
|
-
this.
|
|
2590
|
-
this.htmlEditElement.addEventListener('keydown', event => {
|
|
2591
|
-
if (event.key === 'Escape') {
|
|
2592
|
-
event.consume(true);
|
|
2593
|
-
}
|
|
2594
|
-
});
|
|
2595
|
-
|
|
2596
|
-
const editor = new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({
|
|
2598
|
+
this.#editorState = CodeMirror.EditorState.create({
|
|
2597
2599
|
doc: initialValue,
|
|
2598
2600
|
extensions: [
|
|
2599
2601
|
CodeMirror.keymap.of([
|
|
@@ -2623,58 +2625,49 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2623
2625
|
}),
|
|
2624
2626
|
CodeMirror.EditorView.domEventHandlers({
|
|
2625
2627
|
focusout: event => {
|
|
2628
|
+
if (!this.#editorRef) {
|
|
2629
|
+
return;
|
|
2630
|
+
}
|
|
2626
2631
|
// The relatedTarget is null when no element gains focus, e.g. switching windows.
|
|
2627
2632
|
const relatedTarget = (event.relatedTarget as Node | null);
|
|
2628
|
-
if (relatedTarget && !relatedTarget.isSelfOrDescendant(
|
|
2633
|
+
if (relatedTarget && !relatedTarget.isSelfOrDescendant(this.#editorRef)) {
|
|
2629
2634
|
this.editing?.commit();
|
|
2630
2635
|
}
|
|
2631
2636
|
},
|
|
2632
2637
|
}),
|
|
2633
2638
|
],
|
|
2634
|
-
})
|
|
2635
|
-
this.
|
|
2639
|
+
});
|
|
2640
|
+
this.performUpdate();
|
|
2636
2641
|
resize.call(this);
|
|
2637
|
-
this
|
|
2638
|
-
|
|
2639
|
-
|
|
2642
|
+
this.#editorRef?.focus();
|
|
2643
|
+
this.editing = {commit: commit.bind(this), cancel: dispose.bind(this), resize: resize.bind(this)};
|
|
2640
2644
|
this.treeOutline?.setMultilineEditing(this.editing);
|
|
2641
2645
|
|
|
2642
2646
|
function resize(this: ElementsTreeElement): void {
|
|
2643
|
-
if (this.treeOutline
|
|
2644
|
-
this
|
|
2647
|
+
if (this.treeOutline) {
|
|
2648
|
+
this.#editorWidth = this.treeOutline.visibleWidth() - this.computeLeftIndent() - 30;
|
|
2649
|
+
this.performUpdate();
|
|
2645
2650
|
}
|
|
2646
2651
|
}
|
|
2647
2652
|
|
|
2648
2653
|
function commit(this: ElementsTreeElement): void {
|
|
2649
|
-
if (this
|
|
2650
|
-
commitCallback(initialValue, this.
|
|
2654
|
+
if (this.#editorRef) {
|
|
2655
|
+
commitCallback(initialValue, this.#editorRef.editor.state.doc.toString());
|
|
2651
2656
|
}
|
|
2652
2657
|
dispose.call(this);
|
|
2653
2658
|
}
|
|
2654
2659
|
|
|
2655
2660
|
function dispose(this: ElementsTreeElement): void {
|
|
2656
|
-
if (!this
|
|
2661
|
+
if (!this.#editorRef) {
|
|
2657
2662
|
return;
|
|
2658
2663
|
}
|
|
2659
2664
|
this.editing = null;
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
if (this.htmlEditElement) {
|
|
2663
|
-
this.listItemElement.removeChild(this.htmlEditElement);
|
|
2664
|
-
}
|
|
2665
|
-
this.htmlEditElement = undefined;
|
|
2665
|
+
this.#editorState = null;
|
|
2666
|
+
this.performUpdate();
|
|
2666
2667
|
// Unhide children item.
|
|
2667
2668
|
if (this.childrenListElement) {
|
|
2668
2669
|
this.childrenListElement.style.removeProperty('display');
|
|
2669
2670
|
}
|
|
2670
|
-
// Unhide header items.
|
|
2671
|
-
let child: (ChildNode|null) = this.listItemElement.firstChild;
|
|
2672
|
-
while (child) {
|
|
2673
|
-
if (child instanceof HTMLElement) {
|
|
2674
|
-
child.style.removeProperty('display');
|
|
2675
|
-
}
|
|
2676
|
-
child = child.nextSibling;
|
|
2677
|
-
}
|
|
2678
2671
|
|
|
2679
2672
|
if (this.treeOutline) {
|
|
2680
2673
|
this.treeOutline.setMultilineEditing(null);
|
|
@@ -3016,7 +3009,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
3016
3009
|
}
|
|
3017
3010
|
|
|
3018
3011
|
toggleEditAsHTML(callback?: ((arg0: boolean) => void), startEditing?: boolean): void {
|
|
3019
|
-
if (this.editing && this
|
|
3012
|
+
if (this.editing && this.#editorState) {
|
|
3020
3013
|
this.editing.commit();
|
|
3021
3014
|
return;
|
|
3022
3015
|
}
|
|
@@ -3222,7 +3215,6 @@ export function convertUnicodeCharsToHTMLEntities(text: string): {
|
|
|
3222
3215
|
export interface EditorHandles {
|
|
3223
3216
|
commit: () => void;
|
|
3224
3217
|
cancel: () => void;
|
|
3225
|
-
editor?: TextEditor.TextEditor.TextEditor;
|
|
3226
3218
|
resize: () => void;
|
|
3227
3219
|
}
|
|
3228
3220
|
|
|
@@ -103,7 +103,7 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
103
103
|
${input.objectTree && input.allChildrenFiltered ? html`
|
|
104
104
|
<div class="gray-info-message">${i18nString(UIStrings.noMatchingProperty)}</div>
|
|
105
105
|
` : nothing}
|
|
106
|
-
<devtools-tree @treeelementexpand=${onExpand} .template=${html`
|
|
106
|
+
<devtools-tree show-selection-on-keyboard-focus @treeelementexpand=${onExpand} .template=${html`
|
|
107
107
|
<ul role=tree class="source-code object-properties-section">
|
|
108
108
|
<style>${ObjectUI.ObjectPropertiesSection.objectValueStyles}</style>;
|
|
109
109
|
<style>${ObjectUI.ObjectPropertiesSection.objectPropertiesSectionStyles}</style>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Name: Dependencies sourced from the upstream `chromium` repository
|
|
2
2
|
URL: Internal
|
|
3
3
|
Version: N/A
|
|
4
|
-
Revision:
|
|
4
|
+
Revision: b1e55a8961dbd7de8febb16a1bd10f31de63c4c6
|
|
5
5
|
Update Mechanism: Manual (https://crbug.com/428069060)
|
|
6
6
|
License: BSD-3-Clause
|
|
7
7
|
License File: LICENSE
|
|
@@ -1752,7 +1752,8 @@ function removeNode(node: TreeElement, preserveParentExpandable = false): void {
|
|
|
1752
1752
|
* @attribute hide-overflow
|
|
1753
1753
|
*/
|
|
1754
1754
|
export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
1755
|
-
static readonly observedAttributes =
|
|
1755
|
+
static readonly observedAttributes =
|
|
1756
|
+
['navigation-variant', 'hide-overflow', 'dense', 'show-selection-on-keyboard-focus'];
|
|
1756
1757
|
readonly #treeOutline = new TreeOutlineInShadow(undefined, this);
|
|
1757
1758
|
|
|
1758
1759
|
constructor() {
|
|
@@ -1918,6 +1919,9 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
|
1918
1919
|
case 'dense':
|
|
1919
1920
|
this.#treeOutline.setDense(booleanValueIsTrue);
|
|
1920
1921
|
break;
|
|
1922
|
+
case 'show-selection-on-keyboard-focus':
|
|
1923
|
+
this.#treeOutline.setShowSelectionOnKeyboardFocus(booleanValueIsTrue);
|
|
1924
|
+
break;
|
|
1921
1925
|
}
|
|
1922
1926
|
}
|
|
1923
1927
|
}
|
|
@@ -3235,6 +3235,7 @@ export const knownContextValues = new Set([
|
|
|
3235
3235
|
'removed-size',
|
|
3236
3236
|
'rename',
|
|
3237
3237
|
'render-blocking',
|
|
3238
|
+
'render-blocking-widget',
|
|
3238
3239
|
'rendering',
|
|
3239
3240
|
'rendering-emulations',
|
|
3240
3241
|
'rendering.toggle-prefers-color-scheme',
|
|
@@ -4382,6 +4383,7 @@ export const knownContextValues = new Set([
|
|
|
4382
4383
|
'webgl-warning-fired',
|
|
4383
4384
|
'webmcp.call-inputs',
|
|
4384
4385
|
'webmcp.call-outputs',
|
|
4386
|
+
'webmcp.cancel-call',
|
|
4385
4387
|
'webmcp.canceled',
|
|
4386
4388
|
'webmcp.completed',
|
|
4387
4389
|
'webmcp.copy-tool-description',
|
package/package.json
CHANGED