Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Allow configurable coloring & formatting

  • Loading branch information...
commit 25bb1c3c3f5304c3614b17c3f8a3a58d3aa12188 1 parent 2e0b096
Adam Crabtree (CrabDude's alias) CrabBot authored
Showing with 190 additions and 107 deletions.
  1. +26 −0 examples/colors.js
  2. +79 −84 lib/formatStackTrace.js
  3. +85 −23 lib/trycatch.js
26 examples/colors.js
View
@@ -0,0 +1,26 @@
+var fs = require('fs')
+ , trycatch = require('../lib/trycatch')
+ , _ = require('underscore')._
+
+trycatch.configure({
+ 'long-stack-traces': true
+, colors: {
+ "node": "none"
+ , "node_modules": false
+ , "default": 'yellow'
+ }
+})
+
+trycatch(function() {
+ fs.readFile(__filename, function () {
+ _.map(['Error 1', 'Error 2']
+ , function foo(v) {
+ setTimeout(function() {
+ throw new Error(v)
+ }, 10)
+ })
+ })
+ }
+, function(err) {
+ console.log("Async error caught!\n", err.stack);
+ });
163 lib/formatStackTrace.js
View
@@ -24,108 +24,103 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-module.exports = FormatStackTrace;
+module.exports = function(format, filter) {
+ filter = Array.isArray(filter) ? filter : []
-var path = require('path'),
- d = path.join('/'),
- node_modules = d + 'node_modules' + d;
-
-function FormatStackTrace(error, frames, filter, colors) {
- var lines = [];
- try {
- lines.push(error.toString());
- } catch (e) {
- try {
- lines.push("<error: " + e + ">");
- } catch (ee) {
- lines.push("<error>");
- }
- }
- for (var i = 0; i < frames.length; i++) {
- var frame = frames[i];
- var line;
+ function FormatStackTrace(error, frames) {
+ var lines = [];
try {
- line = FormatSourcePosition(frame, filter);
+ lines.push(error.toString());
} catch (e) {
try {
- line = "<error: " + e + ">";
+ lines.push("<error: " + e + ">");
} catch (ee) {
- // Any code that reaches this point is seriously nasty!
- line = "<error>";
+ lines.push("<error>");
}
}
- if (line !== undefined) {
- line = " at " + line;
-
- if (colors) {
- if (line.indexOf(node_modules) >= 0) {
- line = colors.cyan(line);
- } else if (line.indexOf(d) >= 0) {
- line = colors.red(line);
- } else {
- line = colors.white(line);
+ for (var i = 0; i < frames.length; i++) {
+ var frame = frames[i];
+ var line;
+ try {
+ line = FormatSourcePosition(frame);
+ } catch (e) {
+ try {
+ line = "<error: " + e + ">";
+ } catch (ee) {
+ // Any code that reaches this point is seriously nasty!
+ line = "<error>";
}
}
+ if (line !== undefined) {
+ line = " at " + line;
- lines.push(line);
+ if ('function' === typeof format) {
+ line = format(line)
+ }
+
+ if (line) {
+ lines.push(line);
+ }
+ }
}
+ return lines.join("\n");
}
- return lines.join("\n");
-}
-function FormatSourcePosition(frame, filter) {
- var fileLocation = "";
- if (frame.isNative()) {
- fileLocation = "native";
- } else if (frame.isEval()) {
- fileLocation = "eval at " + frame.getEvalOrigin();
- } else {
- var fileName = frame.getFileName();
- if (fileName) {
- for(var i=0, l=filter.length; i<l; i++) {
- if (fileName.indexOf(filter[i]) !== -1) return;
- }
- fileLocation += fileName;
- var lineNumber = frame.getLineNumber();
- if (lineNumber != null) {
- fileLocation += ":" + lineNumber;
- var columnNumber = frame.getColumnNumber();
- if (columnNumber) {
- fileLocation += ":" + columnNumber;
+ function FormatSourcePosition(frame) {
+ var fileLocation = "";
+ if (frame.isNative()) {
+ fileLocation = "native";
+ } else if (frame.isEval()) {
+ fileLocation = "eval at " + frame.getEvalOrigin();
+ } else {
+ var fileName = frame.getFileName();
+ if (fileName) {
+ for(var i=0, l=filter.length; i<l; i++) {
+ if (fileName.indexOf(filter[i]) !== -1) return;
+ }
+ fileLocation += fileName;
+ var lineNumber = frame.getLineNumber();
+ if (lineNumber != null) {
+ fileLocation += ":" + lineNumber;
+ var columnNumber = frame.getColumnNumber();
+ if (columnNumber) {
+ fileLocation += ":" + columnNumber;
+ }
}
}
}
- }
- if (!fileLocation) {
- fileLocation = "unknown source";
- }
- var line = "";
- var functionName = frame.getFunction().name;
- var addPrefix = true;
- var isConstructor = frame.isConstructor();
- var isMethodCall = !(frame.isToplevel() || isConstructor);
- if (isMethodCall) {
- var methodName = frame.getMethodName();
- line += frame.getTypeName() + ".";
- if (functionName) {
- line += functionName;
- if (methodName && (methodName != functionName)) {
- line += " [as " + methodName + "]";
+ if (!fileLocation) {
+ fileLocation = "unknown source";
+ }
+ var line = "";
+ var functionName = frame.getFunction().name;
+ var addPrefix = true;
+ var isConstructor = frame.isConstructor();
+ var isMethodCall = !(frame.isToplevel() || isConstructor);
+ if (isMethodCall) {
+ var methodName = frame.getMethodName();
+ line += frame.getTypeName() + ".";
+ if (functionName) {
+ line += functionName;
+ if (methodName && (methodName != functionName)) {
+ line += " [as " + methodName + "]";
+ }
+ } else {
+ line += methodName || "<anonymous>";
}
+ } else if (isConstructor) {
+ line += "new " + (functionName || "<anonymous>");
+ } else if (functionName) {
+ line += functionName;
} else {
- line += methodName || "<anonymous>";
+ line += fileLocation;
+ addPrefix = false;
}
- } else if (isConstructor) {
- line += "new " + (functionName || "<anonymous>");
- } else if (functionName) {
- line += functionName;
- } else {
- line += fileLocation;
- addPrefix = false;
- }
- if (addPrefix) {
- line += " (" + fileLocation + ")";
+ if (addPrefix) {
+ line += " (" + fileLocation + ")";
+ }
+ return line;
}
- return line;
-}
+ return FormatStackTrace
+}
108 lib/trycatch.js
View
@@ -4,8 +4,17 @@ var util = require('util')
, hook = require('./hook')
, hooked = false
, fileNameFilter = [__filename, require.resolve('./hook'), 'domain.js']
+ , d = require('path').join('/')
+ , node_modules = d + 'node_modules' + d
, options = {
'long-stack-traces': null
+ , 'colors': {
+ 'node': 'white',
+ 'node_modules': 'cyan',
+ 'default': 'red'
+ }
+ , 'format': defaultFormat
+ , 'filter': fileNameFilter
}
// use colors module, if available
@@ -26,29 +35,63 @@ trycatch.begin = domainTrycatch
// Won't be used until long-stack-traces turned off=>on=>off
trycatch.guard = nopGuard
trycatch.configure = configure
+trycatch.format = FormatStackTrace(defaultFormat, fileNameFilter)
function configure(opts) {
+ var resetFormat = false
+
if ('undefined' !== typeof opts['long-stack-traces']) {
options['long-stack-traces'] = Boolean(opts['long-stack-traces'])
+
+ if (true === options['long-stack-traces']) {
+ if (!hooked) {
+ hooked = true
+
+ // Replace built-in async functions, shim callbacks with generator
+ hookit()
+ }
+
+ // findToken fails when _TOKEN_ deeper than Error.stackTraceLimit
+ Error.stackTraceLimit = Infinity
+ trycatch.begin = longStackTraceBegin
+ trycatch.guard = longStackTraceGuard
+ } else if (false === options['long-stack-traces'] && hooked) {
+ console.warn('Turning long-stack-traces off can result in indeterminate behavior.')
+ Error.stackTraceLimit = 10
+ trycatch.begin = domainTrycatch
+ trycatch.guard = nopGuard
+ }
+ }
+
+ if (null != opts.colors && 'object' === typeof opts.colors) {
+ if ('undefined' !== typeof opts.colors.node) {
+ options.colors.node = opts.colors.node
+ }
+ if ('undefined' !== typeof opts.colors.node_modules) {
+ options.colors.node_modules = opts.colors.node_modules
+ }
+ if ('undefined' !== typeof opts.colors.default) {
+ options.colors.default = opts.colors.default
+ }
}
- if (true === options['long-stack-traces']) {
- if (!hooked) {
- hooked = true
-
- // Replace built-in async functions, shim callbacks with generator
- hookit()
+ if ('undefined' !== typeof opts.format) {
+ if ('function' === typeof opts.format) {
+ options.format = opts.format
+ resetFormat = true
+ } else if (!Boolean(opts.format)) {
+ options.format = defaultFormat
+ resetFormat = true
}
+ }
+
+ if (Array.isArray(opts.filter)) {
+ options.filter = opts.filter
+ resetFormat = true
+ }
- // findToken fails when _TOKEN_ deeper than Error.stackTraceLimit
- Error.stackTraceLimit = Infinity
- trycatch.begin = longStackTraceBegin
- trycatch.guard = longStackTraceGuard
- } else if (false === options['long-stack-traces'] && hooked) {
- console.warn('Turning long-stack-traces off can result in indeterminate behavior.')
- Error.stackTraceLimit = 10
- trycatch.begin = domainTrycatch
- trycatch.guard = nopGuard
+ if (resetFormat) {
+ trycatch.format = FormatStackTrace(options.format, options.filter)
}
}
@@ -161,12 +204,7 @@ function longStackTraceBegin(tryFn, catchFn) {
function generateStack(err, fn) {
if ('function' !== typeof fn) {
- fn = function(error, structuredStackTrace) {
- return FormatStackTrace(error
- , structuredStackTrace
- , fileNameFilter
- , trycatch.colors)
- }
+ fn = trycatch.format
}
if (!err) err = new Error
var old = Error.prepareStackTrace
@@ -206,7 +244,7 @@ function stackSearch(error, structuredStackTrace) {
if (!structuredStackTrace) return
- stack = FormatStackTrace(error, structuredStackTrace, fileNameFilter, trycatch.colors)
+ stack = trycatch.format(error, structuredStackTrace)
for (i=0, l=structuredStackTrace.length; i<l; i++) {
fn = structuredStackTrace[i].fun
@@ -218,4 +256,28 @@ function stackSearch(error, structuredStackTrace) {
}
}
return {stack: stack}
-}
+}
+
+function defaultFormat(line) {
+ var type, color
+
+ if (trycatch.colors) {
+ if (line.indexOf(node_modules) >= 0) {
+ type = "node_modules";
+ } else if (line.indexOf(d) >= 0) {
+ type = "default";
+ } else {
+ type = "node"
+ }
+
+ color = options.colors[type]
+ if ('none' === color || !Boolean(color)) {
+ return
+ }
+
+ if (trycatch.colors[color]) {
+ return trycatch.colors[color](line);
+ }
+ }
+ return line
+}
Please sign in to comment.
Something went wrong with that request. Please try again.