chrome-devtools-frontend 1.0.1555174 → 1.0.1555430
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/front_end/core/protocol_client/InspectorBackend.ts +1 -1
- package/front_end/core/root/Runtime.ts +0 -4
- package/front_end/core/sdk/DOMModel.ts +101 -7
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +1 -1
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +1 -1
- package/front_end/{ui/components → models}/annotations/AnnotationRepository.ts +3 -3
- package/front_end/models/annotations/README.md +7 -0
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +8 -0
- package/front_end/models/stack_trace/StackTrace.ts +13 -2
- package/front_end/models/stack_trace/StackTraceImpl.ts +81 -6
- package/front_end/models/stack_trace/StackTraceModel.ts +35 -3
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +45 -4
- package/front_end/panels/ai_assistance/components/ArtifactsViewer.ts +57 -0
- package/front_end/panels/ai_assistance/components/ChatView.ts +1 -0
- package/front_end/panels/ai_assistance/components/artifactsViewer.css +10 -0
- package/front_end/panels/application/preloading/PreloadingView.ts +12 -6
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +230 -237
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +96 -79
- package/front_end/panels/application/preloading/components/preloadingGrid.css +26 -29
- package/front_end/panels/application/preloading/preloadingView.css +6 -0
- package/front_end/panels/common/Annotation.ts +1 -1
- package/front_end/panels/common/AnnotationManager.ts +1 -1
- package/front_end/panels/common/ExtensionView.ts +1 -0
- package/front_end/panels/console/ConsoleContextSelector.ts +74 -9
- package/front_end/panels/console/consoleContextSelector.css +31 -29
- package/front_end/panels/coverage/coverageListView.css +59 -57
- package/front_end/panels/elements/ElementsPanel.ts +1 -1
- package/front_end/panels/elements/ElementsTreeElement.ts +39 -1
- package/front_end/panels/elements/ElementsTreeOutline.ts +23 -21
- package/front_end/panels/elements/TopLayerContainer.ts +26 -91
- package/front_end/panels/explain/components/ConsoleInsight.ts +3 -3
- package/front_end/panels/network/NetworkItemView.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +1 -1
- package/front_end/panels/network/NetworkPanel.ts +1 -1
- package/front_end/panels/recorder/RecorderController.ts +0 -1
- package/front_end/panels/security/SecurityPanelSidebar.ts +5 -0
- package/front_end/panels/timeline/TimelineUIUtils.ts +5 -8
- package/front_end/panels/timeline/components/TimelineSummary.ts +75 -54
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +16 -25
- package/front_end/panels/timeline/components/insights/Cache.ts +12 -8
- package/front_end/panels/timeline/components/insights/DOMSize.ts +25 -21
- package/front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts +7 -7
- package/front_end/panels/timeline/components/insights/FontDisplay.ts +7 -5
- package/front_end/panels/timeline/components/insights/ForcedReflow.ts +11 -9
- package/front_end/panels/timeline/components/insights/INPBreakdown.ts +7 -6
- package/front_end/panels/timeline/components/insights/ImageDelivery.ts +7 -5
- package/front_end/panels/timeline/components/insights/InsightRenderer.ts +20 -18
- package/front_end/panels/timeline/components/insights/LCPBreakdown.ts +12 -12
- package/front_end/panels/timeline/components/insights/LegacyJavaScript.ts +7 -7
- package/front_end/panels/timeline/components/insights/ModernHTTP.ts +7 -5
- package/front_end/panels/timeline/components/insights/NetworkDependencyTree.ts +15 -13
- package/front_end/panels/timeline/components/insights/RenderBlocking.ts +2 -2
- package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +15 -14
- package/front_end/panels/timeline/components/insights/Table.ts +152 -130
- package/front_end/panels/timeline/components/insights/ThirdParties.ts +11 -9
- package/front_end/panels/timeline/components/timelineSummary.css +58 -57
- package/front_end/panels/timeline/thirdPartyTreeView.css +109 -0
- package/front_end/panels/timeline/timelineDetailsView.css +2 -4
- package/front_end/panels/timeline/timelinePanel.css +0 -110
- package/front_end/ui/legacy/TabbedPane.ts +1 -1
- package/front_end/ui/legacy/ViewManager.ts +2 -32
- package/package.json +1 -1
- /package/front_end/{ui/components → models}/annotations/AnnotationType.ts +0 -0
- /package/front_end/{ui/components → models}/annotations/annotations.ts +0 -0
|
@@ -389,7 +389,6 @@ export interface HostConfigFreestyler {
|
|
|
389
389
|
multimodal?: boolean;
|
|
390
390
|
multimodalUploadInput?: boolean;
|
|
391
391
|
functionCalling?: boolean;
|
|
392
|
-
featureName?: string;
|
|
393
392
|
}
|
|
394
393
|
|
|
395
394
|
export interface HostConfigAiAssistanceNetworkAgent {
|
|
@@ -397,7 +396,6 @@ export interface HostConfigAiAssistanceNetworkAgent {
|
|
|
397
396
|
temperature: number;
|
|
398
397
|
enabled: boolean;
|
|
399
398
|
userTier: string;
|
|
400
|
-
featureName?: string;
|
|
401
399
|
}
|
|
402
400
|
|
|
403
401
|
export interface HostConfigAiAssistancePerformanceAgent {
|
|
@@ -405,7 +403,6 @@ export interface HostConfigAiAssistancePerformanceAgent {
|
|
|
405
403
|
temperature: number;
|
|
406
404
|
enabled: boolean;
|
|
407
405
|
userTier: string;
|
|
408
|
-
featureName?: string;
|
|
409
406
|
}
|
|
410
407
|
|
|
411
408
|
export interface HostConfigAiAssistanceFileAgent {
|
|
@@ -413,7 +410,6 @@ export interface HostConfigAiAssistanceFileAgent {
|
|
|
413
410
|
temperature: number;
|
|
414
411
|
enabled: boolean;
|
|
415
412
|
userTier: string;
|
|
416
|
-
featureName?: string;
|
|
417
413
|
}
|
|
418
414
|
|
|
419
415
|
export interface HostConfigAiCodeCompletion {
|
|
@@ -108,7 +108,15 @@ export const ARIA_ATTRIBUTES = new Set<string>([
|
|
|
108
108
|
'aria-valuetext',
|
|
109
109
|
]);
|
|
110
110
|
|
|
111
|
-
export
|
|
111
|
+
export enum DOMNodeEvents {
|
|
112
|
+
TOP_LAYER_INDEX_CHANGED = 'TopLayerIndexChanged',
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface DOMNodeEventTypes {
|
|
116
|
+
[DOMNodeEvents.TOP_LAYER_INDEX_CHANGED]: void;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export class DOMNode extends Common.ObjectWrapper.ObjectWrapper<DOMNodeEventTypes> {
|
|
112
120
|
#domModel: DOMModel;
|
|
113
121
|
#agent: ProtocolProxyApi.DOMApi;
|
|
114
122
|
ownerDocument!: DOMDocument|null;
|
|
@@ -162,8 +170,14 @@ export class DOMNode {
|
|
|
162
170
|
detached = false;
|
|
163
171
|
#retainedNodes?: Set<Protocol.DOM.BackendNodeId>;
|
|
164
172
|
#adoptedStyleSheets: AdoptedStyleSheet[] = [];
|
|
173
|
+
/**
|
|
174
|
+
* 1-based index of the node in the top layer. Only set
|
|
175
|
+
* for non-backdrop nodes.
|
|
176
|
+
*/
|
|
177
|
+
#topLayerIndex = -1;
|
|
165
178
|
|
|
166
179
|
constructor(domModel: DOMModel) {
|
|
180
|
+
super();
|
|
167
181
|
this.#domModel = domModel;
|
|
168
182
|
this.#agent = this.#domModel.getAgent();
|
|
169
183
|
}
|
|
@@ -285,6 +299,18 @@ export class DOMNode {
|
|
|
285
299
|
return await (childModel?.requestDocument() || null);
|
|
286
300
|
}
|
|
287
301
|
|
|
302
|
+
setTopLayerIndex(idx: number): void {
|
|
303
|
+
const oldIndex = this.#topLayerIndex;
|
|
304
|
+
this.#topLayerIndex = idx;
|
|
305
|
+
if (oldIndex !== idx) {
|
|
306
|
+
this.dispatchEventToListeners(DOMNodeEvents.TOP_LAYER_INDEX_CHANGED);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
topLayerIndex(): number {
|
|
311
|
+
return this.#topLayerIndex;
|
|
312
|
+
}
|
|
313
|
+
|
|
288
314
|
isAdFrameNode(): boolean {
|
|
289
315
|
if (this.isIframe() && this.#frameOwnerFrameId) {
|
|
290
316
|
const frame = FrameManager.instance().getFrame(this.#frameOwnerFrameId);
|
|
@@ -1203,10 +1229,16 @@ export class DOMNodeShortcut {
|
|
|
1203
1229
|
nodeType: number;
|
|
1204
1230
|
nodeName: string;
|
|
1205
1231
|
deferredNode: DeferredDOMNode;
|
|
1206
|
-
|
|
1232
|
+
// Shortctus to elements that children of the element this shortcut is for.
|
|
1233
|
+
// Currently, use for backdrop elements in the top layer.«
|
|
1234
|
+
childShortcuts: DOMNodeShortcut[] = [];
|
|
1235
|
+
constructor(
|
|
1236
|
+
target: Target, backendNodeId: Protocol.DOM.BackendNodeId, nodeType: number, nodeName: string,
|
|
1237
|
+
childShortcuts: DOMNodeShortcut[] = []) {
|
|
1207
1238
|
this.nodeType = nodeType;
|
|
1208
1239
|
this.nodeName = nodeName;
|
|
1209
1240
|
this.deferredNode = new DeferredDOMNode(target, backendNodeId);
|
|
1241
|
+
this.childShortcuts = childShortcuts;
|
|
1210
1242
|
}
|
|
1211
1243
|
}
|
|
1212
1244
|
|
|
@@ -1241,6 +1273,9 @@ export class DOMModel extends SDKModel<EventTypes> {
|
|
|
1241
1273
|
#frameOwnerNode?: DOMNode|null;
|
|
1242
1274
|
#loadNodeAttributesTimeout?: number;
|
|
1243
1275
|
#searchId?: string;
|
|
1276
|
+
#topLayerThrottler = new Common.Throttler.Throttler(100);
|
|
1277
|
+
#topLayerNodes: DOMNode[] = [];
|
|
1278
|
+
|
|
1244
1279
|
constructor(target: Target) {
|
|
1245
1280
|
super(target);
|
|
1246
1281
|
|
|
@@ -1621,10 +1656,6 @@ export class DOMModel extends SDKModel<EventTypes> {
|
|
|
1621
1656
|
this.dispatchEventToListeners(Events.AffectedByStartingStylesFlagUpdated, {node});
|
|
1622
1657
|
}
|
|
1623
1658
|
|
|
1624
|
-
topLayerElementsUpdated(): void {
|
|
1625
|
-
this.dispatchEventToListeners(Events.TopLayerElementsChanged);
|
|
1626
|
-
}
|
|
1627
|
-
|
|
1628
1659
|
pseudoElementRemoved(parentId: Protocol.DOM.NodeId, pseudoElementId: Protocol.DOM.NodeId): void {
|
|
1629
1660
|
const parent = this.idToDOMNode.get(parentId);
|
|
1630
1661
|
if (!parent) {
|
|
@@ -1730,6 +1761,69 @@ export class DOMModel extends SDKModel<EventTypes> {
|
|
|
1730
1761
|
return this.agent.invoke_getTopLayerElements().then(({nodeIds}) => nodeIds);
|
|
1731
1762
|
}
|
|
1732
1763
|
|
|
1764
|
+
topLayerElementsUpdated(): void {
|
|
1765
|
+
void this.#topLayerThrottler.schedule(async () => {
|
|
1766
|
+
// This returns top layer nodes for all local frames.
|
|
1767
|
+
const result = await this.agent.invoke_getTopLayerElements();
|
|
1768
|
+
if (result.getError()) {
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
// Re-set indexes as we re-create top layer nodes list.
|
|
1772
|
+
const previousDocs = new Set<DOMDocument>();
|
|
1773
|
+
for (const node of this.#topLayerNodes) {
|
|
1774
|
+
node.setTopLayerIndex(-1);
|
|
1775
|
+
if (node.ownerDocument) {
|
|
1776
|
+
previousDocs.add(node.ownerDocument);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
this.#topLayerNodes.splice(0);
|
|
1780
|
+
const nodes: DOMNode[] =
|
|
1781
|
+
result.nodeIds.map(id => this.idToDOMNode.get(id)).filter((node): node is DOMNode => Boolean(node));
|
|
1782
|
+
const nodesByDocument = new Map<DOMDocument, DOMNode[]>();
|
|
1783
|
+
for (const node of nodes) {
|
|
1784
|
+
const document = node.ownerDocument;
|
|
1785
|
+
if (!document) {
|
|
1786
|
+
continue;
|
|
1787
|
+
}
|
|
1788
|
+
if (!nodesByDocument.has(document)) {
|
|
1789
|
+
nodesByDocument.set(document, []);
|
|
1790
|
+
}
|
|
1791
|
+
nodesByDocument.get(document)?.push(node);
|
|
1792
|
+
}
|
|
1793
|
+
for (const [document, nodes] of nodesByDocument) {
|
|
1794
|
+
let topLayerIdx = 1;
|
|
1795
|
+
const documentShortcuts = [];
|
|
1796
|
+
for (const [idx, node] of nodes.entries()) {
|
|
1797
|
+
if (node.nodeName() === '::backdrop') {
|
|
1798
|
+
continue;
|
|
1799
|
+
}
|
|
1800
|
+
const childShortcuts = [];
|
|
1801
|
+
const previousNode = result.nodeIds[idx - 1] ? this.idToDOMNode.get(result.nodeIds[idx - 1]) : null;
|
|
1802
|
+
if (previousNode && previousNode.nodeName() === '::backdrop') {
|
|
1803
|
+
childShortcuts.push(
|
|
1804
|
+
new DOMNodeShortcut(this.target(), previousNode.backendNodeId(), 0, previousNode.nodeName()));
|
|
1805
|
+
}
|
|
1806
|
+
const shortcut = new DOMNodeShortcut(this.target(), node.backendNodeId(), 0, node.nodeName(), childShortcuts);
|
|
1807
|
+
node.setTopLayerIndex(topLayerIdx++);
|
|
1808
|
+
this.#topLayerNodes.push(node);
|
|
1809
|
+
documentShortcuts.push(shortcut);
|
|
1810
|
+
previousDocs.delete(document);
|
|
1811
|
+
}
|
|
1812
|
+
this.dispatchEventToListeners(Events.TopLayerElementsChanged, {
|
|
1813
|
+
document,
|
|
1814
|
+
documentShortcuts,
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
// Emit empty events for documents that are no longer in the top layer.
|
|
1818
|
+
for (const document of previousDocs) {
|
|
1819
|
+
this.dispatchEventToListeners(Events.TopLayerElementsChanged, {
|
|
1820
|
+
document,
|
|
1821
|
+
documentShortcuts: [],
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1733
1827
|
getDetachedDOMNodes(): Promise<Protocol.DOM.DetachedElementInfo[]|null> {
|
|
1734
1828
|
return this.agent.invoke_getDetachedDomNodes().then(({detachedNodes}) => detachedNodes);
|
|
1735
1829
|
}
|
|
@@ -1823,7 +1917,7 @@ export interface EventTypes {
|
|
|
1823
1917
|
[Events.ChildNodeCountUpdated]: DOMNode;
|
|
1824
1918
|
[Events.DistributedNodesChanged]: DOMNode;
|
|
1825
1919
|
[Events.MarkersChanged]: DOMNode;
|
|
1826
|
-
[Events.TopLayerElementsChanged]:
|
|
1920
|
+
[Events.TopLayerElementsChanged]: {document: DOMDocument, documentShortcuts: DOMNodeShortcut[]};
|
|
1827
1921
|
[Events.ScrollableFlagUpdated]: {node: DOMNode};
|
|
1828
1922
|
[Events.AffectedByStartingStylesFlagUpdated]: {node: DOMNode};
|
|
1829
1923
|
[Events.AdoptedStyleSheetsModified]: DOMNode;
|
|
@@ -9,7 +9,7 @@ import * as Platform from '../../../core/platform/platform.js';
|
|
|
9
9
|
import * as Root from '../../../core/root/root.js';
|
|
10
10
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
11
11
|
import * as Tracing from '../../../services/tracing/tracing.js';
|
|
12
|
-
import * as Annotations from '
|
|
12
|
+
import * as Annotations from '../../annotations/annotations.js';
|
|
13
13
|
import * as SourceMapScopes from '../../source_map_scopes/source_map_scopes.js';
|
|
14
14
|
import * as Trace from '../../trace/trace.js';
|
|
15
15
|
import {
|
|
@@ -8,7 +8,7 @@ import * as Platform from '../../../core/platform/platform.js';
|
|
|
8
8
|
import * as Root from '../../../core/root/root.js';
|
|
9
9
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
10
10
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
11
|
-
import * as Annotations from '
|
|
11
|
+
import * as Annotations from '../../annotations/annotations.js';
|
|
12
12
|
import {ChangeManager} from '../ChangeManager.js';
|
|
13
13
|
import {debugLog} from '../debug.js';
|
|
14
14
|
import {EvaluateAction, formatError, SideEffectError} from '../EvaluateAction.js';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
6
|
-
import * as Annotations from '
|
|
6
|
+
import * as Annotations from '../../annotations/annotations.js';
|
|
7
7
|
import * as Logs from '../../logs/logs.js';
|
|
8
8
|
import * as NetworkTimeCalculator from '../../network_time_calculator/network_time_calculator.js';
|
|
9
9
|
import * as TextUtils from '../../text_utils/text_utils.js';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import type * as Platform from '../../../core/platform/platform.js';
|
|
6
6
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
7
|
-
import * as Annotations from '
|
|
7
|
+
import * as Annotations from '../../annotations/annotations.js';
|
|
8
8
|
import * as CrUXManager from '../../crux-manager/crux-manager.js';
|
|
9
9
|
import type * as SourceMapScopes from '../../source_map_scopes/source_map_scopes.js';
|
|
10
10
|
import * as Trace from '../../trace/trace.js';
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
-
import * as Common from '
|
|
6
|
-
import * as Root from '
|
|
7
|
-
import type * as SDK from '
|
|
5
|
+
import * as Common from '../../core/common/common.js';
|
|
6
|
+
import * as Root from '../../core/root/root.js';
|
|
7
|
+
import type * as SDK from '../../core/sdk/sdk.js';
|
|
8
8
|
|
|
9
9
|
import {AnnotationType} from './AnnotationType.js';
|
|
10
10
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Annotations Model
|
|
2
|
+
|
|
3
|
+
**IMPORTANT**: this model exists because on the GreenDev project we prototyped a build of DevTools that is able to add annotations to various parts of the UI.
|
|
4
|
+
|
|
5
|
+
This feature is only enabled when Chromium is run with the GreenDev feature flag enabled. There are currently NO PLANS to ship this code to production.
|
|
6
|
+
|
|
7
|
+
If you are reading this and you want to use this code, please speak to jacktfranklin@ first. This code is for a prototype and not in a production state.
|
|
@@ -191,6 +191,14 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
|
|
|
191
191
|
return await model.createFromProtocolRuntime(stackTrace, this.#translateRawFrames.bind(this));
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
async createStackTraceFromDebuggerPaused(
|
|
195
|
+
pausedDetails: SDK.DebuggerModel.DebuggerPausedDetails,
|
|
196
|
+
target: SDK.Target.Target): Promise<StackTrace.StackTrace.DebuggableStackTrace> {
|
|
197
|
+
const model =
|
|
198
|
+
target.model(StackTraceImpl.StackTraceModel.StackTraceModel) as StackTraceImpl.StackTraceModel.StackTraceModel;
|
|
199
|
+
return await model.createFromDebuggerPaused(pausedDetails, this.#translateRawFrames.bind(this));
|
|
200
|
+
}
|
|
201
|
+
|
|
194
202
|
async createLiveLocation(
|
|
195
203
|
rawLocation: SDK.DebuggerModel.Location, updateDelegate: (arg0: LiveLocation) => Promise<void>,
|
|
196
204
|
locationPool: LiveLocationPool): Promise<Location|null> {
|
|
@@ -6,8 +6,11 @@ import type * as Common from '../../core/common/common.js';
|
|
|
6
6
|
import type * as SDK from '../../core/sdk/sdk.js';
|
|
7
7
|
import type * as Workspace from '../workspace/workspace.js';
|
|
8
8
|
|
|
9
|
-
export
|
|
10
|
-
|
|
9
|
+
export type StackTrace = BaseStackTrace<Fragment>;
|
|
10
|
+
export type DebuggableStackTrace = BaseStackTrace<DebuggableFragment>;
|
|
11
|
+
|
|
12
|
+
export interface BaseStackTrace<SyncFragmentT extends Fragment> extends Common.EventTarget.EventTarget<EventTypes> {
|
|
13
|
+
readonly syncFragment: SyncFragmentT;
|
|
11
14
|
readonly asyncFragments: readonly AsyncFragment[];
|
|
12
15
|
}
|
|
13
16
|
|
|
@@ -19,6 +22,10 @@ export interface AsyncFragment extends Fragment {
|
|
|
19
22
|
readonly description: string;
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
export interface DebuggableFragment {
|
|
26
|
+
readonly frames: readonly DebuggableFrame[];
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
export interface Frame {
|
|
23
30
|
readonly url?: string;
|
|
24
31
|
readonly uiSourceCode?: Workspace.UISourceCode.UISourceCode;
|
|
@@ -29,6 +36,10 @@ export interface Frame {
|
|
|
29
36
|
readonly missingDebugInfo?: MissingDebugInfo;
|
|
30
37
|
}
|
|
31
38
|
|
|
39
|
+
export interface DebuggableFrame extends Frame {
|
|
40
|
+
readonly sdkFrame: SDK.DebuggerModel.CallFrame;
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
export const enum MissingDebugInfoType {
|
|
33
44
|
/** No debug information at all for the call frame */
|
|
34
45
|
NO_INFO = 'NO_INFO',
|
|
@@ -3,29 +3,36 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
|
6
|
+
import type * as SDK from '../../core/sdk/sdk.js';
|
|
6
7
|
import type * as Workspace from '../workspace/workspace.js';
|
|
7
8
|
|
|
8
9
|
import type * as StackTrace from './stack_trace.js';
|
|
9
10
|
import type {FrameNode} from './Trie.js';
|
|
10
11
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
export type AnyStackTraceImpl = StackTraceImpl<FragmentImpl|DebuggableFragmentImpl>;
|
|
13
|
+
|
|
14
|
+
export class StackTraceImpl<SyncFragmentT extends FragmentImpl|DebuggableFragmentImpl = FragmentImpl> extends
|
|
15
|
+
Common.ObjectWrapper.ObjectWrapper<StackTrace.StackTrace.EventTypes> implements
|
|
16
|
+
StackTrace.StackTrace.BaseStackTrace<SyncFragmentT> {
|
|
17
|
+
readonly syncFragment: SyncFragmentT;
|
|
14
18
|
readonly asyncFragments: readonly AsyncFragmentImpl[];
|
|
15
19
|
|
|
16
|
-
constructor(syncFragment:
|
|
20
|
+
constructor(syncFragment: SyncFragmentT, asyncFragments: AsyncFragmentImpl[]) {
|
|
17
21
|
super();
|
|
18
22
|
this.syncFragment = syncFragment;
|
|
19
23
|
this.asyncFragments = asyncFragments;
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
const fragment =
|
|
26
|
+
syncFragment instanceof DebuggableFragmentImpl ? syncFragment.fragment : syncFragment as FragmentImpl;
|
|
27
|
+
fragment.stackTraces.add(this);
|
|
28
|
+
|
|
22
29
|
this.asyncFragments.forEach(asyncFragment => asyncFragment.fragment.stackTraces.add(this));
|
|
23
30
|
}
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
export class FragmentImpl implements StackTrace.StackTrace.Fragment {
|
|
27
34
|
readonly node: FrameNode;
|
|
28
|
-
readonly stackTraces = new Set<
|
|
35
|
+
readonly stackTraces = new Set<AnyStackTraceImpl>();
|
|
29
36
|
|
|
30
37
|
/**
|
|
31
38
|
* Fragments are deduplicated based on the node.
|
|
@@ -83,3 +90,71 @@ export class FrameImpl implements StackTrace.StackTrace.Frame {
|
|
|
83
90
|
this.missingDebugInfo = missingDebugInfo;
|
|
84
91
|
}
|
|
85
92
|
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A DebuggableFragmentImpl wraps an existing FragmentImpl. This is important: We can pause at the
|
|
96
|
+
* same location multiple times and the paused information changes each and everytime while the underlying
|
|
97
|
+
* FragmentImpl will stay the same.
|
|
98
|
+
*/
|
|
99
|
+
export class DebuggableFragmentImpl implements StackTrace.StackTrace.DebuggableFragment {
|
|
100
|
+
constructor(readonly fragment: FragmentImpl, private readonly callFrames: SDK.DebuggerModel.CallFrame[]) {
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get frames(): DebuggableFrameImpl[] {
|
|
104
|
+
const frames: DebuggableFrameImpl[] = [];
|
|
105
|
+
|
|
106
|
+
let index = 0;
|
|
107
|
+
for (const node of this.fragment.node.getCallStack()) {
|
|
108
|
+
for (const frame of node.frames) {
|
|
109
|
+
// Each inlined frame gets the same DebugerModel.CallFrame for debugging.
|
|
110
|
+
frames.push(new DebuggableFrameImpl(frame, this.callFrames[index]));
|
|
111
|
+
}
|
|
112
|
+
index++;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return frames;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* A DebuggableFrameImpl wraps an existing FrameImpl. This is important: We can pause at the
|
|
121
|
+
* same location multiple times and the paused information changes each and everytime while the underlying
|
|
122
|
+
* FrameImpl will stay the same.
|
|
123
|
+
*/
|
|
124
|
+
export class DebuggableFrameImpl implements StackTrace.StackTrace.DebuggableFrame {
|
|
125
|
+
readonly #frame: FrameImpl;
|
|
126
|
+
readonly #sdkFrame: SDK.DebuggerModel.CallFrame;
|
|
127
|
+
|
|
128
|
+
constructor(frame: FrameImpl, sdkFrame: SDK.DebuggerModel.CallFrame) {
|
|
129
|
+
this.#frame = frame;
|
|
130
|
+
this.#sdkFrame = sdkFrame;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
get url(): string|undefined {
|
|
134
|
+
return this.#frame.url;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
get uiSourceCode(): Workspace.UISourceCode.UISourceCode|undefined {
|
|
138
|
+
return this.#frame.uiSourceCode;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get name(): string|undefined {
|
|
142
|
+
return this.#frame.name;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
get line(): number {
|
|
146
|
+
return this.#frame.line;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
get column(): number {
|
|
150
|
+
return this.#frame.column;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get missingDebugInfo(): StackTrace.StackTrace.MissingDebugInfo|undefined {
|
|
154
|
+
return this.#frame.missingDebugInfo;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
get sdkFrame(): SDK.DebuggerModel.CallFrame {
|
|
158
|
+
return this.#sdkFrame;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -7,7 +7,14 @@ import type * as Protocol from '../../generated/protocol.js';
|
|
|
7
7
|
|
|
8
8
|
// eslint-disable-next-line @devtools/es-modules-import
|
|
9
9
|
import * as StackTrace from './stack_trace.js';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
type AnyStackTraceImpl,
|
|
12
|
+
AsyncFragmentImpl,
|
|
13
|
+
DebuggableFragmentImpl,
|
|
14
|
+
FragmentImpl,
|
|
15
|
+
FrameImpl,
|
|
16
|
+
StackTraceImpl
|
|
17
|
+
} from './StackTraceImpl.js';
|
|
11
18
|
import {type FrameNode, type RawFrame, Trie} from './Trie.js';
|
|
12
19
|
|
|
13
20
|
/**
|
|
@@ -45,10 +52,21 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
45
52
|
return new StackTraceImpl(syncFragment, asyncFragments);
|
|
46
53
|
}
|
|
47
54
|
|
|
55
|
+
async createFromDebuggerPaused(
|
|
56
|
+
pausedDetails: SDK.DebuggerModel.DebuggerPausedDetails,
|
|
57
|
+
rawFramesToUIFrames: TranslateRawFrames): Promise<StackTrace.StackTrace.DebuggableStackTrace> {
|
|
58
|
+
const [syncFragment, asyncFragments] = await Promise.all([
|
|
59
|
+
this.#createDebuggableFragment(pausedDetails, rawFramesToUIFrames),
|
|
60
|
+
this.#createAsyncFragments(pausedDetails, rawFramesToUIFrames),
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
return new StackTraceImpl(syncFragment, asyncFragments);
|
|
64
|
+
}
|
|
65
|
+
|
|
48
66
|
/** Trigger re-translation of all fragments with the provide script in their call stack */
|
|
49
67
|
async scriptInfoChanged(script: SDK.Script.Script, translateRawFrames: TranslateRawFrames): Promise<void> {
|
|
50
68
|
const translatePromises: Array<Promise<unknown>> = [];
|
|
51
|
-
let stackTracesToUpdate = new Set<
|
|
69
|
+
let stackTracesToUpdate = new Set<AnyStackTraceImpl>();
|
|
52
70
|
|
|
53
71
|
for (const fragment of this.#affectedFragments(script)) {
|
|
54
72
|
// We trigger re-translation only for fragments of leaf-nodes. Any fragment along the ancestor-chain
|
|
@@ -75,8 +93,22 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
75
93
|
return fragment;
|
|
76
94
|
}
|
|
77
95
|
|
|
96
|
+
async #createDebuggableFragment(
|
|
97
|
+
pausedDetails: SDK.DebuggerModel.DebuggerPausedDetails,
|
|
98
|
+
rawFramesToUIFrames: TranslateRawFrames): Promise<DebuggableFragmentImpl> {
|
|
99
|
+
const fragment = this.#createFragment(pausedDetails.callFrames.map(frame => ({
|
|
100
|
+
scriptId: frame.script.scriptId,
|
|
101
|
+
url: frame.script.sourceURL,
|
|
102
|
+
functionName: frame.functionName,
|
|
103
|
+
lineNumber: frame.location().lineNumber,
|
|
104
|
+
columnNumber: frame.location().columnNumber,
|
|
105
|
+
})));
|
|
106
|
+
await this.#translateFragment(fragment, rawFramesToUIFrames);
|
|
107
|
+
return new DebuggableFragmentImpl(fragment, pausedDetails.callFrames);
|
|
108
|
+
}
|
|
109
|
+
|
|
78
110
|
async #createAsyncFragments(
|
|
79
|
-
stackTraceOrPausedEvent: Protocol.Runtime.StackTrace|
|
|
111
|
+
stackTraceOrPausedEvent: Protocol.Runtime.StackTrace|SDK.DebuggerModel.DebuggerPausedDetails,
|
|
80
112
|
rawFramesToUIFrames: TranslateRawFrames): Promise<AsyncFragmentImpl[]> {
|
|
81
113
|
const asyncFragments: AsyncFragmentImpl[] = [];
|
|
82
114
|
const translatePromises: Array<Promise<unknown>> = [];
|
|
@@ -12,10 +12,10 @@ import * as Root from '../../core/root/root.js';
|
|
|
12
12
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
13
13
|
import * as Protocol from '../../generated/protocol.js';
|
|
14
14
|
import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
|
|
15
|
+
import * as Annotations from '../../models/annotations/annotations.js';
|
|
15
16
|
import * as Badges from '../../models/badges/badges.js';
|
|
16
17
|
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
17
18
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
18
|
-
import * as Annotations from '../../ui/components/annotations/annotations.js';
|
|
19
19
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
20
20
|
import * as Snackbars from '../../ui/components/snackbars/snackbars.js';
|
|
21
21
|
import * as UIHelpers from '../../ui/helpers/helpers.js';
|
|
@@ -27,6 +27,7 @@ import * as NetworkPanel from '../network/network.js';
|
|
|
27
27
|
import * as TimelinePanel from '../timeline/timeline.js';
|
|
28
28
|
|
|
29
29
|
import aiAssistancePanelStyles from './aiAssistancePanel.css.js';
|
|
30
|
+
import {ArtifactsViewer} from './components/ArtifactsViewer.js';
|
|
30
31
|
import {
|
|
31
32
|
type AnswerPart,
|
|
32
33
|
type ChatMessage,
|
|
@@ -294,6 +295,8 @@ interface ToolbarViewInput {
|
|
|
294
295
|
onExportConversationClick: () => void;
|
|
295
296
|
onHelpClick: () => void;
|
|
296
297
|
onSettingsClick: () => void;
|
|
298
|
+
onArtifactsSidebarToggle: () => void;
|
|
299
|
+
artifactsSidebarVisible: boolean;
|
|
297
300
|
isLoading: boolean;
|
|
298
301
|
showChatActions: boolean;
|
|
299
302
|
showActiveConversationActions: boolean;
|
|
@@ -386,6 +389,13 @@ function toolbarView(input: ToolbarViewInput): Lit.LitTemplate {
|
|
|
386
389
|
.jslogContext=${'freestyler.settings'}
|
|
387
390
|
.variant=${Buttons.Button.Variant.TOOLBAR}
|
|
388
391
|
@click=${input.onSettingsClick}></devtools-button>
|
|
392
|
+
<!-- If the green experiment is enabled, render the artifacts sidebar toggle button -->
|
|
393
|
+
${Root.Runtime.hostConfig.devToolsGreenDevUi?.enabled ? html`<devtools-button
|
|
394
|
+
title=${i18nString(UIStrings.settings)}
|
|
395
|
+
aria-label=${i18nString(UIStrings.settings)}
|
|
396
|
+
.iconName=${input.artifactsSidebarVisible ? 'left-panel-open' : 'left-panel-close'}
|
|
397
|
+
.variant=${Buttons.Button.Variant.TOOLBAR}
|
|
398
|
+
@click=${input.onArtifactsSidebarToggle}></devtools-button>` : Lit.nothing}
|
|
389
399
|
</devtools-toolbar>
|
|
390
400
|
</div>
|
|
391
401
|
`;
|
|
@@ -396,8 +406,9 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
|
|
|
396
406
|
// clang-format off
|
|
397
407
|
function renderState(): Lit.TemplateResult {
|
|
398
408
|
switch (input.state) {
|
|
399
|
-
case ViewState.CHAT_VIEW:
|
|
400
|
-
|
|
409
|
+
case ViewState.CHAT_VIEW: {
|
|
410
|
+
const aiChatView = html`
|
|
411
|
+
<devtools-ai-chat-view
|
|
401
412
|
.props=${input.props}
|
|
402
413
|
${Lit.Directives.ref((el: Element | undefined) => {
|
|
403
414
|
if (!el || !(el instanceof ChatView)) {
|
|
@@ -407,6 +418,30 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
|
|
|
407
418
|
output.chatView = el;
|
|
408
419
|
})}
|
|
409
420
|
></devtools-ai-chat-view>`;
|
|
421
|
+
// If the green experiment is enabled, render the chat view inside
|
|
422
|
+
// a split view to also have an artifacts viewer sidebar.
|
|
423
|
+
if(Root.Runtime.hostConfig.devToolsGreenDevUi?.enabled) {
|
|
424
|
+
return html`
|
|
425
|
+
<devtools-split-view
|
|
426
|
+
direction="column"
|
|
427
|
+
sidebar-visibility=${input.props.isArtifactsSidebarOpen ? 'visible' : 'hidden'}
|
|
428
|
+
sidebar-position="second"
|
|
429
|
+
style="width: 100%;"
|
|
430
|
+
>
|
|
431
|
+
<div slot="main">
|
|
432
|
+
${aiChatView}
|
|
433
|
+
</div>
|
|
434
|
+
<div slot="sidebar">
|
|
435
|
+
<devtools-widget
|
|
436
|
+
class="fill-panel"
|
|
437
|
+
.widgetConfig=${UI.Widget.widgetConfig(ArtifactsViewer)}
|
|
438
|
+
></devtools-widget>
|
|
439
|
+
</div>
|
|
440
|
+
</devtools-split-view>`;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return aiChatView;
|
|
444
|
+
}
|
|
410
445
|
case ViewState.EXPLORE_VIEW:
|
|
411
446
|
return html`<devtools-widget
|
|
412
447
|
class="fill-panel"
|
|
@@ -482,7 +517,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
482
517
|
#selectedElement: AiAssistanceModel.StylingAgent.NodeContext|null = null;
|
|
483
518
|
#selectedPerformanceTrace: AiAssistanceModel.PerformanceAgent.PerformanceTraceContext|null = null;
|
|
484
519
|
#selectedRequest: AiAssistanceModel.NetworkAgent.RequestContext|null = null;
|
|
485
|
-
|
|
520
|
+
#isArtifactsSidebarOpen = false;
|
|
486
521
|
// Messages displayed in the `ChatView` component.
|
|
487
522
|
#messages: ChatMessage[] = [];
|
|
488
523
|
|
|
@@ -574,6 +609,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
574
609
|
uploadImageInputEnabled: isAiAssistanceMultimodalUploadInputEnabled() &&
|
|
575
610
|
this.#conversation.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
|
|
576
611
|
markdownRenderer,
|
|
612
|
+
isArtifactsSidebarOpen: this.#isArtifactsSidebarOpen,
|
|
577
613
|
onTextSubmit: async (
|
|
578
614
|
text: string, imageInput?: Host.AidaClient.Part,
|
|
579
615
|
multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
|
|
@@ -927,6 +963,11 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
927
963
|
onSettingsClick: () => {
|
|
928
964
|
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
|
|
929
965
|
},
|
|
966
|
+
onArtifactsSidebarToggle: () => {
|
|
967
|
+
this.#isArtifactsSidebarOpen = !this.#isArtifactsSidebarOpen;
|
|
968
|
+
this.requestUpdate();
|
|
969
|
+
},
|
|
970
|
+
artifactsSidebarVisible: this.#isArtifactsSidebarOpen,
|
|
930
971
|
};
|
|
931
972
|
}
|
|
932
973
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Copyright 2025 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as UI from '../../../ui/legacy/legacy.js';
|
|
6
|
+
import * as Lit from '../../../ui/lit/lit.js';
|
|
7
|
+
|
|
8
|
+
import artifactsViewerStyles from './artifactsViewer.css.js';
|
|
9
|
+
|
|
10
|
+
const {html, render} = Lit;
|
|
11
|
+
|
|
12
|
+
export interface ViewInput {
|
|
13
|
+
artifacts: [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const DEFAULT_VIEW = (
|
|
17
|
+
_input: ViewInput,
|
|
18
|
+
_output: Record<string, unknown>,
|
|
19
|
+
target: HTMLElement,
|
|
20
|
+
): void => {
|
|
21
|
+
// clang-format off
|
|
22
|
+
render(
|
|
23
|
+
html`
|
|
24
|
+
<style>${artifactsViewerStyles}</style>
|
|
25
|
+
<div>
|
|
26
|
+
Artifacts Viewer
|
|
27
|
+
</div>
|
|
28
|
+
`,
|
|
29
|
+
target
|
|
30
|
+
);
|
|
31
|
+
// clang-format on
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type View = typeof DEFAULT_VIEW;
|
|
35
|
+
|
|
36
|
+
export class ArtifactsViewer extends UI.Widget.Widget {
|
|
37
|
+
#view: View;
|
|
38
|
+
constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
|
|
39
|
+
super(element);
|
|
40
|
+
this.#view = view;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override wasShown(): void {
|
|
44
|
+
super.wasShown();
|
|
45
|
+
void this.requestUpdate();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override performUpdate(): Promise<void>|void {
|
|
49
|
+
this.#view(
|
|
50
|
+
{
|
|
51
|
+
artifacts: [],
|
|
52
|
+
},
|
|
53
|
+
{},
|
|
54
|
+
this.contentElement,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|