pax_global_header00006660000000000000000000000064120517647660014530gustar00rootroot0000000000000052 comment=37ee5b13fa2b44296dbb4394f670e23a5717d361 async-stacktrace-0.0.2/000077500000000000000000000000001205176476600147665ustar00rootroot00000000000000async-stacktrace-0.0.2/.gitignore000066400000000000000000000000151205176476600167520ustar00rootroot00000000000000node_modules async-stacktrace-0.0.2/ERR.js000066400000000000000000000031431205176476600157550ustar00rootroot00000000000000/* * 2011 Peter 'Pita' Martischka * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS-IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var header = "Async Stacktrace:"; module.exports = function (err, callback) { //there is a error if(err != null) { //if there is already a stacktrace avaiable if(err.stack != null) { //split stack by line var stackParts = err.stack.split("\n"); //check if there is already a header set, if not add one and a empty line if(stackParts[0] != header) { stackParts.unshift(header,""); } //add a new stacktrace line var asyncStackLine = new Error().stack.split("\n")[2]; stackParts.splice(1,0,asyncStackLine); //join the stacktrace err.stack = stackParts.join("\n"); } //no stacktrace, so lets create an error out of this object else { err = new Error(err); } //there is a callback, lets call it if(callback != null) { callback(err); } //no callback, throw the error else { throw err; } } //return true if an error happend return err != null; } async-stacktrace-0.0.2/README.md000066400000000000000000000070071205176476600162510ustar00rootroot00000000000000## Why classic stacktraces are not very helpful when dealing with async functions Look at this example. `one` calls `two`, `two` calls `three`, and `three` calls `four`. All functions call the given callback asynchronous. `four` calls the callback with an error. `three` and `two` passes the error to their callback function and stop executing with `return`. `one` finally throws it ```js function one() { two(function(err){ if(err){ throw err; } console.log("two finished"); }); } function two(callback) { setTimeout(function () { three(function(err) { if(err) { callback(err); return; } console.log("three finished"); callback(); }); }, 0); } function three(callback) { setTimeout(function () { four(function(err) { if(err) { callback(err); return; } console.log("four finished"); callback(); }); }, 0); } function four(callback) { setTimeout(function(){ callback(new Error()); }, 0); } one(); ``` ### When you execute it, you will get this: ``` $ node example_without.js /home/pita/Code/async-stacktrace/example_without.js:5 throw err; ^ Error at Timer.callback (/home/pita/Code/async-stacktrace/example_without.js:47:14) ``` ### The problems here are: * You can see that the error happend in `four`, but you can't see from where `four` was called. The context gets lost * You write the same 4 lines over and over again, just to handle errors ## The solution ### Lets replace this code in `two` and `three` ```js if(err) { callback(err); return; } ``` ### with ```js if(ERR(err, callback)) return; ``` ### and replace this code in `one` ```js if(err){ throw err; } ``` ### with ```js ERR(err); ``` ### This is how it looks like now: ```js var ERR = require("async-stacktrace"); function one() { two(function(err){ ERR(err); console.log("two finished"); }); } function two(callback) { setTimeout(function () { three(function(err) { if(ERR(err, callback)) return; console.log("three finished"); callback(); }); }, 0); } function three(callback) { setTimeout(function () { four(function(err) { if(ERR(err, callback)) return; console.log("four finished"); callback(); }); }, 0); } function four(callback) { setTimeout(function(){ callback(new Error()); }, 0); } one(); ``` ### When you execute it, you will get this: ``` $ node example.js /home/pita/Code/async-stacktrace/ERR.js:57 throw err; ^ Async Stacktrace: at /home/pita/Code/async-stacktrace/example.js:6:6 at /home/pita/Code/async-stacktrace/example.js:17:10 at /home/pita/Code/async-stacktrace/example.js:30:10 Error at Timer.callback (/home/pita/Code/async-stacktrace/example.js:41:14) ``` ### What is new? The "Async Stacktrace" shows you where this error was caught and passed to the next callback. This allows you to see from where `four` was called. You also have less code to write ## npm ``` npm install async-stacktrace ``` ## Usage This is how you require the ERR function ```js var ERR = require("async-stacktrace"); ``` The parameters of `ERR()` are: 1. `err` The error object (can be a string that describes the error too) 2. `callback` (optional) If the callback is set and an error is passed, it will call the callback with the modified stacktrace. Else it will throw the error The return value is true if there is an error. Else its false async-stacktrace-0.0.2/example.js000066400000000000000000000011701205176476600167560ustar00rootroot00000000000000var ERR = require("./ERR"); function one() { two(function(err){ ERR(err); console.log("two finished"); }); } function two(callback) { setTimeout(function () { three(function(err) { if(ERR(err, callback)) return; console.log("three finished"); callback(); }); }, 0); } function three(callback) { setTimeout(function () { four(function(err) { if(ERR(err, callback)) return; console.log("four finished"); callback(); }); }, 0); } function four(callback) { setTimeout(function(){ callback(new Error()); }, 0); } one(); async-stacktrace-0.0.2/example_without.js000066400000000000000000000012551205176476600205450ustar00rootroot00000000000000function one() { two(function(err){ if(err){ throw err; } console.log("two finished"); }); } function two(callback) { setTimeout(function () { three(function(err) { if(err) { callback(err); return; } console.log("three finished"); callback(); }); }, 0); } function three(callback) { setTimeout(function () { four(function(err) { if(err) { callback(err); return; } console.log("four finished"); callback(); }); }, 0); } function four(callback) { setTimeout(function(){ callback(new Error()); }, 0); } one(); async-stacktrace-0.0.2/package.json000066400000000000000000000007121205176476600172540ustar00rootroot00000000000000{ "name" : "async-stacktrace", "description" : "Improves node.js stacktraces and makes it easier to handle errors", "homepage" : "https://github.com/Pita/async-stacktrace", "author" : "Peter 'Pita' Martischka ", "devDependencies" : { "vows" : "0.6.0" }, "main" : "./ERR", "version" : "0.0.2" } async-stacktrace-0.0.2/tests.js000066400000000000000000000045541205176476600164760ustar00rootroot00000000000000var vows = require('vows'); var assert = require('assert'); var ERR = require("./ERR"); var emptyFunc = function(){}; vows.describe('ERR function').addBatch({ 'when its loaded' : { topic: function() { return require("./ERR"); }, 'it returns the ERR function': function(topic){ assert.equal(typeof topic, "function"); }, 'its not global': function(topic){ assert.isUndefined(global.ERR); } } }).addBatch({ 'when you call it without an error' : { 'it returns false' : function() { assert.isFalse(ERR()); } }, 'when you call it with an error' : { 'it returns true' : function() { assert.isTrue(ERR(new Error(), emptyFunc)); } }, 'when you give it a callback and an error': { 'it calls the callback with the error' : function() { ERR(new Error(), function(err) { assert.isNotNull(err); }); } }, 'when you give it no callback and an error': { 'it throws the error' : function() { var wasThrown = false; try { ERR(new Error()); } catch(e) { wasThrown = true; } assert.isTrue(wasThrown); } }, 'when you call it with a string as an error' : { 'it uses the string as an error message' : function(){ var errStr = "testerror"; var err; ERR(errStr, function(_err){ err = _err; }); assert.equal(err.message, errStr); } }, 'when you give it a non-async stacktrace': { 'it turns it into an async stacktrace' : function(){ var errorBefore = new Error(); var stackLinesBefore = errorBefore.stack.split("\n").length; var errorAfter; ERR(errorBefore, function(err){ errorAfter = err; }); var stackLinesAfter = errorAfter.stack.split("\n").length; assert.equal(stackLinesBefore+3, stackLinesAfter); } }, 'when you give it a async stacktrace': { 'it adds a new stack line' : function(){ var err = new Error(); ERR(err, function(_err){ err = _err; }); var stackLinesBefore = err.stack.split("\n").length; ERR(err, function(_err){ err = _err; }); var stackLinesAfter = err.stack.split("\n").length; assert.equal(stackLinesBefore+1, stackLinesAfter); } } }).run();