Skip to content

Commit 8c4edbb

Browse files
Capture stack trace in node.js
1 parent 80ee10a commit 8c4edbb

File tree

4 files changed

+128
-71
lines changed

4 files changed

+128
-71
lines changed

test/CapturedExceptions.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,3 +332,21 @@ CapturedExceptions.ie_10 = {
332332
description: "Unable to get property 'undef' of undefined or null reference",
333333
number: -2146823281
334334
};
335+
336+
CapturedExceptions.node_simple = {
337+
message: 'x is not defined',
338+
name: 'ReferenceError',
339+
type: 'not_defined',
340+
stack: 'ReferenceError: x is not defined\n' +
341+
' at repl:1:5\n' +
342+
' at REPLServer.self.eval (repl.js:110:21)\n' +
343+
' at repl.js:249:20\n' +
344+
' at REPLServer.self.eval (repl.js:122:7)\n' +
345+
' at Interface.<anonymous> (repl.js:239:12)\n' +
346+
' at Interface.EventEmitter.emit (events.js:95:17)\n' +
347+
' at Interface._onLine (readline.js:202:10)\n' +
348+
' at Interface._line (readline.js:531:8)\n' +
349+
' at Interface._ttyWrite (readline.js:760:14)\n' +
350+
' at ReadStream.onkeypress (readline.js:99:10)',
351+
'arguments': [ 'x' ]
352+
};

test/functional/ExceptionLab.html

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta charset="UTF-8"/>
4+
<meta charset="UTF-8" />
55
<title>Exception Lab</title>
66
<style>
77
#info {
@@ -28,42 +28,27 @@
2828

2929
function dumpException(ex) {
3030
ex = ex || new Error("Default error");
31-
var text = "{\n " + getExceptionProps(ex).join(",\n ") + "\n}";
31+
var text = "{\n " + ExceptionLab.getExceptionProps(ex).join(",\n ") + "\n}";
3232
info(text);
3333
lastException = ex;
3434
}
3535

