From 62ea244b669677e9122b1cb2a1827627ec918e5d Mon Sep 17 00:00:00 2001 From: Andreas Madsen Date: Fri, 3 Aug 2012 16:37:23 +0200 Subject: [PATCH 1/2] util: export a new bindHistory function In async operations the history from the tick there called the async function is lost. This method binds the call-tick call-stack to the error object there was returned in the callback function as first argument --- lib/util.js | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/lib/util.js b/lib/util.js index 65888920c8d5..50342b049ba5 100644 --- a/lib/util.js +++ b/lib/util.js @@ -519,6 +519,76 @@ exports.pump = function(readStream, writeStream, callback) { }); }; +// This will bind the current history stack, to the async +// callback error object +exports._bindHistory = function (callback) { + var history = new Error(); + + return function (error) { + // merge history intro error + if (isError(error)) appendHistory(error, history); + + callback.apply(null, arguments); + }; +}; + +function appendHistory(error, history) { + // get the current error.stack handler + var orig = Error.prepareStackTrace; + + // get the history stack list + Error.prepareStackTrace = function (errorObject, stackObject) { + return stackObject; + }; + var historyStack = history.stack; + + // Include the history stack list in the error + Error.prepareStackTrace = function (errorObject, stackObject) { + var modifiedStack = historyStack.slice(1).concat(stackObject); + + if (typeof orig === 'function') { + return orig(errorObject, modifiedStack); + } else { + return FormatStackTrace(errorObject, modifiedStack); + } + }; + // This will need to be performed, so Error.prepareStackTrace is executed + var errorStack = error.stack; + + // the returned error.stack value is cached, so it is safe to restore + // the error.stack handler + Error.prepareStackTrace = orig; +} + +// copyed from deps/v8/src/messages.js +function FormatStackTrace(error, frames) { + var lines = []; + try { + lines.push(error.toString()); + } catch (e) { + try { + lines.push(""); + } catch (ee) { + lines.push(""); + } + } + for (var i = 0; i < frames.length; i++) { + var frame = frames[i]; + var line; + try { + line = frame.toString(); + } catch (e) { + try { + line = ""; + } catch (ee) { + // Any code that reaches this point is seriously nasty! + line = ""; + } + } + lines.push(" at " + line); + } + return lines.join("\n"); +} /** * Inherit the prototype methods from one constructor into another. From 6ebdae13d8c6acbef6b01e9ed44e9acbbb498146 Mon Sep 17 00:00:00 2001 From: Andreas Madsen Date: Fri, 3 Aug 2012 16:55:15 +0200 Subject: [PATCH 2/2] fs: improve error call stack --- lib/fs.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 7c622375e3ab..d339be9d0bff 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -293,9 +293,7 @@ function makeCallback(cb) { return function() {}; } - return function() { - return cb.apply(null, arguments); - }; + return util._bindHistory(cb); } @@ -362,7 +360,7 @@ fs.read = function(fd, buffer, offset, length, position, callback) { callback && callback(err, bytesRead || 0, buffer); } - binding.read(fd, buffer, offset, length, position, wrapper); + binding.read(fd, buffer, offset, length, position, makeCallback(wrapper)); }; fs.readSync = function(fd, buffer, offset, length, position) { @@ -412,7 +410,7 @@ fs.write = function(fd, buffer, offset, length, position, callback) { callback && callback(err, written || 0, buffer); } - binding.write(fd, buffer, offset, length, position, wrapper); + binding.write(fd, buffer, offset, length, position, makeCallback(wrapper)); }; fs.writeSync = function(fd, buffer, offset, length, position) {