chrome-devtools-frontend 1.0.1651641 → 1.0.1654411
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/fixing-skipped-tests/SKILL.md +32 -0
- package/.agents/skills/migrate-chromium-test/SKILL.md +144 -0
- package/docs/get_the_code.md +1 -2
- package/docs/ui_engineering.md +3 -1
- package/eslint.config.mjs +0 -5
- package/front_end/core/sdk/CPUThrottlingManager.ts +13 -8
- package/front_end/core/sdk/CSSMetadata.ts +23 -0
- package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +8 -4
- package/front_end/core/sdk/DOMModel.ts +4 -0
- package/front_end/core/sdk/EmulationModel.ts +4 -0
- package/front_end/core/sdk/ResourceTreeModel.ts +3 -2
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +459 -74
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/foundation/Universe.ts +18 -0
- package/front_end/generated/InspectorBackendCommands.ts +7 -6
- package/front_end/generated/SupportedCSSProperties.js +208 -34
- package/front_end/generated/protocol.ts +64 -7
- package/front_end/models/ai_assistance/AiAgent2.ts +3 -3
- package/front_end/models/ai_assistance/AiConversation.ts +2 -1
- package/front_end/models/ai_assistance/README.md +5 -4
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +11 -164
- package/front_end/models/ai_assistance/ai_assistance.ts +6 -2
- package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +295 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +10 -10
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +12 -11
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +6 -6
- package/front_end/models/ai_assistance/skills/accessibility.md +4 -2
- package/front_end/models/ai_assistance/tools/GetElementAccessibilityDetails.ts +142 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +1 -1
- package/front_end/models/ai_assistance/tools/README.md +22 -2
- package/front_end/models/ai_assistance/tools/{ResolveLighthousePath.ts → ResolveDevtoolsNodePath.ts} +18 -17
- package/front_end/models/ai_assistance/tools/Tool.ts +7 -2
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +10 -8
- package/front_end/models/autofill_manager/AutofillManager.ts +7 -15
- package/front_end/models/bindings/NetworkProject.ts +4 -8
- package/front_end/models/breakpoints/BreakpointManager.ts +9 -9
- package/front_end/models/emulation/DeviceModeModel.ts +24 -0
- package/front_end/models/emulation/EmulatedDevices.ts +108 -0
- package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +36 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +8 -0
- package/front_end/models/issues_manager/IssuesManager.ts +10 -6
- package/front_end/models/javascript_metadata/JavaScriptMetadata.ts +4 -5
- package/front_end/models/live-metrics/LiveMetrics.ts +6 -6
- package/front_end/models/live-metrics/web-vitals-injected/spec/spec.ts +5 -5
- package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +3 -3
- package/front_end/models/logs/LogManager.ts +25 -10
- package/front_end/models/logs/NetworkLog.ts +24 -19
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +14 -5
- package/front_end/models/persistence/IsolatedFileSystem.ts +9 -11
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +5 -3
- package/front_end/models/persistence/NetworkPersistenceManager.ts +73 -44
- package/front_end/models/persistence/PersistenceImpl.ts +4 -5
- package/front_end/models/trace/EntityMapper.ts +1 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +9 -9
- package/front_end/panels/ai_assistance/ExportConversation.ts +4 -1
- package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -2
- package/front_end/panels/application/IndexedDBViews.ts +38 -36
- package/front_end/panels/application/components/AdsView.ts +4 -0
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/autofill/autofill-meta.ts +3 -2
- package/front_end/panels/elements/AccessibilityTreeUtils.ts +26 -15
- package/front_end/panels/elements/AccessibilityTreeView.ts +12 -9
- package/front_end/panels/elements/ElementsTreeOutline.ts +5 -0
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +118 -68
- package/front_end/panels/layer_viewer/Layers3DView.ts +1 -1
- package/front_end/panels/layer_viewer/layerTreeOutline.css +20 -13
- package/front_end/panels/layers/LayersPanel.ts +1 -1
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +64 -17
- package/front_end/panels/mobile_throttling/throttlingSettingsTab.css +5 -0
- package/front_end/panels/network/LinkPreloadGenerator.ts +101 -0
- package/front_end/panels/network/NetworkLogView.ts +28 -0
- package/front_end/panels/network/network.ts +2 -0
- package/front_end/panels/profiler/HeapSnapshotView.ts +121 -33
- package/front_end/panels/profiler/ModuleUIStrings.ts +4 -0
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +0 -12
- package/front_end/panels/timeline/TimelineHistoryManager.ts +38 -37
- package/front_end/panels/timeline/TimelinePanel.ts +32 -8
- package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +7 -6
- package/front_end/panels/timeline/components/LiveMetricsView.ts +38 -38
- package/front_end/panels/timeline/components/MetricCard.ts +18 -18
- package/front_end/panels/timeline/components/liveMetricsView.css +6 -6
- package/front_end/panels/timeline/components/metricCard.css +4 -4
- package/front_end/panels/whats_new/ReleaseNoteText.ts +3 -3
- package/front_end/panels/whats_new/resources/WNDT.md +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/legacy/InspectorDrawerView.ts +7 -5
- package/front_end/ui/legacy/ListWidget.ts +12 -0
- package/front_end/ui/legacy/SplitWidget.ts +12 -11
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +23 -19
- package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +8 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +110 -17
- package/front_end/ui/legacy/treeoutline.css +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +4 -3
|
@@ -17,11 +17,29 @@ Instead of passing a monolithic "grab-bag" context object to all tool handlers,
|
|
|
17
17
|
- `PageExecutionCapability`: For tools executing JavaScript code on the inspected page.
|
|
18
18
|
- `StyleMutationCapability`: For tools managing and applying style mutations via a `ChangeManager`.
|
|
19
19
|
- `TargetCapability`: For tools requiring access to the page's current SDK `Target`.
|
|
20
|
-
- `OriginLockCapability`: For tools enforcing cross-origin security via origin locks. Tools that fetch resources or state from the inspected page (such as styling or source code) must use this capability to verify that the target resource matches the conversation's established origin. This prevents the LLM from executing tools against out-of-origin elements or documents.
|
|
20
|
+
- `OriginLockCapability`: For tools enforcing cross-origin security via origin locks. Tools that fetch resources or state from the inspected page (such as styling or source code) must use this capability to verify that the target resource matches the conversation's established origin. This prevents the LLM from executing tools against out-of-origin elements or documents. Verification should be done by wrapping resolved resources in helper context classes (e.g., `DOMNodeContext`) and calling `isOriginAllowed(establishedOrigin)`.
|
|
21
21
|
|
|
22
22
|
### Unified Context
|
|
23
23
|
|
|
24
|
-
The Agent (e.g., `AiAgent2`) builds the complete dependency union (`
|
|
24
|
+
The Agent (e.g., `AiAgent2`) builds the complete dependency union (`AllToolsCapabilities`) and fulfills all capabilities. When the handler is invoked, TypeScript validates that the provided context matches the intersection of capabilities requested by that tool.
|
|
25
|
+
|
|
26
|
+
## Returning UI Widgets
|
|
27
|
+
|
|
28
|
+
Tools can return rich UI components (widgets) to be rendered directly in the AI Assistance panel alongside text results. To do this, include the widget payload in the `widgets` field of the returned `FunctionCallHandlerResult`:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
return {
|
|
32
|
+
result: JSON.stringify(properties, null, 2),
|
|
33
|
+
widgets: [{
|
|
34
|
+
name: 'DOM_TREE',
|
|
35
|
+
data: {
|
|
36
|
+
root: snapshot,
|
|
37
|
+
title: i18n.i18n.lockedString('Element details'),
|
|
38
|
+
accessibleRevealLabel: i18n.i18n.lockedString('Reveal element'),
|
|
39
|
+
},
|
|
40
|
+
}],
|
|
41
|
+
};
|
|
42
|
+
```
|
|
25
43
|
|
|
26
44
|
## Authoring a New Tool
|
|
27
45
|
|
|
@@ -35,6 +53,8 @@ To author a new tool:
|
|
|
35
53
|
See concrete, production examples of capability-based tools in this directory:
|
|
36
54
|
- [ExecuteJavaScript.ts](ExecuteJavaScript.ts): Demonstrates use of `PageExecutionCapability` and `StyleMutationCapability`.
|
|
37
55
|
- [GetStyles.ts](GetStyles.ts): Demonstrates use of `TargetCapability` and `OriginLockCapability`.
|
|
56
|
+
- [GetElementAccessibilityDetails.ts](GetElementAccessibilityDetails.ts): Demonstrates returning UI widgets (`DOM_TREE`) and origin checks with context wrappers.
|
|
57
|
+
- [ResolveDevtoolsNodePath.ts](ResolveDevtoolsNodePath.ts): Demonstrates path resolution input validation and origin lock checks.
|
|
38
58
|
|
|
39
59
|
## ToolRegistry Lookup
|
|
40
60
|
|
package/front_end/models/ai_assistance/tools/{ResolveLighthousePath.ts → ResolveDevtoolsNodePath.ts}
RENAMED
|
@@ -17,11 +17,11 @@ import {
|
|
|
17
17
|
} from './Tool.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Arguments for resolving a
|
|
20
|
+
* Arguments for resolving a DevTools node path to a backend node ID.
|
|
21
21
|
*/
|
|
22
|
-
export interface
|
|
22
|
+
export interface ResolveDevtoolsNodePathArgs extends ToolArgs {
|
|
23
23
|
/**
|
|
24
|
-
* A
|
|
24
|
+
* A DevTools node path.
|
|
25
25
|
* This is typically a comma-separated list of child indices and tag names
|
|
26
26
|
* representing the path from the root to the target element (e.g., "1,HTML,1,BODY").
|
|
27
27
|
*/
|
|
@@ -30,19 +30,20 @@ export interface ResolveLighthousePathArgs extends ToolArgs {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* A tool that resolves a
|
|
33
|
+
* A tool that resolves a DevTools node path to a backend node ID.
|
|
34
34
|
*
|
|
35
35
|
* This is used by the AI assistant to identify specific DOM nodes referred to in
|
|
36
|
-
* Lighthouse reports
|
|
36
|
+
* Lighthouse reports or other sources using node paths. It ensures the resolved node
|
|
37
|
+
* belongs to the locked origin.
|
|
37
38
|
*/
|
|
38
|
-
export class
|
|
39
|
-
|
|
40
|
-
readonly name = ToolName.
|
|
41
|
-
readonly description = 'Resolves a
|
|
39
|
+
export class ResolveDevtoolsNodePathTool implements Tool<ResolveDevtoolsNodePathArgs, {backendNodeId: number},
|
|
40
|
+
BaseToolCapability&TargetCapability&OriginLockCapability> {
|
|
41
|
+
readonly name = ToolName.RESOLVE_DEVTOOLS_NODE_PATH;
|
|
42
|
+
readonly description = 'Resolves a DevTools node path to a backend node ID.';
|
|
42
43
|
|
|
43
|
-
readonly parameters: Host.AidaClient.FunctionObjectParam<keyof
|
|
44
|
+
readonly parameters: Host.AidaClient.FunctionObjectParam<keyof ResolveDevtoolsNodePathArgs> = {
|
|
44
45
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
45
|
-
description: 'Arguments for resolving a
|
|
46
|
+
description: 'Arguments for resolving a DevTools node path to a backend node ID.',
|
|
46
47
|
nullable: false,
|
|
47
48
|
properties: {
|
|
48
49
|
explanation: {
|
|
@@ -52,14 +53,14 @@ export class ResolveLighthousePathTool implements
|
|
|
52
53
|
},
|
|
53
54
|
path: {
|
|
54
55
|
type: Host.AidaClient.ParametersTypes.STRING,
|
|
55
|
-
description: '
|
|
56
|
+
description: 'DevTools node path string.',
|
|
56
57
|
nullable: false,
|
|
57
58
|
},
|
|
58
59
|
},
|
|
59
60
|
required: ['explanation', 'path'],
|
|
60
61
|
};
|
|
61
62
|
|
|
62
|
-
displayInfoFromArgs(params:
|
|
63
|
+
displayInfoFromArgs(params: ResolveDevtoolsNodePathArgs): {
|
|
63
64
|
title: string,
|
|
64
65
|
thought: string,
|
|
65
66
|
action: string,
|
|
@@ -67,7 +68,7 @@ export class ResolveLighthousePathTool implements
|
|
|
67
68
|
return {
|
|
68
69
|
title: 'Resolving element path',
|
|
69
70
|
thought: params.explanation,
|
|
70
|
-
action: `
|
|
71
|
+
action: `resolveDevtoolsNodePath('${params.path}')`,
|
|
71
72
|
};
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -79,7 +80,7 @@ export class ResolveLighthousePathTool implements
|
|
|
79
80
|
* access to nodes from other origins.
|
|
80
81
|
*/
|
|
81
82
|
async handler(
|
|
82
|
-
params:
|
|
83
|
+
params: ResolveDevtoolsNodePathArgs,
|
|
83
84
|
context: BaseToolCapability&TargetCapability&OriginLockCapability,
|
|
84
85
|
): Promise<FunctionCallHandlerResult<{backendNodeId: number}>> {
|
|
85
86
|
const establishedOrigin = context.getEstablishedOrigin();
|
|
@@ -95,11 +96,11 @@ export class ResolveLighthousePathTool implements
|
|
|
95
96
|
|
|
96
97
|
let nodeId;
|
|
97
98
|
try {
|
|
98
|
-
// Resolves the
|
|
99
|
+
// Resolves the DevTools node path (a representation of the path to a node)
|
|
99
100
|
// and ensures the node is loaded into the frontend DOM model, returning its ID.
|
|
100
101
|
nodeId = await domModel.pushNodeByPathToFrontend(params.path);
|
|
101
102
|
} catch {
|
|
102
|
-
|
|
103
|
+
// pushNodeByPathToFrontend can fail or return undefined
|
|
103
104
|
}
|
|
104
105
|
if (!nodeId) {
|
|
105
106
|
return {error: 'Error: Could not find node by path.'};
|
|
@@ -84,7 +84,7 @@ export interface LighthouseCapability {
|
|
|
84
84
|
* Unified context interface providing all capabilities available in the project.
|
|
85
85
|
* Used by the agent to pass a complete context to any tool type-safely.
|
|
86
86
|
*/
|
|
87
|
-
export type
|
|
87
|
+
export type AllToolsCapabilities = BaseToolCapability&PageExecutionCapability&StyleMutationCapability&TargetCapability&
|
|
88
88
|
OriginLockCapability&LighthouseCapability;
|
|
89
89
|
|
|
90
90
|
/**
|
|
@@ -98,7 +98,8 @@ export const enum ToolName {
|
|
|
98
98
|
LIST_NETWORK_REQUESTS = 'listNetworkRequests',
|
|
99
99
|
GET_NETWORK_REQUEST_DETAILS = 'getNetworkRequestDetails',
|
|
100
100
|
GET_LIGHTHOUSE_AUDITS = 'getLighthouseAudits',
|
|
101
|
-
|
|
101
|
+
RESOLVE_DEVTOOLS_NODE_PATH = 'resolveDevtoolsNodePath',
|
|
102
|
+
GET_ELEMENT_ACCESSIBILITY_DETAILS = 'getElementAccessibilityDetails',
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
/**
|
|
@@ -125,6 +126,10 @@ export interface BaseTool {
|
|
|
125
126
|
export interface Tool<Args extends ToolArgs = ToolArgs, ReturnType = unknown,
|
|
126
127
|
ContextType extends BaseToolCapability = BaseToolCapability> extends BaseTool {
|
|
127
128
|
readonly parameters: Host.AidaClient.FunctionObjectParam<keyof Args>;
|
|
129
|
+
/**
|
|
130
|
+
* Converts the tool arguments into user-friendly display information.
|
|
131
|
+
* This is used by the UI to show what the agent is doing (e.g., in the history/steps log).
|
|
132
|
+
*/
|
|
128
133
|
readonly displayInfoFromArgs?: (
|
|
129
134
|
args: Args,
|
|
130
135
|
) => {
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import {ExecuteJavaScriptTool} from './ExecuteJavaScript.js';
|
|
6
|
+
import {GetElementAccessibilityDetailsTool} from './GetElementAccessibilityDetails.js';
|
|
6
7
|
import {GetLighthouseAuditsTool} from './GetLighthouseAudits.js';
|
|
7
8
|
import {GetNetworkRequestDetailsTool} from './GetNetworkRequestDetails.js';
|
|
8
9
|
import {GetStylesTool} from './GetStyles.js';
|
|
9
10
|
import {ListNetworkRequestsTool} from './ListNetworkRequests.js';
|
|
10
|
-
import {
|
|
11
|
-
import {type
|
|
11
|
+
import {ResolveDevtoolsNodePathTool} from './ResolveDevtoolsNodePath.js';
|
|
12
|
+
import {type AllToolsCapabilities, type Tool, type ToolArgs, ToolName} from './Tool.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Plain object registry containing concrete instantiated tools.
|
|
@@ -24,7 +25,8 @@ export const TOOLS = {
|
|
|
24
25
|
[ToolName.LIST_NETWORK_REQUESTS]: new ListNetworkRequestsTool(),
|
|
25
26
|
[ToolName.GET_NETWORK_REQUEST_DETAILS]: new GetNetworkRequestDetailsTool(),
|
|
26
27
|
[ToolName.GET_LIGHTHOUSE_AUDITS]: new GetLighthouseAuditsTool(),
|
|
27
|
-
[ToolName.
|
|
28
|
+
[ToolName.RESOLVE_DEVTOOLS_NODE_PATH]: new ResolveDevtoolsNodePathTool(),
|
|
29
|
+
[ToolName.GET_ELEMENT_ACCESSIBILITY_DETAILS]: new GetElementAccessibilityDetailsTool(),
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -45,16 +47,16 @@ export class ToolRegistry {
|
|
|
45
47
|
* @param name The string name of the tool to retrieve, used when the tool name is only known at runtime.
|
|
46
48
|
* @returns The generic Tool interface, or undefined if not found.
|
|
47
49
|
*/
|
|
48
|
-
static get(name: string): Tool<ToolArgs, unknown,
|
|
49
|
-
static get(name: string): Tool<ToolArgs, unknown,
|
|
50
|
+
static get(name: string): Tool<ToolArgs, unknown, AllToolsCapabilities>|undefined;
|
|
51
|
+
static get(name: string): Tool<ToolArgs, unknown, AllToolsCapabilities>|undefined {
|
|
50
52
|
// We use a double assertion (`as unknown as Tool<...>`) here. TypeScript's variance
|
|
51
53
|
// rules prevent direct casting from specific concrete tools (which have narrowed,
|
|
52
|
-
// capability-specific contexts) to the generic `Tool` signature that uses `
|
|
54
|
+
// capability-specific contexts) to the generic `Tool` signature that uses `AllToolsCapabilities`.
|
|
53
55
|
// This cast is runtime-safe because any capability requested by a specific tool is
|
|
54
|
-
// guaranteed to be satisfied by `
|
|
56
|
+
// guaranteed to be satisfied by `AllToolsCapabilities`, and the handler will only access
|
|
55
57
|
// the capabilities it expects.
|
|
56
58
|
return Object.prototype.hasOwnProperty.call(TOOLS, name) ?
|
|
57
|
-
TOOLS[name as keyof typeof TOOLS] as unknown as Tool<ToolArgs, unknown,
|
|
59
|
+
TOOLS[name as keyof typeof TOOLS] as unknown as Tool<ToolArgs, unknown, AllToolsCapabilities>:
|
|
58
60
|
undefined;
|
|
59
61
|
}
|
|
60
62
|
}
|
|
@@ -7,27 +7,19 @@ import * as Platform from '../../core/platform/platform.js';
|
|
|
7
7
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
8
8
|
import type * as Protocol from '../../generated/protocol.js';
|
|
9
9
|
|
|
10
|
-
let autofillManagerInstance: AutofillManager;
|
|
11
|
-
|
|
12
10
|
export class AutofillManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
13
11
|
#address = '';
|
|
14
12
|
#filledFields: Protocol.Autofill.FilledField[] = [];
|
|
15
13
|
#matches: Match[] = [];
|
|
16
14
|
#autofillModel: SDK.AutofillModel.AutofillModel|null = null;
|
|
15
|
+
#frameManager: SDK.FrameManager.FrameManager;
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
constructor(targetManager: SDK.TargetManager.TargetManager,
|
|
18
|
+
frameManager: SDK.FrameManager.FrameManager = SDK.FrameManager.FrameManager.instance()) {
|
|
19
19
|
super();
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
static instance(opts: {forceNew: boolean|null} = {forceNew: null}): AutofillManager {
|
|
26
|
-
const {forceNew} = opts;
|
|
27
|
-
if (!autofillManagerInstance || forceNew) {
|
|
28
|
-
autofillManagerInstance = new AutofillManager();
|
|
29
|
-
}
|
|
30
|
-
return autofillManagerInstance;
|
|
20
|
+
this.#frameManager = frameManager;
|
|
21
|
+
targetManager.addModelListener(SDK.AutofillModel.AutofillModel, SDK.AutofillModel.Events.ADDRESS_FORM_FILLED,
|
|
22
|
+
this.#addressFormFilled, this, {scoped: true});
|
|
31
23
|
}
|
|
32
24
|
|
|
33
25
|
async #addressFormFilled({data}: Common.EventTarget.EventTargetEvent<
|
|
@@ -56,7 +48,7 @@ export class AutofillManager extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
56
48
|
|
|
57
49
|
highlightFilledField(filledField: Protocol.Autofill.FilledField): void {
|
|
58
50
|
const backendNodeId = filledField.fieldId;
|
|
59
|
-
const target =
|
|
51
|
+
const target = this.#frameManager.getFrame(filledField.frameId)?.resourceTreeModel().target();
|
|
60
52
|
if (target) {
|
|
61
53
|
const deferredNode = new SDK.DOMModel.DeferredDOMNode(target, backendNodeId);
|
|
62
54
|
const domModel = target.model(SDK.DOMModel.DOMModel);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
|
6
|
+
import * as Root from '../../core/root/root.js';
|
|
6
7
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
7
8
|
import type * as Protocol from '../../generated/protocol.js';
|
|
8
9
|
import type * as Workspace from '../workspace/workspace.js';
|
|
@@ -13,21 +14,16 @@ const uiSourceCodeToAttributionMap = new WeakMap<Workspace.UISourceCode.UISource
|
|
|
13
14
|
}>>();
|
|
14
15
|
const projectToTargetMap = new WeakMap<Workspace.Workspace.Project, SDK.Target.Target>();
|
|
15
16
|
|
|
16
|
-
let networkProjectManagerInstance: NetworkProjectManager;
|
|
17
|
-
|
|
18
17
|
export class NetworkProjectManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
19
|
-
private constructor() {
|
|
20
|
-
super();
|
|
21
|
-
}
|
|
22
18
|
|
|
23
19
|
static instance({forceNew}: {
|
|
24
20
|
forceNew: boolean,
|
|
25
21
|
} = {forceNew: false}): NetworkProjectManager {
|
|
26
|
-
if (!
|
|
27
|
-
|
|
22
|
+
if (!Root.DevToolsContext.globalInstance().has(NetworkProjectManager) || forceNew) {
|
|
23
|
+
Root.DevToolsContext.globalInstance().set(NetworkProjectManager, new NetworkProjectManager());
|
|
28
24
|
}
|
|
29
25
|
|
|
30
|
-
return
|
|
26
|
+
return Root.DevToolsContext.globalInstance().get(NetworkProjectManager);
|
|
31
27
|
}
|
|
32
28
|
}
|
|
33
29
|
|
|
@@ -14,7 +14,6 @@ import * as SourceMapScopes from '../source_map_scopes/source_map_scopes.js';
|
|
|
14
14
|
import type * as TextUtils from '../text_utils/text_utils.js';
|
|
15
15
|
import * as Workspace from '../workspace/workspace.js';
|
|
16
16
|
|
|
17
|
-
let breakpointManagerInstance: BreakpointManager;
|
|
18
17
|
const INITIAL_RESTORE_BREAKPOINT_COUNT = 100;
|
|
19
18
|
|
|
20
19
|
export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> implements
|
|
@@ -35,10 +34,9 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
|
35
34
|
readonly #breakpointByStorageId = new Map<string, Breakpoint>();
|
|
36
35
|
#updateBindingsCallbacks: Array<(uiSourceCode: Workspace.UISourceCode.UISourceCode) => Promise<void>> = [];
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
settings: Common.Settings.Settings, restoreInitialBreakpointCount?: number) {
|
|
37
|
+
constructor(targetManager: SDK.TargetManager.TargetManager, workspace: Workspace.Workspace.WorkspaceImpl,
|
|
38
|
+
debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding,
|
|
39
|
+
settings: Common.Settings.Settings, restoreInitialBreakpointCount?: number) {
|
|
42
40
|
super();
|
|
43
41
|
this.#workspace = workspace;
|
|
44
42
|
this.targetManager = targetManager;
|
|
@@ -85,18 +83,20 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
|
85
83
|
}): BreakpointManager {
|
|
86
84
|
const {forceNew, targetManager, workspace, debuggerWorkspaceBinding, settings, restoreInitialBreakpointCount} =
|
|
87
85
|
opts;
|
|
88
|
-
if (!
|
|
86
|
+
if (!Root.DevToolsContext.globalInstance().has(BreakpointManager) || forceNew) {
|
|
89
87
|
if (!targetManager || !workspace || !debuggerWorkspaceBinding || !settings) {
|
|
90
88
|
throw new Error(
|
|
91
89
|
`Unable to create settings: targetManager, workspace, debuggerWorkspaceBinding, and settings must be provided: ${
|
|
92
90
|
new Error().stack}`);
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
Root.DevToolsContext.globalInstance().set(
|
|
94
|
+
BreakpointManager,
|
|
95
|
+
new BreakpointManager(targetManager, workspace, debuggerWorkspaceBinding, settings,
|
|
96
|
+
restoreInitialBreakpointCount));
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
return
|
|
99
|
+
return Root.DevToolsContext.globalInstance().get(BreakpointManager);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
modelAdded(debuggerModel: SDK.DebuggerModel.DebuggerModel): void {
|
|
@@ -200,6 +200,10 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
static removeInstance(): void {
|
|
204
|
+
deviceModeModelInstance = null;
|
|
205
|
+
}
|
|
206
|
+
|
|
203
207
|
dispose(): void {
|
|
204
208
|
SDK.TargetManager.TargetManager.instance().unobserveModels(SDK.EmulationModel.EmulationModel, this);
|
|
205
209
|
}
|
|
@@ -573,6 +577,25 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
573
577
|
return this.#mode.insets;
|
|
574
578
|
}
|
|
575
579
|
|
|
580
|
+
private currentSafeAreaInsets(): Insets|null {
|
|
581
|
+
if (this.#type !== Type.Device || !this.#mode) {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
return this.#mode.safeAreaInsets ?? null;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private applySafeAreaInsets(insets: Insets|null): void {
|
|
588
|
+
if (!this.#emulationModel) {
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
if (insets) {
|
|
592
|
+
void this.#emulationModel.setSafeAreaInsets(
|
|
593
|
+
{top: insets.top, left: insets.left, bottom: insets.bottom, right: insets.right});
|
|
594
|
+
} else {
|
|
595
|
+
void this.#emulationModel.setSafeAreaInsets({});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
576
599
|
private getScreenOrientationType(): Protocol.Emulation.ScreenOrientationType {
|
|
577
600
|
if (!this.#mode) {
|
|
578
601
|
throw new Error('Mode required to get orientation type.');
|
|
@@ -649,6 +672,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
649
672
|
if (overlayModel) {
|
|
650
673
|
overlayModel.setShowViewportSizeOnResize(this.#type === Type.None);
|
|
651
674
|
}
|
|
675
|
+
this.applySafeAreaInsets(this.currentSafeAreaInsets());
|
|
652
676
|
this.dispatchEventToListeners(Events.UPDATED);
|
|
653
677
|
}
|
|
654
678
|
|
|
@@ -103,6 +103,15 @@ export class EmulatedDevice {
|
|
|
103
103
|
parseIntValue(json, 'bottom'));
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
function parseCutoutShape(json: any): CutoutShape {
|
|
107
|
+
const shape = parseValue(json, 'shape', 'string');
|
|
108
|
+
if (shape !== CutoutShape.PILL && shape !== CutoutShape.NOTCH && shape !== CutoutShape.CIRCLE &&
|
|
109
|
+
shape !== CutoutShape.RECTANGLE) {
|
|
110
|
+
throw new Error('Emulated device mode has unsupported cutout shape: ' + shape);
|
|
111
|
+
}
|
|
112
|
+
return shape;
|
|
113
|
+
}
|
|
114
|
+
|
|
106
115
|
function parseRGBA(json: any): SDK.OverlayModel.HighlightColor {
|
|
107
116
|
const result = {} as SDK.OverlayModel.HighlightColor;
|
|
108
117
|
result.r = parseIntValue(json, 'r');
|
|
@@ -257,6 +266,40 @@ export class EmulatedDevice {
|
|
|
257
266
|
throw new Error('Emulated device mode \'' + mode.title + '\'has wrong mode insets');
|
|
258
267
|
}
|
|
259
268
|
mode.image = (parseValue(modes[i], 'image', 'string', null) as string);
|
|
269
|
+
const safeAreaInsets = parseValue(modes[i], 'safe-area-insets', 'object', null);
|
|
270
|
+
if (safeAreaInsets) {
|
|
271
|
+
mode.safeAreaInsets = parseInsets(safeAreaInsets);
|
|
272
|
+
}
|
|
273
|
+
const cutout = parseValue(modes[i], 'cutout', 'object', null);
|
|
274
|
+
if (cutout) {
|
|
275
|
+
const shape = parseCutoutShape(cutout);
|
|
276
|
+
const baseCutout = {
|
|
277
|
+
x: parseIntValue(cutout, 'x'),
|
|
278
|
+
y: parseIntValue(cutout, 'y'),
|
|
279
|
+
width: parseIntValue(cutout, 'width'),
|
|
280
|
+
height: parseIntValue(cutout, 'height'),
|
|
281
|
+
};
|
|
282
|
+
if (shape === CutoutShape.PILL) {
|
|
283
|
+
mode.cutout = {shape, ...baseCutout, borderRadius: parseIntValue(cutout, 'border-radius')};
|
|
284
|
+
} else if (shape === CutoutShape.NOTCH) {
|
|
285
|
+
mode.cutout = {
|
|
286
|
+
shape,
|
|
287
|
+
...baseCutout,
|
|
288
|
+
upperRadius: parseIntValue(cutout, 'upper-radius'),
|
|
289
|
+
lowerRadius: parseIntValue(cutout, 'lower-radius'),
|
|
290
|
+
};
|
|
291
|
+
} else if (shape === CutoutShape.CIRCLE) {
|
|
292
|
+
mode.cutout = {
|
|
293
|
+
shape,
|
|
294
|
+
...baseCutout,
|
|
295
|
+
cx: parseIntValue(cutout, 'cx'),
|
|
296
|
+
cy: parseIntValue(cutout, 'cy'),
|
|
297
|
+
radius: parseIntValue(cutout, 'radius'),
|
|
298
|
+
};
|
|
299
|
+
} else {
|
|
300
|
+
mode.cutout = {shape, ...baseCutout};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
260
303
|
result.modes.push(mode);
|
|
261
304
|
}
|
|
262
305
|
result.#showByDefault = (parseValue(json, 'show-by-default', 'boolean', undefined) as boolean);
|
|
@@ -359,6 +402,35 @@ export class EmulatedDevice {
|
|
|
359
402
|
},
|
|
360
403
|
image: this.modes[i].image || undefined,
|
|
361
404
|
};
|
|
405
|
+
const safeAreaInsets = this.modes[i].safeAreaInsets;
|
|
406
|
+
if (safeAreaInsets) {
|
|
407
|
+
mode['safe-area-insets'] = {
|
|
408
|
+
left: safeAreaInsets.left,
|
|
409
|
+
top: safeAreaInsets.top,
|
|
410
|
+
right: safeAreaInsets.right,
|
|
411
|
+
bottom: safeAreaInsets.bottom,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
const cutout = this.modes[i].cutout;
|
|
415
|
+
if (cutout) {
|
|
416
|
+
mode.cutout = {
|
|
417
|
+
shape: cutout.shape,
|
|
418
|
+
x: cutout.x,
|
|
419
|
+
y: cutout.y,
|
|
420
|
+
width: cutout.width,
|
|
421
|
+
height: cutout.height,
|
|
422
|
+
};
|
|
423
|
+
if (cutout.shape === CutoutShape.PILL) {
|
|
424
|
+
mode.cutout['border-radius'] = cutout.borderRadius;
|
|
425
|
+
} else if (cutout.shape === CutoutShape.NOTCH) {
|
|
426
|
+
mode.cutout['upper-radius'] = cutout.upperRadius;
|
|
427
|
+
mode.cutout['lower-radius'] = cutout.lowerRadius;
|
|
428
|
+
} else if (cutout.shape === CutoutShape.CIRCLE) {
|
|
429
|
+
mode.cutout.cx = cutout.cx;
|
|
430
|
+
mode.cutout.cy = cutout.cy;
|
|
431
|
+
mode.cutout.radius = cutout.radius;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
362
434
|
json['modes'].push(mode);
|
|
363
435
|
}
|
|
364
436
|
|
|
@@ -637,7 +709,24 @@ export interface Mode {
|
|
|
637
709
|
orientation: string;
|
|
638
710
|
insets: Insets;
|
|
639
711
|
image: string|null;
|
|
712
|
+
safeAreaInsets?: Insets;
|
|
713
|
+
cutout?: Cutout;
|
|
640
714
|
}
|
|
715
|
+
export const enum CutoutShape {
|
|
716
|
+
PILL = 'pill',
|
|
717
|
+
NOTCH = 'notch',
|
|
718
|
+
CIRCLE = 'circle',
|
|
719
|
+
RECTANGLE = 'rectangle',
|
|
720
|
+
}
|
|
721
|
+
export interface BaseCutout {
|
|
722
|
+
x: number;
|
|
723
|
+
y: number;
|
|
724
|
+
width: number;
|
|
725
|
+
height: number;
|
|
726
|
+
}
|
|
727
|
+
export type Cutout = BaseCutout&({shape: CutoutShape.RECTANGLE}|{shape: CutoutShape.PILL, borderRadius: number}|
|
|
728
|
+
{shape: CutoutShape.NOTCH, upperRadius: number, lowerRadius: number}|
|
|
729
|
+
{shape: CutoutShape.CIRCLE, cx: number, cy: number, radius: number});
|
|
641
730
|
export interface Orientation {
|
|
642
731
|
width: number;
|
|
643
732
|
height: number;
|
|
@@ -655,6 +744,25 @@ export interface JSONMode {
|
|
|
655
744
|
top: number,
|
|
656
745
|
bottom: number,
|
|
657
746
|
};
|
|
747
|
+
'safe-area-insets'?: {
|
|
748
|
+
left: number,
|
|
749
|
+
right: number,
|
|
750
|
+
top: number,
|
|
751
|
+
bottom: number,
|
|
752
|
+
};
|
|
753
|
+
cutout?: {
|
|
754
|
+
shape: string,
|
|
755
|
+
x: number,
|
|
756
|
+
y: number,
|
|
757
|
+
width: number,
|
|
758
|
+
height: number,
|
|
759
|
+
'border-radius'?: number,
|
|
760
|
+
'upper-radius'?: number,
|
|
761
|
+
'lower-radius'?: number,
|
|
762
|
+
cx?: number,
|
|
763
|
+
cy?: number,
|
|
764
|
+
radius?: number,
|
|
765
|
+
};
|
|
658
766
|
}
|
|
659
767
|
|
|
660
768
|
// These props should quoted for the script to work properly
|
|
@@ -316,4 +316,40 @@ export interface DuplicateStringGroup {
|
|
|
316
316
|
distance: number,
|
|
317
317
|
}>;
|
|
318
318
|
truncated?: boolean;
|
|
319
|
+
length?: number;
|
|
320
|
+
hash?: number;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export interface NativeContextSize {
|
|
324
|
+
nodeId: number;
|
|
325
|
+
nodeIndex: number;
|
|
326
|
+
nodeName: string;
|
|
327
|
+
attributedSize: number;
|
|
328
|
+
retainedSize: number;
|
|
329
|
+
selfSize: number;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export interface NativeContextSizes {
|
|
333
|
+
nativeContexts: NativeContextSize[];
|
|
334
|
+
sharedSize: number;
|
|
335
|
+
noAttributionSize: number;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export const enum DOMLinkState {
|
|
339
|
+
UNKNOWN = 0,
|
|
340
|
+
ATTACHED = 1,
|
|
341
|
+
DETACHED = 2,
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export interface ObjectInfo {
|
|
345
|
+
id: number;
|
|
346
|
+
name: string;
|
|
347
|
+
type: string;
|
|
348
|
+
nodeIndex: number;
|
|
349
|
+
detachedness: DOMLinkState;
|
|
350
|
+
selfSize: number;
|
|
351
|
+
retainedSize: number;
|
|
352
|
+
distance: number;
|
|
353
|
+
edgeCount: number;
|
|
354
|
+
retainerCount: number;
|
|
319
355
|
}
|
|
@@ -267,6 +267,10 @@ export class HeapSnapshotProxy extends HeapSnapshotProxyObject {
|
|
|
267
267
|
return this.callMethodPromise('interfaceDefinitions');
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
getNativeContextSizes(): Promise<HeapSnapshotModel.NativeContextSizes> {
|
|
271
|
+
return this.callMethodPromise('getNativeContextSizes');
|
|
272
|
+
}
|
|
273
|
+
|
|
270
274
|
aggregatesWithFilter(filter: HeapSnapshotModel.NodeFilter):
|
|
271
275
|
Promise<Record<string, HeapSnapshotModel.AggregatedInfo>> {
|
|
272
276
|
return this.callMethodPromise('aggregatesWithFilter', filter);
|
|
@@ -295,6 +299,10 @@ export class HeapSnapshotProxy extends HeapSnapshotProxyObject {
|
|
|
295
299
|
return this.callMethodPromise('nodeIndexForId', nodeId);
|
|
296
300
|
}
|
|
297
301
|
|
|
302
|
+
getObjectInfo(nodeIndex: number): Promise<HeapSnapshotModel.ObjectInfo> {
|
|
303
|
+
return this.callMethodPromise('getObjectInfo', nodeIndex);
|
|
304
|
+
}
|
|
305
|
+
|
|
298
306
|
createEdgesProvider(nodeIndex: number): HeapSnapshotProviderProxy {
|
|
299
307
|
return this.callFactoryMethod('createEdgesProvider', HeapSnapshotProviderProxy, nodeIndex);
|
|
300
308
|
}
|
|
@@ -180,6 +180,7 @@ export function createIssuesFromProtocolIssue(
|
|
|
180
180
|
|
|
181
181
|
export interface IssuesManagerCreationOptions {
|
|
182
182
|
forceNew: boolean;
|
|
183
|
+
frameManager?: SDK.FrameManager.FrameManager;
|
|
183
184
|
/** Throw an error if this is not the first instance created */
|
|
184
185
|
ensureFirst: boolean;
|
|
185
186
|
showThirdPartyIssuesSetting?: Common.Settings.Setting<boolean>;
|
|
@@ -224,18 +225,20 @@ export class IssuesManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
224
225
|
#thirdPartyCookiePhaseoutIssueCount = new Map<IssueKind, number>();
|
|
225
226
|
#issuesById = new Map<string, Issue>();
|
|
226
227
|
#issuesByOutermostTarget: WeakMap<SDK.Target.Target, Set<Issue>> = new Map();
|
|
228
|
+
#frameManager: SDK.FrameManager.FrameManager;
|
|
227
229
|
|
|
228
|
-
constructor(
|
|
229
|
-
|
|
230
|
-
|
|
230
|
+
constructor(private readonly showThirdPartyIssuesSetting?: Common.Settings.Setting<boolean>,
|
|
231
|
+
private readonly hideIssueSetting?: Common.Settings.Setting<HideIssueMenuSetting>,
|
|
232
|
+
frameManager: SDK.FrameManager.FrameManager = SDK.FrameManager.FrameManager.instance()) {
|
|
231
233
|
super();
|
|
234
|
+
this.#frameManager = frameManager;
|
|
232
235
|
new SourceFrameIssuesManager(this);
|
|
233
236
|
SDK.TargetManager.TargetManager.instance().observeModels(SDK.IssuesModel.IssuesModel, this);
|
|
234
237
|
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
235
238
|
SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,
|
|
236
239
|
this.#onPrimaryPageChanged, this);
|
|
237
|
-
SDK.FrameManager.
|
|
238
|
-
|
|
240
|
+
this.#frameManager.addEventListener(SDK.FrameManager.Events.FRAME_ADDED_TO_TARGET, this.#onFrameAddedToTarget,
|
|
241
|
+
this);
|
|
239
242
|
|
|
240
243
|
// issueFilter uses the 'show-third-party-issues' setting. Clients of IssuesManager need
|
|
241
244
|
// a full update when the setting changes to get an up-to-date issues list.
|
|
@@ -263,7 +266,8 @@ export class IssuesManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
263
266
|
}
|
|
264
267
|
|
|
265
268
|
if (!issuesManagerInstance || opts.forceNew) {
|
|
266
|
-
issuesManagerInstance =
|
|
269
|
+
issuesManagerInstance =
|
|
270
|
+
new IssuesManager(opts.showThirdPartyIssuesSetting, opts.hideIssueSetting, opts.frameManager);
|
|
267
271
|
}
|
|
268
272
|
|
|
269
273
|
return issuesManagerInstance;
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import type * as Common from '../../core/common/common.js';
|
|
6
|
+
import * as Root from '../../core/root/root.js';
|
|
6
7
|
|
|
7
8
|
import {NativeFunctions} from './NativeFunctions.js';
|
|
8
9
|
|
|
9
|
-
let javaScriptMetadataInstance: JavaScriptMetadataImpl;
|
|
10
|
-
|
|
11
10
|
export class JavaScriptMetadataImpl implements Common.JavaScriptMetaData.JavaScriptMetaData {
|
|
12
11
|
private readonly uniqueFunctions: Map<string, string[][]>;
|
|
13
12
|
private readonly receiverMethods: Map<string, Map<string, string[][]>>;
|
|
@@ -15,11 +14,11 @@ export class JavaScriptMetadataImpl implements Common.JavaScriptMetaData.JavaScr
|
|
|
15
14
|
forceNew: boolean|null,
|
|
16
15
|
} = {forceNew: null}): JavaScriptMetadataImpl {
|
|
17
16
|
const {forceNew} = opts;
|
|
18
|
-
if (!
|
|
19
|
-
|
|
17
|
+
if (!Root.DevToolsContext.globalInstance().has(JavaScriptMetadataImpl) || forceNew) {
|
|
18
|
+
Root.DevToolsContext.globalInstance().set(JavaScriptMetadataImpl, new JavaScriptMetadataImpl());
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
return
|
|
21
|
+
return Root.DevToolsContext.globalInstance().get(JavaScriptMetadataImpl);
|
|
23
22
|
}
|
|
24
23
|
constructor() {
|
|
25
24
|
this.uniqueFunctions = new Map();
|