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 * as Common from '../../../core/common/common.js' ;
56import * as Platform from '../../../core/platform/platform.js' ;
67// eslint-disable-next-line rulesdir/no-imports-in-directory
78import type * as SDK from '../../../core/sdk/sdk.js' ;
89import type * as Protocol from '../../../generated/protocol.js' ;
910import * as Types from '../types/types.js' ;
1011
12+ import { data as metaHandlerData , type MetaHandlerData } from './MetaHandler.js' ;
13+
1114export interface ScriptsData {
1215 /** Note: this is only populated when the "Enhanced Traces" feature is enabled. */
1316 scripts : Map < Protocol . Runtime . ScriptId , Script > ;
@@ -18,7 +21,9 @@ export interface Script {
1821 frame : string ;
1922 ts : Types . Timing . Micro ;
2023 url ?: string ;
24+ sourceUrl ?: string ;
2125 content ?: string ;
26+ /** Note: this is the literal text given as the sourceMappingURL value. It has not been resolved relative to the script url. */
2227 sourceMapUrl ?: string ;
2328 sourceMap ?: SDK . SourceMap . SourceMap ;
2429}
@@ -30,8 +35,10 @@ export function reset(): void {
3035}
3136
3237export function handleEvent ( event : Types . Events . Event ) : void {
33- const getOrMakeScript = ( scriptId : Protocol . Runtime . ScriptId ) : Script =>
34- Platform . MapUtilities . getWithDefault ( scriptById , scriptId , ( ) => ( { scriptId, frame : '' , ts : 0 } as Script ) ) ;
38+ const getOrMakeScript = ( scriptIdAsNumber : number ) : Script => {
39+ const scriptId = String ( scriptIdAsNumber ) as Protocol . Runtime . ScriptId ;
40+ return Platform . MapUtilities . getWithDefault ( scriptById , scriptId , ( ) => ( { scriptId, frame : '' , ts : 0 } as Script ) ) ;
41+ } ;
3542
3643 if ( Types . Events . isTargetRundownEvent ( event ) && event . args . data ) {
3744 const { scriptId, frame} = event . args . data ;
@@ -43,9 +50,12 @@ export function handleEvent(event: Types.Events.Event): void {
4350 }
4451
4552 if ( Types . Events . isV8SourceRundownEvent ( event ) ) {
46- const { scriptId, url, sourceMapUrl} = event . args . data ;
53+ const { scriptId, url, sourceUrl , sourceMapUrl} = event . args . data ;
4754 const script = getOrMakeScript ( scriptId ) ;
4855 script . url = url ;
56+ if ( sourceUrl ) {
57+ script . sourceUrl = sourceUrl ;
58+ }
4959 if ( sourceMapUrl ) {
5060 script . sourceMapUrl = sourceMapUrl ;
5161 }
@@ -67,18 +77,65 @@ export function handleEvent(event: Types.Events.Event): void {
6777 }
6878}
6979
80+ function findFrame ( meta : MetaHandlerData , frameId : string ) : Types . Events . TraceFrame | null {
81+ for ( const frames of meta . frameByProcessId ?. values ( ) ) {
82+ const frame = frames . get ( frameId ) ;
83+ if ( frame ) {
84+ return frame ;
85+ }
86+ }
87+
88+ return null ;
89+ }
90+
7091export async function finalize ( options : Types . Configuration . ParseOptions ) : Promise < void > {
7192 if ( ! options . resolveSourceMap ) {
7293 return ;
7394 }
7495
96+ const meta = metaHandlerData ( ) ;
97+
7598 const promises = [ ] ;
7699 for ( const script of scriptById . values ( ) ) {
77- if ( script . sourceMapUrl ) {
78- promises . push ( options . resolveSourceMap ( script . sourceMapUrl ) . then ( sourceMap => {
79- script . sourceMap = sourceMap ;
80- } ) ) ;
100+ // No frame or url means the script came from somewhere we don't care about.
101+ // Note: scripts from inline <SCRIPT> elements use the url of the HTML document,
102+ // so aren't ignored.
103+ if ( ! script . frame || ! script . url || ! script . sourceMapUrl ) {
104+ continue ;
105+ }
106+
107+ const frameUrl = findFrame ( meta , script . frame ) ?. url as Platform . DevToolsPath . UrlString | undefined ;
108+ if ( ! frameUrl ) {
109+ continue ;
110+ }
111+
112+ // If there is a `sourceURL` magic comment, resolve the compiledUrl against the frame url.
113+ // example: `// #sourceURL=foo.js` for target frame https://www.example.com/home -> https://www.example.com/home/foo.js
114+ let sourceUrl = script . url ;
115+ if ( script . sourceUrl ) {
116+ sourceUrl = Common . ParsedURL . ParsedURL . completeURL ( frameUrl , script . sourceUrl ) ?? script . sourceUrl ;
81117 }
118+
119+ // Resolve the source map url. The value given by v8 may be relative, so resolve it here.
120+ // This process should match the one in `SourceMapManager.attachSourceMap`.
121+ const sourceMapUrl =
122+ Common . ParsedURL . ParsedURL . completeURL ( sourceUrl as Platform . DevToolsPath . UrlString , script . sourceMapUrl ) ;
123+ if ( ! sourceMapUrl ) {
124+ continue ;
125+ }
126+
127+ const params : Types . Configuration . ResolveSourceMapParams = {
128+ scriptId : script . scriptId ,
129+ scriptUrl : sourceUrl as Platform . DevToolsPath . UrlString ,
130+ sourceMapUrl : sourceMapUrl as Platform . DevToolsPath . UrlString ,
131+ frame : script . frame as Protocol . Page . FrameId ,
132+ } ;
133+ const promise = options . resolveSourceMap ( params ) . then ( sourceMap => {
134+ if ( sourceMap ) {
135+ script . sourceMap = sourceMap ;
136+ }
137+ } ) ;
138+ promises . push ( promise ) ;
82139 }
83140 await Promise . all ( promises ) ;
84141}
0 commit comments