StackTracey
Platform-agnostic callstack access helper.
Why
What for
- Better exception reporting for Node and browsers
- Advanced logging (displaying call locations)
- Assertion printing
How to
npm install stacktracey
StackTracey = require ('stacktracey')
Captures current call stack:
stack = new StackTracey ()
Parses stacks from Error
object:
stack = new StackTracey (error)
stack = new StackTracey (error.stack)
It is an array instance:
stack instanceof Array
stack.length
stack[0]
Each item exposes:
{
beforeParse: <original text>,
callee: <function name>,
calleeShort: <shortened function name>,
file: <full path to file>, // e.g. /Users/john/my_project/src/foo.js
fileShort: <shortened path to file>, // e.g. src/foo.js
fileName: <file name>', // e.g. foo.js
line: <line number>, // starts from 1
column: <column number>, // starts from 1
index: /* true if occured in HTML file at index page */,
native: /* true if occured in native browser code */,
thirdParty: /* true if occured in library code */,
hide: /* true if marked as hidden by "// @hide" tag */
}
Accessing sources:
stack = stack.withSources // will return a copy of stack with all items supplied with sources
top = stack[0]
top = stack.withSource (0)
top = StackTracey.withSource (stack[0])
This will return item supplied with source code info (already mapped through sourcemaps):
{
...
line: <original line number>,
column: <original column number>,
sourceFile: <original source file object>,
sourceLine: <original source line text>
}
To learn about sourceFile
object, read get-source docs.
Cleaning output
stack = stack.withSources.clean
- Excludes locations marked with
isThirdParty
(library calls) - Excludes locations marked with
// @hide
comment (user defined exclusion) - Merges repeated lines (via
.mergeRepeatedLines
)
You can augment isThirdParty
predicate with new rules:
StackTracey.isThirdParty.include (path => path.includes ('my-lib'))
StackTracey.isThirdParty.except (path => path.includes ('jquery'))
P.S. It is better to call .clean
on stacks supplied with sources (i.e. after calling .withSources
), to make // @hide
magic work, and to make isThirdParty
work by recognizing proper file names, if your source is compiled from other sources and has a sourcemap attached.
Pretty printing
const prettyPrintedString = new StackTracey ().pretty
It produces a nice compact table layout, supplied with source lines (if available). You can even replace the default NodeJS exception printer with this!
at shouldBeVisibleInStackTrace test.js:25 const shouldBeVisibleInStackTrace = () => new StackTracey ()
at it test.js:100 const stack = shouldBeVisibleInStackTrace ()
at callFn node_modules/mocha/lib/runnable.js:326 var result = fn.call(ctx);
at run node_modules/mocha/lib/runnable.js:319 callFn(this.fn);
at runTest node_modules/mocha/lib/runner.js:422 test.run(fn);
at node_modules/mocha/lib/runner.js:528 self.runTest(function(err) {
at next node_modules/mocha/lib/runner.js:342 return fn();
at node_modules/mocha/lib/runner.js:352 next(suites.pop());
at next node_modules/mocha/lib/runner.js:284 return fn();
at <anonymous> node_modules/mocha/lib/runner.js:320 next(0);
Array methods
All StackTracey instances expose map
, filter
, concat
, reverse
and slice
methods. These methods will return mapped, filtered, joined, reversed and sliced stacks, respectively:
s = new StackTracey ().slice (1).filter (x => !x.isThirdParty)
s instanceof StackTracey
s instanceof Array
Other methods of the Array
are supported too, but they will return Array
instances, not StackTracey instances. You can convert from array via this:
stack = new StackTracey (array)
..and to array via this (but generally this is not needed — you can pass around StackTracey instances as if they were real Arrays):
Array.from (stack)
You can compare two locations via this predicate (tests file
, line
and column
for equality):
StackTracey.locationsEqual (a, b)