package/package.json000644 000765 000024 0000001057 13106522435013021 0ustar00000000 000000 { "author": "Felix Geisendörfer (http://debuggable.com/)", "name": "stack-trace", "description": "Get v8 stack traces as an array of CallSite objects.", "version": "0.0.10", "homepage": "https://github.com/felixge/node-stack-trace", "repository": { "type": "git", "url": "git://github.com/felixge/node-stack-trace.git" }, "main": "./lib/stack-trace", "engines": { "node": "*" }, "license": "MIT", "dependencies": {}, "devDependencies": { "far": "0.0.3", "long-stack-traces": "0.1.2" } } package/.npmignore000644 000765 000024 0000000005 13106522145012520 0ustar00000000 000000 test/package/License000644 000765 000024 0000002115 13106522145012032 0ustar00000000 000000 Copyright (c) 2011 Felix Geisendörfer (felix@debuggable.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/Makefile000644 000765 000024 0000000154 13106522145012166 0ustar00000000 000000 SHELL := /bin/bash test: @./test/run.js release: git push git push --tags npm publish . .PHONY: test package/Readme.md000644 000765 000024 0000007152 13106522145012252 0ustar00000000 000000 # stack-trace Get v8 stack traces as an array of CallSite objects. ## Install ``` bash npm install stack-trace ``` ## Usage The stack-trace module makes it easy for you to capture the current stack: ``` javascript var stackTrace = require('stack-trace'); var trace = stackTrace.get(); require('assert').strictEqual(trace[0].getFileName(), __filename); ``` However, sometimes you have already popped the stack you are interested in, and all you have left is an `Error` object. This module can help: ``` javascript var stackTrace = require('stack-trace'); var err = new Error('something went wrong'); var trace = stackTrace.parse(err); require('assert').strictEqual(trace[0].getFileName(), __filename); ``` Please note that parsing the `Error#stack` property is not perfect, only certain properties can be retrieved with it as noted in the API docs below. ## Long stack traces stack-trace works great with [long-stack-traces][], when parsing an `err.stack` that has crossed the event loop boundary, a `CallSite` object returning `'----------------------------------------'` for `getFileName()` is created. All other methods of the event loop boundary call site return `null`. [long-stack-traces]: https://github.com/tlrobinson/long-stack-traces ## API ### stackTrace.get([belowFn]) Returns an array of `CallSite` objects, where element `0` is the current call site. When passing a function on the current stack as the `belowFn` parameter, the returned array will only include `CallSite` objects below this function. ### stackTrace.parse(err) Parses the `err.stack` property of an `Error` object into an array compatible with those returned by `stackTrace.get()`. However, only the following methods are implemented on the returned `CallSite` objects. * getTypeName * getFunctionName * getMethodName * getFileName * getLineNumber * getColumnNumber * isNative Note: Except `getFunctionName()`, all of the above methods return exactly the same values as you would get from `stackTrace.get()`. `getFunctionName()` is sometimes a little different, but still useful. ### CallSite The official v8 CallSite object API can be found [here][v8stackapi]. A quick excerpt: > A CallSite object defines the following methods: > > * **getThis**: returns the value of this > * **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. > * **getFunction**: returns the current function > * **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. > * **getMethodName**: returns the name of the property of this or one of its prototypes that holds the current function > * **getFileName**: if this function was defined in a script returns the name of the script > * **getLineNumber**: if this function was defined in a script returns the current line number > * **getColumnNumber**: if this function was defined in a script returns the current column number > * **getEvalOrigin**: if this function was created using a call to eval returns a CallSite object representing the location where eval was called > * **isToplevel**: is this a toplevel invocation, that is, is this the global object? > * **isEval**: does this call take place in code defined by a call to eval? > * **isNative**: is this call in native V8 code? > * **isConstructor**: is this a constructor call? [v8stackapi]: http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi ## License stack-trace is licensed under the MIT license. package/lib/stack-trace.js000644 000765 000024 0000006471 13106522145014043 0ustar00000000 000000 exports.get = function(belowFn) { var oldLimit = Error.stackTraceLimit; Error.stackTraceLimit = Infinity; var dummyObject = {}; var v8Handler = Error.prepareStackTrace; Error.prepareStackTrace = function(dummyObject, v8StackTrace) { return v8StackTrace; }; Error.captureStackTrace(dummyObject, belowFn || exports.get); var v8StackTrace = dummyObject.stack; Error.prepareStackTrace = v8Handler; Error.stackTraceLimit = oldLimit; return v8StackTrace; }; exports.parse = function(err) { if (!err.stack) { return []; } var self = this; var lines = err.stack.split('\n').slice(1); return lines .map(function(line) { if (line.match(/^\s*[-]{4,}$/)) { return self._createParsedCallSite({ fileName: line, lineNumber: null, functionName: null, typeName: null, methodName: null, columnNumber: null, 'native': null, }); } var lineMatch = line.match(/at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/); if (!lineMatch) { return; } var object = null; var method = null; var functionName = null; var typeName = null; var methodName = null; var isNative = (lineMatch[5] === 'native'); if (lineMatch[1]) { functionName = lineMatch[1]; var methodStart = functionName.lastIndexOf('.'); if (functionName[methodStart-1] == '.') methodStart--; if (methodStart > 0) { object = functionName.substr(0, methodStart); method = functionName.substr(methodStart + 1); var objectEnd = object.indexOf('.Module'); if (objectEnd > 0) { functionName = functionName.substr(objectEnd + 1); object = object.substr(0, objectEnd); } } typeName = null; } if (method) { typeName = object; methodName = method; } if (method === '') { methodName = null; functionName = null; } var properties = { fileName: lineMatch[2] || null, lineNumber: parseInt(lineMatch[3], 10) || null, functionName: functionName, typeName: typeName, methodName: methodName, columnNumber: parseInt(lineMatch[4], 10) || null, 'native': isNative, }; return self._createParsedCallSite(properties); }) .filter(function(callSite) { return !!callSite; }); }; function CallSite(properties) { for (var property in properties) { this[property] = properties[property]; } } var strProperties = [ 'this', 'typeName', 'functionName', 'methodName', 'fileName', 'lineNumber', 'columnNumber', 'function', 'evalOrigin' ]; var boolProperties = [ 'topLevel', 'eval', 'native', 'constructor' ]; strProperties.forEach(function (property) { CallSite.prototype[property] = null; CallSite.prototype['get' + property[0].toUpperCase() + property.substr(1)] = function () { return this[property]; } }); boolProperties.forEach(function (property) { CallSite.prototype[property] = false; CallSite.prototype['is' + property[0].toUpperCase() + property.substr(1)] = function () { return this[property]; } }); exports._createParsedCallSite = function(properties) { return new CallSite(properties); };