Skip to content

Commit 2ea50df

Browse files
Connor ClarkDevtools-frontend LUCI CQ
authored andcommitted
[RPP] Add ScriptsHandler for content and source maps
Bug: 394373632, 394373852 Change-Id: If57823fcae581a0788a9339dc1cf1db2c9521412 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6253620 Auto-Submit: Connor Clark <[email protected]> Commit-Queue: Adam Raine <[email protected]> Reviewed-by: Adam Raine <[email protected]>
1 parent 3f890ce commit 2ea50df

File tree

12 files changed

+170
-2
lines changed

12 files changed

+170
-2
lines changed

config/gni/devtools_grd_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ grd_files_debug_sources = [
11011101
"front_end/models/trace/handlers/RendererHandler.js",
11021102
"front_end/models/trace/handlers/SamplesHandler.js",
11031103
"front_end/models/trace/handlers/ScreenshotsHandler.js",
1104+
"front_end/models/trace/handlers/ScriptsHandler.js",
11041105
"front_end/models/trace/handlers/SelectorStatsHandler.js",
11051106
"front_end/models/trace/handlers/ServerTimingsHandler.js",
11061107
"front_end/models/trace/handlers/Threads.js",

front_end/core/sdk/EnhancedTracesParser.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ describe('EnhancedTracesParser', () => {
7373
isModule: false,
7474
url: 'http://localhost:8080/index.html',
7575
hasSourceUrl: false,
76-
sourceMapUrl: 'http://localhost:8080/source',
76+
sourceMapUrl: 'http://localhost:8080/source.map.json',
7777
length: 13,
7878
sourceText: 'source text 1',
7979
auxData: {

front_end/models/trace/handlers/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ devtools_module("handlers") {
3434
"RendererHandler.ts",
3535
"SamplesHandler.ts",
3636
"ScreenshotsHandler.ts",
37+
"ScriptsHandler.ts",
3738
"SelectorStatsHandler.ts",
3839
"ServerTimingsHandler.ts",
3940
"Threads.ts",
@@ -94,6 +95,7 @@ ts_library("unittests") {
9495
"RendererHandler.test.ts",
9596
"SamplesHandler.test.ts",
9697
"ScreenshotsHandler.test.ts",
98+
"ScriptsHandler.test.ts",
9799
"SelectorStatsHandler.test.ts",
98100
"ServerTimingsHandler.test.ts",
99101
"Threads.test.ts",

front_end/models/trace/handlers/FramesHandler.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ async function processTrace(events: readonly Trace.Types.Events.Event[]): Promis
2727
}
2828
for (const handlerName of handlersInOrder) {
2929
const handler = Trace.Handlers.ModelHandlers[handlerName];
30-
await handler.finalize();
30+
await handler.finalize({});
3131
}
3232
}
3333

front_end/models/trace/handlers/ModelHandlers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export * as PageLoadMetrics from './PageLoadMetricsHandler.js';
2626
export * as Renderer from './RendererHandler.js';
2727
export * as Samples from './SamplesHandler.js';
2828
export * as Screenshots from './ScreenshotsHandler.js';
29+
export * as Scripts from './ScriptsHandler.js';
2930
export * as SelectorStats from './SelectorStatsHandler.js';
3031
export * as ServerTimings from './ServerTimingsHandler.js';
3132
export * as UserInteractions from './UserInteractionsHandler.js';
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// eslint-disable-next-line rulesdir/no-imports-in-directory
6+
import type * as SDK from '../../../core/sdk/sdk.js';
7+
import {TraceLoader} from '../../../testing/TraceLoader.js';
8+
import * as Trace from '../trace.js';
9+
10+
describe('ScriptsHandler', () => {
11+
beforeEach(async function() {
12+
Trace.Handlers.ModelHandlers.Scripts.reset();
13+
const events = await TraceLoader.rawEvents(this, 'enhanced-traces.json.gz');
14+
for (const event of events) {
15+
Trace.Handlers.ModelHandlers.Scripts.handleEvent(event);
16+
}
17+
await Trace.Handlers.ModelHandlers.Scripts.finalize({
18+
async resolveSourceMap(url: string): Promise<SDK.SourceMap.SourceMapV3> {
19+
// Don't need to actually make a source map.
20+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
21+
return {test: url} as any;
22+
}
23+
});
24+
});
25+
26+
afterEach(() => {
27+
Trace.Handlers.ModelHandlers.Scripts.reset();
28+
});
29+
30+
it('collects scripts contents', async function() {
31+
const data = Trace.Handlers.ModelHandlers.Scripts.data();
32+
assert.deepEqual([...data.scripts.values()], [
33+
{
34+
scriptId: '1',
35+
url: 'http://localhost:8080/index.html',
36+
content: ' text ',
37+
sourceMapUrl: 'http://localhost:8080/source.map.json',
38+
sourceMap: {test: 'http://localhost:8080/source.map.json'}
39+
},
40+
{scriptId: '2', url: 'http://localhost:8080/index.html', content: 'source text 2'},
41+
]);
42+
});
43+
});
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
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 Platform from '../../../core/platform/platform.js';
6+
// eslint-disable-next-line rulesdir/no-imports-in-directory
7+
import type * as SDK from '../../../core/sdk/sdk.js';
8+
import type * as Protocol from '../../../generated/protocol.js';
9+
import * as Types from '../types/types.js';
10+
11+
export interface ScriptsData {
12+
/** Note: this is only populated when the "Enhanced Traces" feature is enabled. */
13+
scripts: Map<Protocol.Runtime.ScriptId, {}>;
14+
}
15+
16+
interface Script {
17+
scriptId: Protocol.Runtime.ScriptId;
18+
url?: string;
19+
content?: string;
20+
sourceMapUrl?: string;
21+
sourceMap?: SDK.SourceMap.SourceMapV3;
22+
}
23+
24+
const scriptById = new Map<Protocol.Runtime.ScriptId, Script>();
25+
26+
export function reset(): void {
27+
scriptById.clear();
28+
}
29+
30+
export function handleEvent(event: Types.Events.Event): void {
31+
if (Types.Events.isScriptRundownEvent(event)) {
32+
const {scriptId, url, sourceMapUrl} = event.args.data;
33+
const script = Platform.MapUtilities.getWithDefault(scriptById, scriptId, () => ({scriptId} as Script));
34+
script.url = url;
35+
// Ignore nonsense values, which is what this was when initially implemented.
36+
// TODO(cjamcl): https://g-issues.chromium.org/issues/337909145#comment15
37+
if (sourceMapUrl && sourceMapUrl !== url && sourceMapUrl.endsWith('.json')) {
38+
script.sourceMapUrl = sourceMapUrl;
39+
}
40+
return;
41+
}
42+
43+
if (Types.Events.isScriptSourceRundownEvent(event)) {
44+
const {scriptId, sourceText} = event.args.data;
45+
const script = Platform.MapUtilities.getWithDefault(scriptById, scriptId, () => ({scriptId} as Script));
46+
script.content = sourceText;
47+
return;
48+
}
49+
}
50+
51+
export async function finalize(options: Types.Configuration.ParseOptions): Promise<void> {
52+
if (!options.resolveSourceMap) {
53+
return;
54+
}
55+
56+
const promises = [];
57+
for (const script of scriptById.values()) {
58+
if (script.sourceMapUrl) {
59+
promises.push(options.resolveSourceMap(script.sourceMapUrl).then(sourceMap => {
60+
script.sourceMap = sourceMap;
61+
}));
62+
}
63+
}
64+
await Promise.all(promises);
65+
}
66+
67+
export function data(): ScriptsData {
68+
return {
69+
scripts: scriptById,
70+
};
71+
}

front_end/models/trace/types/Configuration.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import type * as SDK from '../../../core/sdk/sdk.js';
6+
57
import type * as File from './File.js';
68

79
export interface Configuration {
@@ -64,4 +66,5 @@ export interface ParseOptions {
6466
*/
6567
isCPUProfile?: boolean;
6668
metadata?: File.MetaData;
69+
resolveSourceMap?: (url: string) => Promise<SDK.SourceMap.SourceMapV3>;
6770
}

front_end/models/trace/types/TraceEvents.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3073,3 +3073,43 @@ export interface LegacyLayerPaintEventPicture {
30733073
rect: Array<number>;
30743074
serializedPicture: string;
30753075
}
3076+
3077+
export interface ScriptRundownEvent extends Event {
3078+
cat: 'disabled-by-default-devtools.v8-source-rundown';
3079+
args: Args&{
3080+
data: {
3081+
isolate: string,
3082+
executionContextId: Protocol.Runtime.ExecutionContextId,
3083+
scriptId: Protocol.Runtime.ScriptId,
3084+
startLine: number,
3085+
startColumn: number,
3086+
endLine: number,
3087+
endColumn: number,
3088+
url: string,
3089+
hash: string,
3090+
isModule: boolean,
3091+
hasSourceUrl: boolean,
3092+
sourceMapUrl?: string,
3093+
},
3094+
};
3095+
}
3096+
3097+
export function isScriptRundownEvent(event: Event): event is ScriptRundownEvent {
3098+
return event.cat === 'disabled-by-default-devtools.v8-source-rundown';
3099+
}
3100+
3101+
export interface ScriptSourceRundownEvent extends Event {
3102+
cat: 'disabled-by-default-devtools.v8-source-rundown-sources';
3103+
args: Args&{
3104+
data: {
3105+
isolate: string,
3106+
scriptId: Protocol.Runtime.ScriptId,
3107+
length?: number,
3108+
sourceText?: string,
3109+
},
3110+
};
3111+
}
3112+
3113+
export function isScriptSourceRundownEvent(event: Event): event is ScriptSourceRundownEvent {
3114+
return event.cat === 'disabled-by-default-devtools.v8-source-rundown-sources';
3115+
}

front_end/panels/timeline/fixtures/traces/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,7 @@ Trace containing a cross-origin navigation where DOM size events from the pre-na
258258
### lcp-fetchpriority-high
259259

260260
A page that loads an image as the LCP resource with fetchpriority=high set.
261+
262+
### enhanced-traces
263+
264+
(faked) script contents and source map urls, from the new "enhanced traces" feature. See http://crbug.com/337909145

0 commit comments

Comments
 (0)