@@ -23,14 +23,58 @@ function getConsumer(mapPath: string, sourceMap: any) {
2323 c = new SourceMapConsumer ( sourceMap ) ;
2424 consumerCache . set ( mapPath , c ) ;
2525 } catch ( error ) {
26- console . error ( `Failed to create SourceMapConsumer for ${ mapPath } :` , error ) ;
26+ // Keep quiet in production-like console; failures just fall back to original stack
27+ console . debug && console . debug ( `SourceMapConsumer failed for ${ mapPath } :` , error ) ;
2728 return null ;
2829 }
2930 }
3031 return c ;
3132}
3233
33- function loadAndExtractMap ( mapPath : string ) {
34+ function safeReadText ( path : string ) : string | null {
35+ try {
36+ if ( File . exists ( path ) ) {
37+ return File . fromPath ( path ) . readTextSync ( ) ;
38+ }
39+ } catch ( _ ) { }
40+ return null ;
41+ }
42+
43+ function findInlineOrLinkedMapFromJs ( jsPath : string ) : { key : string ; text : string } | null {
44+ const jsText = safeReadText ( jsPath ) ;
45+ if ( ! jsText ) return null ;
46+
47+ // Look for the last sourceMappingURL directive
48+ // Supports both //# and /*# */ styles; capture up to line end or */
49+ const re = / [ # @ ] \s * s o u r c e M a p p i n g U R L = ( [ ^ \s * ] + ) (?: \s * \* \/ ) ? / g;
50+ let match : RegExpExecArray | null = null ;
51+ let last : RegExpExecArray | null = null ;
52+ while ( ( match = re . exec ( jsText ) ) ) last = match ;
53+ if ( ! last ) return null ;
54+
55+ const url = last [ 1 ] ;
56+ if ( url . startsWith ( 'data:application/json' ) ) {
57+ const base64 = url . split ( ',' ) [ 1 ] ;
58+ if ( ! base64 ) return null ;
59+ try {
60+ const text = atob ( base64 ) ;
61+ return { key : `inline:${ jsPath } ` , text } ;
62+ } catch ( _ ) {
63+ return null ;
64+ }
65+ }
66+
67+ // Linked .map file (relative)
68+ const jsDir = jsPath . substring ( 0 , jsPath . lastIndexOf ( '/' ) ) ;
69+ const mapPath = `${ jsDir } /${ url } ` ;
70+ const text = safeReadText ( mapPath ) ;
71+ if ( text ) {
72+ return { key : mapPath , text } ;
73+ }
74+ return null ;
75+ }
76+
77+ function loadAndExtractMap ( mapPath : string , fallbackJsPath ?: string ) {
3478 // check cache first
3579 if ( ! loadedSourceMaps ) {
3680 loadedSourceMaps = new Map ( ) ;
@@ -67,12 +111,24 @@ function loadAndExtractMap(mapPath: string) {
67111 mapText = binary ;
68112 }
69113 } catch ( error ) {
70- console . error ( `Failed to load source map ${ mapPath } :` , error ) ;
114+ console . debug && console . debug ( `Failed to load source map ${ mapPath } :` , error ) ;
71115 return null ;
72116 }
73117 } else {
74- // no source maps
75- return null ;
118+ // Try fallback: read inline or linked map from the JS file itself
119+ if ( fallbackJsPath ) {
120+ const alt = findInlineOrLinkedMapFromJs ( fallbackJsPath ) ;
121+ if ( alt && alt . text ) {
122+ mapText = alt . text ;
123+ // Cache under both the requested key and the alt key so future lookups are fast
124+ loadedSourceMaps . set ( alt . key , alt . text ) ;
125+ } else {
126+ return null ;
127+ }
128+ } else {
129+ // no source maps
130+ return null ;
131+ }
76132 }
77133 }
78134 loadedSourceMaps . set ( mapPath , mapText ) ; // cache it
@@ -92,9 +148,19 @@ function remapFrame(file: string, line: number, column: number) {
92148 if ( usingSourceMapFiles ) {
93149 sourceMapFileExt = '.map' ;
94150 }
95- const mapPath = `${ appPath } /${ file . replace ( 'file:///app/' , '' ) } ${ sourceMapFileExt } ` ;
151+ const rel = file . replace ( 'file:///app/' , '' ) ;
152+ const jsPath = `${ appPath } /${ rel } ` ;
153+ let mapPath = `${ jsPath } ${ sourceMapFileExt } ` ; // default: same name + .map
154+
155+ // Fallback: if .mjs.map missing, try .js.map
156+ if ( ! File . exists ( mapPath ) && rel . endsWith ( '.mjs' ) ) {
157+ const jsMapFallback = `${ appPath } /${ rel . replace ( / \. m j s $ / , '.js.map' ) } ` ;
158+ if ( File . exists ( jsMapFallback ) ) {
159+ mapPath = jsMapFallback ;
160+ }
161+ }
96162
97- const sourceMap = loadAndExtractMap ( mapPath ) ;
163+ const sourceMap = loadAndExtractMap ( mapPath , jsPath ) ;
98164
99165 if ( ! sourceMap ) {
100166 return { source : null , line : 0 , column : 0 } ;
@@ -108,26 +174,44 @@ function remapFrame(file: string, line: number, column: number) {
108174 try {
109175 return consumer . originalPositionFor ( { line, column } ) ;
110176 } catch ( error ) {
111- console . error ( `Failed to get original position for ${ file } :${ line } :${ column } :`, error ) ;
177+ console . debug && console . debug ( `Remap failed for ${ file } :${ line } :${ column } :`, error ) ;
112178 return { source : null , line : 0 , column : 0 } ;
113179 }
114180}
115181
116182function remapStack ( raw : string ) : string {
117183 const lines = raw . split ( '\n' ) ;
118184 const out = lines . map ( ( line ) => {
119- const m = / \( ( .+ ) : ( \d + ) : ( \d + ) \) / . exec ( line ) ;
120- if ( ! m ) return line ;
185+ // 1) Parenthesized frame: at fn (file:...:L:C)
186+ let m = / \( ( .+ ) : ( \d + ) : ( \d + ) \) / . exec ( line ) ;
187+ if ( m ) {
188+ try {
189+ const [ _ , file , l , c ] = m ;
190+ const orig = remapFrame ( file , + l , + c ) ;
191+ if ( ! orig . source ) return line ;
192+ return line . replace ( / \( .+ \) / , `(${ orig . source } :${ orig . line } :${ orig . column } )` ) ;
193+ } catch ( error ) {
194+ console . debug && console . debug ( 'Remap failed for frame:' , line , error ) ;
195+ return line ;
196+ }
197+ }
121198
122- try {
123- const [ _ , file , l , c ] = m ;
124- const orig = remapFrame ( file , + l , + c ) ;
125- if ( ! orig . source ) return line ;
126- return line . replace ( / \( .+ \) / , `(${ orig . source } :${ orig . line } :${ orig . column } )` ) ;
127- } catch ( error ) {
128- console . error ( 'Failed to remap stack frame:' , line , error ) ;
129- return line ; // return original line if remapping fails
199+ // 2) Bare frame: at file:///app/vendor.js:L:C (no parentheses)
200+ const bare = / ( \s + a t \s + ) ( [ ^ \s ( ) ] + ) : ( \d + ) : ( \d + ) / . exec ( line ) ;
201+ if ( bare ) {
202+ try {
203+ const [ , prefix , file , l , c ] = bare ;
204+ const orig = remapFrame ( file , + l , + c ) ;
205+ if ( ! orig . source ) return line ;
206+ const replacement = `${ prefix } ${ orig . source } :${ orig . line } :${ orig . column } ` ;
207+ return line . replace ( bare [ 0 ] , replacement ) ;
208+ } catch ( error ) {
209+ console . debug && console . debug ( 'Remap failed for bare frame:' , line , error ) ;
210+ return line ;
211+ }
130212 }
213+
214+ return line ;
131215 } ) ;
132216 return out . join ( '\n' ) ;
133217}
@@ -141,7 +225,7 @@ function remapStack(raw: string): string {
141225 try {
142226 return remapStack ( rawStack ) ;
143227 } catch ( error ) {
144- console . error ( 'Failed to remap stack trace , returning original:', error ) ;
228+ console . debug && console . debug ( 'Remap failed , returning original:', error ) ;
145229 return rawStack ; // fallback to original stack trace
146230 }
147231} ;
0 commit comments