@@ -2,22 +2,20 @@ package jstack.js;
22
33import haxe .CallStack ;
44import sourcemap .SourcePos ;
5- import js .Lib ;
5+ import js .Error ;
66import haxe .io .Path ;
77import js .Browser ;
88import haxe .Http ;
99
10- using StringTools ;
11-
1210/**
1311 * Handles source map
1412 */
1513class JStack {
1614
1715 /** Create instance just to invoke `inject()` */
18- static private var instance = new JStack ();
16+ static var instance = new JStack ();
1917 /** User-defined callback which will be invoked when sourceMap is loaded */
20- static private var onReadyCallback : Void -> Void ;
18+ static var onReadyCallback : Void -> Void ;
2119
2220 /** Indicates if source map is loaded */
2321 public var ready (default ,null ) : Bool = false ;
@@ -28,25 +26,35 @@ class JStack {
2826 * A call to this method is automatically injected in `static main()` function of your app.
2927 * You don't need to use this method manually.
3028 */
31- static public function onReady (callback : Void -> Void ) : Void
32- {
29+ static public function onReady (callback : Void -> Void ) {
3330 onReadyCallback = callback ;
3431 if (instance .ready ) callback ();
3532 }
3633
34+ /**
35+ * Overwrite this method to handle uncaught exceptions manually.
36+ * Any returned value will be written to stderr.
37+ * @param e - Uncaught exception.
38+ */
39+ @:access (haxe. CallStack )
40+ static public dynamic function uncaughtExceptionHandler (e : Error ) : String {
41+ var stack = CallStack .getStack (e );
42+ var error = e .message + CallStack .toString (stack ) + ' \n ' ;
43+ return error ;
44+ }
3745
38- private function new ()
39- {
46+ function new () {
47+ if (isNode ()) {
48+ untyped __js__ (' process.on("uncaughtException", {0})' , _uncaughtExceptionHandler );
49+ }
4050 inject ();
4151 }
4252
43-
4453 /**
4554 * Loads source map and injects hooks into `haxe.CallStack`.
4655 * It's asynchronous process so haxe-related positions in call stack might be not available right away.
4756 */
48- public function inject () : Void
49- {
57+ public function inject () {
5058 loadSourceMap (function (sourceMapData : String ) {
5159 var mapper = new SourceMap (sourceMapData );
5260
@@ -66,9 +74,8 @@ class JStack {
6674 /**
6775 * Load source map and pass it to `callback`
6876 */
69- private function loadSourceMap (callback : String -> Void ) : Void
70- {
71- if (untyped __js__ (" typeof window != 'undefined'" )) {
77+ function loadSourceMap (callback : String -> Void ) {
78+ if (! isNode ()) {
7279 loadInBrowser (callback );
7380 } else {
7481 loadInNode (callback );
@@ -79,8 +86,7 @@ class JStack {
7986 /**
8087 * Do the job in browser environment
8188 */
82- private function loadInBrowser (callback : String -> Void ) : Void
83- {
89+ function loadInBrowser (callback : String -> Void ) {
8490 var file = getCurrentDirInBrowser () + ' /' + Tools .getSourceMapFileName ();
8591 var http = new Http (file );
8692
@@ -97,8 +103,7 @@ class JStack {
97103 /**
98104 * Do the job in nodejs environment
99105 */
100- public function loadInNode (callback : String -> Void ) : Void
101- {
106+ public function loadInNode (callback : String -> Void ) {
102107 var dir : String = untyped __js__ (" __dirname" );
103108 var fs = untyped __js__ (" require('fs')" );
104109
@@ -115,8 +120,7 @@ class JStack {
115120 /**
116121 * Scans DOM for <script> tags to find current script directory
117122 */
118- public function getCurrentDirInBrowser () : String
119- {
123+ public function getCurrentDirInBrowser () : String {
120124 var file = Tools .getOutputFileName ();
121125 var scripts = Browser .document .getElementsByTagName (' script' );
122126
@@ -132,22 +136,37 @@ class JStack {
132136 return path .dir ;
133137 }
134138
139+ /**
140+ * Actual handler used for uncaught exceptions
141+ * @param e -
142+ */
143+ static function _uncaughtExceptionHandler (e : Error ) {
144+ var error = uncaughtExceptionHandler (e );
145+ if (error != null && error .length > 0 ) {
146+ untyped __js__ (' console.log({0})' , error );
147+ }
148+ }
149+
150+ /**
151+ Check if currently run on nodejs.
152+ **/
153+ static function isNode () : Bool {
154+ return untyped __js__ (" typeof window == 'undefined'" );
155+ }
135156}
136157
137158
138159/**
139160 * Represents call stack position
140161 */
141162@:keep
142- private class StackPos
143- {
163+ class StackPos {
144164 /** JS side */
145- private var js : Dynamic ;
165+ var js : Dynamic ;
146166 /** HX side */
147- private var hx : Dynamic ;
167+ var hx : Dynamic ;
148168
149- public function new (js : Dynamic , hx : SourcePos )
150- {
169+ public function new (js : Dynamic , hx : SourcePos ) {
151170 this .js = js ;
152171 this .hx = hx ;
153172 }
0 commit comments