@@ -29,7 +29,7 @@ const readFilep = promisify(fs.readFile);
2929export interface MapInfoInput {
3030 outputFile : string ;
3131 mapFile : string ;
32- mapConsumer : sourceMap . RawSourceMap ;
32+ mapConsumer : sourceMap . SourceMapConsumer ;
3333 // the sources are in ascending order from
3434 // shortest to longest
3535 sources : string [ ] ;
@@ -59,24 +59,23 @@ async function processSourcemap(
5959 }
6060 mapPath = path . normalize ( mapPath ) ;
6161
62- let contents ;
62+ let rawSourceMapString ;
6363 try {
64- contents = await readFilep ( mapPath , 'utf8' ) ;
64+ rawSourceMapString = await readFilep ( mapPath , 'utf8' ) ;
6565 } catch ( e ) {
6666 throw new Error ( 'Could not read sourcemap file ' + mapPath + ': ' + e ) ;
6767 }
6868
69- let consumer : sourceMap . RawSourceMap ;
69+ let rawSourceMap ;
7070 try {
71- // TODO: Determine how to reconsile the type conflict where `consumer`
72- // is constructed as a SourceMapConsumer but is used as a
73- // RawSourceMap.
74- // TODO: Resolve the cast of `contents as any` (This is needed because the
75- // type is expected to be of `RawSourceMap` but the existing
76- // working code uses a string.)
77- consumer = new sourceMap . SourceMapConsumer (
78- contents as { } as sourceMap . RawSourceMap
79- ) as { } as sourceMap . RawSourceMap ;
71+ rawSourceMap = JSON . parse ( rawSourceMapString ) ;
72+ } catch ( e ) {
73+ throw new Error ( 'Could not parse the raw sourcemap ' + mapPath + ': ' + e ) ;
74+ }
75+
76+ let consumer : sourceMap . SourceMapConsumer ;
77+ try {
78+ consumer = await new sourceMap . SourceMapConsumer ( rawSourceMapString ) ;
8079 } catch ( e ) {
8180 throw new Error (
8281 'An error occurred while reading the ' +
@@ -93,40 +92,57 @@ async function processSourcemap(
9392 * containing the map file. Otherwise, use the name of the output
9493 * file (with the .map extension removed) as the output file.
9594 */
96- const outputBase = consumer . file
97- ? consumer . file
95+ const outputBase = rawSourceMap . file
96+ ? rawSourceMap . file
9897 : path . basename ( mapPath , '.map' ) ;
9998 const parentDir = path . dirname ( mapPath ) ;
10099 const outputPath = path . normalize ( path . join ( parentDir , outputBase ) ) ;
101100
102- // the sources are in ascending order from shortest to longest
103- const nonemptySources = consumer . sources
104- . filter ( val => ! ! val )
105- . sort ( ( src1 , src2 ) => src1 . length - src2 . length ) ;
101+ // The paths of the sources that are relative to the source map file. Sort
102+ // them in ascending order from shortest to longest.
103+ // For webpack file path, normalize the path after the webpack prefix so that
104+ // the source map library can recognize it.
105+ const sourcesRelToSrcmap = rawSourceMap . sources
106+ . filter ( ( val : string ) => ! ! val )
107+ . map ( ( val : string ) => {
108+ if ( val . toLowerCase ( ) . startsWith ( WEBPACK_PREFIX ) ) {
109+ return (
110+ WEBPACK_PREFIX +
111+ path . normalize ( val . substr ( WEBPACK_PREFIX . length ) ) . replace ( / \\ / g, '/' )
112+ ) ;
113+ }
114+ return val ;
115+ } )
116+ . sort ( ( src1 : string , src2 : string ) => src1 . length - src2 . length ) ;
106117
107- const normalizedSources = nonemptySources
118+ // The paths of the sources that are relative to the current process's working
119+ // directory. These are the ones that are used for the fuzzy search (thus are
120+ // platform specific, e.g. using '\\' on Windows and using '/' in Unix, etc.).
121+ // For webpack file path, the prefix is filtered out for better fuzzy search
122+ // result.
123+ const normalizedSourcesRelToProc = sourcesRelToSrcmap
108124 . map ( ( src : string ) => {
109125 if ( src . toLowerCase ( ) . startsWith ( WEBPACK_PREFIX ) ) {
110126 return src . substring ( WEBPACK_PREFIX . length ) ;
111127 }
112128 return src ;
113129 } )
114130 . map ( ( relPath : string ) => {
115- // resolve the paths relative to the map file so that
116- // they are relative to the process's current working
117- // directory
131+ // resolve the paths relative to the map file so that they are relative to
132+ // the process's current working directory
118133 return path . normalize ( path . join ( parentDir , relPath ) ) ;
119134 } ) ;
120135
121- if ( normalizedSources . length === 0 ) {
136+ if ( normalizedSourcesRelToProc . length === 0 ) {
122137 throw new Error ( 'No sources listed in the sourcemap file ' + mapPath ) ;
123138 }
124- for ( const src of normalizedSources ) {
139+
140+ for ( const src of normalizedSourcesRelToProc ) {
125141 infoMap . set ( path . normalize ( src ) , {
126142 outputFile : outputPath ,
127143 mapFile : mapPath ,
128144 mapConsumer : consumer ,
129- sources : nonemptySources ,
145+ sources : sourcesRelToSrcmap ,
130146 } ) ;
131147 }
132148}
@@ -223,7 +239,6 @@ export class SourceMapper {
223239 const relPath = path
224240 . relative ( path . dirname ( entry . mapFile ) , inputPath )
225241 . replace ( / \\ / g, '/' ) ;
226-
227242 /**
228243 * Note: Since `entry.sources` is in ascending order from shortest
229244 * to longest, the first source path that ends with the
@@ -245,27 +260,26 @@ export class SourceMapper {
245260 column : colNumber , // to be zero-based
246261 } ;
247262
248- // TODO: Determine how to remove the explicit cast here.
249- const consumer : sourceMap . SourceMapConsumer =
250- entry . mapConsumer as { } as sourceMap . SourceMapConsumer ;
251- const allPos = consumer . allGeneratedPositionsFor ( sourcePos ) ;
263+ const allPos = entry . mapConsumer . allGeneratedPositionsFor ( sourcePos ) ;
252264 /*
253265 * Based on testing, it appears that the following code is needed to
254266 * properly get the correct mapping information.
255267 *
256268 * In particular, the generatedPositionFor() alone doesn't appear to
257269 * give the correct mapping information.
258270 */
259- const mappedPos : sourceMap . Position =
271+ const mappedPos : sourceMap . NullablePosition =
260272 allPos && allPos . length > 0
261273 ? allPos . reduce ( ( accumulator , value ) => {
262- return value . line < accumulator . line ? value : accumulator ;
274+ return ( value . line ?? 0 ) < ( accumulator . line ?? 0 )
275+ ? value
276+ : accumulator ;
263277 } )
264- : consumer . generatedPositionFor ( sourcePos ) ;
278+ : entry . mapConsumer . generatedPositionFor ( sourcePos ) ;
265279
266280 return {
267281 file : entry . outputFile ,
268- line : mappedPos . line - 1 , // convert the one-based line numbers returned
282+ line : ( mappedPos . line ?? 0 ) - 1 , // convert the one-based line numbers returned
269283 // by the SourceMapConsumer to the expected
270284 // zero-based output.
271285 // TODO: The `sourceMap.Position` type definition has a `column`
0 commit comments