[
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directory\n# Deployed apps should consider commenting this line out:\n# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git\nnode_modules\n"
  },
  {
    "path": ".npmignore",
    "content": ".travis.yml\ntest\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n- '13'\n- '12'\n- '11'\n- '10'\n- '9'\n- '8'\n- '7'\n- '6'\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-2020 Thomas Watson Steen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Stackman\n\nGive Stackman an error and he will give an array of stack frames with\nextremely detailed information for each frame in the stack trace.\n\nWith Stackman you get access to the actual source code and surrounding\nlines for where the error occurred, you get to know if it happened\ninside a 3rd party module, in Node.js or in your own code. For a full\nlist of information, check out the API below.\n\n[![npm](https://img.shields.io/npm/v/stackman.svg)](https://www.npmjs.com/package/stackman)\n[![Build status](https://travis-ci.org/watson/stackman.svg?branch=master)](https://travis-ci.org/watson/stackman)\n[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)\n[![sponsor](https://img.shields.io/badge/sponsored%20by-Elastic-3360A3.svg)](https://www.elastic.co)\n\n## Install\n\n```\nnpm install stackman\n```\n\n## Basic usage\n\n```javascript\nvar stackman = require('stackman')()\n\nvar err = new Error('Oops!')\n\nstackman.callsites(err, function (err, callsites) {\n  if (err) throw err\n\n  callsites.forEach(function (callsite) {\n    console.log('Error occured in at %s line %d',\n      callsite.getFileName(),\n      callsite.getLineNumber())\n  })\n})\n```\n\n## Gotchas\n\n### `error.stack`\n\nThis module works because V8 (the JavaScript engine behind Node.js)\nallows us to hook into the stack trace generator function before that\nstack trace is generated. It's triggered by accessing the `.stack`\nproperty on the Error object, so please don't do that before parsing the\nerror to stackman, else this will not work!\n\nIf you want to output the regular stack trace, just do so after parsing\nthe callsites:\n\n```javascript\n// first call stackman.callsites with the error\nstackman.callsites(err, function () {...})\n\n// then you can print out the stack trace\nconsole.log(err.stack)\n```\n\n## Stackman API\n\n### `var stackman = Stackman([options])`\n\nThis module exposes a single function which you must call to get a\n`stackman` object.\n\nThe function takes an optional options object as its only argument.\nThese are the available options:\n\n- `fileCacheMax` - When source files are read from disk, they are kept\n  in memory in an LRU cache to speed up processing of future errors. You\n  can change the max number of files kept in the LRU cache using this\n  property (default: 500)\n- `sourceMapCacheMax` - When source maps are read from disk, the\n  processed source maps are kept in memory in an LRU cache to speed up\n  processing of future errors. You can change the max number of source\n  maps kept in the LRU cache using this property (default: 100)\n\n### `stackman.callsites(err[, options], callback)`\n\nGiven an error object, this function will call the `callback` with an\noptional error as the first argument and an array of\n[CallSite](#callsite-api) objects as the 2nd (a call site is a frame in\nthe stack trace).\n\nNote that any error related to loading or parsing source maps will be\nsuppressed. If a source map related error occurs, Stackman behaves as if\nthe `sourcemap` option is `false`.\n\nOptions:\n\n- `sourcemap` - A boolean specifying if Stackman should look for and\n  process source maps (default: `true`)\n\n### `var properties = stackman.properties(err)`\n\nGiven an error object, this function will return an object containing\nall the custom properties from the original error object (beside date\nobjects, properties of type `object` and `function` are not included in\nthis object).\n\n### `stackman.sourceContexts(callsites[, options], callback)`\n\nConvenience function to get the source context for all call sites in the\n`callsites` argument in one go (instead of iterating over the call sites\nand calling\n[`callsite.sourceContext()`](#callsitesourcecontextoptions-callback) for\neach of them).\n\nCalls the `callback` with an optional error object as the first argument\nand an array of [source context objects](#source-context) as the 2nd.\nEach element in the context array matches a call site in the `callsites`\narray.\n\nOptions:\n\n- `lines` - Total number of lines of soruce context to be loaded with\n  the call site line in the center (default: `5`)\n- `inAppLines` - Total number of lines of soruce context to be loaded\n  with the call site line in the center if `callsite.isApp()` is `true`.\n  Overwrites `lines` (default: `5`)\n- `libraryLines` - Number of lines of soruce context to be loaded with\n  the call site line in the center if `callsite.isApp()` is `false`.\n  Overwrites `lines` (default: `5`)\n\nAll node core call sites and call sites where no lines were collected\ndue to the above options being `0`, will have the context value `null`.\n\n## CallSite API\n\nA CallSite object is an object provided by the [V8 stack trace\nAPI](https://github.com/v8/v8/wiki/Stack-Trace-API) representing a frame\nin the stack trace. Stackman will decorate each CallSite object with\ncustom functions and behavior.\n\n### `callsite.sourcemap`\n\nIf source map support is enabled and a source map have been found for\nthe CallSite, this property will be a reference to a\n[`SourceMapConsumer`](https://github.com/mozilla/source-map#sourcemapconsumer)\nobject representing the given CallSite.\n\nIf set, all functions on the CallSite object will be source map aware.\nI.e. their return values will be related to the original source code and\nnot the transpiled source code.\n\n### `var val = callsite.getThis()`\n\n_Inherited from V8_\n\nReturns the value of `this`.\n\nTo maintain restrictions imposed on strict mode functions, frames that\nhave a strict mode function and all frames below (its caller etc.) are\nnot allow to access their receiver and function objects. For those\nframes, `getThis()` will return `undefined`.\n\n### `var str = callsite.getTypeName()`\n\n_Inherited from V8_\n\nReturns the type of `this` as a string. This is the name of the function\nstored in the constructor field of `this`, if available, otherwise the\nobject's `[[Class]]` internal property.\n\n### `var str = callsite.getTypeNameSafely()`\n\nA safer version of\n[`callsite.getTypeName()`](#var-str--callsitegettypename) that safely\nhandles an exception that sometimes is thrown when using `\"use strict\"`\nin which case `null` is returned.\n\n### `var fn = callsite.getFunction()`\n\n_Inherited from V8_\n\nReturns the current function.\n\nTo maintain restrictions imposed on strict mode functions, frames that\nhave a strict mode function and all frames below (its caller etc.) are\nnot allow to access their receiver and function objects. For those\nframes, `getFunction()` will return `undefined`.\n\n### `var str = callsite.getFunctionName()`\n\n_Inherited from V8_\n\nReturns the name of the current function, typically its name property.\nIf a name property is not available an attempt will be made to try to\ninfer a name from the function's context.\n\n### `var str = callsite.getFunctionNameSanitized()`\n\nGuaranteed to always return the most meaningful function name. If none\ncan be determined, the string `<anonymous>` will be returned.\n\n### `var str = callsite.getMethodName()`\n\n_Inherited from V8_\n\nReturns the name of the property of this or one of its prototypes that\nholds the current function.\n\n### `var str = callsite.getFileName()`\n\n_Inherited from V8 if `callsite.sourcemap` is `undefined`_\n\nIf this function was defined in a script returns the name of the script.\n\n### `var str = callsite.getRelativeFileName()`\n\nReturns a filename realtive to `process.cwd()`.\n\n### `var num = callsite.getLineNumber()`\n\n_Inherited from V8 if `callsite.sourcemap` is `undefined`_\n\nIf this function was defined in a script returns the current line\nnumber.\n\n### `var num = callsite.getColumnNumber()`\n\n_Inherited from V8 if `callsite.sourcemap` is `undefined`_\n\nIf this function was defined in a script returns the current column\nnumber.\n\n### `var str = callsite.getEvalOrigin()`\n\n_Inherited from V8_\n\nIf this function was created using a call to eval returns a CallSite\nobject representing the location where eval was called.\n\nNote that since Node.js v12.11.0, this function returns `undefined`\nunless `eval` was used.\n\n### `var str = callsite.getModuleName()`\n\nReturns the name of the module if `isModule()` is `true`. Otherwise\nreturns `null`.\n\n### `var bool = callsite.isToplevel()`\n\n_Inherited from V8_\n\nIs this a toplevel invocation, that is, is this the global object?\n\n### `var bool = callsite.isEval()`\n\n_Inherited from V8_\n\nDoes this call take place in code defined by a call to eval?\n\n### `var bool = callsite.isNative()`\n\n_Inherited from V8_\n\nIs this call in native V8 code?\n\n### `var bool = callsite.isConstructor()`\n\n_Inherited from V8_\n\nIs this a constructor call?\n\n### `var bool = callsite.isApp()`\n\nIs this inside the app? (i.e. not native, not node code and not a module\ninside the `node_modules` directory)\n\n### `var bool = callsite.isModule()`\n\nIs this inside the `node_modules` directory?\n\n### `var bool = callsite.isNode()`\n\nIs this inside node core?\n\n### `callsite.sourceContext([lines, ]callback)`\n\nGet the source code surrounding the call site line.\n\nIf the `callsite` is a node core call site, the `callback` will be\ncalled with an error.\n\nArguments:\n\n- `lines` - Total number of lines of soruce context to be loaded with\n  the call site line in the center (default: `5`)\n- `callback` - called when the source context have been loaded with an\n  optional error object as the first argument and a [source context\n  object](#source-context) as the 2nd\n\n## Source Context\n\nThe source context objects provided by\n[`callsite.sourceContext`](#callsitesourcecontextoptions-callback)\ncontains the following properties:\n\n- `pre` - The lines before the main callsite line\n- `line` - The main callsite line\n- `post` - The lines after the main callsite line\n\n## Troubleshooting\n\nTo enable debug mode, set the environment variable `DEBUG=stackman`.\n\n## Acknowledgements\n\nThis project was kindly sponsored by [Elastic](https://www.elastic.co).\n\n## License\n\n[MIT](LICENSE)\n"
  },
  {
    "path": "index.js",
    "content": "'use strict'\n\nvar fs = require('fs')\nvar path = require('path')\nvar asyncCache = require('async-cache')\nvar afterAll = require('after-all-results')\nvar errorCallsites = require('error-callsites')\nvar loadSourceMap = require('load-source-map')\nvar debug = require('debug')('stackman')\n\nvar LINES_OF_CONTEXT = 5\nvar ESCAPED_REGEX_PATH_SEP = path.sep === '/' ? '/' : '\\\\\\\\'\nvar MODULE_FOLDER_REGEX = new RegExp('.*node_modules' + ESCAPED_REGEX_PATH_SEP + '([^' + ESCAPED_REGEX_PATH_SEP + ']*)')\n\nmodule.exports = function stackman (opts) {\n  if (!opts) opts = {}\n\n  var fileCache = asyncCache({\n    max: opts.fileCacheMax || 500,\n    load: function (file, cb) {\n      debug('reading %s', file)\n      fs.readFile(file, { encoding: 'utf8' }, function (err, data) {\n        if (err) return cb(err)\n        cb(null, data.split(/\\r?\\n/))\n      })\n    }\n  })\n\n  var sourceMapCache = asyncCache({\n    max: opts.sourceMapCacheMax || 100,\n    load: function (file, cb) {\n      debug('loading source map for %s', file)\n      loadSourceMap(file, cb)\n    }\n  })\n\n  return {\n    callsites: callsites,\n    properties: properties,\n    sourceContexts: sourceContexts\n  }\n\n  function callsites (err, opts, cb) {\n    if (typeof opts === 'function') return callsites(err, null, opts)\n\n    var _callsites = errorCallsites(err)\n\n    if (!validStack(_callsites)) {\n      var _err = new Error('Could not process callsites')\n      process.nextTick(function () {\n        cb(_err)\n      })\n    } else if (!opts || opts.sourcemap !== false) {\n      sourcemapify(_callsites, function (err) {\n        if (err) {\n          debug('error processing source map: %s', err.message)\n        }\n        _callsites.forEach(extendCallsite)\n        cb(null, _callsites)\n      })\n    } else {\n      _callsites.forEach(extendCallsite)\n      process.nextTick(function () {\n        cb(null, _callsites)\n      })\n    }\n  }\n\n  function properties (err) {\n    var properties = {}\n    Object.keys(err).forEach(function (key) {\n      if (key === 'stack') return // 'stack' seems to be enumerable in Node 0.11\n      var val = err[key]\n      if (val === null) return // null is typeof object and well break the switch below\n      switch (typeof val) {\n        case 'function':\n          return\n        case 'object':\n          // ignore all objects except Dates\n          if (typeof val.toISOString !== 'function') return\n          val = val.toISOString()\n      }\n      properties[key] = val\n    })\n    return properties\n  }\n\n  function sourceContexts (callsites, opts, cb) {\n    if (typeof opts === 'function') return sourceContexts(callsites, null, opts)\n    if (!opts) opts = {}\n\n    opts.inAppLines = opts.inAppLines >= 0 ? opts.inAppLines : (opts.lines || LINES_OF_CONTEXT)\n    opts.libraryLines = opts.libraryLines >= 0 ? opts.libraryLines : (opts.lines || LINES_OF_CONTEXT)\n\n    var next = afterAll(cb)\n\n    callsites.forEach(function (callsite) {\n      var lines = callsite.isApp() ? opts.inAppLines : opts.libraryLines\n      if (lines > 0 && !callsite.isNode()) {\n        callsite.sourceContext(lines, next())\n      } else {\n        next()(null, null)\n      }\n    })\n  }\n\n  function validStack (callsites) {\n    return Array.isArray(callsites) &&\n           typeof callsites[0] === 'object' &&\n           typeof callsites[0].getFileName === 'function'\n  }\n\n  function getRelativeFileName () {\n    var filename = this.getFileName()\n    if (!filename) return\n    var root = process.cwd()\n    if (root[root.length - 1] !== path.sep) root += path.sep\n    return !~filename.indexOf(root) ? filename : filename.substr(root.length)\n  }\n\n  function getTypeNameSafely () {\n    try {\n      return this.getTypeName()\n    } catch (e) {\n      // This seems to happen sometimes when using 'use strict',\n      // stemming from `getTypeName`.\n      // [TypeError: Cannot read property 'constructor' of undefined]\n      return null\n    }\n  }\n\n  function getFunctionNameSanitized () {\n    var fnName = this.getFunctionName()\n    if (fnName) return fnName\n    var typeName = this.getTypeNameSafely()\n    if (typeName) return typeName + '.' + (this.getMethodName() || '<anonymous>')\n    return '<anonymous>'\n  }\n\n  function getModuleName () {\n    var filename = this.getFileName() || ''\n    var match = filename.match(MODULE_FOLDER_REGEX)\n    return match ? match[1] : null\n  }\n\n  function isApp () {\n    return !this.isNode() && !~(this.getFileName() || '').indexOf('node_modules' + path.sep)\n  }\n\n  function isModule () {\n    return !!~(this.getFileName() || '').indexOf('node_modules' + path.sep)\n  }\n\n  function isNode () {\n    if (this.isNative()) return true\n    var filename = this.getFileName() || ''\n    return (!path.isAbsolute(filename) && filename[0] !== '.')\n  }\n\n  function sourceContext (linesOfContext, cb) {\n    var _err\n\n    if (typeof linesOfContext === 'function') {\n      cb = linesOfContext\n      linesOfContext = LINES_OF_CONTEXT\n    }\n\n    if (linesOfContext <= 0) {\n      _err = new Error('Cannot collect less than one line of source context')\n      process.nextTick(function () {\n        cb(_err)\n      })\n      return\n    }\n\n    if (this.isNode()) {\n      _err = new Error('Can\\'t get source context of a Node core callsite')\n      process.nextTick(function () {\n        cb(_err)\n      })\n      return\n    }\n\n    var callsite = this\n    var filename = this.getFileName() || ''\n    var source = this.sourcemap\n      ? this.sourcemap.sourceContentFor(filename, true)\n      : null\n\n    if (source) {\n      process.nextTick(function () {\n        cb(null, parseSource(source, callsite, linesOfContext))\n      })\n    } else {\n      fileCache.get(filename, function (err, lines) {\n        if (err) {\n          debug('error reading %s: %s', filename, err.message)\n          cb(err)\n        } else {\n          cb(null, parseSource(lines, callsite, linesOfContext))\n        }\n      })\n    }\n  }\n\n  function parseSource (lines, callsite, linesOfContext) {\n    var index = callsite.getLineNumber() - 1\n    var preLinesOfContext = Math.ceil((linesOfContext - 1) / 2)\n    var postLinesOfContext = Math.floor((linesOfContext - 1) / 2)\n    return {\n      pre: lines.slice(Math.max(0, index - preLinesOfContext), index),\n      line: lines[index],\n      post: lines.slice(index + 1, index + 1 + postLinesOfContext)\n    }\n  }\n\n  function sourcemapify (callsites, cb) {\n    var next = afterAll(function (err, consumers) {\n      if (err) return cb(err)\n\n      consumers.forEach(function (consumer, index) {\n        if (!consumer) return\n        Object.defineProperty(callsites[index], 'sourcemap', {\n          writable: true,\n          value: consumer\n        })\n      })\n\n      cb()\n    })\n\n    callsites.forEach(function (callsite) {\n      getSourceMapConsumer(callsite, next())\n    })\n  }\n\n  function getSourceMapConsumer (callsite, cb) {\n    if (isNode.call(callsite)) return process.nextTick(cb)\n    var filename = callsite.getFileName()\n    sourceMapCache.get(filename, cb)\n  }\n\n  function extendCallsite (callsite) {\n    var getLineNumber = callsite.getLineNumber\n    var getColumnNumber = callsite.getColumnNumber\n    var getFileName = callsite.getFileName\n    var position = null\n    var properties = {\n      getRelativeFileName: {\n        writable: true,\n        value: getRelativeFileName\n      },\n      getTypeNameSafely: {\n        writable: true,\n        value: getTypeNameSafely\n      },\n      getFunctionNameSanitized: {\n        writable: true,\n        value: getFunctionNameSanitized\n      },\n      getModuleName: {\n        writable: true,\n        value: getModuleName\n      },\n      isApp: {\n        writable: true,\n        value: isApp\n      },\n      isModule: {\n        writable: true,\n        value: isModule\n      },\n      isNode: {\n        writable: true,\n        value: isNode\n      },\n      sourceContext: {\n        writable: true,\n        value: sourceContext\n      }\n    }\n\n    if (callsite.sourcemap) {\n      properties.getFileName = {\n        writable: true,\n        value: function () {\n          var filename = getFileName.call(callsite)\n          var sourceFile = getPosition().source\n          if (!sourceFile) return filename\n          var sourceDir = path.dirname(filename)\n          return path.resolve(path.join(sourceDir, sourceFile))\n        }\n      }\n      properties.getLineNumber = {\n        writable: true,\n        value: function () {\n          return getPosition().line || getLineNumber.call(callsite)\n        }\n      }\n      properties.getColumnNumber = {\n        writable: true,\n        value: function () {\n          return getPosition().column || getColumnNumber.call(callsite)\n        }\n      }\n    }\n\n    Object.defineProperties(callsite, properties)\n\n    function getPosition () {\n      if (!position) {\n        try {\n          position = callsite.sourcemap.originalPositionFor({\n            line: getLineNumber.call(callsite),\n            column: getColumnNumber.call(callsite)\n          })\n        } catch (e) {\n          debug('error fetching source map position: %s', e.message)\n          return {}\n        }\n      }\n\n      return position\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"stackman\",\n  \"version\": \"4.0.1\",\n  \"description\": \"Enhance an error stacktrace with code excerpts and other goodies\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"after-all-results\": \"^2.0.0\",\n    \"async-cache\": \"^1.1.0\",\n    \"debug\": \"^4.1.1\",\n    \"error-callsites\": \"^2.0.3\",\n    \"load-source-map\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"longjohn\": \"^0.2.12\",\n    \"semver\": \"^6.3.0\",\n    \"standard\": \"^14.3.3\",\n    \"tape\": \"^4.13.2\"\n  },\n  \"scripts\": {\n    \"test\": \"standard && node test/strict.js && node test/non-strict.js && node test/longjohn.js && node test/sourcemap.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/watson/stackman.git\"\n  },\n  \"keywords\": [\n    \"v8\",\n    \"stack\",\n    \"stacktrace\",\n    \"stackframe\",\n    \"callsite\",\n    \"callsites\",\n    \"frame\",\n    \"source\",\n    \"debug\",\n    \"log\",\n    \"error\",\n    \"trace\"\n  ],\n  \"author\": \"Thomas Watson Steen <w@tson.dk>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/watson/stackman/issues\"\n  },\n  \"homepage\": \"https://github.com/watson/stackman\",\n  \"coordinates\": [\n    56.043843,\n    12.609477\n  ],\n  \"standard\": {\n    \"ignore\": [\n      \"/test/fixtures/lib/\"\n    ]\n  }\n}\n"
  },
  {
    "path": "test/fixtures/lib/error-broken.js",
    "content": "'use strict';\n\n// Just a little prefixing line\nvar generateError = function generateError() {\n  var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'foo';\n  return new Error(msg);\n};\n\nmodule.exports = generateError;\n\n//# sourceMappingURL=error-broken.js.map\n"
  },
  {
    "path": "test/fixtures/lib/error-inline-broken.js",
    "content": "'use strict';\n\n// Just a little prefixing line\nvar generateError = function generateError() {\n  var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'foo';\n  return new Error(msg);\n};\n\nmodule.exports = generateError;\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9lcnJvci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBTSxnQkFBZ0IsU0FBaEIsYUFBZ0I7QUFBQSxNQUFDLEdBQUQsdUVBQU8sS0FBUDtBQUFBLFNBQWlCLElBQUksS0FBSixDQUFVLEdBQVYsQ0FBakI7QUFBQSxDQUF0Qjs7QUFFQSxPQUFPLE9BQVAsR0FBaUIsYUFBakIiLCJmaWxlIjoiZXJyb3ItaW5saW5lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSnVzdCBhIGxpdHRsZSBwcmVmaXhpbmcgbGluZVxuY29uc3QgZ2VuZXJhdGVFcnJvciA9IChtc2cgPSAnZm9vJykgPT4gbmV3IEVycm9yKG1zZylcblxubW9kdWxlLmV4cG9ydHMgPSBnZW5lcmF0ZUVycm9yXG4iXX0=\n"
  },
  {
    "path": "test/fixtures/lib/error-inline.js",
    "content": "'use strict';\n\n// Just a little prefixing line\nvar generateError = function generateError() {\n  var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'foo';\n  return new Error(msg);\n};\n\nmodule.exports = generateError;\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9lcnJvci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBTSxnQkFBZ0IsU0FBaEIsYUFBZ0I7QUFBQSxNQUFDLEdBQUQsdUVBQU8sS0FBUDtBQUFBLFNBQWlCLElBQUksS0FBSixDQUFVLEdBQVYsQ0FBakI7QUFBQSxDQUF0Qjs7QUFFQSxPQUFPLE9BQVAsR0FBaUIsYUFBakIiLCJmaWxlIjoiZXJyb3ItaW5saW5lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSnVzdCBhIGxpdHRsZSBwcmVmaXhpbmcgbGluZVxuY29uc3QgZ2VuZXJhdGVFcnJvciA9IChtc2cgPSAnZm9vJykgPT4gbmV3IEVycm9yKG1zZylcblxubW9kdWxlLmV4cG9ydHMgPSBnZW5lcmF0ZUVycm9yXG4iXX0="
  },
  {
    "path": "test/fixtures/lib/error-map-missing.js",
    "content": "'use strict';\n\n// Just a little prefixing line\nvar generateError = function generateError() {\n  var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'foo';\n  return new Error(msg);\n};\n\nmodule.exports = generateError;\n\n//# sourceMappingURL=invalid.js.map\n"
  },
  {
    "path": "test/fixtures/lib/error-src-embedded.js",
    "content": "'use strict';\n\n// Just a little prefixing line\nvar generateError = function generateError() {\n  var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'foo';\n  return new Error(msg);\n};\n\nmodule.exports = generateError;\n\n//# sourceMappingURL=error-src-embedded.js.map\n"
  },
  {
    "path": "test/fixtures/lib/error-src-missing.js",
    "content": "'use strict';\n\n// Just a little prefixing line\nvar generateError = function generateError() {\n  var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'foo';\n  return new Error(msg);\n};\n\nmodule.exports = generateError;\n\n//# sourceMappingURL=error-src-missing.js.map\n"
  },
  {
    "path": "test/fixtures/lib/error.js",
    "content": "'use strict';\n\n// Just a little prefixing line\nvar generateError = function generateError() {\n  var msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'foo';\n  return new Error(msg);\n};\n\nmodule.exports = generateError;\n\n//# sourceMappingURL=error.js.map"
  },
  {
    "path": "test/fixtures/src/error.js",
    "content": "// Just a little prefixing line\nconst generateError = (msg = 'foo') => new Error(msg)\n\nmodule.exports = generateError\n"
  },
  {
    "path": "test/longjohn.js",
    "content": "'use strict'\n\nrequire('longjohn')\nvar test = require('tape')\nvar stackman = require('../')()\n\ntest('longjohn, regular error', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.ok(callsites.length > 0, 'should have stack frames')\n    t.end()\n  })\n})\n\ntest('longjohn, thrown error', function (t) {\n  try {\n    throw new Error('foo')\n  } catch (err) {\n    stackman.callsites(err, function (err, callsites) {\n      t.error(err)\n      t.ok(callsites.length > 0, 'should have stack frames')\n      t.end()\n    })\n  }\n})\n"
  },
  {
    "path": "test/non-strict.js",
    "content": "var test = require('tape')\nvar stackman = require('../')()\n\ntest('callsite.getThis()', function (t) {\n  var err = new Error('foo')\n  var self = this\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getThis(), self)\n    t.end()\n  })\n})\n\ntest('callsite.getFunction()', function fn (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getFunction(), fn)\n    t.end()\n  })\n})\n"
  },
  {
    "path": "test/sourcemap.js",
    "content": "'use strict'\n\nvar path = require('path')\nvar test = require('tape')\nvar stackman = require('../')()\n\ntest('source maps disabled', function (t) {\n  var err = require('./fixtures/lib/error')()\n  stackman.callsites(err, { sourcemap: false }, assertSourceMapNotLoaded.bind(null, t, 'error.js'))\n})\n\ntest('source map inlined', function (t) {\n  var err = require('./fixtures/lib/error-inline')()\n  stackman.callsites(err, assertSourceFound.bind(null, t))\n})\n\ntest('source map linked', function (t) {\n  t.test('source mapped source code embedded', function (t) {\n    var err = require('./fixtures/lib/error-src-embedded')()\n    stackman.callsites(err, assertSourceFound.bind(null, t))\n  })\n\n  t.test('source mapped source code on disk', function (t) {\n    var err = require('./fixtures/lib/error')()\n    stackman.callsites(err, assertSourceFound.bind(null, t))\n  })\n\n  t.test('source mapped source code not found', function (t) {\n    var err = require('./fixtures/lib/error-src-missing')()\n    stackman.callsites(err, assertSourceNotFound.bind(null, t))\n  })\n})\n\ntest('fails', function (t) {\n  t.test('inlined source map broken', function (t) {\n    var err = require('./fixtures/lib/error-inline-broken')()\n    stackman.callsites(err, assertSourceMapNotLoaded.bind(null, t, 'error-inline-broken.js'))\n  })\n\n  t.test('linked source map not found', function (t) {\n    var err = require('./fixtures/lib/error-map-missing')()\n    stackman.callsites(err, assertSourceMapNotLoaded.bind(null, t, 'error-map-missing.js'))\n  })\n\n  t.test('linked source map broken', function (t) {\n    var err = require('./fixtures/lib/error-broken')()\n    stackman.callsites(err, assertSourceMapNotLoaded.bind(null, t, 'error-broken.js'))\n  })\n})\n\nfunction assertSourceMapNotLoaded (t, filename, err, callsites) {\n  t.error(err)\n  var callsite = callsites[0]\n  t.equal(callsite.getFileName(), path.join(__dirname, 'fixtures', 'lib', filename))\n  t.equal(callsite.getRelativeFileName(), path.join('test', 'fixtures', 'lib', filename))\n  t.equal(callsite.getLineNumber(), 6)\n  t.equal(callsite.getColumnNumber(), 10)\n  t.equal(callsite.getFunctionName(), 'generateError')\n  t.equal(callsite.getFunctionNameSanitized(), 'generateError')\n  t.equal(callsite.isApp(), __dirname.indexOf('node_modules') === -1)\n  callsite.sourceContext(function (err, context) {\n    t.error(err)\n    t.equal(context.line, '  return new Error(msg);')\n    t.end()\n  })\n}\n\nfunction assertSourceFound (t, err, callsites) {\n  t.error(err)\n  var callsite = callsites[0]\n  t.equal(callsite.getFileName(), path.join(__dirname, 'fixtures', 'src', 'error.js'))\n  t.equal(callsite.getRelativeFileName(), path.join('test', 'fixtures', 'src', 'error.js'))\n  t.equal(callsite.getLineNumber(), 2)\n  t.equal(callsite.getColumnNumber(), 39)\n  t.equal(callsite.getFunctionName(), 'generateError')\n  t.equal(callsite.getFunctionNameSanitized(), 'generateError')\n  t.equal(callsite.isApp(), __dirname.indexOf('node_modules') === -1)\n  callsite.sourceContext(function (err, context) {\n    t.error(err)\n    t.deepEqual(context.pre, ['// Just a little prefixing line'])\n    t.equal(context.line, 'const generateError = (msg = \\'foo\\') => new Error(msg)')\n    t.deepEqual(context.post, ['', 'module.exports = generateError'])\n    t.end()\n  })\n}\n\nfunction assertSourceNotFound (t, err, callsites) {\n  t.error(err)\n  var callsite = callsites[0]\n  t.equal(callsite.getFileName(), path.join(__dirname, 'fixtures', 'src', 'not', 'found.js'))\n  t.equal(callsite.getRelativeFileName(), path.join('test', 'fixtures', 'src', 'not', 'found.js'))\n  t.equal(callsite.getLineNumber(), 2)\n  t.equal(callsite.getColumnNumber(), 39)\n  t.equal(callsite.getFunctionName(), 'generateError')\n  t.equal(callsite.getFunctionNameSanitized(), 'generateError')\n  t.equal(callsite.isApp(), __dirname.indexOf('node_modules') === -1)\n  callsite.sourceContext(function (err, context) {\n    t.equal(err.code, 'ENOENT')\n    t.equal(context, undefined)\n    t.end()\n  })\n}\n"
  },
  {
    "path": "test/strict.js",
    "content": "'use strict'\n\nvar fs = require('fs')\nvar path = require('path')\nvar semver = require('semver')\nvar test = require('tape')\nvar stackman = require('../')()\n\ntest('stackman.callsites()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.ok(Array.isArray(callsites))\n    t.ok(callsites.length > 0, 'should have at least one element')\n    callsites.forEach(function (callsite, index) {\n      t.equal(typeof callsite.getThis, 'function', 'getThis should be a function')\n      t.equal(typeof callsite.getTypeName, 'function', 'getTypeName should be a function')\n      t.equal(typeof callsite.getTypeNameSafely, 'function', 'getTypeNameSafely should be a function')\n      t.equal(typeof callsite.getFunction, 'function', 'getFunction should be a function')\n      t.equal(typeof callsite.getFunctionName, 'function', 'getFunctionName should be a function')\n      t.equal(typeof callsite.getFunctionNameSanitized, 'function', 'getFunctionNameSanitized should be a function')\n      t.equal(typeof callsite.getMethodName, 'function', 'getMethodName should be a function')\n      t.equal(typeof callsite.getFileName, 'function', 'getFileName should be a function')\n      t.equal(typeof callsite.getRelativeFileName, 'function', 'getRelativeFileName should be a function')\n      t.equal(typeof callsite.getLineNumber, 'function', 'getLineNumber should be a function')\n      t.equal(typeof callsite.getColumnNumber, 'function', 'getColumnNumber should be a function')\n      t.equal(typeof callsite.getEvalOrigin, 'function', 'getEvalOrigin should be a function')\n      t.equal(typeof callsite.getModuleName, 'function', 'getModuleName should be a function')\n      t.equal(typeof callsite.isToplevel, 'function', 'isToplevel should be a function')\n      t.equal(typeof callsite.isEval, 'function', 'isEval should be a function')\n      t.equal(typeof callsite.isNative, 'function', 'isNative should be a function')\n      t.equal(typeof callsite.isConstructor, 'function', 'isConstructor should be a function')\n      t.equal(typeof callsite.isApp, 'function', 'isApp should be a function')\n      t.equal(typeof callsite.isModule, 'function', 'isModule should be a function')\n      t.equal(typeof callsite.isNode, 'function', 'isNode should be a function')\n      t.equal(typeof callsite.sourceContext, 'function', 'sourceContext should be a function')\n    })\n    t.end()\n  })\n})\n\ntest('callsite.getThis()', function (t) {\n  var err = new Error('foo')\n  var self = this\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    var callsite = callsites[0]\n    if (semver.gte(process.version, '0.12.0')) {\n      t.equal(callsite.getThis(), undefined)\n    } else {\n      t.equal(callsite.getThis(), self)\n    }\n    t.end()\n  })\n})\n\ntest('callsite.getTypeName()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getTypeName(), 'Test')\n    t.end()\n  })\n})\n\ntest('callsite.getTypeNameSafely()', function (t) {\n  // TODO: It would be nice if we could get the non-safe version to\n  // throw in a test\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getTypeNameSafely(), 'Test')\n    t.end()\n  })\n})\n\ntest('callsite.getFunction()', function fn (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    var callsite = callsites[0]\n    if (semver.gte(process.version, '0.12.0')) {\n      t.equal(callsite.getFunction(), undefined)\n    } else {\n      t.equal(callsite.getFunction(), fn)\n    }\n    t.end()\n  })\n})\n\ntest('callsite.getFunctionName() - anonymous', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getFunctionName(), null)\n    t.end()\n  })\n})\n\ntest('callsite.getFunctionName() - named', function named (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getFunctionName(), 'named')\n    t.end()\n  })\n})\n\ntest('callsite.getFunctionNameSanitized() - anonymous', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getFunctionNameSanitized(), 'Test.<anonymous>')\n    t.end()\n  })\n})\n\ntest('callsite.getFunctionNameSanitized() - named', function named (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getFunctionNameSanitized(), 'named')\n    t.end()\n  })\n})\n\ntest('callsite.getMethodName()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getMethodName(), null)\n    t.end()\n  })\n})\n\ntest('callsite.getFileName()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getFileName(), __filename)\n    t.end()\n  })\n})\n\ntest('callsite.getRelativeFileName()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getRelativeFileName(), 'test/strict.js')\n    t.end()\n  })\n})\n\ntest('callsite.getLineNumber()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.ok(callsites[0].getLineNumber() > 1)\n    t.end()\n  })\n})\n\ntest('callsite.getColumnNumber()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getColumnNumber(), 13)\n    t.end()\n  })\n})\n\ntest('callsite.getEvalOrigin()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].getEvalOrigin(), semver.gte(process.version, '12.11.0') ? undefined : __filename)\n    t.end()\n  })\n})\n\ntest('callsite.getEvalOrigin()', function (t) {\n  var err = eval('new Error(\\'foo\\')') // eslint-disable-line no-eval\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    var actual = callsites[0].getEvalOrigin()\n    var expected = new RegExp(`^eval at <anonymous> \\\\(${__filename}:\\\\d+:\\\\d+\\\\)$`)\n    t.ok(expected.test(actual), 'should match regex', { actual, expected })\n    t.end()\n  })\n})\n\ntest('callsite.getModuleName()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    var callsite = callsites[0]\n    if (__filename.indexOf(path.sep + 'node_modules' + path.sep) === -1) {\n      t.equal(callsite.getModuleName(), null)\n    } else {\n      t.equal(callsite.getModuleName(), 'stackman')\n    }\n    t.end()\n  })\n})\n\ntest('callsite.isToplevel()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].isToplevel(), false)\n    t.end()\n  })\n})\n\ntest('callsite.isEval()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].isEval(), false)\n    t.end()\n  })\n})\n\ntest('callsite.isNative()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].isNative(), false)\n    t.end()\n  })\n})\n\ntest('callsite.isConstructor()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].isConstructor(), false)\n    t.end()\n  })\n})\n\ntest('callsite.isApp()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    var callsite = callsites[0]\n    if (__filename.indexOf(path.sep + 'node_modules' + path.sep) === -1) {\n      t.equal(callsite.isApp(), true)\n    } else {\n      t.equal(callsite.isApp(), false)\n    }\n    t.end()\n  })\n})\n\ntest('callsite.isModule()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    var callsite = callsites[0]\n    if (__filename.indexOf(path.sep + 'node_modules' + path.sep) === -1) {\n      t.equal(callsite.isModule(), false)\n    } else {\n      t.equal(callsite.isModule(), true)\n    }\n    t.end()\n  })\n})\n\ntest('callsite.isNode()', function (t) {\n  var err = new Error('foo')\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n    t.equal(callsites[0].isNode(), false)\n    t.end()\n  })\n})\n\ntest('callsite.sourceContext()', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    callsites[0].sourceContext(function (err, context) {\n      t.error(err)\n      t.equal(typeof context, 'object')\n      t.equal(typeof context.line, 'string')\n      t.ok(Array.isArray(context.pre), 'should be an array')\n      t.ok(Array.isArray(context.post), 'should be an array')\n      t.equal(context.pre.length, 2)\n      t.equal(context.post.length, 2)\n      t.equal(context.line.trim(), 'var err = new Error()')\n      t.end()\n    })\n  })\n})\n\ntest('callsite.sourceContext() - node core', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    var callsite = callsites[0]\n    Object.defineProperty(callsite, 'isNode', {\n      writable: true,\n      value: function () { return true }\n    })\n\n    callsites[0].sourceContext(function (err, context) {\n      t.equal(err.message, 'Can\\'t get source context of a Node core callsite')\n      t.end()\n    })\n  })\n})\n\ntest('callsite.sourceContext(0)', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    callsites[0].sourceContext(0, function (err, context) {\n      t.equal(err.message, 'Cannot collect less than one line of source context')\n      t.notOk(context)\n      t.end()\n    })\n  })\n})\n\ntest('callsite.sourceContext(1)', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    callsites[0].sourceContext(1, function (err, context) {\n      t.error(err)\n      t.equal(context.pre.length, 0)\n      t.equal(context.line.trim(), 'var err = new Error()')\n      t.equal(context.post.length, 0)\n      t.end()\n    })\n  })\n})\n\ntest('callsite.sourceContext(2)', function (t) {\n  // line before\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    callsites[0].sourceContext(2, function (err, context) {\n      t.error(err)\n      t.equal(context.pre.length, 1)\n      t.equal(context.pre[0].trim(), '// line before')\n      t.equal(context.line.trim(), 'var err = new Error()')\n      t.equal(context.post.length, 0)\n      t.end()\n    })\n  })\n})\n\ntest('callsite.sourceContext(3)', function (t) {\n  // line before\n  var err = new Error()\n  // line after\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    callsites[0].sourceContext(3, function (err, context) {\n      t.error(err)\n      t.equal(context.pre.length, 1)\n      t.equal(context.pre[0].trim(), '// line before')\n      t.equal(context.line.trim(), 'var err = new Error()')\n      t.equal(context.post.length, 1)\n      t.equal(context.post[0].trim(), '// line after')\n      t.end()\n    })\n  })\n})\n\ntest('callsite.sourceContext(4)', function (t) {\n  // line before 2\n  // line before 1\n  var err = new Error()\n  // line after\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    callsites[0].sourceContext(4, function (err, context) {\n      t.error(err)\n      t.equal(context.pre.length, 2)\n      t.equal(context.pre[0].trim(), '// line before 2')\n      t.equal(context.pre[1].trim(), '// line before 1')\n      t.equal(context.line.trim(), 'var err = new Error()')\n      t.equal(context.post.length, 1)\n      t.equal(context.post[0].trim(), '// line after')\n      t.end()\n    })\n  })\n})\n\ntest('stackman.properties()', function (t) {\n  fs.readFile('./no_such_file', function (err) {\n    err.foo = 'bar'\n    var props = stackman.properties(err)\n    t.equal(props.errno, err.errno)\n    t.equal(props.code, 'ENOENT')\n    t.equal(props.path, './no_such_file')\n    t.equal(props.foo, 'bar')\n    t.end()\n  })\n})\n\ntest('stackman.sourceContexts(callsites)', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    stackman.sourceContexts(callsites, function (err, contexts) {\n      t.error(err)\n      contexts.forEach(function (context, index) {\n        var callsite = callsites[index]\n\n        if (callsite.isNode()) {\n          t.equal(context, null)\n        } else {\n          t.equal(typeof context, 'object')\n          t.equal(typeof context.line, 'string')\n          t.ok(Array.isArray(context.pre), 'should be an array')\n          t.ok(Array.isArray(context.post), 'should be an array')\n          t.equal(context.pre.length, 2)\n          t.equal(context.post.length, 2)\n        }\n      })\n      t.end()\n    })\n  })\n})\n\ntest('stackman.sourceContexts(callsites, {lines: 7})', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    stackman.sourceContexts(callsites, { lines: 7 }, function (err, contexts) {\n      t.error(err)\n      contexts.forEach(function (context, index) {\n        var callsite = callsites[index]\n\n        if (callsite.isNode()) {\n          t.equal(context, null)\n        } else {\n          t.equal(typeof context, 'object')\n          t.equal(typeof context.line, 'string')\n          t.ok(Array.isArray(context.pre), 'should be an array')\n          t.ok(Array.isArray(context.post), 'should be an array')\n          t.equal(context.pre.length, 3)\n          t.equal(context.post.length, 3)\n        }\n      })\n      t.end()\n    })\n  })\n})\n\ntest('stackman.sourceContexts(callsites, {inAppLines: 7, libraryLines: 3})', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    stackman.sourceContexts(callsites, { inAppLines: 7, libraryLines: 3 }, function (err, contexts) {\n      t.error(err)\n      contexts.forEach(function (context, index) {\n        var callsite = callsites[index]\n\n        if (callsite.isNode()) {\n          t.equal(context, null)\n        } else {\n          t.equal(typeof context, 'object')\n          t.equal(typeof context.line, 'string')\n          t.ok(Array.isArray(context.pre), 'should be an array')\n          t.ok(Array.isArray(context.post), 'should be an array')\n          if (callsite.isApp()) {\n            t.equal(context.pre.length, 3)\n            t.equal(context.post.length, 3)\n          } else {\n            t.equal(context.pre.length, 1)\n            t.equal(context.post.length, 1)\n          }\n        }\n      })\n      t.end()\n    })\n  })\n})\n\ntest('stackman.sourceContexts(callsites, {libraryLines: 0})', function (t) {\n  var err = new Error()\n  stackman.callsites(err, function (err, callsites) {\n    t.error(err)\n\n    stackman.sourceContexts(callsites, { libraryLines: 0 }, function (err, contexts) {\n      t.error(err)\n      contexts.forEach(function (context, index) {\n        var callsite = callsites[index]\n\n        if (callsite.isApp()) {\n          t.equal(typeof context, 'object')\n          t.equal(typeof context.line, 'string')\n          t.ok(Array.isArray(context.pre), 'should be an array')\n          t.ok(Array.isArray(context.post), 'should be an array')\n          t.equal(context.pre.length, 2)\n          t.equal(context.post.length, 2)\n        } else {\n          t.equal(context, null)\n        }\n      })\n      t.end()\n    })\n  })\n})\n"
  }
]