fs: fix 'object is not a function' callback errors
Use a default callback if the user omitted one. Avoids errors like the one below: fs.js:777 if (err) return callback(err); ^ TypeError: object is not a function at fs.appendFile (fs.js:777:21) at Object.oncomplete (fs.js:297:15) This commit fixes the behavior of fs.lchmod(), fs.lchown() and fs.readFile() when the callback is omitted. Before, they silently swallowed errors. Fixes #4352.
This commit is contained in:
parent
03b00dcca9
commit
a80434736b
@ -59,8 +59,31 @@ In busy processes, the programmer is _strongly encouraged_ to use the
|
|||||||
asynchronous versions of these calls. The synchronous versions will block
|
asynchronous versions of these calls. The synchronous versions will block
|
||||||
the entire process until they complete--halting all connections.
|
the entire process until they complete--halting all connections.
|
||||||
|
|
||||||
Relative path to filename can be used, remember however that this path will be relative
|
Relative path to filename can be used, remember however that this path will be
|
||||||
to `process.cwd()`.
|
relative to `process.cwd()`.
|
||||||
|
|
||||||
|
Most fs functions let you omit the callback argument. If you do, a default
|
||||||
|
callback is used that rethrows errors. To get a trace to the original call
|
||||||
|
site, set the NODE_DEBUG environment variable:
|
||||||
|
|
||||||
|
$ cat script.js
|
||||||
|
function bad() {
|
||||||
|
require('fs').readFile('/');
|
||||||
|
}
|
||||||
|
bad();
|
||||||
|
|
||||||
|
$ env NODE_DEBUG=fs node script.js
|
||||||
|
fs.js:66
|
||||||
|
throw err;
|
||||||
|
^
|
||||||
|
Error: EISDIR, read
|
||||||
|
at rethrow (fs.js:61:21)
|
||||||
|
at maybeCallback (fs.js:79:42)
|
||||||
|
at Object.fs.readFile (fs.js:153:18)
|
||||||
|
at bad (/path/to/script.js:2:17)
|
||||||
|
at Object.<anonymous> (/path/to/script.js:5:1)
|
||||||
|
<etc.>
|
||||||
|
|
||||||
|
|
||||||
## fs.rename(oldPath, newPath, [callback])
|
## fs.rename(oldPath, newPath, [callback])
|
||||||
|
|
||||||
|
59
lib/fs.js
59
lib/fs.js
@ -52,6 +52,27 @@ var O_WRONLY = constants.O_WRONLY || 0;
|
|||||||
|
|
||||||
var isWindows = process.platform === 'win32';
|
var isWindows = process.platform === 'win32';
|
||||||
|
|
||||||
|
function rethrow(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybeCallback(cb) {
|
||||||
|
return typeof cb === 'function' ? cb : rethrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that callbacks run in the global context. Only use this function
|
||||||
|
// for callbacks that are passed to the binding layer, callbacks that are
|
||||||
|
// invoked from JS already run in the proper scope.
|
||||||
|
function makeCallback(cb) {
|
||||||
|
if (typeof cb !== 'function') {
|
||||||
|
return rethrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
return cb.apply(null, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function assertEncoding(encoding) {
|
function assertEncoding(encoding) {
|
||||||
if (encoding && !Buffer.isEncoding(encoding)) {
|
if (encoding && !Buffer.isEncoding(encoding)) {
|
||||||
throw new Error('Unknown encoding: ' + encoding);
|
throw new Error('Unknown encoding: ' + encoding);
|
||||||
@ -110,8 +131,7 @@ fs.existsSync = function(path) {
|
|||||||
|
|
||||||
fs.readFile = function(path, encoding_) {
|
fs.readFile = function(path, encoding_) {
|
||||||
var encoding = typeof(encoding_) === 'string' ? encoding_ : null;
|
var encoding = typeof(encoding_) === 'string' ? encoding_ : null;
|
||||||
var callback = arguments[arguments.length - 1];
|
var callback = maybeCallback(arguments[arguments.length - 1]);
|
||||||
if (typeof(callback) !== 'function') callback = function() {};
|
|
||||||
|
|
||||||
assertEncoding(encoding);
|
assertEncoding(encoding);
|
||||||
|
|
||||||
@ -295,21 +315,6 @@ Object.defineProperty(exports, '_stringToFlags', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Ensure that callbacks run in the global context. Only use this function
|
|
||||||
// for callbacks that are passed to the binding layer, callbacks that are
|
|
||||||
// invoked from JS already run in the proper scope.
|
|
||||||
function makeCallback(cb) {
|
|
||||||
if (typeof cb !== 'function') {
|
|
||||||
// faster than returning a ref to a global no-op function
|
|
||||||
return function() {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return function() {
|
|
||||||
return cb.apply(null, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Yes, the follow could be easily DRYed up but I provide the explicit
|
// Yes, the follow could be easily DRYed up but I provide the explicit
|
||||||
// list to make the arguments clear.
|
// list to make the arguments clear.
|
||||||
|
|
||||||
@ -425,9 +430,11 @@ fs.write = function(fd, buffer, offset, length, position, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callback = maybeCallback(callback);
|
||||||
|
|
||||||
function wrapper(err, written) {
|
function wrapper(err, written) {
|
||||||
// Retain a reference to buffer so that it can't be GC'ed too soon.
|
// Retain a reference to buffer so that it can't be GC'ed too soon.
|
||||||
callback && callback(err, written || 0, buffer);
|
callback(err, written || 0, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.write(fd, buffer, offset, length, position, wrapper);
|
binding.write(fd, buffer, offset, length, position, wrapper);
|
||||||
@ -470,6 +477,7 @@ fs.truncate = function(path, len, callback) {
|
|||||||
} else if (typeof len === 'undefined') {
|
} else if (typeof len === 'undefined') {
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
|
callback = maybeCallback(callback);
|
||||||
fs.open(path, 'w', function(er, fd) {
|
fs.open(path, 'w', function(er, fd) {
|
||||||
if (er) return callback(er);
|
if (er) return callback(er);
|
||||||
binding.ftruncate(fd, len, function(er) {
|
binding.ftruncate(fd, len, function(er) {
|
||||||
@ -659,7 +667,7 @@ fs.fchmodSync = function(fd, mode) {
|
|||||||
|
|
||||||
if (constants.hasOwnProperty('O_SYMLINK')) {
|
if (constants.hasOwnProperty('O_SYMLINK')) {
|
||||||
fs.lchmod = function(path, mode, callback) {
|
fs.lchmod = function(path, mode, callback) {
|
||||||
callback = callback || (function() {});
|
callback = maybeCallback(callback);
|
||||||
fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
|
fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
@ -709,7 +717,7 @@ fs.chmodSync = function(path, mode) {
|
|||||||
|
|
||||||
if (constants.hasOwnProperty('O_SYMLINK')) {
|
if (constants.hasOwnProperty('O_SYMLINK')) {
|
||||||
fs.lchown = function(path, uid, gid, callback) {
|
fs.lchown = function(path, uid, gid, callback) {
|
||||||
callback = callback || (function() {});
|
callback = maybeCallback(callback);
|
||||||
fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
|
fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
@ -782,8 +790,7 @@ fs.futimesSync = function(fd, atime, mtime) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function writeAll(fd, buffer, offset, length, position, callback) {
|
function writeAll(fd, buffer, offset, length, position, callback) {
|
||||||
var callback_ = arguments[arguments.length - 1];
|
callback = maybeCallback(arguments[arguments.length - 1]);
|
||||||
callback = (typeof(callback_) == 'function' ? callback_ : null);
|
|
||||||
|
|
||||||
// write(fd, buffer, offset, length, position, callback)
|
// write(fd, buffer, offset, length, position, callback)
|
||||||
fs.write(fd, buffer, offset, length, position, function(writeErr, written) {
|
fs.write(fd, buffer, offset, length, position, function(writeErr, written) {
|
||||||
@ -808,8 +815,7 @@ fs.writeFile = function(path, data, encoding_, callback) {
|
|||||||
var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
|
var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
|
||||||
assertEncoding(encoding);
|
assertEncoding(encoding);
|
||||||
|
|
||||||
var callback_ = arguments[arguments.length - 1];
|
callback = maybeCallback(arguments[arguments.length - 1]);
|
||||||
callback = (typeof(callback_) == 'function' ? callback_ : null);
|
|
||||||
fs.open(path, 'w', 438 /*=0666*/, function(openErr, fd) {
|
fs.open(path, 'w', 438 /*=0666*/, function(openErr, fd) {
|
||||||
if (openErr) {
|
if (openErr) {
|
||||||
if (callback) callback(openErr);
|
if (callback) callback(openErr);
|
||||||
@ -843,8 +849,7 @@ fs.appendFile = function(path, data, encoding_, callback) {
|
|||||||
var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
|
var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8');
|
||||||
assertEncoding(encoding);
|
assertEncoding(encoding);
|
||||||
|
|
||||||
var callback_ = arguments[arguments.length - 1];
|
callback = maybeCallback(arguments[arguments.length - 1]);
|
||||||
callback = (typeof(callback_) == 'function' ? callback_ : null);
|
|
||||||
|
|
||||||
fs.open(path, 'a', 438 /*=0666*/, function(err, fd) {
|
fs.open(path, 'a', 438 /*=0666*/, function(err, fd) {
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
@ -1158,7 +1163,7 @@ fs.realpathSync = function realpathSync(p, cache) {
|
|||||||
|
|
||||||
fs.realpath = function realpath(p, cache, cb) {
|
fs.realpath = function realpath(p, cache, cb) {
|
||||||
if (typeof cb !== 'function') {
|
if (typeof cb !== 'function') {
|
||||||
cb = cache;
|
cb = maybeCallback(cache);
|
||||||
cache = null;
|
cache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user