chrome-devtools-frontend 1.0.1706026 → 1.0.1708524
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/code-review/SKILL.md +121 -0
- package/front_end/core/sdk/DOMModel.ts +13 -6
- package/front_end/core/sdk/NetworkRequest.ts +43 -7
- package/front_end/core/sdk/SourceMap.ts +4 -13
- package/front_end/core/sdk/SourceMapScopesInfo.ts +134 -86
- package/front_end/core/text_utils/ContentData.ts +18 -1
- package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +102 -4
- package/front_end/generated/InspectorBackendCommands.ts +7 -1
- package/front_end/generated/SupportedCSSProperties.ts +11 -2
- package/front_end/generated/protocol-mapping.d.ts +31 -0
- package/front_end/generated/protocol-proxy-api.d.ts +32 -0
- package/front_end/generated/protocol.ts +11 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +1 -0
- package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.ts +26 -3
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +15 -16
- package/front_end/models/ai_assistance/skills/Skill.ts +1 -2
- package/front_end/models/ai_assistance/skills/SkillRegistry.ts +2 -0
- package/front_end/models/ai_assistance/skills/lighthouse.md +33 -0
- package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +6 -6
- package/front_end/models/ai_assistance/tools/RunLighthouse.ts +8 -5
- package/front_end/models/bindings/CompilerScriptMapping.ts +102 -45
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +25 -33
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +33 -39
- package/front_end/models/bindings/StylesSourceMapping.ts +3 -0
- package/front_end/models/extensions/ExtensionEndpoint.ts +27 -6
- package/front_end/models/extensions/LanguageExtensionEndpoint.ts +106 -21
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +4 -2
- package/front_end/models/javascript_metadata/NativeFunctions.ts +6 -2
- package/front_end/models/persistence/NetworkPersistenceManager.ts +4 -3
- package/front_end/models/source_map_scopes/NamesResolver.ts +0 -8
- package/front_end/models/stack_trace/StackTraceImpl.ts +138 -47
- package/front_end/models/stack_trace/StackTraceModel.ts +117 -84
- package/front_end/models/stack_trace/Trie.ts +27 -0
- package/front_end/panels/accessibility/ARIAAttributesView.ts +6 -6
- package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +2 -2
- package/front_end/panels/accessibility/AccessibilityNodeView.ts +6 -9
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +83 -69
- package/front_end/panels/accessibility/AccessibilitySubPane.ts +24 -9
- package/front_end/panels/accessibility/SourceOrderView.ts +7 -3
- package/front_end/panels/accessibility/accessibilitySidebarView.css +5 -3
- package/front_end/panels/application/serviceWorkersView.css +1 -1
- package/front_end/panels/common/CommentThreadWidget.ts +30 -1
- package/front_end/panels/common/CommentsOverlayWidget.ts +42 -38
- package/front_end/panels/common/common-meta.ts +21 -9
- package/front_end/panels/console/ConsoleInsightTeaser.ts +25 -19
- package/front_end/panels/console/ConsoleViewMessage.ts +51 -21
- package/front_end/panels/console/console-meta.ts +1 -5
- package/front_end/panels/elements/DOMTreeWidget.ts +207 -586
- package/front_end/panels/elements/ElementsPanel.ts +1 -5
- package/front_end/panels/elements/StylePropertyTreeElement.ts +100 -5
- package/front_end/panels/lighthouse/LighthouseController.ts +9 -4
- package/front_end/panels/network/NetworkConfigView.ts +231 -187
- package/front_end/panels/network/RequestPayloadView.ts +22 -14
- package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +0 -1
- package/front_end/panels/recorder/RecordingView.ts +42 -47
- package/front_end/panels/recorder/StepEditor.ts +1 -0
- package/front_end/panels/recorder/recordingView.css +4 -4
- package/front_end/panels/sources/CSSPlugin.ts +11 -0
- package/front_end/panels/sources/CoveragePlugin.ts +34 -23
- package/front_end/panels/sources/NavigatorView.ts +97 -52
- package/front_end/panels/sources/Plugin.ts +15 -1
- package/front_end/panels/sources/SourcesView.ts +47 -80
- package/front_end/panels/sources/TabbedEditorContainer.ts +27 -2
- package/front_end/panels/sources/UISourceCodeFrame.ts +11 -2
- package/front_end/panels/sources/navigatorTree.css +2 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +17 -0
- package/front_end/ui/components/suggestion_input/SuggestionInput.ts +10 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeGenerationTeaser.ts +2 -2
- package/front_end/ui/components/text_editor/aiCodeCompletionTeaser.css +0 -11
- package/front_end/ui/components/text_editor/aiCodeGenerationTeaser.css +0 -11
- package/front_end/ui/legacy/SoftDropDown.ts +17 -4
- package/front_end/ui/legacy/StackPane.ts +141 -0
- package/front_end/ui/legacy/TextPrompt.ts +37 -7
- package/front_end/ui/legacy/Toolbar.ts +7 -5
- package/front_end/ui/legacy/Widget.ts +3 -3
- package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +85 -0
- package/front_end/ui/legacy/components/inline_editor/positionAreaEditor.css +61 -0
- package/front_end/ui/legacy/components/utils/Linkifier.ts +21 -45
- package/front_end/ui/legacy/inspectorCommon.css +11 -0
- package/front_end/ui/legacy/legacy.ts +2 -0
- package/front_end/ui/legacy/softContextMenu.css +2 -0
- package/front_end/ui/settings/ConsoleSettings.ts +7 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +10 -0
- package/package.json +1 -1
|
@@ -10,6 +10,76 @@ import type * as Bindings from '../bindings/bindings.js';
|
|
|
10
10
|
import {PrivateAPI} from './ExtensionAPI.js';
|
|
11
11
|
import {ExtensionEndpoint} from './ExtensionEndpoint.js';
|
|
12
12
|
|
|
13
|
+
const isObject = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;
|
|
14
|
+
const isString = (value: unknown): value is string => typeof value === 'string';
|
|
15
|
+
const isNumber = (value: unknown): value is number => typeof value === 'number';
|
|
16
|
+
const isBoolean = (value: unknown): value is boolean => typeof value === 'boolean';
|
|
17
|
+
const isStringArray = (value: unknown): value is string[] => Array.isArray(value) && value.every(isString);
|
|
18
|
+
const isNumberArray = (value: unknown): value is number[] => Array.isArray(value) && value.every(isNumber);
|
|
19
|
+
|
|
20
|
+
const isRawLocationRange = (value: unknown): value is Chrome.DevTools.RawLocationRange => {
|
|
21
|
+
return isObject(value) && isString(value.rawModuleId) && isNumber(value.startOffset) && isNumber(value.endOffset);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isSourceLocation = (value: unknown): value is Chrome.DevTools.SourceLocation => {
|
|
25
|
+
return isObject(value) && isString(value.rawModuleId) && isString(value.sourceFileURL) &&
|
|
26
|
+
isNumber(value.lineNumber) && isNumber(value.columnNumber);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const isVariable = (value: unknown): value is Chrome.DevTools.Variable => {
|
|
30
|
+
return isObject(value) && isString(value.scope) && isString(value.name) && isString(value.type) &&
|
|
31
|
+
(value.nestedName === undefined || isStringArray(value.nestedName));
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const isScopeInfo = (value: unknown): value is Chrome.DevTools.ScopeInfo => {
|
|
35
|
+
return isObject(value) && isString(value.type) && isString(value.typeName) &&
|
|
36
|
+
(value.icon === undefined || isString(value.icon));
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const isFunctionInfo = (value: unknown): value is Chrome.DevTools.FunctionInfo => {
|
|
40
|
+
return isObject(value) && isString(value.name);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const isForeignObject = (value: unknown): value is Chrome.DevTools.ForeignObject => {
|
|
44
|
+
return isObject(value) && value.type === 'reftype' &&
|
|
45
|
+
(value.valueClass === 'local' || value.valueClass === 'global' || value.valueClass === 'operand') &&
|
|
46
|
+
isNumber(value.index);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const isRemoteObject = (value: unknown): value is Chrome.DevTools.RemoteObject => {
|
|
50
|
+
return isObject(value) &&
|
|
51
|
+
(value.type === 'object' || value.type === 'undefined' || value.type === 'string' || value.type === 'number' ||
|
|
52
|
+
value.type === 'boolean' || value.type === 'bigint' || value.type === 'array' || value.type === 'null') &&
|
|
53
|
+
isBoolean(value.hasChildren) && (value.className === undefined || isString(value.className)) &&
|
|
54
|
+
(value.description === undefined || isString(value.description)) &&
|
|
55
|
+
(value.objectId === undefined || isString(value.objectId)) &&
|
|
56
|
+
(value.linearMemoryAddress === undefined || isNumber(value.linearMemoryAddress)) &&
|
|
57
|
+
(value.linearMemorySize === undefined || isNumber(value.linearMemorySize));
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const isPropertyDescriptor = (value: unknown): value is Chrome.DevTools.PropertyDescriptor => {
|
|
61
|
+
return isObject(value) && isString(value.name) && (isRemoteObject(value.value) || isForeignObject(value.value));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const isAddRawModuleResult = (value: unknown): value is string[]|{missingSymbolFiles: string[]} => {
|
|
65
|
+
return isStringArray(value) || (isObject(value) && isStringArray(value.missingSymbolFiles));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const isGetFunctionInfoResult =
|
|
69
|
+
(value: unknown): value is {frames: Chrome.DevTools.FunctionInfo[], missingSymbolFiles: string[]}|
|
|
70
|
+
{missingSymbolFiles: string[]}|{frames: Chrome.DevTools.FunctionInfo[]} => {
|
|
71
|
+
if (!isObject(value)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if ('frames' in value && (!Array.isArray(value.frames) || !value.frames.every(isFunctionInfo))) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if ('missingSymbolFiles' in value && !isStringArray(value.missingSymbolFiles)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return 'frames' in value || 'missingSymbolFiles' in value;
|
|
81
|
+
};
|
|
82
|
+
|
|
13
83
|
class LanguageExtensionEndpointImpl extends ExtensionEndpoint {
|
|
14
84
|
private plugin: LanguageExtensionEndpoint;
|
|
15
85
|
#pluginManager: Bindings.DebuggerLanguagePlugins.DebuggerLanguagePluginManager;
|
|
@@ -90,12 +160,13 @@ export class LanguageExtensionEndpoint implements Bindings.DebuggerLanguagePlugi
|
|
|
90
160
|
/**
|
|
91
161
|
* Notify the plugin about a new script
|
|
92
162
|
*/
|
|
93
|
-
addRawModule(rawModuleId: string, symbolsURL: string,
|
|
163
|
+
addRawModule(rawModuleId: string, symbolsURL: string,
|
|
164
|
+
rawModule: Chrome.DevTools.RawModule): Promise<string[]|{missingSymbolFiles: string[]}> {
|
|
94
165
|
if (!this.canAccessURL(symbolsURL) || !this.canAccessURL(rawModule.url)) {
|
|
95
166
|
return Promise.resolve([]);
|
|
96
167
|
}
|
|
97
|
-
return this.endpoint.sendRequest(
|
|
98
|
-
|
|
168
|
+
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.AddRawModule,
|
|
169
|
+
{rawModuleId, symbolsURL, rawModule}, isAddRawModuleResult);
|
|
99
170
|
}
|
|
100
171
|
|
|
101
172
|
/**
|
|
@@ -110,8 +181,10 @@ export class LanguageExtensionEndpoint implements Bindings.DebuggerLanguagePlugi
|
|
|
110
181
|
*/
|
|
111
182
|
sourceLocationToRawLocation(sourceLocation: Chrome.DevTools.SourceLocation):
|
|
112
183
|
Promise<Chrome.DevTools.RawLocationRange[]> {
|
|
113
|
-
return this.endpoint.sendRequest(
|
|
114
|
-
|
|
184
|
+
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation,
|
|
185
|
+
{sourceLocation},
|
|
186
|
+
(value): value is Chrome.DevTools.RawLocationRange[] =>
|
|
187
|
+
Array.isArray(value) && value.every(isRawLocationRange));
|
|
115
188
|
}
|
|
116
189
|
|
|
117
190
|
/**
|
|
@@ -119,27 +192,31 @@ export class LanguageExtensionEndpoint implements Bindings.DebuggerLanguagePlugi
|
|
|
119
192
|
*/
|
|
120
193
|
rawLocationToSourceLocation(rawLocation: Chrome.DevTools.RawLocation): Promise<Chrome.DevTools.SourceLocation[]> {
|
|
121
194
|
return this.endpoint.sendRequest(
|
|
122
|
-
PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation, {rawLocation}
|
|
195
|
+
PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation, {rawLocation},
|
|
196
|
+
(value): value is Chrome.DevTools.SourceLocation[] => Array.isArray(value) && value.every(isSourceLocation));
|
|
123
197
|
}
|
|
124
198
|
|
|
125
199
|
getScopeInfo(type: string): Promise<Chrome.DevTools.ScopeInfo> {
|
|
126
|
-
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo, {type});
|
|
200
|
+
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo, {type}, isScopeInfo);
|
|
127
201
|
}
|
|
128
202
|
|
|
129
203
|
/**
|
|
130
204
|
* List all variables in lexical scope at a given location in a raw module
|
|
131
205
|
*/
|
|
132
206
|
listVariablesInScope(rawLocation: Chrome.DevTools.RawLocation): Promise<Chrome.DevTools.Variable[]> {
|
|
133
|
-
return this.endpoint.sendRequest(
|
|
207
|
+
return this.endpoint.sendRequest(
|
|
208
|
+
PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope, {rawLocation},
|
|
209
|
+
(value): value is Chrome.DevTools.Variable[] => Array.isArray(value) && value.every(isVariable));
|
|
134
210
|
}
|
|
135
211
|
|
|
136
212
|
/**
|
|
137
213
|
* List all function names (including inlined frames) at location
|
|
138
214
|
*/
|
|
139
|
-
getFunctionInfo(rawLocation: Chrome.DevTools.RawLocation):
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo, {rawLocation}
|
|
215
|
+
getFunctionInfo(rawLocation: Chrome.DevTools.RawLocation):
|
|
216
|
+
Promise<{frames: Chrome.DevTools.FunctionInfo[], missingSymbolFiles: string[]}|{missingSymbolFiles: string[]}|
|
|
217
|
+
{frames: Chrome.DevTools.FunctionInfo[]}> {
|
|
218
|
+
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo, {rawLocation},
|
|
219
|
+
isGetFunctionInfoResult);
|
|
143
220
|
}
|
|
144
221
|
|
|
145
222
|
/**
|
|
@@ -147,8 +224,9 @@ export class LanguageExtensionEndpoint implements Bindings.DebuggerLanguagePlugi
|
|
|
147
224
|
* that rawLocation is in.
|
|
148
225
|
*/
|
|
149
226
|
getInlinedFunctionRanges(rawLocation: Chrome.DevTools.RawLocation): Promise<Chrome.DevTools.RawLocationRange[]> {
|
|
150
|
-
return this.endpoint.sendRequest(
|
|
151
|
-
|
|
227
|
+
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges, {rawLocation},
|
|
228
|
+
(value): value is Chrome.DevTools.RawLocationRange[] =>
|
|
229
|
+
Array.isArray(value) && value.every(isRawLocationRange));
|
|
152
230
|
}
|
|
153
231
|
|
|
154
232
|
/**
|
|
@@ -156,22 +234,29 @@ export class LanguageExtensionEndpoint implements Bindings.DebuggerLanguagePlugi
|
|
|
156
234
|
* called by the function or inline frame that rawLocation is in.
|
|
157
235
|
*/
|
|
158
236
|
getInlinedCalleesRanges(rawLocation: Chrome.DevTools.RawLocation): Promise<Chrome.DevTools.RawLocationRange[]> {
|
|
159
|
-
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges, {rawLocation}
|
|
237
|
+
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges, {rawLocation},
|
|
238
|
+
(value): value is Chrome.DevTools.RawLocationRange[] =>
|
|
239
|
+
Array.isArray(value) && value.every(isRawLocationRange));
|
|
160
240
|
}
|
|
161
241
|
|
|
162
242
|
async getMappedLines(rawModuleId: string, sourceFileURL: string): Promise<number[]|undefined> {
|
|
163
243
|
return await this.endpoint.sendRequest(
|
|
164
|
-
PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines, {rawModuleId, sourceFileURL}
|
|
244
|
+
PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines, {rawModuleId, sourceFileURL},
|
|
245
|
+
(value): value is number[]|undefined => value === undefined || isNumberArray(value));
|
|
165
246
|
}
|
|
166
247
|
|
|
167
|
-
async evaluate(expression: string, context: Chrome.DevTools.RawLocation,
|
|
168
|
-
|
|
169
|
-
return await this.endpoint.sendRequest(
|
|
170
|
-
|
|
248
|
+
async evaluate(expression: string, context: Chrome.DevTools.RawLocation,
|
|
249
|
+
stopId: number): Promise<Chrome.DevTools.RemoteObject|Chrome.DevTools.ForeignObject|null> {
|
|
250
|
+
return await this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.FormatValue,
|
|
251
|
+
{expression, context, stopId},
|
|
252
|
+
(value): value is Chrome.DevTools.RemoteObject|Chrome.DevTools.ForeignObject|
|
|
253
|
+
null => value === null || isRemoteObject(value) || isForeignObject(value));
|
|
171
254
|
}
|
|
172
255
|
|
|
173
256
|
getProperties(objectId: Chrome.DevTools.RemoteObjectId): Promise<Chrome.DevTools.PropertyDescriptor[]> {
|
|
174
|
-
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetProperties, {objectId}
|
|
257
|
+
return this.endpoint.sendRequest(PrivateAPI.LanguageExtensionPluginCommands.GetProperties, {objectId},
|
|
258
|
+
(value): value is Chrome.DevTools.PropertyDescriptor[] =>
|
|
259
|
+
Array.isArray(value) && value.every(isPropertyDescriptor));
|
|
175
260
|
}
|
|
176
261
|
|
|
177
262
|
releaseObject(objectId: Chrome.DevTools.RemoteObjectId): Promise<void> {
|
|
@@ -8,6 +8,8 @@ import {PrivateAPI} from './ExtensionAPI.js';
|
|
|
8
8
|
import {ExtensionEndpoint} from './ExtensionEndpoint.js';
|
|
9
9
|
import type {RecorderPluginManager} from './RecorderPluginManager.js';
|
|
10
10
|
|
|
11
|
+
const isString = (value: unknown): value is string => typeof value === 'string';
|
|
12
|
+
|
|
11
13
|
export class RecorderExtensionEndpoint extends ExtensionEndpoint {
|
|
12
14
|
private readonly name: string;
|
|
13
15
|
private readonly mediaType?: string;
|
|
@@ -63,7 +65,7 @@ export class RecorderExtensionEndpoint extends ExtensionEndpoint {
|
|
|
63
65
|
* [1]: https://github.com/puppeteer/replay/blob/main/src/Schema.ts#L245
|
|
64
66
|
*/
|
|
65
67
|
stringify(recording: Object): Promise<string> {
|
|
66
|
-
return this.sendRequest(PrivateAPI.RecorderExtensionPluginCommands.Stringify, {recording});
|
|
68
|
+
return this.sendRequest(PrivateAPI.RecorderExtensionPluginCommands.Stringify, {recording}, isString);
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
/**
|
|
@@ -74,7 +76,7 @@ export class RecorderExtensionEndpoint extends ExtensionEndpoint {
|
|
|
74
76
|
* [1]: https://github.com/puppeteer/replay/blob/main/src/Schema.ts#L243
|
|
75
77
|
*/
|
|
76
78
|
stringifyStep(step: Object): Promise<string> {
|
|
77
|
-
return this.sendRequest(PrivateAPI.RecorderExtensionPluginCommands.StringifyStep, {step});
|
|
79
|
+
return this.sendRequest(PrivateAPI.RecorderExtensionPluginCommands.StringifyStep, {step}, isString);
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
/**
|
|
@@ -2035,7 +2035,7 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
|
|
|
2035
2035
|
},
|
|
2036
2036
|
{
|
|
2037
2037
|
name: "read",
|
|
2038
|
-
signatures: [["?
|
|
2038
|
+
signatures: [["?formats"]],
|
|
2039
2039
|
receivers: ["Clipboard"]
|
|
2040
2040
|
},
|
|
2041
2041
|
{
|
|
@@ -3220,7 +3220,7 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
|
|
|
3220
3220
|
{
|
|
3221
3221
|
name: "focus",
|
|
3222
3222
|
signatures: [["?options"]],
|
|
3223
|
-
receivers: ["HTMLOrSVGElement","SVGElement","MathMLElement","HTMLElement"]
|
|
3223
|
+
receivers: ["HTMLOrSVGElement","SVGElement","MathMLElement","HTMLElement","CSSPseudoElement","Focusable"]
|
|
3224
3224
|
},
|
|
3225
3225
|
{
|
|
3226
3226
|
name: "assign",
|
|
@@ -9167,6 +9167,10 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
|
|
|
9167
9167
|
name: "scrollIntoViewIfNeeded",
|
|
9168
9168
|
signatures: [["?centerIfNeeded"]]
|
|
9169
9169
|
},
|
|
9170
|
+
{
|
|
9171
|
+
name: "Focusable",
|
|
9172
|
+
signatures: [["target"]]
|
|
9173
|
+
},
|
|
9170
9174
|
{
|
|
9171
9175
|
name: "getBoxQuads",
|
|
9172
9176
|
signatures: [["?options"]]
|
|
@@ -579,13 +579,14 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe
|
|
|
579
579
|
|
|
580
580
|
static isForbiddenNetworkUrl(urlString: Platform.DevToolsPath.UrlString): boolean {
|
|
581
581
|
const trimmedUrl = urlString.trim().toLowerCase();
|
|
582
|
-
if (trimmedUrl.startsWith('
|
|
583
|
-
trimmedUrl.startsWith('
|
|
582
|
+
if (trimmedUrl.startsWith('chrome:') || trimmedUrl.startsWith('data:') || trimmedUrl.startsWith('blob:') ||
|
|
583
|
+
trimmedUrl.startsWith('javascript:') || trimmedUrl.startsWith('about:') || trimmedUrl.startsWith('mailto:') ||
|
|
584
|
+
trimmedUrl.startsWith('vbscript:')) {
|
|
584
585
|
return true;
|
|
585
586
|
}
|
|
586
587
|
const url = Common.ParsedURL.ParsedURL.fromString(urlString);
|
|
587
588
|
if (!url) {
|
|
588
|
-
return
|
|
589
|
+
return true;
|
|
589
590
|
}
|
|
590
591
|
if ((url.scheme === 'http' || url.scheme === 'https') && (!url.host || url.host === '.' || url.host === '..')) {
|
|
591
592
|
return true;
|
|
@@ -820,14 +820,6 @@ async function getFunctionNameFromScopeStart(script: SDK.Script.Script, rawLineN
|
|
|
820
820
|
return name;
|
|
821
821
|
}
|
|
822
822
|
|
|
823
|
-
export async function resolveDebuggerFrameFunctionName(frame: SDK.DebuggerModel.CallFrame): Promise<string|null> {
|
|
824
|
-
const startLocation = frame.localScope()?.range()?.start;
|
|
825
|
-
if (!startLocation) {
|
|
826
|
-
return null;
|
|
827
|
-
}
|
|
828
|
-
return await getFunctionNameFromScopeStart(frame.script, startLocation.lineNumber, startLocation.columnNumber);
|
|
829
|
-
}
|
|
830
|
-
|
|
831
823
|
export async function resolveProfileFrameFunctionName(
|
|
832
824
|
{scriptId, lineNumber, columnNumber}: Partial<Protocol.Runtime.CallFrame>, target: SDK.Target.Target|null,
|
|
833
825
|
debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding): Promise<string|null> {
|
|
@@ -8,7 +8,7 @@ import type * as Workspace from '../workspace/workspace.js';
|
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line @devtools/es-modules-import
|
|
10
10
|
import type * as StackTrace from './stack_trace.js';
|
|
11
|
-
import type
|
|
11
|
+
import {type EvalOrigin, FrameKind, type FrameNode, type ParsedFrameInfo} from './Trie.js';
|
|
12
12
|
|
|
13
13
|
export type AnyStackTraceImpl = StackTraceImpl<FragmentImpl|DebuggableFragmentImpl|ParsedErrorStackFragmentImpl>;
|
|
14
14
|
|
|
@@ -57,17 +57,7 @@ export class FragmentImpl implements StackTrace.StackTrace.Fragment {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
get frames(): FrameImpl[] {
|
|
60
|
-
|
|
61
|
-
return [];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const frames: FrameImpl[] = [];
|
|
65
|
-
|
|
66
|
-
for (const node of this.node.getCallStack()) {
|
|
67
|
-
frames.push(...node.frames);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return frames;
|
|
60
|
+
return this.node ? consolidate([...this.node.getCallStack()]).map(({frame}) => frame) : [];
|
|
71
61
|
}
|
|
72
62
|
}
|
|
73
63
|
|
|
@@ -108,6 +98,90 @@ export class FrameImpl implements StackTrace.StackTrace.Frame {
|
|
|
108
98
|
}
|
|
109
99
|
}
|
|
110
100
|
|
|
101
|
+
/** A frame of a fragment after outlined frames were merged with their callers. */
|
|
102
|
+
export interface LogicalFrame {
|
|
103
|
+
/** Node frame for non-merged groups (same identity as `node.frames[inlineIndex]`), a fresh copy for merged groups. */
|
|
104
|
+
readonly frame: FrameImpl;
|
|
105
|
+
/** The node this frame was translated from. */
|
|
106
|
+
readonly node: FrameNode;
|
|
107
|
+
/** Index of `node` in the call stack (0 = top). Equals the index into `DebuggerPausedDetails.callFrames`. */
|
|
108
|
+
readonly nodeIndex: number;
|
|
109
|
+
/** Index of `frame` in `node.frames`. Equals `CallFrame.inlineFrameIndex`. */
|
|
110
|
+
readonly inlineIndex: number;
|
|
111
|
+
/** Set only on the last frame of a group: the node that physically invoked this logical frame. */
|
|
112
|
+
readonly invocationNode?: FrameNode;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Drops HIDDEN nodes and merges each OUTLINED node with its callers into one group of logical frames.
|
|
117
|
+
*
|
|
118
|
+
* The chain continues with callers whose `functionKeys.top` equals the previous member's `functionKeys.bottom`,
|
|
119
|
+
* skipping HIDDEN and not-authored nodes. It ends with the first VISIBLE member (the terminator), or before a
|
|
120
|
+
* non-matching caller.
|
|
121
|
+
*/
|
|
122
|
+
export function consolidate(callStack: readonly FrameNode[]): LogicalFrame[] {
|
|
123
|
+
const result: LogicalFrame[] = [];
|
|
124
|
+
for (let i = 0; i < callStack.length; ++i) {
|
|
125
|
+
const node = callStack[i];
|
|
126
|
+
if (node.kind === FrameKind.HIDDEN) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (node.kind === FrameKind.VISIBLE || !node.functionKeys) {
|
|
130
|
+
node.frames.forEach((frame, inlineIndex) => result.push({
|
|
131
|
+
frame,
|
|
132
|
+
node,
|
|
133
|
+
nodeIndex: i,
|
|
134
|
+
inlineIndex,
|
|
135
|
+
invocationNode: inlineIndex === node.frames.length - 1 ? node : undefined,
|
|
136
|
+
}));
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// `node` is OUTLINED: start a chain.
|
|
141
|
+
const group = node.frames.map((frame, inlineIndex) => ({frame, node, nodeIndex: i, inlineIndex}));
|
|
142
|
+
let bottom = node.functionKeys.bottom;
|
|
143
|
+
let terminator: FrameNode|undefined;
|
|
144
|
+
let lastConsumed = i;
|
|
145
|
+
for (let j = i + 1; j < callStack.length && !terminator; ++j) {
|
|
146
|
+
const caller = callStack[j];
|
|
147
|
+
if (caller.kind === FrameKind.HIDDEN || isNotAuthored(caller)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (!caller.functionKeys || caller.functionKeys.top !== bottom) {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
// Skip `caller.frames[0]`: it's the same logical frame as the previous member's bottom frame.
|
|
154
|
+
for (let k = 1; k < caller.frames.length; ++k) {
|
|
155
|
+
group.push({frame: caller.frames[k], node: caller, nodeIndex: j, inlineIndex: k});
|
|
156
|
+
}
|
|
157
|
+
bottom = caller.functionKeys.bottom;
|
|
158
|
+
terminator = caller.kind === FrameKind.VISIBLE ? caller : undefined;
|
|
159
|
+
lastConsumed = j;
|
|
160
|
+
}
|
|
161
|
+
// HIDDEN and not-authored nodes after the last chain member are processed by the outer loop.
|
|
162
|
+
i = lastConsumed;
|
|
163
|
+
|
|
164
|
+
const rawName = terminator?.rawFrame.functionName;
|
|
165
|
+
group.forEach(({frame: f, ...rest}, idx) => result.push({
|
|
166
|
+
...rest,
|
|
167
|
+
frame: new FrameImpl(f.url, f.uiSourceCode, f.name, f.line, f.column, f.missingDebugInfo, rawName, f.isWasm,
|
|
168
|
+
idx < group.length - 1),
|
|
169
|
+
invocationNode: idx === group.length - 1 ? terminator : undefined,
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Frames that the authored function can't have called directly (e.g. `Array.prototype.forEach` calling an outlined
|
|
177
|
+
* callback, or an unmapped runtime helper). A chain looks past them.
|
|
178
|
+
*
|
|
179
|
+
* Builtins are unmapped like any other frame without authored code, see `TranslatedRawFrame.unmapped`.
|
|
180
|
+
*/
|
|
181
|
+
function isNotAuthored(node: FrameNode): boolean {
|
|
182
|
+
return node.kind === FrameKind.VISIBLE && !node.functionKeys && node.isUnmapped;
|
|
183
|
+
}
|
|
184
|
+
|
|
111
185
|
/**
|
|
112
186
|
* Converts the internal recursive `EvalOrigin` trie representation into the public-facing
|
|
113
187
|
* linear `ParsedErrorStackFrameImpl` representation.
|
|
@@ -125,9 +199,10 @@ function createParsedErrorStackFrameImplFromEvalOrigin(
|
|
|
125
199
|
return undefined;
|
|
126
200
|
}
|
|
127
201
|
const frame = evalOrigin.frames[0];
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
202
|
+
const info = parsedFrameInfo?.evalOrigin?.parsedFrameInfo;
|
|
203
|
+
const nestedOrigin = createParsedErrorStackFrameImplFromEvalOrigin(evalOrigin.evalOrigin, info);
|
|
204
|
+
// An eval origin is a single location that is also its own invocation.
|
|
205
|
+
return new ParsedErrorStackFrameImpl(frame, info, info, nestedOrigin);
|
|
131
206
|
}
|
|
132
207
|
|
|
133
208
|
export class ParsedErrorStackFragmentImpl implements StackTrace.StackTrace.ParsedErrorStackFragment {
|
|
@@ -139,27 +214,33 @@ export class ParsedErrorStackFragmentImpl implements StackTrace.StackTrace.Parse
|
|
|
139
214
|
return [];
|
|
140
215
|
}
|
|
141
216
|
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
for (const frame of node.frames) {
|
|
147
|
-
frames.push(new ParsedErrorStackFrameImpl(frame, node.parsedFrameInfo, evalOrigin));
|
|
217
|
+
const evalOrigins = new Map<FrameNode, ParsedErrorStackFrameImpl|undefined>();
|
|
218
|
+
return consolidate([...this.fragment.node.getCallStack()]).map(({frame, node, invocationNode}) => {
|
|
219
|
+
if (!evalOrigins.has(node)) {
|
|
220
|
+
evalOrigins.set(node, createParsedErrorStackFrameImplFromEvalOrigin(node.evalOrigin, node.parsedFrameInfo));
|
|
148
221
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
222
|
+
return new ParsedErrorStackFrameImpl(frame, node.parsedFrameInfo, invocationNode?.parsedFrameInfo,
|
|
223
|
+
evalOrigins.get(node));
|
|
224
|
+
});
|
|
152
225
|
}
|
|
153
226
|
}
|
|
154
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Location properties (e.g. `isAsync`) describe where execution is, and come from the node a frame was translated
|
|
230
|
+
* from. Invocation properties (e.g. `isConstructor`) describe how the physical function was called, and only exist
|
|
231
|
+
* on the last frame of a group of inlined or merged frames.
|
|
232
|
+
*/
|
|
155
233
|
export class ParsedErrorStackFrameImpl implements StackTrace.StackTrace.ParsedErrorStackFrame {
|
|
156
234
|
readonly #frame: FrameImpl;
|
|
157
|
-
readonly #
|
|
235
|
+
readonly #locationInfo?: ParsedFrameInfo;
|
|
236
|
+
readonly #invocationInfo?: ParsedFrameInfo;
|
|
158
237
|
readonly #evalOrigin?: ParsedErrorStackFrameImpl;
|
|
159
238
|
|
|
160
|
-
constructor(frame: FrameImpl,
|
|
239
|
+
constructor(frame: FrameImpl, locationInfo?: ParsedFrameInfo, invocationInfo?: ParsedFrameInfo,
|
|
240
|
+
evalOrigin?: ParsedErrorStackFrameImpl) {
|
|
161
241
|
this.#frame = frame;
|
|
162
|
-
this.#
|
|
242
|
+
this.#locationInfo = locationInfo;
|
|
243
|
+
this.#invocationInfo = invocationInfo;
|
|
163
244
|
this.#evalOrigin = evalOrigin;
|
|
164
245
|
}
|
|
165
246
|
|
|
@@ -186,13 +267,13 @@ export class ParsedErrorStackFrameImpl implements StackTrace.StackTrace.ParsedEr
|
|
|
186
267
|
}
|
|
187
268
|
|
|
188
269
|
get isAsync(): boolean|undefined {
|
|
189
|
-
return this.#
|
|
270
|
+
return this.#locationInfo?.isAsync;
|
|
190
271
|
}
|
|
191
272
|
get isConstructor(): boolean|undefined {
|
|
192
|
-
return this.#
|
|
273
|
+
return this.#invocationInfo?.isConstructor;
|
|
193
274
|
}
|
|
194
275
|
get isEval(): boolean|undefined {
|
|
195
|
-
return this.#
|
|
276
|
+
return this.#locationInfo?.isEval;
|
|
196
277
|
}
|
|
197
278
|
get evalOrigin(): ParsedErrorStackFrameImpl|undefined {
|
|
198
279
|
return this.#evalOrigin;
|
|
@@ -204,19 +285,19 @@ export class ParsedErrorStackFrameImpl implements StackTrace.StackTrace.ParsedEr
|
|
|
204
285
|
return this.#frame.isInline;
|
|
205
286
|
}
|
|
206
287
|
get wasmModuleName(): string|undefined {
|
|
207
|
-
return this.#
|
|
288
|
+
return this.#locationInfo?.wasmModuleName;
|
|
208
289
|
}
|
|
209
290
|
get wasmFunctionIndex(): number|undefined {
|
|
210
|
-
return this.#
|
|
291
|
+
return this.#locationInfo?.wasmFunctionIndex;
|
|
211
292
|
}
|
|
212
293
|
get typeName(): string|undefined {
|
|
213
|
-
return this.#
|
|
294
|
+
return this.#invocationInfo?.typeName;
|
|
214
295
|
}
|
|
215
296
|
get methodName(): string|undefined {
|
|
216
|
-
return this.#
|
|
297
|
+
return this.#invocationInfo?.methodName;
|
|
217
298
|
}
|
|
218
299
|
get promiseIndex(): number|undefined {
|
|
219
|
-
return this.#
|
|
300
|
+
return this.#locationInfo?.promiseIndex;
|
|
220
301
|
}
|
|
221
302
|
}
|
|
222
303
|
|
|
@@ -226,6 +307,12 @@ export class ParsedErrorStackFrameImpl implements StackTrace.StackTrace.ParsedEr
|
|
|
226
307
|
* FragmentImpl will stay the same.
|
|
227
308
|
*/
|
|
228
309
|
export class DebuggableFragmentImpl implements StackTrace.StackTrace.DebuggableFragment {
|
|
310
|
+
/**
|
|
311
|
+
* Virtual call frames for inlined frames, so that reading `frames` repeatedly (e.g. after `UPDATED`) yields
|
|
312
|
+
* identical `sdkFrame`s. A new DebuggableFragmentImpl is created per pause, so this lives as long as `callFrames`.
|
|
313
|
+
*/
|
|
314
|
+
readonly #virtualCallFrames = new Map<string, SDK.DebuggerModel.CallFrame>();
|
|
315
|
+
|
|
229
316
|
constructor(readonly fragment: FragmentImpl, private readonly callFrames: SDK.DebuggerModel.CallFrame[]) {
|
|
230
317
|
}
|
|
231
318
|
|
|
@@ -234,20 +321,24 @@ export class DebuggableFragmentImpl implements StackTrace.StackTrace.DebuggableF
|
|
|
234
321
|
return [];
|
|
235
322
|
}
|
|
236
323
|
|
|
237
|
-
|
|
324
|
+
return consolidate([...this.fragment.node.getCallStack()]).map(({frame, nodeIndex, inlineIndex}) => {
|
|
325
|
+
return new DebuggableFrameImpl(frame, this.#sdkFrameFor(nodeIndex, inlineIndex, frame.name ?? ''));
|
|
326
|
+
});
|
|
327
|
+
}
|
|
238
328
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const sdkFrame = inlineIdx === 0 ? this.callFrames[index] :
|
|
244
|
-
this.callFrames[index].createVirtualCallFrame(inlineIdx, frame.name ?? '');
|
|
245
|
-
frames.push(new DebuggableFrameImpl(frame, sdkFrame));
|
|
246
|
-
}
|
|
247
|
-
index++;
|
|
329
|
+
#sdkFrameFor(nodeIndex: number, inlineIndex: number, name: string): SDK.DebuggerModel.CallFrame {
|
|
330
|
+
const physical = this.callFrames[nodeIndex];
|
|
331
|
+
if (inlineIndex === 0) {
|
|
332
|
+
return physical;
|
|
248
333
|
}
|
|
249
|
-
|
|
250
|
-
|
|
334
|
+
// The name is part of the key, as a re-translation can change the name at the same indices.
|
|
335
|
+
const key = `${nodeIndex}:${inlineIndex}:${name}`;
|
|
336
|
+
let frame = this.#virtualCallFrames.get(key);
|
|
337
|
+
if (!frame) {
|
|
338
|
+
frame = physical.createVirtualCallFrame(inlineIndex, name);
|
|
339
|
+
this.#virtualCallFrames.set(key, frame);
|
|
340
|
+
}
|
|
341
|
+
return frame;
|
|
251
342
|
}
|
|
252
343
|
}
|
|
253
344
|
|