Socket
Socket
Sign inDemoInstall

stackman

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stackman - npm Package Compare versions

Comparing version 1.2.7 to 2.0.0

test/fixtures/generateError.js

401

index.js

@@ -5,5 +5,6 @@ 'use strict'

var path = require('path')
var semver = require('semver')
var callsites = require('error-callsites')
var afterAll = require('after-all')
var asyncCache = require('async-cache')
var afterAll = require('after-all-results')
var errorCallsites = require('error-callsites')
var loadSourceMap = require('load-source-map')
var debug = require('debug')('stackman')

@@ -13,181 +14,291 @@

var syncCache = require('lru-cache')({ max: 500 })
var asyncCache = require('async-cache')({
max: 500,
load: function (file, cb) {
debug('reading ' + file)
fs.readFile(file, READ_FILE_OPTS, cb)
}
})
var LINES_OF_CONTEXT = 7
var READ_FILE_OPTS = semver.lt(process.version, '0.9.11') ? 'utf8' : { encoding: 'utf8' }
var ESCAPED_REGEX_PATH_SEP = path.sep === '/' ? '/' : '\\\\'
var MODULE_FOLDER_REGEX = new RegExp('.*node_modules' + ESCAPED_REGEX_PATH_SEP + '([^' + ESCAPED_REGEX_PATH_SEP + ']*)')
module.exports = function (opts) {
if (opts instanceof Error) throw new Error('Stackman not initialized yet. Please do so first and parse the error to the returned function instead')
module.exports = function stackman (opts) {
if (!opts) opts = {}
var linesOfContext = opts.context || LINES_OF_CONTEXT
var sync = opts.sync
var stackFilter
if (opts.filter === undefined) {
// noop
} else if (typeof opts.filter === 'string') {
stackFilter = function (callsite) {
var filename = callsite.getFileName()
return filename ? filename.indexOf(opts.filter) === -1 : true
var fileCache = asyncCache({
max: opts.fileCacheMax || 500,
load: function (file, cb) {
debug('reading %s', file)
fs.readFile(file, {encoding: 'utf8'}, cb)
}
} else if (Array.isArray(opts.filter)) {
stackFilter = function (callsite) {
var path = callsite.getFileName()
return !opts.filter.some(function (segment) {
return path.indexOf(segment) !== -1
})
var sourceMapCache = asyncCache({
max: opts.sourceMapCacheMax || 100,
load: function (file, cb) {
debug('loading source map for %s', file)
loadSourceMap(file, cb)
}
})
return {
callsites: callsites,
properties: properties,
sourceContexts: sourceContexts
}
function callsites (err, opts, cb) {
if (typeof opts === 'function') return callsites(err, null, opts)
var _callsites = errorCallsites(err)
if (!validStack(_callsites)) {
process.nextTick(function () {
cb(new Error('Could not process callsites'))
})
} else if (!opts || opts.sourcemap !== false) {
sourcemapify(_callsites, function (err) {
if (err) return cb(err)
_callsites.forEach(extendCallsite)
cb(null, _callsites)
})
} else {
_callsites.forEach(extendCallsite)
process.nextTick(function () {
cb(null, _callsites)
})
}
}
var parseLines = function (lines, callsite) {
var lineno = callsite.getLineNumber()
return {
pre: lines.slice(Math.max(0, lineno - (linesOfContext + 1)), lineno - 1),
line: lines[lineno - 1],
post: lines.slice(lineno, lineno + linesOfContext)
function properties (err) {
var properties = {}
Object.keys(err).forEach(function (key) {
if (key === 'stack') return // 'stack' seems to be enumerable in Node 0.11
var val = err[key]
if (val === null) return // null is typeof object and well break the switch below
switch (typeof val) {
case 'function':
return
case 'object':
// ignore all objects except Dates
if (typeof val.toISOString !== 'function') return
val = val.toISOString()
}
properties[key] = val
})
return properties
}
function sourceContexts (callsites, opts, cb) {
if (typeof opts === 'function') return sourceContexts(callsites, null, opts)
if (!opts) opts = {}
var next = afterAll(cb)
callsites.forEach(function (callsite) {
if (callsite.isNode()) {
next()(null, null)
} else {
callsite.sourceContext(opts, next())
}
})
}
function validStack (callsites) {
return Array.isArray(callsites) &&
typeof callsites[0] === 'object' &&
typeof callsites[0].getFileName === 'function'
}
function getRelativeFileName () {
var filename = this.getFileName()
if (!filename) return
var root = process.cwd()
if (root[root.length - 1] !== path.sep) root += path.sep
return !~filename.indexOf(root) ? filename : filename.substr(root.length)
}
function getTypeNameSafely () {
try {
return this.getTypeName()
} catch (e) {
// This seems to happen sometimes when using 'use strict',
// stemming from `getTypeName`.
// [TypeError: Cannot read property 'constructor' of undefined]
return null
}
}
return function (err, cb) {
var stack = callsites(err)
function getFunctionNameSanitized () {
var fnName = this.getFunctionName()
if (fnName) return fnName
var typeName = this.getTypeNameSafely()
if (typeName) return typeName + '.' + (this.getMethodName() || '<anonymous>')
return '<anonymous>'
}
if (stackFilter && Array.isArray(stack)) stack = stack.filter(stackFilter)
function getModuleName () {
var filename = this.getFileName() || ''
var match = filename.match(MODULE_FOLDER_REGEX)
return match ? match[1] : null
}
var result = {
properties: getProperties(err),
frames: stack
function isApp () {
return !this.isNode() && !~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}
function isModule () {
return !!~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}
function isNode () {
if (this.isNative()) return true
var filename = this.getFileName() || ''
return (!isAbsolute(filename) && filename[0] !== '.')
}
function sourceContext (opts, cb) {
if (typeof opts === 'function') {
cb = opts
opts = {}
}
if (!sync) {
var next = afterAll(function () {
cb(result)
if (this.isNode()) {
process.nextTick(function () {
cb(new Error('Can\'t get source context of a Node core callsite'))
})
return
}
if (!validStack(stack)) return sync ? result : undefined
var callsite = this
var filename = this.getFileName() || ''
var source = this.sourcemap
? this.sourcemap.sourceContentFor(filename, true)
: null
stack.forEach(function (callsite) {
callsite.getRelativeFileName = getRelativeFileName.bind(callsite)
callsite.getTypeNameSafely = getTypeNameSafely.bind(callsite)
callsite.getFunctionNameSanitized = getFunctionNameSanitized.bind(callsite)
callsite.getModuleName = getModuleName.bind(callsite)
callsite.isApp = isApp.bind(callsite)
callsite.isModule = isModule.bind(callsite)
callsite.isNode = isNode.bind(callsite)
if (source) {
process.nextTick(function () {
cb(null, parseSource(source, callsite, opts))
})
} else {
fileCache.get(filename, function (err, source) {
if (err) {
debug('error reading %s: %s', filename, err.message)
cb(err)
} else {
cb(null, parseSource(source, callsite, opts))
}
})
}
}
if (callsite.isNode()) return // internal Node files are not full path names. Ignore them.
function parseSource (source, callsite, opts) {
var lines = source.split(/\r?\n/)
var linesOfContext = opts.lines || LINES_OF_CONTEXT
var lineno = callsite.getLineNumber()
return {
pre: lines.slice(Math.max(0, lineno - (linesOfContext + 1)), lineno - 1),
line: lines[lineno - 1],
post: lines.slice(lineno, lineno + linesOfContext)
}
}
var filename = callsite.getFileName() || ''
function sourcemapify (callsites, cb) {
var next = afterAll(function (err, consumers) {
if (err) return cb(err)
if (!sync) {
var done = next()
asyncCache.get(filename, function (err, data) {
if (err) {
debug('error reading ' + filename + ': ' + err.message)
} else {
data = data.split(/\r?\n/)
callsite.context = parseLines(data, callsite)
}
done()
consumers.forEach(function (consumer, index) {
if (!consumer) return
Object.defineProperty(callsites[index], 'sourcemap', {
writable: true,
value: consumer
})
} else if (syncCache.has(filename)) {
callsite.context = parseLines(syncCache.get(filename), callsite)
} else {
debug('reading ' + filename)
try {
var data = fs.readFileSync(filename, READ_FILE_OPTS)
} catch (e) {
debug('error reading ' + filename + ': ' + e.message)
return
}
data = data.split(/\r?\n/)
syncCache.set(filename, data)
callsite.context = parseLines(data, callsite)
}
})
cb()
})
return sync ? result : undefined
callsites.forEach(function (callsite) {
getSourceMapConsumer(callsite, next())
})
}
}
var validStack = function (stack) {
return Array.isArray(stack) &&
typeof stack[0] === 'object' &&
typeof stack[0].getFileName === 'function'
}
var getRelativeFileName = function () {
var filename = this.getFileName()
if (!filename) return
var root = process.cwd()
if (root[root.length - 1] !== path.sep) root += path.sep
return !~filename.indexOf(root) ? filename : filename.substr(root.length)
}
var getTypeNameSafely = function () {
try {
return this.getTypeName()
} catch (e) {
// This seems to happen sometimes when using 'use strict',
// stemming from `getTypeName`.
// [TypeError: Cannot read property 'constructor' of undefined]
return null
function getSourceMapConsumer (callsite, cb) {
if (isNode.call(callsite)) return process.nextTick(cb)
var filename = callsite.getFileName()
sourceMapCache.get(filename, cb)
}
}
var getFunctionNameSanitized = function () {
var fnName = this.getFunctionName()
if (fnName) return fnName
var typeName = this.getTypeNameSafely()
if (typeName) return typeName + '.' + (this.getMethodName() || '<anonymous>')
return '<anonymous>'
}
function extendCallsite (callsite) {
var getLineNumber = callsite.getLineNumber
var getColumnNumber = callsite.getColumnNumber
var getFileName = callsite.getFileName
var position = null
var properties = {
getRelativeFileName: {
writable: true,
value: getRelativeFileName
},
getTypeNameSafely: {
writable: true,
value: getTypeNameSafely
},
getFunctionNameSanitized: {
writable: true,
value: getFunctionNameSanitized
},
getModuleName: {
writable: true,
value: getModuleName
},
isApp: {
writable: true,
value: isApp
},
isModule: {
writable: true,
value: isModule
},
isNode: {
writable: true,
value: isNode
},
sourceContext: {
writable: true,
value: sourceContext
}
}
var getModuleName = function () {
var filename = this.getFileName() || ''
var match = filename.match(MODULE_FOLDER_REGEX)
if (match) return match[1]
}
if (callsite.sourcemap) {
properties.getFileName = {
writable: true,
value: function () {
var filename = getFileName.call(callsite)
var sourceFile = getPosition().source
if (!sourceFile) return filename
var sourceDir = path.dirname(filename)
return path.resolve(path.join(sourceDir, sourceFile))
}
}
properties.getLineNumber = {
writable: true,
value: function () {
return getPosition().line || getLineNumber.call(callsite)
}
}
properties.getColumnNumber = {
writable: true,
value: function () {
return getPosition().column || getColumnNumber.call(callsite)
}
}
}
var isApp = function () {
return !this.isNode() && !~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}
Object.defineProperties(callsite, properties)
var isModule = function () {
return !!~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}
function getPosition () {
if (!position) {
position = callsite.sourcemap.originalPositionFor({
line: getLineNumber.call(callsite),
column: getColumnNumber.call(callsite)
})
}
var isNode = function () {
if (this.isNative()) return true
var filename = this.getFileName() || ''
return (!isAbsolute(filename) && filename[0] !== '.')
}
var getProperties = function (err) {
var properties = {}
Object.keys(err).forEach(function (key) {
if (key === 'stack') return // 'stack' seems to be enumerable in Node 0.11
var val = err[key]
if (val === null) return // null is typeof object and well break the switch below
switch (typeof val) {
case 'function':
return
case 'object':
// ignore all objects except Dates
if (typeof val.toISOString !== 'function') return
val = val.toISOString()
return position
}
properties[key] = val
})
return properties
}
}
{
"name": "stackman",
"version": "1.2.7",
"version": "2.0.0",
"description": "Enhance an error stacktrace with code excerpts and other goodies",
"main": "index.js",
"dependencies": {
"after-all": "^2.0.2",
"after-all-results": "^2.0.0",
"async-cache": "^1.1.0",
"debug": "^2.2.0",
"error-callsites": "^1.0.1",
"lru-cache": "^4.0.1",
"path-is-absolute": "^1.0.1",
"semver": "^5.3.0"
"load-source-map": "^1.0.0",
"path-is-absolute": "^1.0.1"
},
"devDependencies": {
"longjohn": "=0.2.9",
"standard": "^8.5.0",
"semver": "^5.3.0",
"standard": "^9.0.2",
"tape": "^4.6.2"
},
"scripts": {
"test": "standard && tape test/test.js && tape test/longjohn.js"
"test": "standard && node test/strict.js && node test/non-strict.js && node test/longjohn.js && node test/sourcemap.js"
},

@@ -34,2 +34,4 @@ "repository": {

"callsites",
"frame",
"source",
"debug",

@@ -47,5 +49,10 @@ "log",

"coordinates": [
55.6809887,
12.5643973
]
55.6809959,
12.5644639
],
"standard": {
"ignore": [
"/test/fixtures/"
]
}
}

@@ -13,2 +13,3 @@ # Stackman

[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)
[![sponsor](https://img.shields.io/badge/sponsored%20by-Opbeat-3360A3.svg)](https://opbeat.com)

@@ -24,15 +25,15 @@ ## Install

```javascript
var stackman = require('stackman')();
var stackman = require('stackman')()
var err = new Error('Oops!');
var err = new Error('Oops!')
stackman(err, function (stack) {
stack.frames.forEach(function (frame) {
// output: <example.js:3> var err = new Error('Oops!');
console.log('<%s:%s> %s',
frame.getFileName(),
frame.getLineNumber(),
frame.context.line);
});
});
stackman.callsites(err, function (err, callsites) {
if (err) throw err
callsites.forEach(function (callsite) {
console.log('Error occured in at %s line %d',
callsite.getFileName(),
callsite.getLineNumber())
})
})
```

@@ -44,120 +45,244 @@

This works because V8 (the JavaScript engine behind Node.js) allows us
to hook into the stack trace generator function before that stack trace
is generated. It's triggered by accessing the `.stack` property on the
Error object, so please don't do that before parsing the error to
stackman, else this will not work!
This module works because V8 (the JavaScript engine behind Node.js)
allows us to hook into the stack trace generator function before that
stack trace is generated. It's triggered by accessing the `.stack`
property on the Error object, so please don't do that before parsing the
error to stackman, else this will not work!
If you want to output the regular stack trace, just do so after parsing
it to stackman:
the callsites:
```javascript
// first call stackman with the error
stackman(err, ...);
// first call stackman.callsites with the error
stackman.callsites(err, function () {...})
// then you can print out the stack trace
console.log(err.stack);
console.log(err.stack)
```
## API
## Stackman API
### Module
### `var stackman = Stackman([options])`
Parse options to the main stackman function to customize the default
behavior:
This module exposes a single function which you must call to get a
`stackman` object.
```javascript
var options = {
context: 5,
filter: '/node_modules/my-module/'
}
var stackman = require('stackman')(options)
```
The function takes an optional options object as its only argument.
These are the available options:
- `fileCacheMax` - When source files are read from disk, they are kept
in memory in an LRU cache to speed up processing of future errors. You
can change the max number of files kept in the LRU cache using this
property (default: 500)
- `sourceMapCacheMax` - When source maps are read from disk, the
processed source maps are kept in memory in an LRU cache to speed up
processing of future errors. You can change the max number of source
maps kept in the LRU cache using this property (default: 100)
### `stackman.callsites(err[, options], callback)`
Given an error object, this function will call the `callback` with an
optional error as the first argument and an array of
[CallSite](#callsite-api) objects as the 2nd (a call site is a frame in
the stack trace).
Options:
- `context` - Number of lines of context to be loaded on each side of
the callsite line (default: `7`)
- `filter` - Accepts a single path segment or an array of path segments.
Will filter out any stack frames that matches the given path segments.
- `sync` - Set to `true` if you want stackman to behave synchronously.
If set, the result will be returned and the callback will be ignored
(default: `false`)
- `sourcemap` - A boolean specifying if Stackman should look for an
process source maps (default: `true`)
The `stackman` function takes two arguments:
### `var properties = stackman.properties(err)`
- `err` - the error to be parsed
- `callback` - a callback which will be called with the a stack object
when the parsing is completed
Given an error object, this function will return an object containing
all the custom properties from the original error object (beside date
objects, properties of type `object` and `function` are not included in
this object).
#### The `stack` object:
### `stackman.sourceContexts(callsites[, options], callback)`
The callback given to the `stackman` function is called with a stack
object when the parsing is completed. The `stack` object have two
important properties:
Convenience function to get the source context for all call sites in the
`callsites` argument in one go (instead of iterating over the call sites
and calling
[`callsite.sourceContext()`](#callsitesourcecontextoptions-callback) for
each of them).
- `properties` - An object containing all the custom properties from the
original error object (properties of type `object` and `function` are
not included in this object)
- `frames` - An array of stack-frames, also called callsite objects
Calls the `callback` with an optional error object as the first argument
and an array of [source context objects](#source-context) as the 2nd.
Each element in the context array matches a call site in the `callsites`
array. The optional `options` object will be passed on to
[`callsite.sourceContext()`](#callsitesourcecontextoptions-callback).
### Callsite
All node core call sites will have the context value `null`.
#### Custom properties
## CallSite API
- `callsite.context.pre` - The lines before the main callsite line
- `callsite.context.line` - The main callsite line
- `callsite.context.post` - The lines after the main callsite line
A CallSite object is an object provided by the [V8 stack trace
API](https://github.com/v8/v8/wiki/Stack-Trace-API) representing a frame
in the stack trace. Stackman will decorate each CallSite object with
custom functions and behavior.
#### Custom methods
### `callsite.sourcemap`
- `callsite.getTypeNameSafely()` - A safer version of
`callsite.getTypeName()` as this safely handles an exception that
sometimes is thrown when using `"use strict"`. Otherwise it returns
the type of this as a string. This is the name of the function stored
in the constructor field of this, if available, otherwise the object's
[[Class]] internal property
- `callsite.getRelativeFileName()` - Returns a filename realtive to `process.cwd()`
- `callsite.getFunctionNameSanitized()` - Guaranteed to always return
the most meaningful function name. If none can be determined, the
string `<anonymous>` will be returned
- `callsite.getModuleName()` - Returns the name of the module if
`isModule()` is true
- `callsite.isApp()` - Is this inside the app? (i.e. not native, not
node code and not a module inside the node_modules directory)
- `callsite.isModule()` - Is this inside the node_modules directory?
- `callsite.isNode()` - Is this inside node core?
If source map support is enabled and a source map have been found for
the CallSite, this property will be a reference to a
[`SourceMapConsumer`](https://github.com/mozilla/source-map#sourcemapconsumer)
object representing the given CallSite.
#### Methods inherited from V8
If set, all functions on the CallSite object will be source map aware.
I.e. their return values will be related to the original source code and
not the transpiled source code.
The follwoing methods are inherited from the [V8 stack trace
API](https://code.google.com/p/v8-wiki/wiki/JavaScriptStackTraceApi).
### `var val = callsite.getThis()`
- `callsite.getThis()` - returns the value of this
- `callsite.getTypeName()` - returns the type of this as a string. This
is the name of the function stored in the constructor field of this,
if available, otherwise the object's [[Class]] internal property.
- `callsite.getFunction()` - returns the current function
- `callsite.getFunctionName()` - returns the name of the current
function, typically its name property. If a name property is not
available an attempt will be made to try to infer a name from the
function's context.
- `callsite.getMethodName()` - returns the name of the property of this
or one of its prototypes that holds the current function
- `callsite.getFileName()` - if this function was defined in a script
returns the name of the script
- `callsite.getLineNumber()` - if this function was defined in a script
returns the current line number
- `callsite.getColumnNumber()` - if this function was defined in a
script returns the current column number
- `callsite.getEvalOrigin()` - if this function was created using a call
to eval returns a CallSite object representing the location where eval
was called
- `callsite.isToplevel()` - is this a toplevel invocation, that is, is
this the global object?
- `callsite.isEval()` - does this call take place in code defined by a
call to eval?
- `callsite.isNative()` - is this call in native V8 code?
- `callsite.isConstructor()` - is this a constructor call?
_Inherited from V8_
Returns the value of `this`.
To maintain restrictions imposed on strict mode functions, frames that
have a strict mode function and all frames below (its caller etc.) are
not allow to access their receiver and function objects. For those
frames, `getThis()` will return `undefined`.
### `var str = callsite.getTypeName()`
_Inherited from V8_
Returns the type of `this` as a string. This is the name of the function
stored in the constructor field of `this`, if available, otherwise the
object's `[[Class]]` internal property.
### `var str = callsite.getTypeNameSafely()`
A safer version of
[`callsite.getTypeName()`](#var-str--callsitegettypename) that safely
handles an exception that sometimes is thrown when using `"use strict"`
in which case `null` is returned.
### `var fn = callsite.getFunction()`
_Inherited from V8_
Returns the current function.
To maintain restrictions imposed on strict mode functions, frames that
have a strict mode function and all frames below (its caller etc.) are
not allow to access their receiver and function objects. For those
frames, `getFunction()` will return `undefined`.
### `var str = callsite.getFunctionName()`
_Inherited from V8_
Returns the name of the current function, typically its name property.
If a name property is not available an attempt will be made to try to
infer a name from the function's context.
### `var str = callsite.getFunctionNameSanitized()`
Guaranteed to always return the most meaningful function name. If none
can be determined, the string `<anonymous>` will be returned.
### `var str = callsite.getMethodName()`
_Inherited from V8_
Returns the name of the property of this or one of its prototypes that
holds the current function.
### `var str = callsite.getFileName()`
_Inherited from V8 if `callsite.sourcemap` is `undefined`_
If this function was defined in a script returns the name of the script.
### `var str = callsite.getRelativeFileName()`
Returns a filename realtive to `process.cwd()`.
### `var num = callsite.getLineNumber()`
_Inherited from V8 if `callsite.sourcemap` is `undefined`_
If this function was defined in a script returns the current line
number.
### `var num = callsite.getColumnNumber()`
_Inherited from V8 if `callsite.sourcemap` is `undefined`_
If this function was defined in a script returns the current column
number.
### `var str = callsite.getEvalOrigin()`
_Inherited from V8_
If this function was created using a call to eval returns a CallSite
object representing the location where eval was called.
### `var str = callsite.getModuleName()`
Returns the name of the module if `isModule()` is `true`. Otherwise
returns `null`.
### `var bool = callsite.isToplevel()`
_Inherited from V8_
Is this a toplevel invocation, that is, is this the global object?
### `var bool = callsite.isEval()`
_Inherited from V8_
Does this call take place in code defined by a call to eval?
### `var bool = callsite.isNative()`
_Inherited from V8_
Is this call in native V8 code?
### `var bool = callsite.isConstructor()`
_Inherited from V8_
Is this a constructor call?
### `var bool = callsite.isApp()`
Is this inside the app? (i.e. not native, not node code and not a module
inside the `node_modules` directory)
### `var bool = callsite.isModule()`
Is this inside the `node_modules` directory?
### `var bool = callsite.isNode()`
Is this inside node core?
### `callsite.sourceContext([options, ]callback)`
Calls the `callback` with an optional error object as the first argument
and a [source context object](#source-context) as the 2nd.
If the `callsite` is a node core call site, the `callback` will be
called with an error.
Options:
- `lines` - Number of lines of soruce context to be loaded on each side
of the call site line (default: `7`)
## Source Context
The source context objects provided by
[`callsite.sourceContext`](#callsitesourcecontextoptions-callback)
contains the following properties:
- `pre` - The lines before the main callsite line
- `line` - The main callsite line
- `post` - The lines after the main callsite line
## Troubleshooting

@@ -167,4 +292,8 @@

## Acknowledgements
This project was kindly sponsored by [Opbeat](https://opbeat.com).
## License
MIT

@@ -5,8 +5,9 @@ 'use strict'

var test = require('tape')
var Stackman = require('../')
var stackman = require('../')()
test('longjohn, regular error', function (t) {
var err = new Error('foo')
Stackman()(err, function (stack) {
t.ok(stack.frames.length > 0, 'should have stack frames')
stackman.callsites(err, function (err, callsites) {
t.error(err)
t.ok(callsites.length > 0, 'should have stack frames')
t.end()

@@ -20,4 +21,5 @@ })

} catch (err) {
Stackman()(err, function (stack) {
t.ok(stack.frames.length > 0, 'should have stack frames')
stackman.callsites(err, function (err, callsites) {
t.error(err)
t.ok(callsites.length > 0, 'should have stack frames')
t.end()

@@ -24,0 +26,0 @@ })

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc