Skip to content

Commit dc858f0

Browse files
Try harder to map stack of uncaught exceptions on nodejs (fixes #5)
1 parent 2345986 commit dc858f0

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

haxelib.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"license" : "MIT",
55
"tags" : ["js", "php7", "stack", "callstack", "stacktrace"],
66
"description" : "Friendly stack traces for JS and PHP7 targets. Makes them point to haxe sources.",
7-
"version" : "2.2.0",
8-
"releasenote" : "Custom entry point with -D JSTACK_MAIN=my.SomeClass.entryPoint",
7+
"version" : "2.2.1",
8+
"releasenote" : "Try harder to map stack of uncaught exceptions on nodejs.",
99
"classPath" : "src",
1010
"contributors" : ["RealyUniqueName"],
1111
"dependencies" : {

src/jstack/js/JStack.hx

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)