36-
function dumpException1() {
36+
function dumpExceptionError() {
3737
dumpException();
3838
}
3939

40-
function dumpException2() {
41-
try {
42-
undef();
43-
} catch (ex) {
44-
dumpException(ex);
45-
}
46-
}
47-
48-
function dumpException3() {
40+
function dumpExceptionAnonymous() {
4941
dumpException((function(x) {
5042
try {
5143
x.undef();
44+
return null;
5245
} catch (ex) {
5346
return ex;
5447
}
5548
})(null));
5649
}
5750

58-
function createException4() {
59-
return createException();
60-
}
61-
62-
function dumpException4() {
63-
dumpException(createException4());
64-
}
65-
66-
function dumpException5() {
51+
function dumpExceptionInEval() {
6752
try {
6853
//eval("x.undef()");
6954
eval("getExceptionProps()");
@@ -72,10 +57,10 @@
7257
}
7358
}
7459

75-
function dumpException6() {
60+
function dumpExceptionMultiLine() {
7661
var fn = function() {
7762
return {
78-
name: "provide multi-line source in exception"
63+
name: "provide multi-line message in exception"
7964
};
8065
};
8166
try {
@@ -92,14 +77,12 @@
9277
document.getElementById("userAgent").innerHTML = navigator.userAgent;
9378
</script>
9479
<textarea id="info">Info</textarea>
95-
<br/>
96-
<button onclick="dumpException1();">Exception 1</button>
97-
<button onclick="dumpException2();">Exception 2</button>
98-
<button onclick="dumpException3();">Exception 3</button>
99-
<button onclick="dumpException4();">Exception 4</button>
100-
<button onclick="dumpException5();">Exception 5</button>
101-
<button onclick="dumpException6();">Exception 6</button>
102-
<br/>
80+
<br />
81+
<button onclick="dumpExceptionError();" title="new Error()">Exception 1</button>
82+
<button onclick="dumpExceptionAnonymous();" title="Stack with anonymous function">Exception 2</button>
83+
<button onclick="dumpExceptionInEval();" title="Exception in eval()">Exception 3</button>
84+
<button onclick="dumpExceptionMultiLine();" title="Multi-line message in exception">Exception 4</button>
85+
<br />
10386
<button onclick="dumpStacktrace();">Process stack trace</button>
10487
<button onclick="dumpStacktrace(true);">Guess anonymous functions</button>
10588
</body>

test/functional/ExceptionLab.js

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,68 @@
1-
function createException() {
2-
return ((function(x) {
3-
try {
4-
x.undef();
5-
return x;
6-
} catch (ex) {
7-
return ex;
8-
}
9-
})(null));
10-
}
1+
/*global module, exports, define*/
2+
(function(global) {
3+
function createException() {
4+
return ((function(x) {
5+
try {
6+
x.undef();
7+
return x;
8+
} catch (ex) {
9+
return ex;
10+
}
11+
})(null));
12+
}
1113

12-
function printProp(prop, value) {
13-
if (typeof value === "string") {
14-
value = '"' + value.replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, '\\n" +\n "') + '"';
14+
function printProp(prop, value) {
15+
if (typeof value === "string") {
16+
value = '"' + value.replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, '\\n" +\n "') + '"';
17+
}
18+
return prop + ': ' + value;
1519
}
16-
return prop + ': ' + value;
17-
}
1820

19-
function getExceptionProps(ex) {
20-
/*jshint forin:false*/
21-
var prop, props = [], exceptionPropertyNames = {
22-
message: true,
23-
name: true,
24-
stack: true,
25-
stacktrace: true,
26-
'arguments': true
27-
};
21+
function getExceptionProps(ex) {
22+
/*jshint forin:false*/
23+
var prop, props = [], exceptionPropertyNames = {
24+
message: true,
25+
name: true,
26+
stack: true,
27+
stacktrace: true,
28+
'arguments': true
29+
};
2830

29-
// find all (including non-enumerable) own properties
30-
if (typeof Object.getOwnPropertyNames === "function") {
31-
var ownPropertyNames = Object.getOwnPropertyNames(ex);
32-
for (var i = 0; i < ownPropertyNames.length; i++) {
33-
exceptionPropertyNames[ownPropertyNames[i]] = true;
31+
// find all (including non-enumerable) own properties
32+
if (typeof Object.getOwnPropertyNames === "function") {
33+
var ownPropertyNames = Object.getOwnPropertyNames(ex);
34+
for (var i = 0; i < ownPropertyNames.length; i++) {
35+
exceptionPropertyNames[ownPropertyNames[i]] = true;
36+
}
3437
}
35-
}
3638

37-
// find onw and inherited enumerable properties
38-
for (prop in ex) {
39-
exceptionPropertyNames[prop] = true;
40-
}
39+
// find own and inherited enumerable properties
40+
for (prop in ex) {
41+
exceptionPropertyNames[prop] = true;
42+
}
4143

42-
for (prop in exceptionPropertyNames) {
43-
var value = ex[prop];
44-
if (typeof value !== "undefined") {
45-
props.push(printProp(prop, value));
44+
for (prop in exceptionPropertyNames) {
45+
var value = ex[prop];
46+
if (typeof value !== "undefined") {
47+
props.push(printProp(prop, value));
48+
}
4649
}
50+
return props;
51+
}
52+
53+
var api = {
54+
createException: createException,
55+
getExceptionProps: getExceptionProps
56+
};
57+
58+
if (typeof exports === 'object') {
59+
// Node
60+
module.exports = api;
61+
} else if (typeof define === 'function' && define.amd) {
62+
// AMD
63+
define(api);
64+
} else {
65+
// Browser globals
66+
global.ExceptionLab = api;
4767
}
48-
return props;
49-
}
68+
}(this));

test/functional/testNode.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*global require, console*/
2+
var ExceptionLab = require("./ExceptionLab");
3+
//stacktrace.js
4+
5+
var lastException;
6+
7+
function info(text) {
8+
console.log(text);
9+
}
10+
11+
function dumpException(ex) {
12+
ex = ex || new Error("Default error");
13+
var text = "{\n " + ExceptionLab.getExceptionProps(ex).join(",\n ") + "\n}";
14+
info(text);
15+
lastException = ex;
16+
console.log(ex.arguments);
17+
}
18+
19+
function dumpExceptionMultiLine() {
20+
var fn = function() {
21+
return {
22+
name: "provide multi-line message in exception"
23+
};
24+
};
25+
try {
26+
fn.nonExistentMethod();
27+
} catch (ex) {
28+
dumpException(ex);
29+
}
30+
}
31+
32+
dumpExceptionMultiLine();
33+
34+
/*
35+
> Object.getOwnPropertyNames(lastException)
36+
[ 'stack', 'arguments', 'type', 'message' ]
37+
*/

0 commit comments

Comments
 (0)