diff --git a/lib/binding.js b/lib/binding.js index baa885d2..101af11a 100644 --- a/lib/binding.js +++ b/lib/binding.js @@ -20,7 +20,7 @@ var getPathParts = require('./filesystem').getPathParts; * @return {*} Return (if callback is not provided). */ function maybeCallback(callback, thisArg, func) { - if (callback) { + if (callback && (typeof callback === 'function' || typeof callback.oncomplete === 'function')) { var err = null; var val; try { @@ -266,11 +266,36 @@ Binding.prototype.realpath = function(filepath, encoding, callback) { }); }; +/** + * Fill a Float64Array with stat information + * This is based on the internal FillStatsArray function in Node. + * https://github.com/nodejs/node/blob/4e05952a8a75af6df625415db612d3a9a1322682/src/node_file.cc#L533 + * @param {object} stats An object with file stats + * @param {Float64Array} statValues A Float64Array where stat values should be inserted + * @returns {void} + */ +function fillStatsArray(stats, statValues) { + statValues[0] = stats.dev; + statValues[1] = stats.mode; + statValues[2] = stats.nlink; + statValues[3] = stats.uid; + statValues[4] = stats.gid; + statValues[5] = stats.rdev; + statValues[6] = stats.blksize; + statValues[7] = stats.ino; + statValues[8] = stats.size; + statValues[9] = stats.blocks; + statValues[10] = +stats.atime; + statValues[11] = +stats.mtime; + statValues[12] = +stats.ctime; + statValues[13] = +stats.birthtime; +} /** * Stat an item. * @param {string} filepath Path. - * @param {function(Error, Stats)} callback Callback (optional). + * @param {function(Error, Stats)|Float64Array} callback Callback (optional). In Node 7.7.0+ this will be a Float64Array + * that should be filled with stat values. * @return {Stats|undefined} Stats or undefined (if sync). */ Binding.prototype.stat = function(filepath, callback) { @@ -283,7 +308,16 @@ Binding.prototype.stat = function(filepath, callback) { if (!item) { throw new FSError('ENOENT', filepath); } - return new Stats(item.getStats()); + var stats = item.getStats(); + + // In Node 7.7.0+, binding.stat accepts a Float64Array as the second argument, + // which should be filled with stat values. + // In prior versions of Node, binding.stat simply returns a Stats instance. + if (callback instanceof Float64Array) { + fillStatsArray(stats, callback); + } else { + return new Stats(stats); + } }); }; @@ -291,14 +325,24 @@ Binding.prototype.stat = function(filepath, callback) { /** * Stat an item. * @param {number} fd File descriptor. - * @param {function(Error, Stats)} callback Callback (optional). + * @param {function(Error, Stats)|Float64Array} callback Callback (optional). In Node 7.7.0+ this will be a Float64Array + * that should be filled with stat values. * @return {Stats|undefined} Stats or undefined (if sync). */ Binding.prototype.fstat = function(fd, callback) { return maybeCallback(callback, this, function() { var descriptor = this._getDescriptorById(fd); var item = descriptor.getItem(); - return new Stats(item.getStats()); + var stats = item.getStats(); + + // In Node 7.7.0+, binding.stat accepts a Float64Array as the second argument, + // which should be filled with stat values. + // In prior versions of Node, binding.stat simply returns a Stats instance. + if (callback instanceof Float64Array) { + fillStatsArray(stats, callback); + } else { + return new Stats(stats); + } }); }; @@ -933,7 +977,8 @@ Binding.prototype.readlink = function(pathname, encoding, callback) { /** * Stat an item. * @param {string} filepath Path. - * @param {function(Error, Stats)} callback Callback (optional). + * @param {function(Error, Stats)|Float64Array} callback Callback (optional). In Node 7.7.0+ this will be a Float64Array + * that should be filled with stat values. * @return {Stats|undefined} Stats or undefined (if sync). */ Binding.prototype.lstat = function(filepath, callback) { @@ -942,7 +987,16 @@ Binding.prototype.lstat = function(filepath, callback) { if (!item) { throw new FSError('ENOENT', filepath); } - return new Stats(item.getStats()); + var stats = item.getStats(); + + // In Node 7.7.0+, binding.stat accepts a Float64Array as the second argument, + // which should be filled with stat values. + // In prior versions of Node, binding.stat simply returns a Stats instance. + if (callback instanceof Float64Array) { + fillStatsArray(stats, callback); + } else { + return new Stats(item.getStats()); + } }); };