@@ -99,6 +99,10 @@ namespace ts {
9999 let sourceMapDataList : SourceMapData [ ] | undefined ;
100100 let disabled : boolean = ! ( compilerOptions . sourceMap || compilerOptions . inlineSourceMap ) ;
101101
102+ let completedSections : SourceMapSectionDefinition [ ] ;
103+ let sectionStartLine : number ;
104+ let sectionStartColumn : number ;
105+
102106 return {
103107 initialize,
104108 reset,
@@ -146,6 +150,9 @@ namespace ts {
146150 lastEncodedNameIndex = 0 ;
147151
148152 // Initialize source map data
153+ completedSections = [ ] ;
154+ sectionStartLine = 0 ;
155+ sectionStartColumn = 0 ;
149156 sourceMapData = {
150157 sourceMapFilePath,
151158 jsSourceMappingURL : ! compilerOptions . inlineSourceMap ? getBaseFileName ( normalizeSlashes ( sourceMapFilePath ) ) : undefined ! , // TODO: GH#18217
@@ -214,6 +221,68 @@ namespace ts {
214221 lastEncodedNameIndex = undefined ;
215222 sourceMapData = undefined ! ;
216223 sourceMapDataList = undefined ! ;
224+ completedSections = undefined ! ;
225+ sectionStartLine = undefined ! ;
226+ sectionStartColumn = undefined ! ;
227+ }
228+
229+ interface SourceMapSection {
230+ version : 3 ;
231+ file : string ;
232+ sourceRoot ?: string ;
233+ sources : string [ ] ;
234+ names ?: string [ ] ;
235+ mappings : string ;
236+ sourcesContent ?: string [ ] ;
237+ sections ?: undefined ;
238+ }
239+
240+ type SourceMapSectionDefinition =
241+ | { offset : { line : number , column : number } , url : string } // Included for completeness
242+ | { offset : { line : number , column : number } , map : SourceMap } ;
243+
244+ interface SectionalSourceMap {
245+ version : 3 ;
246+ file : string ;
247+ sections : SourceMapSectionDefinition [ ] ;
248+ }
249+
250+ type SourceMap = SectionalSourceMap | SourceMapSection ;
251+
252+ function captureSection ( ) : SourceMapSection {
253+ return {
254+ version : 3 ,
255+ file : sourceMapData . sourceMapFile ,
256+ sourceRoot : sourceMapData . sourceMapSourceRoot ,
257+ sources : sourceMapData . sourceMapSources ,
258+ names : sourceMapData . sourceMapNames ,
259+ mappings : sourceMapData . sourceMapMappings ,
260+ sourcesContent : sourceMapData . sourceMapSourcesContent ,
261+ } ;
262+ }
263+
264+ function resetSectionalData ( ) : void {
265+ sourceMapData . sourceMapSources = [ ] ;
266+ sourceMapData . sourceMapNames = [ ] ;
267+ sourceMapData . sourceMapMappings = "" ;
268+ sourceMapData . sourceMapSourcesContent = compilerOptions . inlineSources ? [ ] : undefined ;
269+ }
270+
271+ function generateMap ( ) : SourceMap {
272+ if ( completedSections . length ) {
273+ const last = {
274+ offset : { line : sectionStartLine , column : sectionStartColumn } ,
275+ map : captureSection ( )
276+ } ;
277+ return {
278+ version : 3 ,
279+ file : last . map . file ,
280+ sections : [ ...completedSections , last ]
281+ } ;
282+ }
283+ else {
284+ return captureSection ( ) ;
285+ }
217286 }
218287
219288 // Encoding for sourcemap span
@@ -284,8 +353,8 @@ namespace ts {
284353 sourceLinePos . line ++ ;
285354 sourceLinePos . character ++ ;
286355
287- const emittedLine = writer . getLine ( ) ;
288- const emittedColumn = writer . getColumn ( ) ;
356+ const emittedLine = writer . getLine ( ) - sectionStartLine ;
357+ const emittedColumn = emittedLine === 0 ? writer . getColumn ( ) - sectionStartColumn : writer . getColumn ( ) ;
289358
290359 // If this location wasn't recorded or the location in source is going backwards, record the span
291360 if ( ! lastRecordedSourceMapSpan ||
@@ -333,6 +402,38 @@ namespace ts {
333402 }
334403
335404 if ( node ) {
405+ if ( isUnparsedSource ( node ) && node . sourceMapText !== undefined ) {
406+ if ( lastRecordedSourceMapSpan && lastRecordedSourceMapSpan === lastEncodedSourceMapSpan ) { // If we've recorded some spans, save them
407+ completedSections . push ( { offset : { line : sectionStartLine , column : sectionStartColumn } , map : captureSection ( ) } ) ;
408+ resetSectionalData ( ) ;
409+ }
410+ const text = node . sourceMapText ;
411+ let parsed : { } | undefined ;
412+ try {
413+ parsed = JSON . parse ( text ) ;
414+ }
415+ catch {
416+ // empty
417+ }
418+ const offset = { line : writer . getLine ( ) , column : writer . getColumn ( ) } ;
419+ completedSections . push ( parsed
420+ ? {
421+ offset,
422+ map : parsed as SourceMap
423+ }
424+ : {
425+ offset,
426+ // This is just passes the buck on sourcemaps we don't really understand, instead of issuing an error (which would be difficult this late)
427+ url : `data:application/json;charset=utf-8;base64,${ base64encode ( sys , text ) } `
428+ }
429+ ) ;
430+ const emitResult = emitCallback ( hint , node ) ;
431+ sectionStartLine = writer . getLine ( ) ;
432+ sectionStartColumn = writer . getColumn ( ) ;
433+ lastRecordedSourceMapSpan = undefined ! ;
434+ lastEncodedSourceMapSpan = undefined ! ;
435+ return emitResult ;
436+ }
336437 const emitNode = node . emitNode ;
337438 const emitFlags = emitNode && emitNode . flags || EmitFlags . None ;
338439 const range = emitNode && emitNode . sourceMapRange ;
@@ -452,15 +553,7 @@ namespace ts {
452553
453554 encodeLastRecordedSourceMapSpan ( ) ;
454555
455- return JSON . stringify ( {
456- version : 3 ,
457- file : sourceMapData . sourceMapFile ,
458- sourceRoot : sourceMapData . sourceMapSourceRoot ,
459- sources : sourceMapData . sourceMapSources ,
460- names : sourceMapData . sourceMapNames ,
461- mappings : sourceMapData . sourceMapMappings ,
462- sourcesContent : sourceMapData . sourceMapSourcesContent ,
463- } ) ;
556+ return JSON . stringify ( generateMap ( ) ) ;
464557 }
465558
466559 /**
0 commit comments