11import './globals' ;
2-
32import './debugger/webinspector-network' ;
43import './debugger/webinspector-dom' ;
54import './debugger/webinspector-css' ;
6- // require('./debugger/webinspector-network');
7- // require('./debugger/webinspector-dom');
8- // require('./debugger/webinspector-css');
9-
10- /**
11- * Source map remapping for stack traces for the runtime in-flight error displays
12- * Currently this is very slow. Need to find much faster way to remap stack traces.
13- * NOTE: This likely should not be in core because errors can happen on boot before core is fully loaded. Ideally the runtime should provide this in full but unsure.
14- */
155import { File , knownFolders } from './file-system' ;
166// import/destructure style helps commonjs/esm build issues
177import * as sourceMapJs from 'source-map-js' ;
188const { SourceMapConsumer } = sourceMapJs ;
199
20- // note: webpack config can by default use 'source-map' files with runtimes v9+
10+ // note: bundlers can by default use 'source-map' files with runtimes v9+
2111// helps avoid having to decode the inline base64 source maps
22- // currently same performance on inline vs file source maps so file source maps may just be cleaner
2312const usingSourceMapFiles = true ;
2413let loadedSourceMaps : Map < string , any > ;
2514let consumerCache : Map < string , any > ;
@@ -30,9 +19,13 @@ function getConsumer(mapPath: string, sourceMap: any) {
3019 }
3120 let c = consumerCache . get ( mapPath ) ;
3221 if ( ! c ) {
33- // parse once
34- c = new SourceMapConsumer ( sourceMap ) ;
35- consumerCache . set ( mapPath , c ) ;
22+ try {
23+ c = new SourceMapConsumer ( sourceMap ) ;
24+ consumerCache . set ( mapPath , c ) ;
25+ } catch ( error ) {
26+ console . error ( `Failed to create SourceMapConsumer for ${ mapPath } :` , error ) ;
27+ return null ;
28+ }
3629 }
3730 return c ;
3831}
@@ -43,35 +36,43 @@ function loadAndExtractMap(mapPath: string) {
4336 loadedSourceMaps = new Map ( ) ;
4437 }
4538 let mapText = loadedSourceMaps . get ( mapPath ) ;
46- // Note: not sure if separate source map files or inline is better
47- // need to test build times one way or other with webpack, vite and rspack
48- // but this handles either way
4939 if ( mapText ) {
5040 return mapText ; // already loaded
5141 } else {
5242 if ( File . exists ( mapPath ) ) {
53- const contents = File . fromPath ( mapPath ) . readTextSync ( ) ;
54- if ( usingSourceMapFiles ) {
55- mapText = contents ;
56- } else {
57- // parse out the inline base64
58- const match = contents . match ( / \/ \/ [ # @ ] s o u r c e M a p p i n g U R L = d a t a : a p p l i c a t i o n \/ j s o n [ ^ , ] + , ( .+ ) $ / ) ;
59- const base64 = match [ 1 ] ;
60- const binary = atob ( base64 ) ;
61- // this is the raw text of the source map
62- // seems to work without doing the decodeURIComponent trick
63- mapText = binary ;
64- // // escape each char code into %XX and let decodeURIComponent build the UTF-8 string
65- // mapText = decodeURIComponent(
66- // binary
67- // .split('')
68- // .map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
69- // .join('')
70- // );
43+ try {
44+ const contents = File . fromPath ( mapPath ) . readTextSync ( ) ;
45+
46+ // Note: we may want to do this, keeping for reference if needed in future.
47+ // Check size before processing (skip very large source maps)
48+ // const maxSizeBytes = 10 * 1024 * 1024; // 10MB limit
49+ // if (contents.length > maxSizeBytes) {
50+ // console.warn(`Source map ${mapPath} is too large (${contents.length} bytes), skipping...`);
51+ // return null;
52+ // }
53+
54+ if ( usingSourceMapFiles ) {
55+ mapText = contents ;
56+ } else {
57+ // parse out the inline base64
58+ const match = contents . match ( / \/ \/ [ # @ ] s o u r c e M a p p i n g U R L = d a t a : a p p l i c a t i o n \/ j s o n [ ^ , ] + , ( .+ ) $ / ) ;
59+ if ( ! match ) {
60+ console . warn ( `Invalid source map format in ${ mapPath } ` ) ;
61+ return null ;
62+ }
63+ const base64 = match [ 1 ] ;
64+ const binary = atob ( base64 ) ;
65+ // this is the raw text of the source map
66+ // seems to work without doing decodeURIComponent tricks
67+ mapText = binary ;
68+ }
69+ } catch ( error ) {
70+ console . error ( `Failed to load source map ${ mapPath } :` , error ) ;
71+ return null ;
7172 }
7273 } else {
7374 // no source maps
74- return { source : null , line : 0 , column : 0 } ;
75+ return null ;
7576 }
7677 }
7778 loadedSourceMaps . set ( mapPath , mapText ) ; // cache it
@@ -80,8 +81,9 @@ function loadAndExtractMap(mapPath: string) {
8081
8182function remapFrame ( file : string , line : number , column : number ) {
8283 /**
83- * webpack config can use source map files or inline.
84+ * bundlers can use source map files or inline.
8485 * To use source map files, run with `--env.sourceMap=source-map`.
86+ * Notes:
8587 * @nativescript /webpack 5.1 enables `source-map` files by default when using runtimes v9+.
8688 */
8789
@@ -92,32 +94,56 @@ function remapFrame(file: string, line: number, column: number) {
9294 }
9395 const mapPath = `${ appPath } /${ file . replace ( 'file:///app/' , '' ) } ${ sourceMapFileExt } ` ;
9496
95- // 3) hand it to the consumer
9697 const sourceMap = loadAndExtractMap ( mapPath ) ;
98+
99+ if ( ! sourceMap ) {
100+ return { source : null , line : 0 , column : 0 } ;
101+ }
102+
97103 const consumer = getConsumer ( mapPath , sourceMap ) ;
98- return consumer . originalPositionFor ( { line, column } ) ;
104+ if ( ! consumer ) {
105+ return { source : null , line : 0 , column : 0 } ;
106+ }
107+
108+ try {
109+ return consumer . originalPositionFor ( { line, column } ) ;
110+ } catch ( error ) {
111+ console . error ( `Failed to get original position for ${ file } :${ line } :${ column } :` , error ) ;
112+ return { source : null , line : 0 , column : 0 } ;
113+ }
99114}
100115
101116function remapStack ( raw : string ) : string {
102117 const lines = raw . split ( '\n' ) ;
103118 const out = lines . map ( ( line ) => {
104119 const m = / \( ( .+ ) : ( \d + ) : ( \d + ) \) / . exec ( line ) ;
105120 if ( ! m ) return line ;
106- const [ _ , file , l , c ] = m ;
107- const orig = remapFrame ( file , + l , + c ) ;
108- if ( ! orig . source ) return line ;
109- return line . replace ( / \( .+ \) / , `(${ orig . source } :${ orig . line } :${ orig . column } )` ) ;
121+
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
130+ }
110131 } ) ;
111132 return out . join ( '\n' ) ;
112133}
113134
114135/**
115- * Added in 9.0 runtimes.
116- * Allows the runtime to remap stack traces before displaying them in the in-flight error screens.
136+ * Added with 9.0 runtimes.
137+ * Allows the runtime to remap stack traces before displaying them via in-flight error screens.
117138 */
118139( global as any ) . __ns_remapStack = ( rawStack : string ) => {
119140 // console.log('Remapping stack trace...');
120- return remapStack ( rawStack ) ;
141+ try {
142+ return remapStack ( rawStack ) ;
143+ } catch ( error ) {
144+ console . error ( 'Failed to remap stack trace, returning original:' , error ) ;
145+ return rawStack ; // fallback to original stack trace
146+ }
121147} ;
122148/**
123149 * End of source map remapping for stack traces
0 commit comments