Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Improve call-stacks in async fs oprations #3816

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,7 @@ function makeCallback(cb) {
return function() {};
}

return function() {
return cb.apply(null, arguments);
};
return util._bindHistory(cb);
}


Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
70 changes: 70 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not going to run new Error() every time anything with makeCallback() is called. Just not going to happen.


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) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not going to override (i.e. "monkey patch") native functionality. It's not Node's place to do such things.

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("<error: " + e + ">");
} catch (ee) {
lines.push("<error>");
}
}
for (var i = 0; i < frames.length; i++) {
var frame = frames[i];
var line;
try {
line = frame.toString();
} catch (e) {
try {
line = "<error: " + e + ">";
} catch (ee) {
// Any code that reaches this point is seriously nasty!
line = "<error>";
}
}
lines.push(" at " + line);
}
return lines.join("\n");
}

/**
* Inherit the prototype methods from one constructor into another.
Expand Down