@@ -14,13 +14,19 @@ class JStack {
1414
1515 /** Create instance just to invoke `inject()` */
1616 static var instance = new JStack ();
17+ /** Source map instance */
18+ static var mapper : SourceMap ;
1719 /** User-defined callback which will be invoked when sourceMap is loaded */
1820 static var onReadyCallback : Void -> Void ;
1921
22+ /** Native stack lines like: at /home/alex/Work/HaXe/jstack/build/js/test.js:729:22 */
23+ static var stackFile = ~/ ^ at (. +? js):([0-9 ] + ):([0-9 ] + )$ / ;
24+ /** Native stack lines like: at Object.Lab.level4 (/home/alex/Work/HaXe/jstack/build/js/test.js:70:9) */
25+ static var stackFunctionFile = ~/ ^ at (. +? ) \( (. +? js):([0-9 ] + ):([0-9 ] + )\) $ / ;
26+
2027 /** Indicates if source map is loaded */
2128 public var ready (default ,null ) : Bool = false ;
2229
23-
2430 /**
2531 * Invoke `callback` when source map is loaded.
2632 * A call to this method is automatically injected in `static main()` function of your app.
@@ -38,7 +44,7 @@ class JStack {
3844 */
3945 @:access (haxe. CallStack )
4046 static public dynamic function uncaughtExceptionHandler (e : Error ) : String {
41- var stack = CallStack .getStack (e );
47+ var stack = CallStack .getStack (e ). map ( improveStackItem ) ;
4248 var error = e .message + CallStack .toString (stack ) + ' \n ' ;
4349 return error ;
4450 }
@@ -56,7 +62,7 @@ class JStack {
5662 */
5763 public function inject () {
5864 loadSourceMap (function (sourceMapData : String ) {
59- var mapper = new SourceMap (sourceMapData );
65+ mapper = new SourceMap (sourceMapData );
6066
6167 CallStack .wrapCallSite = function (site ) {
6268 var pos = mapper .originalPositionFor (site .getLineNumber (), site .getColumnNumber ());
@@ -153,6 +159,53 @@ class JStack {
153159 static function isNode () : Bool {
154160 return untyped __js__ (" typeof window == 'undefined'" );
155161 }
162+
163+ /**
164+ Try to make a better stack.
165+ **/
166+ static function improveStackItem (item : StackItem ) : StackItem {
167+ switch (item ) {
168+ case Module (line ) if (stackFile .match (line )):
169+ var file = stackFile .matched (1 );
170+ if (file != currentFile ()) return item ;
171+
172+ var line = Std .parseInt (stackFile .matched (2 ));
173+ var column = Std .parseInt (stackFile .matched (3 ));
174+ var pos = mapper .originalPositionFor (line , column );
175+
176+ return FilePos (null , pos .source , pos .originalLine );
177+
178+ case Module (line ) if (stackFunctionFile .match (line )):
179+ var file = stackFunctionFile .matched (2 );
180+ if (file != currentFile ()) return item ;
181+
182+ var line = Std .parseInt (stackFunctionFile .matched (3 ));
183+ var column = Std .parseInt (stackFunctionFile .matched (4 ));
184+ var pos = mapper .originalPositionFor (line , column );
185+
186+ if (pos == null ) return item ;
187+
188+ var fn = stackFunctionFile .matched (1 ).split (' .' );
189+ var method = fn .pop ();
190+ var cls = fn .join (' .' );
191+ var methodItem = (cls != null && method != null ? Method (cls , method ) : null );
192+
193+ return FilePos (methodItem , pos .source , pos .originalLine );
194+
195+ case _ :
196+ return item ;
197+ }
198+ }
199+
200+ /**
201+ Returns full name of currently being executed js file.
202+ **/
203+ static function currentFile () : Null <String > {
204+ if (isNode ()) {
205+ return untyped __js__ (' __filename' );
206+ }
207+ return null ;
208+ }
156209}
157210
158211
0 commit comments