Skip to content

Latest commit

 

History

History
255 lines (183 loc) · 10.1 KB

README.md

File metadata and controls

255 lines (183 loc) · 10.1 KB

StackTracey

Build Status Windows Build Status Coverage Status NPM Scrutinizer Code Quality dependencies Status

Parses call stacks. Reads sources. Clean & filtered output. Sourcemaps. Node & browsers.

Why

  • Simple
  • Works in Node and browsers, *nix and Windows
  • Allows hiding library calls / ad-hoc exclusion (via // @hide marker)
  • Provides source text for call locations
  • Fetches sources synchronously (even in browsers) via get-source
  • Full sourcemap support
  • Extracts useful information from SyntaxError instances
  • Pretty printing screen shot 2017-09-27 at 16 53 46

What For

How To

npm install stacktracey
StackTracey = require ('stacktracey')

Captures the current call stack:

stack = new StackTracey ()            // captures the current call stack

Parses stacks from an Error object:

stack = new StackTracey (error)       // parses error.stack
stack = new StackTracey (error.stack) // raw string

It is an array instance:

stack instanceof Array // returns true
stack.length           // num entries
stack[0]               // top

...where each item exposes:

{
    beforeParse:  <original text>,
    callee:       <function name>,
    calleeShort:  <shortened function name>,
    file:         <full path to file>,       // e.g. /Users/john/my_project/node_modules/foobar/main.js
    fileRelative: <relative path to file>,   // e.g. node_modules/foobar/main.js
    fileShort:    <short path to file>,      // e.g. foobar/main.js
    fileName:     <file name>,               // e.g. main.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    */,
    syntaxError:    /* true if generated from a SyntaxError instance */
}

Accessing sources:

stack = stack.withSources // will return a copy of stack with all items supplied with sources
top   = stack[0]          // top item

...or:

top = stack.withSource (0) // supplies source for an individiual item

...or:

top = StackTracey.withSource (stack[0]) // supplies source for an individiual item

It will return an item supplied with the source code info (already mapped through sourcemaps):

{
    ... // all the previously described fields

    line:       <original line number>,
    column:     <original column number>,
    sourceFile: <original source file object>,
    sourceLine: <original source line text>
}

To learn about the sourceFile object, read the get-source docs.

Cleaning Output

stack = stack.withSources.clean
  1. Excludes locations marked with the isThirdParty flag (library calls)
  2. Excludes locations marked with a // @hide comment (user defined exclusion)
  3. Merges repeated lines (via the .mergeRepeatedLines)

You can augment the global isThirdParty predicate with new rules:

StackTracey.isThirdParty.include (path => path.includes ('my-lib')) // paths including 'my-lib' will be marked as thirdParty
StackTracey.isThirdParty.except (path => path.includes ('jquery')) // jquery paths won't be marked as thirdParty

P.S. It is better to call .clean on stacks supplied with sources (i.e. after the .withSources), to make the // @hide magic work, and to make third-party recognition work by reading proper file names in case if your source is compiled from other sources (and has a sourcemap attached).

Pretty Printing

const prettyPrintedString = new StackTracey (error).pretty

...or (for pretty printing cleaned output):

const prettyPrintedString = new StackTracey (error).clean.pretty

It produces a nice compact table layout (thanks to as-table), supplied with source lines (if available):

at shouldBeVisibleInStackTrace     test.js:25                 const shouldBeVisibleInStackTrace = () => new StackTracey ()
at it                              test.js:100                const stack = shouldBeVisibleInStackTrace ()                
at callFn                          mocha/lib/runnable.js:326  var result = fn.call(ctx);                                  
at run                             mocha/lib/runnable.js:319  callFn(this.fn);                                            
at runTest                         mocha/lib/runner.js:422    test.run(fn);                                               
at                                 mocha/lib/runner.js:528    self.runTest(function(err) {                                
at next                            mocha/lib/runner.js:342    return fn();                                                
at                                 mocha/lib/runner.js:352    next(suites.pop());                                         
at next                            mocha/lib/runner.js:284    return fn();                                                
at <anonymous>                     mocha/lib/runner.js:320    next(0);                  

You can even replace the default NodeJS exception printer with this! This is how you can do it:

process.on ('uncaughtException',  e => { /* print the stack here */ })
process.on ('unhandledRejection', e => { /* print the stack here */ })

But the most simple way to achieve that is to use the ololog library (that is built upon StackTracey and several other handy libraries coded by me). Check it out, it's pretty awesome and will blow your brains out :)

const log = require ('ololog').handleNodeErrors ()

// you can also print Errors by simply passing them to the log() function

screen shot 2018-05-11 at 19 51 03

Overriding Max Column Widths in Pretty Printed Tables

If you get your pretty printed tables undesirably trimmed, you can try changing these numbers:

StackTracey.maxColumnWidths = {

    callee:     30,
    file:       40,
    sourceLine: 80
}

Parsing SyntaxError instances

For example, when trying to require a file named test_files/syntax_error.js:

// next line contains a syntax error (not a valid JavaScript)
foo->bar ()

...the pretty printed call stack for the error thrown would be something like:

at (syntax error)                  test_files/syntax_error.js:2  foo->bar ()
at it                              test.js:184                   try { require ('./test_files/syntax_error.js') }
at runCallback                     timers.js:781
at tryOnImmediate                  timers.js:743
at processImmediate [as _immediat  timers.js:714

...where the first line is generated from parsing the raw output from the util.inspect call in Node. Unfortunately, this won't work in older versions of Node (v4 and below) as these versions can't provide any meaningful information for a SyntaxError instance.

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) // current stack shifted by 1 and cleaned from library calls

s instanceof StackTracey // true
s instanceof Array       // true

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)

Extra Stuff

You can compare two locations via this predicate (tests file, line and column for equality):

StackTracey.locationsEqual (a, b)

Resetting source cache (calls getSource.resetCache () from get-source):

StackTracey.resetCache ()

Projects That Use StackTracey

  • Ololog — a better console.log for the log-driven debugging junkies!
  • CCXT — a cryptocurrency trading library that supports 130+ exchanges
  • pnpm — a fast, disk space efficient package manager (faster than npm and Yarn!)
  • panic-overlay — a lightweight standalone alternative to react-error-overlay