chrome-devtools-frontend 1.0.1704172 → 1.0.1706026
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/AUTHORS +1 -0
- package/docs/architecture_of_devtools.md +1 -1
- package/docs/cookbook/localization.md +2 -2
- package/eslint.config.mjs +1 -0
- package/front_end/Images/src/nodejsHex.svg +28 -0
- package/front_end/core/common/README.md +4 -3
- package/front_end/core/sdk/CPUThrottlingManager.ts +14 -10
- package/front_end/core/sdk/DOMModel.ts +65 -20
- package/front_end/core/sdk/DebuggerModel.ts +0 -4
- package/front_end/core/sdk/PageResourceLoader.ts +12 -11
- package/front_end/core/sdk/SourceMap.ts +7 -5
- package/front_end/core/sdk/SourceMapFunctionRanges.ts +22 -37
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +3 -3
- package/front_end/core/sdk/SourceMapScopesInfo.ts +50 -62
- package/front_end/entrypoints/formatter_actions/formatter_actions.ts +18 -0
- package/front_end/entrypoints/formatter_worker/Substitute.ts +9 -8
- package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +9 -4
- package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +140 -20
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +16 -5
- package/front_end/entrypoints/inspector_main/nodeIcon.css +1 -1
- package/front_end/foundation/Universe.ts +9 -0
- package/front_end/generated/InspectorBackendCommands.ts +4 -3
- package/front_end/generated/protocol.ts +17 -1
- package/front_end/models/ai_assistance/AiConversation.ts +16 -3
- package/front_end/models/ai_assistance/skills/accessibility.md +8 -7
- package/front_end/models/formatter/FormatterWorkerPool.ts +14 -4
- package/front_end/models/javascript_metadata/NativeFunctions.ts +6 -2
- package/front_end/models/source_map_scopes/NamesResolver.ts +69 -42
- package/front_end/models/source_map_scopes/ScopeChainModel.ts +13 -45
- package/front_end/models/source_map_scopes/ScopeChainResolver.ts +101 -0
- package/front_end/models/source_map_scopes/source_map_scopes.ts +2 -0
- package/front_end/panels/application/BackgroundServiceView.ts +1 -0
- package/front_end/panels/application/components/AdsView.ts +6 -6
- package/front_end/panels/application/components/BackForwardCacheView.ts +1 -1
- package/front_end/panels/console/ConsolePrompt.ts +2 -1
- package/front_end/panels/elements/CSSRuleValidator.ts +3 -0
- package/front_end/panels/elements/ClassesPaneWidget.ts +4 -1
- package/front_end/panels/elements/LayoutPane.ts +17 -20
- package/front_end/panels/network/NetworkLogViewColumns.ts +10 -3
- package/front_end/panels/network/ShowMoreDetailsWidget.ts +1 -1
- package/front_end/panels/security/SecurityPanel.ts +14 -7
- package/front_end/panels/sources/BreakpointEditDialog.ts +13 -1
- package/front_end/panels/sources/DebuggerPlugin.ts +69 -58
- package/front_end/panels/sources/EditingLocationHistoryManager.ts +6 -6
- package/front_end/panels/sources/OpenFileQuickOpen.ts +2 -2
- package/front_end/panels/sources/Plugin.ts +3 -2
- package/front_end/panels/sources/ResourceOriginPlugin.ts +14 -17
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +2 -2
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/SourcesView.ts +25 -82
- package/front_end/panels/sources/TabbedEditorContainer.ts +75 -21
- package/front_end/panels/sources/UISourceCodeFrame.ts +22 -13
- package/front_end/panels/sources/sourcesView.css +17 -27
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +1 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/source-map-scopes-codec/README.chromium +2 -2
- package/front_end/third_party/source-map-scopes-codec/package/CONTRIBUTING.md +14 -1
- package/front_end/third_party/source-map-scopes-codec/package/README.md +8 -6
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts +4 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/deno.json +6 -2
- package/front_end/third_party/source-map-scopes-codec/package/package.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js +18 -2
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.ts +22 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js +33 -5
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.ts +41 -5
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js +0 -2
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +99 -36
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +143 -49
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.ts +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +40 -18
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +51 -21
- package/front_end/third_party/source-map-scopes-codec/package/src/scopes.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js +18 -4
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.ts +18 -4
- package/front_end/ui/comments/CommentOverlayManager.ts +23 -10
- package/front_end/ui/components/text_editor/javascript.ts +128 -52
- package/front_end/ui/legacy/README.md +12 -12
- package/front_end/ui/legacy/SearchableView.ts +125 -74
- package/front_end/ui/legacy/components/source_frame/FontView.ts +5 -5
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +13 -13
- package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +2 -6
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +3 -2
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
- package/front_end/Images/nodeIcon.avif +0 -0
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
7
7
|
import * as Bindings from '../../../models/bindings/bindings.js';
|
|
8
|
+
import * as Formatter from '../../../models/formatter/formatter.js';
|
|
8
9
|
import * as JavaScriptMetaData from '../../../models/javascript_metadata/javascript_metadata.js';
|
|
9
10
|
import * as SourceMapScopes from '../../../models/source_map_scopes/source_map_scopes.js';
|
|
10
11
|
import * as CodeMirror from '../../../third_party/codemirror.next/codemirror.next.js';
|
|
@@ -12,9 +13,43 @@ import * as UI from '../../legacy/legacy.js';
|
|
|
12
13
|
|
|
13
14
|
import {type ArgumentHintsTooltip, closeTooltip, cursorTooltip} from './cursor_tooltip.js';
|
|
14
15
|
|
|
15
|
-
export
|
|
16
|
+
export interface CompletionOptions {
|
|
17
|
+
location?: () => Promise<SDK.DebuggerModel.Location|null>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface EvaluationTarget {
|
|
21
|
+
callFrame?: SDK.DebuggerModel.CallFrame;
|
|
22
|
+
location?: SDK.DebuggerModel.Location;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function resolveEvaluationTarget(options?: CompletionOptions): Promise<EvaluationTarget> {
|
|
26
|
+
const selectedCallFrame = getExecutionContext()?.debuggerModel.selectedCallFrame() ?? undefined;
|
|
27
|
+
if (!options?.location) {
|
|
28
|
+
return {callFrame: selectedCallFrame, location: selectedCallFrame?.location()};
|
|
29
|
+
}
|
|
30
|
+
const location = await options.location() ?? undefined;
|
|
31
|
+
if (selectedCallFrame && location && selectedCallFrame.script.scriptId === location.scriptId &&
|
|
32
|
+
selectedCallFrame.location().lineNumber === location.lineNumber &&
|
|
33
|
+
selectedCallFrame.location().columnNumber === location.columnNumber) {
|
|
34
|
+
return {callFrame: selectedCallFrame, location};
|
|
35
|
+
}
|
|
36
|
+
return {location};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Whether we can complete properties of expressions on behalf of `target`.
|
|
41
|
+
*
|
|
42
|
+
* If we are not paused at the target location, there is no call frame in which the local variables at that location
|
|
43
|
+
* exist. Evaluating in the global scope instead would silently resolve them to unrelated globals, so we only offer
|
|
44
|
+
* the (statically known) variable names in that case.
|
|
45
|
+
*/
|
|
46
|
+
function canCompleteProperties(target: EvaluationTarget): boolean {
|
|
47
|
+
return Boolean(target.callFrame) || !target.location;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function completion(options?: CompletionOptions): CodeMirror.Extension {
|
|
16
51
|
return CodeMirror.javascript.javascriptLanguage.data.of({
|
|
17
|
-
autocomplete: javascriptCompletionSource,
|
|
52
|
+
autocomplete: (cx: CodeMirror.CompletionContext) => javascriptCompletionSource(cx, options),
|
|
18
53
|
});
|
|
19
54
|
}
|
|
20
55
|
|
|
@@ -169,14 +204,15 @@ export function getQueryType(tree: CodeMirror.Tree, pos: number, doc: CodeMirror
|
|
|
169
204
|
return {type: QueryType.EXPRESSION};
|
|
170
205
|
}
|
|
171
206
|
|
|
172
|
-
export async function javascriptCompletionSource(
|
|
173
|
-
Promise<CodeMirror.CompletionResult|null> {
|
|
207
|
+
export async function javascriptCompletionSource(
|
|
208
|
+
cx: CodeMirror.CompletionContext, options?: CompletionOptions): Promise<CodeMirror.CompletionResult|null> {
|
|
174
209
|
const query = getQueryType(CodeMirror.syntaxTree(cx.state), cx.pos, cx.state.doc);
|
|
175
210
|
if (!query || query.from === undefined && !cx.explicit && query.type === QueryType.EXPRESSION) {
|
|
176
211
|
return null;
|
|
177
212
|
}
|
|
178
213
|
|
|
179
|
-
const
|
|
214
|
+
const target = await resolveEvaluationTarget(options);
|
|
215
|
+
const script = target.callFrame?.script ?? target.location?.script() ?? null;
|
|
180
216
|
if (script &&
|
|
181
217
|
Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().pluginManager.hasPluginForScript(script)) {
|
|
182
218
|
return null;
|
|
@@ -186,7 +222,7 @@ export async function javascriptCompletionSource(cx: CodeMirror.CompletionContex
|
|
|
186
222
|
let quote: string|undefined = undefined;
|
|
187
223
|
if (query.type === QueryType.EXPRESSION) {
|
|
188
224
|
const [scope, global] = await Promise.all([
|
|
189
|
-
completeExpressionInScope(),
|
|
225
|
+
completeExpressionInScope(target),
|
|
190
226
|
completeExpressionGlobal(),
|
|
191
227
|
]);
|
|
192
228
|
if (scope.completions.length) {
|
|
@@ -198,6 +234,9 @@ export async function javascriptCompletionSource(cx: CodeMirror.CompletionContex
|
|
|
198
234
|
result = global;
|
|
199
235
|
}
|
|
200
236
|
} else if (query.type === QueryType.PROPERTY_NAME || query.type === QueryType.PROPERTY_EXPRESSION) {
|
|
237
|
+
if (!canCompleteProperties(target)) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
201
240
|
const objectExpr = (query.relatedNode as CodeMirror.SyntaxNode).getChild('Expression');
|
|
202
241
|
if (query.type === QueryType.PROPERTY_EXPRESSION) {
|
|
203
242
|
quote = query.from === undefined ? '\'' : cx.state.sliceDoc(query.from, query.from + 1);
|
|
@@ -205,14 +244,14 @@ export async function javascriptCompletionSource(cx: CodeMirror.CompletionContex
|
|
|
205
244
|
if (!objectExpr) {
|
|
206
245
|
return null;
|
|
207
246
|
}
|
|
208
|
-
result = await completeProperties(
|
|
209
|
-
|
|
247
|
+
result = await completeProperties(cx.state.sliceDoc(objectExpr.from, objectExpr.to), quote,
|
|
248
|
+
cx.state.sliceDoc(cx.pos, cx.pos + 1) === ']', target);
|
|
210
249
|
} else if (query.type === QueryType.POTENTIALLY_RETRIEVING_FROM_MAP) {
|
|
211
250
|
const potentialMapObject = query.relatedNode;
|
|
212
|
-
if (!potentialMapObject) {
|
|
251
|
+
if (!potentialMapObject || !canCompleteProperties(target)) {
|
|
213
252
|
return null;
|
|
214
253
|
}
|
|
215
|
-
result = await maybeCompleteKeysFromMap(cx.state.sliceDoc(potentialMapObject.from, potentialMapObject.to));
|
|
254
|
+
result = await maybeCompleteKeysFromMap(cx.state.sliceDoc(potentialMapObject.from, potentialMapObject.to), target);
|
|
216
255
|
} else {
|
|
217
256
|
return null;
|
|
218
257
|
}
|
|
@@ -236,8 +275,19 @@ async function evaluateExpression(
|
|
|
236
275
|
context: SDK.RuntimeModel.ExecutionContext,
|
|
237
276
|
expression: string,
|
|
238
277
|
group: string,
|
|
278
|
+
substituteNames = true,
|
|
279
|
+
target?: EvaluationTarget,
|
|
239
280
|
): Promise<SDK.RemoteObject.RemoteObject|null> {
|
|
240
|
-
const
|
|
281
|
+
const callFrame = target ? target.callFrame : context.debuggerModel.selectedCallFrame();
|
|
282
|
+
if (substituteNames && callFrame?.script.isJavaScript()) {
|
|
283
|
+
const nameMap = await SourceMapScopes.NamesResolver.allVariablesInCallFrame(
|
|
284
|
+
callFrame, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance());
|
|
285
|
+
try {
|
|
286
|
+
expression = await Formatter.FormatterWorkerPool.formatterWorkerPool().javaScriptSubstitute(expression, nameMap);
|
|
287
|
+
} catch {
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const evaluationOptions = {
|
|
241
291
|
expression,
|
|
242
292
|
objectGroup: group,
|
|
243
293
|
includeCommandLineAPI: true,
|
|
@@ -247,8 +297,9 @@ async function evaluateExpression(
|
|
|
247
297
|
throwOnSideEffect: true,
|
|
248
298
|
timeout: 500,
|
|
249
299
|
replMode: true,
|
|
250
|
-
}
|
|
251
|
-
|
|
300
|
+
};
|
|
301
|
+
const result =
|
|
302
|
+
callFrame ? await callFrame.evaluate(evaluationOptions) : await context.evaluate(evaluationOptions, false, false);
|
|
252
303
|
if ('error' in result || result.exceptionDetails || !result.object) {
|
|
253
304
|
return null;
|
|
254
305
|
}
|
|
@@ -265,7 +316,7 @@ const primitivePrototypes = new Map<string, string>([
|
|
|
265
316
|
|
|
266
317
|
const maxCacheAge = 30_000;
|
|
267
318
|
|
|
268
|
-
|
|
319
|
+
const cacheByTargetManager = new WeakMap<SDK.TargetManager.TargetManager, PropertyCache>();
|
|
269
320
|
|
|
270
321
|
/**
|
|
271
322
|
* Store recent collections of property completions. The empty string
|
|
@@ -274,15 +325,13 @@ let cacheInstance: PropertyCache|null = null;
|
|
|
274
325
|
class PropertyCache {
|
|
275
326
|
readonly #cache = new Map<string, Promise<CompletionSet>>();
|
|
276
327
|
|
|
277
|
-
constructor() {
|
|
328
|
+
constructor(targetManager: SDK.TargetManager.TargetManager) {
|
|
278
329
|
const clear = (): void => this.#cache.clear();
|
|
279
|
-
SDK.
|
|
280
|
-
SDK.ConsoleModel.ConsoleModel, SDK.ConsoleModel.Events.CommandEvaluated, clear);
|
|
330
|
+
targetManager.addModelListener(SDK.ConsoleModel.ConsoleModel, SDK.ConsoleModel.Events.CommandEvaluated, clear);
|
|
281
331
|
UI.Context.Context.instance().addFlavorChangeListener(SDK.RuntimeModel.ExecutionContext, clear);
|
|
282
|
-
SDK.
|
|
283
|
-
|
|
284
|
-
SDK.
|
|
285
|
-
SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, clear);
|
|
332
|
+
targetManager.addModelListener(SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerResumed, clear);
|
|
333
|
+
targetManager.addModelListener(SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, clear);
|
|
334
|
+
targetManager.addModelListener(SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.CallFrameSelected, clear);
|
|
286
335
|
}
|
|
287
336
|
|
|
288
337
|
get(expression: string): Promise<CompletionSet>|undefined {
|
|
@@ -299,21 +348,24 @@ class PropertyCache {
|
|
|
299
348
|
}
|
|
300
349
|
|
|
301
350
|
static instance(): PropertyCache {
|
|
302
|
-
|
|
303
|
-
|
|
351
|
+
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
352
|
+
let cache = cacheByTargetManager.get(targetManager);
|
|
353
|
+
if (!cache) {
|
|
354
|
+
cache = new PropertyCache(targetManager);
|
|
355
|
+
cacheByTargetManager.set(targetManager, cache);
|
|
304
356
|
}
|
|
305
|
-
return
|
|
357
|
+
return cache;
|
|
306
358
|
}
|
|
307
359
|
}
|
|
308
360
|
|
|
309
|
-
async function maybeCompleteKeysFromMap(objectVariable: string): Promise<CompletionSet> {
|
|
361
|
+
async function maybeCompleteKeysFromMap(objectVariable: string, target?: EvaluationTarget): Promise<CompletionSet> {
|
|
310
362
|
const result = new CompletionSet();
|
|
311
363
|
const context = getExecutionContext();
|
|
312
364
|
if (!context) {
|
|
313
365
|
return result;
|
|
314
366
|
}
|
|
315
|
-
const maybeRetrieveKeys =
|
|
316
|
-
|
|
367
|
+
const maybeRetrieveKeys = await evaluateExpression(context, `[...Map.prototype.keys.call(${objectVariable})]`,
|
|
368
|
+
'completion', /* substituteNames */ true, target);
|
|
317
369
|
if (!maybeRetrieveKeys) {
|
|
318
370
|
return result;
|
|
319
371
|
}
|
|
@@ -333,6 +385,7 @@ async function completeProperties(
|
|
|
333
385
|
expression: string,
|
|
334
386
|
quoted?: string,
|
|
335
387
|
hasBracket = false,
|
|
388
|
+
target?: EvaluationTarget,
|
|
336
389
|
): Promise<CompletionSet> {
|
|
337
390
|
const cache = PropertyCache.instance();
|
|
338
391
|
if (!quoted) {
|
|
@@ -345,7 +398,7 @@ async function completeProperties(
|
|
|
345
398
|
if (!context) {
|
|
346
399
|
return new CompletionSet();
|
|
347
400
|
}
|
|
348
|
-
const result = completePropertiesInner(expression, context, quoted, hasBracket);
|
|
401
|
+
const result = completePropertiesInner(expression, context, quoted, hasBracket, target);
|
|
349
402
|
if (!quoted) {
|
|
350
403
|
cache.set(expression, result);
|
|
351
404
|
}
|
|
@@ -357,12 +410,13 @@ async function completePropertiesInner(
|
|
|
357
410
|
context: SDK.RuntimeModel.ExecutionContext,
|
|
358
411
|
quoted?: string,
|
|
359
412
|
hasBracket = false,
|
|
413
|
+
target?: EvaluationTarget,
|
|
360
414
|
): Promise<CompletionSet> {
|
|
361
415
|
const result = new CompletionSet();
|
|
362
416
|
if (!context) {
|
|
363
417
|
return result;
|
|
364
418
|
}
|
|
365
|
-
let object = await evaluateExpression(context, expression, 'completion');
|
|
419
|
+
let object = await evaluateExpression(context, expression, 'completion', expression !== 'globalThis', target);
|
|
366
420
|
if (!object) {
|
|
367
421
|
return result;
|
|
368
422
|
}
|
|
@@ -378,7 +432,7 @@ async function completePropertiesInner(
|
|
|
378
432
|
|
|
379
433
|
const toPrototype = primitivePrototypes.get(object.type);
|
|
380
434
|
if (toPrototype) {
|
|
381
|
-
object = await evaluateExpression(context, toPrototype + '.prototype', 'completion');
|
|
435
|
+
object = await evaluateExpression(context, toPrototype + '.prototype', 'completion', /* substituteNames */ false);
|
|
382
436
|
}
|
|
383
437
|
|
|
384
438
|
const functionType = expression === 'globalThis' ? 'function' : 'method';
|
|
@@ -403,23 +457,43 @@ async function completePropertiesInner(
|
|
|
403
457
|
return result;
|
|
404
458
|
}
|
|
405
459
|
|
|
406
|
-
async function completeExpressionInScope(): Promise<CompletionSet> {
|
|
460
|
+
async function completeExpressionInScope(target: EvaluationTarget): Promise<CompletionSet> {
|
|
407
461
|
const result = new CompletionSet();
|
|
408
|
-
|
|
409
|
-
|
|
462
|
+
if (target.callFrame) {
|
|
463
|
+
const scopeChain =
|
|
464
|
+
await SourceMapScopes.ScopeChainResolver.ScopeChainResolver.instance().resolveScopeChain(target.callFrame);
|
|
465
|
+
const scopes = await Promise.all(scopeChain.map(scope => scope.object().getAllProperties(false, false)));
|
|
466
|
+
for (const scope of scopes) {
|
|
467
|
+
for (const property of scope.properties || []) {
|
|
468
|
+
if (!property.value && !property.getter) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
result.add({
|
|
472
|
+
label: property.name,
|
|
473
|
+
type: property.value?.type === 'function' ? 'function' : 'variable',
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return result;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (!target.location) {
|
|
410
481
|
return result;
|
|
411
482
|
}
|
|
412
483
|
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
484
|
+
const mappings = await SourceMapScopes.NamesResolver.allVariablesAtPosition(
|
|
485
|
+
target.location, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance());
|
|
486
|
+
for (const scope of mappings) {
|
|
487
|
+
const mappedGeneratedNames = new Set(scope.bindings.values());
|
|
488
|
+
for (const [origName, genName] of scope.bindings) {
|
|
489
|
+
if (genName !== null) {
|
|
490
|
+
result.add({label: origName, type: 'variable'});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
for (const genName of scope.generatedNames) {
|
|
494
|
+
if (!mappedGeneratedNames.has(genName)) {
|
|
495
|
+
result.add({label: genName, type: 'variable'});
|
|
496
|
+
}
|
|
423
497
|
}
|
|
424
498
|
}
|
|
425
499
|
return result;
|
|
@@ -471,8 +545,8 @@ export async function isExpressionComplete(expression: string): Promise<boolean>
|
|
|
471
545
|
return false;
|
|
472
546
|
}
|
|
473
547
|
|
|
474
|
-
export function argumentHints(): ArgumentHintsTooltip {
|
|
475
|
-
return cursorTooltip(getArgumentHints);
|
|
548
|
+
export function argumentHints(options?: CompletionOptions): ArgumentHintsTooltip {
|
|
549
|
+
return cursorTooltip((state, pos) => getArgumentHints(state, pos, options));
|
|
476
550
|
}
|
|
477
551
|
|
|
478
552
|
export function closeArgumentsHintsTooltip(
|
|
@@ -486,8 +560,8 @@ export function closeArgumentsHintsTooltip(
|
|
|
486
560
|
return true;
|
|
487
561
|
}
|
|
488
562
|
|
|
489
|
-
async function getArgumentHints(
|
|
490
|
-
|
|
563
|
+
async function getArgumentHints(state: CodeMirror.EditorState, pos: number,
|
|
564
|
+
options?: CompletionOptions): Promise<(() => CodeMirror.TooltipView)|null> {
|
|
491
565
|
const node = CodeMirror.syntaxTree(state).resolveInner(pos).enterUnfinishedNodesBefore(pos);
|
|
492
566
|
|
|
493
567
|
if (node.name !== 'ArgList') {
|
|
@@ -497,7 +571,7 @@ async function getArgumentHints(
|
|
|
497
571
|
if (!callee) {
|
|
498
572
|
return null;
|
|
499
573
|
}
|
|
500
|
-
const argumentList = await getArgumentsForExpression(callee, state.doc);
|
|
574
|
+
const argumentList = await getArgumentsForExpression(callee, state.doc, options);
|
|
501
575
|
if (!argumentList) {
|
|
502
576
|
return null;
|
|
503
577
|
}
|
|
@@ -516,14 +590,15 @@ async function getArgumentHints(
|
|
|
516
590
|
return () => tooltipBuilder(argumentList, argumentIndex);
|
|
517
591
|
}
|
|
518
592
|
|
|
519
|
-
async function getArgumentsForExpression(
|
|
520
|
-
|
|
593
|
+
async function getArgumentsForExpression(callee: CodeMirror.SyntaxNode, doc: CodeMirror.Text,
|
|
594
|
+
options?: CompletionOptions): Promise<string[][]|null> {
|
|
521
595
|
const context = getExecutionContext();
|
|
522
596
|
if (!context) {
|
|
523
597
|
return null;
|
|
524
598
|
}
|
|
599
|
+
const target = await resolveEvaluationTarget(options);
|
|
525
600
|
const expression = doc.sliceString(callee.from, callee.to);
|
|
526
|
-
const result = await evaluateExpression(context, expression, 'argumentsHint');
|
|
601
|
+
const result = await evaluateExpression(context, expression, 'argumentsHint', /* substituteNames */ true, target);
|
|
527
602
|
if (result?.type !== 'function') {
|
|
528
603
|
return null;
|
|
529
604
|
}
|
|
@@ -532,7 +607,8 @@ async function getArgumentsForExpression(
|
|
|
532
607
|
if (!first || callee.name !== 'MemberExpression') {
|
|
533
608
|
return null;
|
|
534
609
|
}
|
|
535
|
-
return await evaluateExpression(context, doc.sliceString(first.from, first.to), 'argumentsHint'
|
|
610
|
+
return await evaluateExpression(context, doc.sliceString(first.from, first.to), 'argumentsHint',
|
|
611
|
+
/* substituteNames */ true, target);
|
|
536
612
|
};
|
|
537
613
|
return await getArgumentsForFunctionValue(result, objGetter, expression)
|
|
538
614
|
.finally(() => context.runtimeModel.releaseObjectGroup('argumentsHint'));
|
|
@@ -73,11 +73,11 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
73
73
|
bindings: [
|
|
74
74
|
{
|
|
75
75
|
shortcut: 'Ctrl+E',
|
|
76
|
-
platform: UI.ActionRegistration.Platforms.
|
|
76
|
+
platform: UI.ActionRegistration.Platforms.WINDOWS_LINUX,
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
shortcut: 'Meta+E',
|
|
80
|
-
platform: UI.ActionRegistration.Platforms.
|
|
80
|
+
platform: UI.ActionRegistration.Platforms.MAC,
|
|
81
81
|
},
|
|
82
82
|
],
|
|
83
83
|
});
|
|
@@ -87,7 +87,7 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
87
87
|
|
|
88
88
|
#### Context types
|
|
89
89
|
The `contextTypes` property determines the context under which the action is available.
|
|
90
|
-
A context is defined as set 'flavors' or classes, which usually represent views, that are added and removed to the context as the user interacts with the application (e.g when the user moves across views).
|
|
90
|
+
A context is defined as set of 'flavors' or classes, which usually represent views, that are added and removed to the context as the user interacts with the application (e.g when the user moves across views).
|
|
91
91
|
(See [`UI.Context`](./Context.js)).
|
|
92
92
|
Therefore, an action can only be triggered when one of its respective context types is visible.
|
|
93
93
|
These flavors can be retrieved invoking the method `flavors` inside the class `UI.Context.Context`.
|
|
@@ -97,10 +97,10 @@ In this case, the action will always be available, regardless of which context i
|
|
|
97
97
|
|
|
98
98
|
#### Key bindings
|
|
99
99
|
|
|
100
|
-
The `bindings` property defines
|
|
100
|
+
The `bindings` property defines `platform` and `keybindSets` properties along with the `shortcut` property containing the actual keyboard shortcut.
|
|
101
101
|
These two extra properties add more conditions (additional to the ones introduced by the `contextTypes` property discussed before) that need to be fulfilled to trigger a particular action.
|
|
102
102
|
|
|
103
|
-
- `platform` refers to the OS on which DevTools is running and can be either `
|
|
103
|
+
- `platform` refers to the OS on which DevTools is running and can be either `MAC`, `WINDOWS_LINUX` or `WINDOWS`. (See [`UI.ActionRegistration`](./ActionRegistration.ts)).
|
|
104
104
|
- `keybindSets` refers to the selected shortcut preset, which can be changed in `settings -> shortcuts -> “Match shortcuts from preset”`.
|
|
105
105
|
A key binding will be used when the selected preset matches any of the keybind sets declared by the binding.
|
|
106
106
|
|
|
@@ -125,16 +125,16 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
125
125
|
contextTypes: undefined,
|
|
126
126
|
bindings: [
|
|
127
127
|
{
|
|
128
|
-
platform:
|
|
128
|
+
platform: UI.ActionRegistration.Platforms.WINDOWS_LINUX,
|
|
129
129
|
shortcut: 'Esc',
|
|
130
130
|
},
|
|
131
131
|
],
|
|
132
132
|
});
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
These two key bindings both allocate the same key for the `
|
|
135
|
+
These two key bindings both allocate the same key for the `WINDOWS_LINUX` platform (the first one is global across platforms) in the `ElementsPanel` context (the second one is global across context types) and both are global across keybind sets.
|
|
136
136
|
|
|
137
|
-
If key bindings were declared such that **at least one** of the three variables (`platform
|
|
137
|
+
If key bindings were declared such that **at least one** of the three variables (`platform`, `contextTypes` and `keybindSets`) doesn't overlap, then no duplication would occur.
|
|
138
138
|
For example, the following is **not** a form of duplication:
|
|
139
139
|
|
|
140
140
|
```ts
|
|
@@ -147,7 +147,7 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
147
147
|
bindings: [
|
|
148
148
|
{
|
|
149
149
|
shortcut: 'Esc',
|
|
150
|
-
keybindSets: [
|
|
150
|
+
keybindSets: [UI.ActionRegistration.KeybindSet.DEVTOOLS_DEFAULT],
|
|
151
151
|
},
|
|
152
152
|
],
|
|
153
153
|
});
|
|
@@ -160,12 +160,12 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
160
160
|
contextTypes: undefined,
|
|
161
161
|
bindings: [
|
|
162
162
|
{
|
|
163
|
-
platform:
|
|
163
|
+
platform: UI.ActionRegistration.Platforms.WINDOWS_LINUX,
|
|
164
164
|
shortcut: 'Esc',
|
|
165
|
-
keybindSets: [
|
|
165
|
+
keybindSets: [UI.ActionRegistration.KeybindSet.VS_CODE],
|
|
166
166
|
},
|
|
167
167
|
],
|
|
168
168
|
});
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
In this case,
|
|
171
|
+
In this case, the keybindings are declared for different keybind sets and thus do not result in duplication.
|