@@ -23,7 +23,11 @@ import type {
2323 Statement ,
2424} from '@babel/types'
2525import { walk } from 'estree-walker'
26- import type { RawSourceMap } from 'source-map-js'
26+ import {
27+ type RawSourceMap ,
28+ SourceMapConsumer ,
29+ SourceMapGenerator ,
30+ } from 'source-map-js'
2731import {
2832 normalScriptDefaultVar ,
2933 processNormalScript ,
@@ -809,6 +813,7 @@ export function compileScript(
809813 args += `, { ${ destructureElements . join ( ', ' ) } }`
810814 }
811815
816+ let templateMap
812817 // 9. generate return statement
813818 let returned
814819 if (
@@ -858,7 +863,7 @@ export function compileScript(
858863 }
859864 // inline render function mode - we are going to compile the template and
860865 // inline it right here
861- const { code, ast, preamble, tips, errors } = compileTemplate ( {
866+ const { code, ast, preamble, tips, errors, map } = compileTemplate ( {
862867 filename,
863868 ast : sfc . template . ast ,
864869 source : sfc . template . content ,
@@ -876,6 +881,7 @@ export function compileScript(
876881 bindingMetadata : ctx . bindingMetadata ,
877882 } ,
878883 } )
884+ templateMap = map
879885 if ( tips . length ) {
880886 tips . forEach ( warnOnce )
881887 }
@@ -1014,19 +1020,28 @@ export function compileScript(
10141020 )
10151021 }
10161022
1023+ const content = ctx . s . toString ( )
1024+ let map =
1025+ options . sourceMap !== false
1026+ ? ( ctx . s . generateMap ( {
1027+ source : filename ,
1028+ hires : true ,
1029+ includeContent : true ,
1030+ } ) as unknown as RawSourceMap )
1031+ : undefined
1032+ // merge source maps of the script setup and template in inline mode
1033+ if ( templateMap && map ) {
1034+ const offset = content . indexOf ( returned )
1035+ const templateLineOffset =
1036+ content . slice ( 0 , offset ) . split ( / \r ? \n / ) . length - 1
1037+ map = mergeSourceMaps ( map , templateMap , templateLineOffset )
1038+ }
10171039 return {
10181040 ...scriptSetup ,
10191041 bindings : ctx . bindingMetadata ,
10201042 imports : ctx . userImports ,
1021- content : ctx . s . toString ( ) ,
1022- map :
1023- options . sourceMap !== false
1024- ? ( ctx . s . generateMap ( {
1025- source : filename ,
1026- hires : true ,
1027- includeContent : true ,
1028- } ) as unknown as RawSourceMap )
1029- : undefined ,
1043+ content,
1044+ map,
10301045 scriptAst : scriptAst ?. body ,
10311046 scriptSetupAst : scriptSetupAst ?. body ,
10321047 deps : ctx . deps ? [ ...ctx . deps ] : undefined ,
@@ -1284,3 +1299,42 @@ function isStaticNode(node: Node): boolean {
12841299 }
12851300 return false
12861301}
1302+
1303+ export function mergeSourceMaps (
1304+ scriptMap : RawSourceMap ,
1305+ templateMap : RawSourceMap ,
1306+ templateLineOffset : number ,
1307+ ) : RawSourceMap {
1308+ const generator = new SourceMapGenerator ( )
1309+ const addMapping = ( map : RawSourceMap , lineOffset = 0 ) => {
1310+ const consumer = new SourceMapConsumer ( map )
1311+ ; ( consumer as any ) . sources . forEach ( ( sourceFile : string ) => {
1312+ ; ( generator as any ) . _sources . add ( sourceFile )
1313+ const sourceContent = consumer . sourceContentFor ( sourceFile )
1314+ if ( sourceContent != null ) {
1315+ generator . setSourceContent ( sourceFile , sourceContent )
1316+ }
1317+ } )
1318+ consumer . eachMapping ( m => {
1319+ if ( m . originalLine == null ) return
1320+ generator . addMapping ( {
1321+ generated : {
1322+ line : m . generatedLine + lineOffset ,
1323+ column : m . generatedColumn ,
1324+ } ,
1325+ original : {
1326+ line : m . originalLine ,
1327+ column : m . originalColumn ,
1328+ } ,
1329+ source : m . source ,
1330+ name : m . name ,
1331+ } )
1332+ } )
1333+ }
1334+
1335+ addMapping ( scriptMap )
1336+ addMapping ( templateMap , templateLineOffset )
1337+ ; ( generator as any ) . _sourceRoot = scriptMap . sourceRoot
1338+ ; ( generator as any ) . _file = scriptMap . file
1339+ return ( generator as any ) . toJSON ( )
1340+ }
0 commit comments