chrome-devtools-frontend 1.0.1613465 → 1.0.1614363
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/.agents/skills/verification/SKILL.md +5 -1
- package/AUTHORS +1 -0
- package/front_end/core/common/VersionController.ts +17 -1
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/OverlayModel.ts +2 -4
- package/front_end/core/sdk/sdk-meta.ts +13 -0
- package/front_end/entrypoints/device_mode_emulation_frame/device_mode_emulation_frame.ts +4 -0
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -1
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -1
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/entrypoints/shell/shell.ts +4 -0
- package/front_end/entrypoints/trace_app/trace_app.ts +4 -0
- package/front_end/generated/InspectorBackendCommands.ts +2 -2
- package/front_end/generated/protocol.ts +5 -3
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +10 -2
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +23 -7
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +161 -36
- package/front_end/models/ai_assistance/agents/README.md +77 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +6 -4
- package/front_end/models/javascript_metadata/NativeFunctions.js +673 -639
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +142 -0
- package/front_end/models/stack_trace/StackTrace.ts +18 -0
- package/front_end/models/stack_trace/StackTraceImpl.ts +96 -4
- package/front_end/models/stack_trace/Trie.ts +21 -0
- package/front_end/models/stack_trace/stack_trace_impl.ts +2 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +13 -3
- package/front_end/panels/ai_assistance/components/ChatView.ts +4 -3
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +6 -2
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +4 -3
- package/front_end/panels/ai_assistance/components/optInChangeDialog.css +1 -2
- package/front_end/panels/application/WebMCPView.ts +249 -17
- package/front_end/panels/application/components/ProtocolHandlersView.ts +2 -2
- package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +7 -0
- package/front_end/panels/console/ConsoleContextSelector.ts +1 -1
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -3
- package/front_end/panels/css_overview/CSSOverviewModel.ts +1 -2
- package/front_end/panels/elements/StylesSidebarPane.ts +3 -1
- package/front_end/panels/emulation/DeviceModeToolbar.ts +13 -4
- package/front_end/panels/network/RequestConditionsDrawer.ts +4 -2
- package/front_end/panels/network/RequestPayloadView.ts +8 -3
- package/front_end/panels/network/RequestTimingView.ts +6 -7
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +7 -5
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +1 -1
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +9 -17
- package/front_end/panels/protocol_monitor/JSONEditor.ts +29 -3
- package/front_end/panels/settings/AISettingsTab.ts +14 -3
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror/codemirror-tsconfig.json +4 -4
- package/front_end/third_party/lighthouse/lighthouse-tsconfig.json +1 -1
- package/front_end/tsconfig.json +2 -1
- package/front_end/ui/legacy/EmptyWidget.ts +2 -2
- package/front_end/ui/legacy/TextPrompt.ts +1 -1
- package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +1 -2
- package/front_end/ui/legacy/components/color_picker/ContrastOverlay.ts +4 -5
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +12 -7
- package/front_end/ui/lit/lit.ts +4 -1
- package/front_end/ui/lit/render.ts +81 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +8 -1
- package/package.json +1 -1
- /package/front_end/third_party/codemirror/package/addon/runmode/{runmode-standalone.mjs.d.ts → runmode-standalone.d.mts} +0 -0
- /package/front_end/third_party/codemirror/package/mode/css/{css.mjs.d.ts → css.d.mts} +0 -0
- /package/front_end/third_party/codemirror/package/mode/javascript/{javascript.mjs.d.ts → javascript.d.mts} +0 -0
- /package/front_end/third_party/codemirror/package/mode/xml/{xml.mjs.d.ts → xml.d.mts} +0 -0
- /package/front_end/third_party/lighthouse/report-assets/{report-generator.mjs.d.ts → report-generator.d.mts} +0 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as Common from '../../core/common/common.js';
|
|
6
|
+
import type * as Platform from '../../core/platform/platform.js';
|
|
7
|
+
|
|
8
|
+
import type {RawFrame} from './Trie.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Takes a V8 Error#stack string and extracts structured information.
|
|
12
|
+
*/
|
|
13
|
+
export function parseRawFramesFromErrorStack(stack: string): RawFrame[] {
|
|
14
|
+
const lines = stack.split('\n');
|
|
15
|
+
const rawFrames: RawFrame[] = [];
|
|
16
|
+
for (const line of lines) {
|
|
17
|
+
const match = /^\s*at\s+(.*)/.exec(line);
|
|
18
|
+
if (!match) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let lineContent = match[1];
|
|
23
|
+
let isAsync = false;
|
|
24
|
+
if (lineContent.startsWith('async ')) {
|
|
25
|
+
isAsync = true;
|
|
26
|
+
lineContent = lineContent.substring(6);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let isConstructor = false;
|
|
30
|
+
if (lineContent.startsWith('new ')) {
|
|
31
|
+
isConstructor = true;
|
|
32
|
+
lineContent = lineContent.substring(4);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let functionName = '';
|
|
36
|
+
let url = '';
|
|
37
|
+
let lineNumber = -1;
|
|
38
|
+
let columnNumber = -1;
|
|
39
|
+
let typeName: string|undefined;
|
|
40
|
+
let methodName: string|undefined;
|
|
41
|
+
let isEval = false;
|
|
42
|
+
let isWasm = false;
|
|
43
|
+
let wasmModuleName: string|undefined;
|
|
44
|
+
let wasmFunctionIndex: number|undefined;
|
|
45
|
+
let promiseIndex: number|undefined;
|
|
46
|
+
let evalOrigin: RawFrame|undefined;
|
|
47
|
+
|
|
48
|
+
const openParenIndex = lineContent.indexOf(' (');
|
|
49
|
+
if (lineContent.endsWith(')') && openParenIndex !== -1) {
|
|
50
|
+
functionName = lineContent.substring(0, openParenIndex).trim();
|
|
51
|
+
let location = lineContent.substring(openParenIndex + 2, lineContent.length - 1);
|
|
52
|
+
|
|
53
|
+
if (location.startsWith('eval at ')) {
|
|
54
|
+
isEval = true;
|
|
55
|
+
const commaIndex = location.lastIndexOf(', ');
|
|
56
|
+
let evalOriginStr = location;
|
|
57
|
+
if (commaIndex !== -1) {
|
|
58
|
+
evalOriginStr = location.substring(0, commaIndex);
|
|
59
|
+
location = location.substring(commaIndex + 2);
|
|
60
|
+
} else {
|
|
61
|
+
location = '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (evalOriginStr.startsWith('eval at ')) {
|
|
65
|
+
evalOriginStr = evalOriginStr.substring(8);
|
|
66
|
+
}
|
|
67
|
+
const innerOpenParen = evalOriginStr.indexOf(' (');
|
|
68
|
+
let evalFunctionName = evalOriginStr;
|
|
69
|
+
let evalLocation = '';
|
|
70
|
+
if (innerOpenParen !== -1) {
|
|
71
|
+
evalFunctionName = evalOriginStr.substring(0, innerOpenParen).trim();
|
|
72
|
+
evalLocation = evalOriginStr.substring(innerOpenParen + 2, evalOriginStr.length - 1);
|
|
73
|
+
evalOrigin = parseRawFramesFromErrorStack(` at ${evalFunctionName} (${evalLocation})`)[0];
|
|
74
|
+
} else {
|
|
75
|
+
evalOrigin = parseRawFramesFromErrorStack(` at ${evalFunctionName}`)[0];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (location.startsWith('index ')) {
|
|
80
|
+
promiseIndex = parseInt(location.substring(6), 10);
|
|
81
|
+
url = '';
|
|
82
|
+
} else if (location.includes(':wasm-function[')) {
|
|
83
|
+
isWasm = true;
|
|
84
|
+
const wasmMatch = /^(.*):wasm-function\[(\d+)\]:(0x[0-9a-fA-F]+)$/.exec(location);
|
|
85
|
+
if (wasmMatch) {
|
|
86
|
+
url = wasmMatch[1];
|
|
87
|
+
wasmFunctionIndex = parseInt(wasmMatch[2], 10);
|
|
88
|
+
columnNumber = parseInt(wasmMatch[3], 16);
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
const splitResult = Common.ParsedURL.ParsedURL.splitLineAndColumn(location);
|
|
92
|
+
url = splitResult.url;
|
|
93
|
+
lineNumber = splitResult.lineNumber ?? -1;
|
|
94
|
+
columnNumber = splitResult.columnNumber ?? -1;
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
const splitResult = Common.ParsedURL.ParsedURL.splitLineAndColumn(lineContent);
|
|
98
|
+
url = splitResult.url;
|
|
99
|
+
lineNumber = splitResult.lineNumber ?? -1;
|
|
100
|
+
columnNumber = splitResult.columnNumber ?? -1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Handle "typeName.methodName [as alias]"
|
|
104
|
+
if (functionName) {
|
|
105
|
+
const aliasMatch = /(.*)\s+\[as\s+(.*)\]/.exec(functionName);
|
|
106
|
+
if (aliasMatch) {
|
|
107
|
+
methodName = aliasMatch[2];
|
|
108
|
+
functionName = aliasMatch[1];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const dotIndex = functionName.indexOf('.');
|
|
112
|
+
if (dotIndex !== -1) {
|
|
113
|
+
typeName = functionName.substring(0, dotIndex);
|
|
114
|
+
methodName = methodName ?? functionName.substring(dotIndex + 1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (isWasm && typeName) {
|
|
118
|
+
wasmModuleName = typeName;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
rawFrames.push({
|
|
123
|
+
url: url as Platform.DevToolsPath.UrlString,
|
|
124
|
+
functionName,
|
|
125
|
+
lineNumber,
|
|
126
|
+
columnNumber,
|
|
127
|
+
parsedFrameInfo: {
|
|
128
|
+
isAsync,
|
|
129
|
+
isConstructor,
|
|
130
|
+
isEval,
|
|
131
|
+
evalOrigin,
|
|
132
|
+
isWasm,
|
|
133
|
+
wasmModuleName,
|
|
134
|
+
wasmFunctionIndex,
|
|
135
|
+
typeName,
|
|
136
|
+
methodName,
|
|
137
|
+
promiseIndex,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return rawFrames;
|
|
142
|
+
}
|
|
@@ -8,6 +8,7 @@ import type * as Workspace from '../workspace/workspace.js';
|
|
|
8
8
|
|
|
9
9
|
export type StackTrace = BaseStackTrace<Fragment>;
|
|
10
10
|
export type DebuggableStackTrace = BaseStackTrace<DebuggableFragment>;
|
|
11
|
+
export type ParsedErrorStackTrace = BaseStackTrace<ParsedErrorStackFragment>;
|
|
11
12
|
|
|
12
13
|
export interface BaseStackTrace<SyncFragmentT extends Fragment> extends Common.EventTarget.EventTarget<EventTypes> {
|
|
13
14
|
readonly syncFragment: SyncFragmentT;
|
|
@@ -26,6 +27,10 @@ export interface DebuggableFragment {
|
|
|
26
27
|
readonly frames: readonly DebuggableFrame[];
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
export interface ParsedErrorStackFragment {
|
|
31
|
+
readonly frames: readonly ParsedErrorStackFrame[];
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
export interface Frame {
|
|
30
35
|
readonly url?: string;
|
|
31
36
|
readonly uiSourceCode?: Workspace.UISourceCode.UISourceCode;
|
|
@@ -41,6 +46,19 @@ export interface Frame {
|
|
|
41
46
|
readonly rawName?: string;
|
|
42
47
|
}
|
|
43
48
|
|
|
49
|
+
export interface ParsedErrorStackFrame extends Frame {
|
|
50
|
+
readonly isAsync?: boolean;
|
|
51
|
+
readonly isConstructor?: boolean;
|
|
52
|
+
readonly isEval?: boolean;
|
|
53
|
+
readonly evalOrigin?: ParsedErrorStackFrame;
|
|
54
|
+
readonly isWasm?: boolean;
|
|
55
|
+
readonly wasmModuleName?: string;
|
|
56
|
+
readonly wasmFunctionIndex?: number;
|
|
57
|
+
readonly typeName?: string;
|
|
58
|
+
readonly methodName?: string;
|
|
59
|
+
readonly promiseIndex?: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
44
62
|
export interface DebuggableFrame extends Frame {
|
|
45
63
|
readonly sdkFrame: SDK.DebuggerModel.CallFrame;
|
|
46
64
|
}
|
|
@@ -7,11 +7,12 @@ import type * as SDK from '../../core/sdk/sdk.js';
|
|
|
7
7
|
import type * as Workspace from '../workspace/workspace.js';
|
|
8
8
|
|
|
9
9
|
import type * as StackTrace from './stack_trace.js';
|
|
10
|
-
import type {FrameNode} from './Trie.js';
|
|
10
|
+
import type {FrameNode, ParsedFrameInfo} from './Trie.js';
|
|
11
11
|
|
|
12
|
-
export type AnyStackTraceImpl = StackTraceImpl<FragmentImpl|DebuggableFragmentImpl>;
|
|
12
|
+
export type AnyStackTraceImpl = StackTraceImpl<FragmentImpl|DebuggableFragmentImpl|ParsedErrorStackFragmentImpl>;
|
|
13
13
|
|
|
14
|
-
export class StackTraceImpl<SyncFragmentT extends FragmentImpl|DebuggableFragmentImpl =
|
|
14
|
+
export class StackTraceImpl<SyncFragmentT extends FragmentImpl|DebuggableFragmentImpl|ParsedErrorStackFragmentImpl =
|
|
15
|
+
FragmentImpl> extends
|
|
15
16
|
Common.ObjectWrapper.ObjectWrapper<StackTrace.StackTrace.EventTypes> implements
|
|
16
17
|
StackTrace.StackTrace.BaseStackTrace<SyncFragmentT> {
|
|
17
18
|
readonly syncFragment: SyncFragmentT;
|
|
@@ -23,7 +24,9 @@ export class StackTraceImpl<SyncFragmentT extends FragmentImpl|DebuggableFragmen
|
|
|
23
24
|
this.asyncFragments = asyncFragments;
|
|
24
25
|
|
|
25
26
|
const fragment =
|
|
26
|
-
syncFragment instanceof DebuggableFragmentImpl
|
|
27
|
+
(syncFragment instanceof DebuggableFragmentImpl || syncFragment instanceof ParsedErrorStackFragmentImpl) ?
|
|
28
|
+
syncFragment.fragment :
|
|
29
|
+
syncFragment as FragmentImpl;
|
|
27
30
|
fragment.stackTraces.add(this);
|
|
28
31
|
|
|
29
32
|
this.asyncFragments.forEach(asyncFragment => asyncFragment.fragment.stackTraces.add(this));
|
|
@@ -99,6 +102,95 @@ export class FrameImpl implements StackTrace.StackTrace.Frame {
|
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
export class ParsedErrorStackFragmentImpl implements StackTrace.StackTrace.ParsedErrorStackFragment {
|
|
106
|
+
constructor(readonly fragment: FragmentImpl) {
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get frames(): ParsedErrorStackFrameImpl[] {
|
|
110
|
+
if (!this.fragment.node) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const frames: ParsedErrorStackFrameImpl[] = [];
|
|
115
|
+
|
|
116
|
+
for (const node of this.fragment.node.getCallStack()) {
|
|
117
|
+
for (const frame of node.frames) {
|
|
118
|
+
frames.push(new ParsedErrorStackFrameImpl(frame, node.parsedFrameInfo, node.evalOriginFrames));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return frames;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export class ParsedErrorStackFrameImpl implements StackTrace.StackTrace.ParsedErrorStackFrame {
|
|
127
|
+
readonly #frame: FrameImpl;
|
|
128
|
+
readonly #parsedFrameInfo?: ParsedFrameInfo;
|
|
129
|
+
readonly #evalOriginFrames?: FrameImpl[];
|
|
130
|
+
|
|
131
|
+
constructor(frame: FrameImpl, parsedFrameInfo?: ParsedFrameInfo, evalOriginFrames?: FrameImpl[]) {
|
|
132
|
+
this.#frame = frame;
|
|
133
|
+
this.#parsedFrameInfo = parsedFrameInfo;
|
|
134
|
+
this.#evalOriginFrames = evalOriginFrames;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
get url(): string|undefined {
|
|
138
|
+
return this.#frame.url;
|
|
139
|
+
}
|
|
140
|
+
get uiSourceCode(): Workspace.UISourceCode.UISourceCode|undefined {
|
|
141
|
+
return this.#frame.uiSourceCode;
|
|
142
|
+
}
|
|
143
|
+
get name(): string|undefined {
|
|
144
|
+
return this.#frame.name;
|
|
145
|
+
}
|
|
146
|
+
get line(): number {
|
|
147
|
+
return this.#frame.line;
|
|
148
|
+
}
|
|
149
|
+
get column(): number {
|
|
150
|
+
return this.#frame.column;
|
|
151
|
+
}
|
|
152
|
+
get missingDebugInfo(): StackTrace.StackTrace.MissingDebugInfo|undefined {
|
|
153
|
+
return this.#frame.missingDebugInfo;
|
|
154
|
+
}
|
|
155
|
+
get rawName(): string|undefined {
|
|
156
|
+
return this.#frame.rawName;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get isAsync(): boolean|undefined {
|
|
160
|
+
return this.#parsedFrameInfo?.isAsync;
|
|
161
|
+
}
|
|
162
|
+
get isConstructor(): boolean|undefined {
|
|
163
|
+
return this.#parsedFrameInfo?.isConstructor;
|
|
164
|
+
}
|
|
165
|
+
get isEval(): boolean|undefined {
|
|
166
|
+
return this.#parsedFrameInfo?.isEval;
|
|
167
|
+
}
|
|
168
|
+
get evalOrigin(): ParsedErrorStackFrameImpl|undefined {
|
|
169
|
+
if (!this.#evalOriginFrames || this.#evalOriginFrames.length === 0) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
return new ParsedErrorStackFrameImpl(this.#evalOriginFrames[0], this.#parsedFrameInfo?.evalOrigin?.parsedFrameInfo);
|
|
173
|
+
}
|
|
174
|
+
get isWasm(): boolean|undefined {
|
|
175
|
+
return this.#parsedFrameInfo?.isWasm;
|
|
176
|
+
}
|
|
177
|
+
get wasmModuleName(): string|undefined {
|
|
178
|
+
return this.#parsedFrameInfo?.wasmModuleName;
|
|
179
|
+
}
|
|
180
|
+
get wasmFunctionIndex(): number|undefined {
|
|
181
|
+
return this.#parsedFrameInfo?.wasmFunctionIndex;
|
|
182
|
+
}
|
|
183
|
+
get typeName(): string|undefined {
|
|
184
|
+
return this.#parsedFrameInfo?.typeName;
|
|
185
|
+
}
|
|
186
|
+
get methodName(): string|undefined {
|
|
187
|
+
return this.#parsedFrameInfo?.methodName;
|
|
188
|
+
}
|
|
189
|
+
get promiseIndex(): number|undefined {
|
|
190
|
+
return this.#parsedFrameInfo?.promiseIndex;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
102
194
|
/**
|
|
103
195
|
* A DebuggableFragmentImpl wraps an existing FragmentImpl. This is important: We can pause at the
|
|
104
196
|
* same location multiple times and the paused information changes each and everytime while the underlying
|
|
@@ -6,6 +6,19 @@ import type * as Protocol from '../../generated/protocol.js';
|
|
|
6
6
|
|
|
7
7
|
import type {FragmentImpl, FrameImpl} from './StackTraceImpl.js';
|
|
8
8
|
|
|
9
|
+
export interface ParsedFrameInfo {
|
|
10
|
+
readonly isAsync?: boolean;
|
|
11
|
+
readonly isConstructor?: boolean;
|
|
12
|
+
readonly isEval?: boolean;
|
|
13
|
+
readonly evalOrigin?: RawFrame;
|
|
14
|
+
readonly isWasm?: boolean;
|
|
15
|
+
readonly wasmModuleName?: string;
|
|
16
|
+
readonly wasmFunctionIndex?: number;
|
|
17
|
+
readonly typeName?: string;
|
|
18
|
+
readonly methodName?: string;
|
|
19
|
+
readonly promiseIndex?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
/**
|
|
10
23
|
* Intentionally very close to a {@link Protocol.Runtime.CallFrame} but with optional `scriptId`.
|
|
11
24
|
*/
|
|
@@ -15,6 +28,8 @@ export interface RawFrame {
|
|
|
15
28
|
readonly functionName?: string;
|
|
16
29
|
readonly lineNumber: number;
|
|
17
30
|
readonly columnNumber: number;
|
|
31
|
+
|
|
32
|
+
readonly parsedFrameInfo?: ParsedFrameInfo;
|
|
18
33
|
}
|
|
19
34
|
|
|
20
35
|
/**
|
|
@@ -42,10 +57,13 @@ export class FrameNode implements FrameNodeBase<FrameNode, AnyFrameNode> {
|
|
|
42
57
|
frames: FrameImpl[] = [];
|
|
43
58
|
|
|
44
59
|
fragment?: FragmentImpl;
|
|
60
|
+
parsedFrameInfo?: ParsedFrameInfo;
|
|
61
|
+
evalOriginFrames?: FrameImpl[];
|
|
45
62
|
|
|
46
63
|
constructor(rawFrame: RawFrame, parent: AnyFrameNode) {
|
|
47
64
|
this.rawFrame = rawFrame;
|
|
48
65
|
this.parent = parent;
|
|
66
|
+
this.parsedFrameInfo = rawFrame.parsedFrameInfo;
|
|
49
67
|
}
|
|
50
68
|
|
|
51
69
|
/**
|
|
@@ -98,6 +116,9 @@ export class Trie {
|
|
|
98
116
|
|
|
99
117
|
const compareResult = compareRawFrames(child.rawFrame, rawFrame);
|
|
100
118
|
if (compareResult === 0) {
|
|
119
|
+
if (rawFrame.parsedFrameInfo && !child.parsedFrameInfo) {
|
|
120
|
+
child.parsedFrameInfo = rawFrame.parsedFrameInfo;
|
|
121
|
+
}
|
|
101
122
|
return child;
|
|
102
123
|
}
|
|
103
124
|
if (compareResult > 0) {
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
+
import * as DetailedErrorStackParser from './DetailedErrorStackParser.js';
|
|
5
6
|
import * as StackTraceImpl from './StackTraceImpl.js';
|
|
6
7
|
import * as StackTraceModel from './StackTraceModel.js';
|
|
7
8
|
import * as Trie from './Trie.js';
|
|
8
9
|
|
|
9
10
|
export {
|
|
11
|
+
DetailedErrorStackParser,
|
|
10
12
|
StackTraceImpl,
|
|
11
13
|
StackTraceModel,
|
|
12
14
|
Trie,
|
|
@@ -729,7 +729,7 @@ export function renderStep({step, isLoading, markdownRenderer, isLast}: {
|
|
|
729
729
|
// clang-format off
|
|
730
730
|
return html`
|
|
731
731
|
<details class=${stepClasses}
|
|
732
|
-
jslog=${VisualLogging.
|
|
732
|
+
jslog=${VisualLogging.expand('step').track({click: true})}
|
|
733
733
|
.open=${Boolean(step.requestApproval)}>
|
|
734
734
|
<summary>
|
|
735
735
|
<div class="summary">
|
|
@@ -755,6 +755,7 @@ interface WidgetMakerResponse {
|
|
|
755
755
|
customRevealTitle?: Platform.UIString.LocalizedString;
|
|
756
756
|
// Can be null if the widget is only used to add the Reveal CTA.
|
|
757
757
|
title: Lit.LitTemplate|Platform.UIString.LocalizedString|null;
|
|
758
|
+
jslogContext?: string;
|
|
758
759
|
}
|
|
759
760
|
|
|
760
761
|
const nodeCache = new Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode>();
|
|
@@ -823,6 +824,7 @@ async function makeComputedStyleWidget(widgetData: ComputedStyleAiWidget): Promi
|
|
|
823
824
|
</span>
|
|
824
825
|
</span>`,
|
|
825
826
|
// clang-format on
|
|
827
|
+
jslogContext: 'computed-styles',
|
|
826
828
|
};
|
|
827
829
|
}
|
|
828
830
|
|
|
@@ -836,6 +838,7 @@ async function makeCoreWebVitalsWidget(widgetData: CoreVitalsAiWidget): Promise<
|
|
|
836
838
|
renderedWidget,
|
|
837
839
|
revealable: new TimelineUtils.Helpers.RevealableCoreVitals(widgetData.data.insightSetKey),
|
|
838
840
|
title: lockedString(UIStringsNotTranslate.coreVitals),
|
|
841
|
+
jslogContext: 'core-web-vitals',
|
|
839
842
|
};
|
|
840
843
|
}
|
|
841
844
|
|
|
@@ -872,6 +875,7 @@ async function makeStylePropertiesWidget(widgetData: StylePropertiesAiWidget): P
|
|
|
872
875
|
node: domNodeForId,
|
|
873
876
|
})}
|
|
874
877
|
></devtools-widget>`,
|
|
878
|
+
jslogContext: 'standalone-styles',
|
|
875
879
|
};
|
|
876
880
|
}
|
|
877
881
|
|
|
@@ -894,6 +898,7 @@ async function makeLcpBreakdownWidget(widgetData: LcpBreakdownAiWidget): Promise
|
|
|
894
898
|
renderedWidget,
|
|
895
899
|
revealable: new TimelineUtils.Helpers.RevealableInsight(insight),
|
|
896
900
|
title: lockedString(UIStringsNotTranslate.lcpBreakdown),
|
|
901
|
+
jslogContext: 'lcp-breakdown',
|
|
897
902
|
};
|
|
898
903
|
}
|
|
899
904
|
|
|
@@ -922,7 +927,8 @@ async function makeBottomUpTimelineTreeWidget(widgetData: BottomUpTreeAiWidget):
|
|
|
922
927
|
return {
|
|
923
928
|
renderedWidget,
|
|
924
929
|
revealable: new TimelineUtils.Helpers.RevealableBottomUpProfile(widgetData.data.bounds),
|
|
925
|
-
title: lockedString(UIStringsNotTranslate.bottomUpTree)
|
|
930
|
+
title: lockedString(UIStringsNotTranslate.bottomUpTree),
|
|
931
|
+
jslogContext: 'bottom-up',
|
|
926
932
|
};
|
|
927
933
|
}
|
|
928
934
|
|
|
@@ -947,6 +953,7 @@ function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTempla
|
|
|
947
953
|
<devtools-button class="widget-reveal-button"
|
|
948
954
|
.variant=${Buttons.Button.Variant.TEXT}
|
|
949
955
|
.accessibleLabel=${lockedString(UIStringsNotTranslate.reveal)}
|
|
956
|
+
.jslogContext=${'reveal'}
|
|
950
957
|
@click=${onReveal}
|
|
951
958
|
>
|
|
952
959
|
${response.customRevealTitle ?? lockedString(UIStringsNotTranslate.reveal)}
|
|
@@ -956,7 +963,7 @@ function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTempla
|
|
|
956
963
|
|
|
957
964
|
// clang-format off
|
|
958
965
|
return html`
|
|
959
|
-
<div class=${classes}>
|
|
966
|
+
<div class=${classes} jslog=${ifDefined(response.jslogContext ? VisualLogging.section(response.jslogContext) : undefined)}>
|
|
960
967
|
${response.title ? html`
|
|
961
968
|
<div class="widget-header">
|
|
962
969
|
<h3 class="widget-name">${response.title}</h3>
|
|
@@ -986,6 +993,7 @@ async function makePerformanceTraceWidget(widgetData: PerformanceTraceAiWidget):
|
|
|
986
993
|
title: null,
|
|
987
994
|
revealable: new Timeline.TimelinePanel.ParsedTraceRevealable(widgetData.data.parsedTrace),
|
|
988
995
|
customRevealTitle: lockedString(UIStringsNotTranslate.revealTrace),
|
|
996
|
+
jslogContext: 'performance-trace',
|
|
989
997
|
};
|
|
990
998
|
}
|
|
991
999
|
|
|
@@ -1045,6 +1053,7 @@ async function makeDomTreeWidget(widgetData: DomTreeAiWidget): Promise<WidgetMak
|
|
|
1045
1053
|
renderedWidget,
|
|
1046
1054
|
revealable: new SDK.DOMModel.DeferredDOMNode(root.domModel().target(), root.backendNodeId()),
|
|
1047
1055
|
title: lockedString(UIStringsNotTranslate.lcpElement),
|
|
1056
|
+
jslogContext: 'dom-snapshot',
|
|
1048
1057
|
};
|
|
1049
1058
|
}
|
|
1050
1059
|
|
|
@@ -1607,5 +1616,6 @@ async function makeTimelineRangeSummaryWidget(widgetData: TimelineRangeSummaryAi
|
|
|
1607
1616
|
renderedWidget: template,
|
|
1608
1617
|
revealable: new TimelineUtils.Helpers.RevealableTimeRange(bounds),
|
|
1609
1618
|
title: lockedString(UIStringsNotTranslate.performanceSummary),
|
|
1619
|
+
jslogContext: 'timeline-range-summary',
|
|
1610
1620
|
};
|
|
1611
1621
|
}
|
|
@@ -96,7 +96,7 @@ export interface Props {
|
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
interface ChatWidgetInput extends Props {
|
|
99
|
+
export interface ChatWidgetInput extends Props {
|
|
100
100
|
handleScroll: (ev: Event) => void;
|
|
101
101
|
handleSuggestionClick: (title: string) => void;
|
|
102
102
|
handleMessageContainerRef: (el: Element|undefined) => void;
|
|
@@ -367,12 +367,13 @@ export class ChatView extends HTMLElement {
|
|
|
367
367
|
};
|
|
368
368
|
|
|
369
369
|
async #getSummary(): Promise<string> {
|
|
370
|
-
|
|
370
|
+
const cacheKey = this.#props.conversationMarkdown.replace(/\*\*Export Timestamp \(UTC\):\*\* .*\n\n/, '');
|
|
371
|
+
if (this.#cachedSummary?.markdown === cacheKey) {
|
|
371
372
|
return this.#cachedSummary.summary;
|
|
372
373
|
}
|
|
373
374
|
try {
|
|
374
375
|
const summary = await this.#props.generateConversationSummary(this.#props.conversationMarkdown);
|
|
375
|
-
this.#cachedSummary = {markdown:
|
|
376
|
+
this.#cachedSummary = {markdown: cacheKey, summary};
|
|
376
377
|
return summary;
|
|
377
378
|
} catch (err) {
|
|
378
379
|
console.error(err);
|
|
@@ -10,6 +10,7 @@ import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
|
|
10
10
|
import * as Snackbars from '../../../ui/components/snackbars/snackbars.js';
|
|
11
11
|
import * as UI from '../../../ui/legacy/legacy.js';
|
|
12
12
|
import * as Lit from '../../../ui/lit/lit.js';
|
|
13
|
+
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
13
14
|
|
|
14
15
|
import styles from './exportForAgentsDialog.css.js';
|
|
15
16
|
|
|
@@ -85,7 +86,7 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
|
85
86
|
|
|
86
87
|
render(html`
|
|
87
88
|
<style>${styles}</style>
|
|
88
|
-
<div class="export-for-agents-dialog">
|
|
89
|
+
<div class="export-for-agents-dialog" jslog=${VisualLogging.dialog('ai-export-for-agents')}>
|
|
89
90
|
<header>
|
|
90
91
|
<h1 id="export-for-agents-dialog-title" tabindex="-1">
|
|
91
92
|
${i18nString(UIStrings.exportForAgents)}
|
|
@@ -122,7 +123,10 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
|
122
123
|
${i18nString(UIStrings.generatingSummary)}
|
|
123
124
|
</span>
|
|
124
125
|
` : Lit.nothing}
|
|
125
|
-
|
|
126
|
+
${isPrompt ?
|
|
127
|
+
html`<textarea class="prompt" readonly .value=${input.state.isPromptLoading ? '' : exportText}></textarea>` :
|
|
128
|
+
html`<textarea class="conversation" readonly .value=${exportText}></textarea>`
|
|
129
|
+
}
|
|
126
130
|
</main>
|
|
127
131
|
<div class="disclaimer">${i18nString(UIStrings.disclaimer)}</div>
|
|
128
132
|
<footer>
|
|
@@ -9,6 +9,7 @@ import * as Input from '../../../ui/components/input/input.js';
|
|
|
9
9
|
import type {MarkdownLitRenderer} from '../../../ui/components/markdown_view/MarkdownView.js';
|
|
10
10
|
import * as UI from '../../../ui/legacy/legacy.js';
|
|
11
11
|
import * as Lit from '../../../ui/lit/lit.js';
|
|
12
|
+
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
12
13
|
|
|
13
14
|
import chatMessageStyles from './chatMessage.css.js';
|
|
14
15
|
import {type ModelChatMessage, renderStep, type Step, titleForStep} from './ChatMessage.js';
|
|
@@ -119,14 +120,14 @@ function renderInlineWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate,
|
|
|
119
120
|
|
|
120
121
|
// clang-format off
|
|
121
122
|
return html`
|
|
122
|
-
<div class="inline-wrapper" ?data-open=${input.isExpanded}>
|
|
123
|
+
<div class="inline-wrapper" ?data-open=${input.isExpanded} jslog=${VisualLogging.section('walkthrough-container')}>
|
|
123
124
|
<span class="inline-icon">
|
|
124
125
|
${input.isLoading ?
|
|
125
126
|
html`<devtools-spinner aria-label=${lockedString(UIStrings.inProgress)}></devtools-spinner>` :
|
|
126
127
|
html`<devtools-icon name=${icon}></devtools-icon>`
|
|
127
128
|
}
|
|
128
129
|
</span>
|
|
129
|
-
<details class="walkthrough-inline" ?open=${input.isExpanded} @toggle=${onToggle}>
|
|
130
|
+
<details class="walkthrough-inline" ?open=${input.isExpanded} @toggle=${onToggle} jslog=${VisualLogging.expand('walkthrough').track({click: true})}>
|
|
130
131
|
<summary ?data-has-widgets=${!input.isLoading && hasWidgets}>
|
|
131
132
|
<span class="walkthrough-inline-title">
|
|
132
133
|
${input.isExpanded ?
|
|
@@ -151,7 +152,7 @@ function renderSidebarWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate
|
|
|
151
152
|
|
|
152
153
|
// clang-format off
|
|
153
154
|
return html`
|
|
154
|
-
<div class="walkthrough-view">
|
|
155
|
+
<div class="walkthrough-view" jslog=${VisualLogging.section('walkthrough-container')}>
|
|
155
156
|
<div class="walkthrough-header">
|
|
156
157
|
<h2 class="walkthrough-title">${i18nString(UIStrings.title)}</h2>
|
|
157
158
|
<devtools-button
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
gap: var(--sys-size-8);
|
|
26
26
|
margin-bottom: var(--sys-size-8);
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
h1 {
|
|
29
29
|
margin: 0;
|
|
30
30
|
color: var(--sys-color-on-surface);
|
|
31
31
|
font: var(--sys-typescale-headline5);
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
devtools-icon {
|
|
48
48
|
width: var(--sys-size-9);
|
|
49
49
|
height: var(--sys-size-9);
|
|
50
|
-
color: var(--sys-color-on-primary);
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
52
|
}
|