From d3a7750d75b48b20f8f5a088be489e610b336292 Mon Sep 17 00:00:00 2001 From: "David Humphrey (:humph) david.humphrey@senecacollege.ca" Date: Wed, 27 Nov 2013 10:34:19 -0500 Subject: [PATCH] Switch to node.js' callback pattrn, update public API to match node.js --- dist/idbfs.js | 51 +++++++++++++++++++++++++++++++++------- src/fs.js | 52 ++++++++++++++++++++++++++++++++++------- tests/spec/node.spec.js | 4 +--- 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/dist/idbfs.js b/dist/idbfs.js index c7701c1..989c944 100644 --- a/dist/idbfs.js +++ b/dist/idbfs.js @@ -8509,6 +8509,19 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr return true; } + // node.js supports a calling pattern that leaves off a callback. + function maybeCallback(callback) { + if(typeof callback === "function") { + return callback; + } + return function(err) { + if(err) { + throw err; + } + }; + } + + /* * FileSystem * @@ -8776,7 +8789,6 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(!options) { options = { encoding: null, flag: 'r' }; } else if(typeof options === "function") { - callback = options; options = { encoding: null, flag: 'r' }; } else if(typeof options === "string") { options = { encoding: options, flag: 'r' }; @@ -8853,7 +8865,6 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(!options) { options = { encoding: 'utf8', flag: 'w' }; } else if(typeof options === "function") { - callback = options; options = { encoding: 'utf8', flag: 'w' }; } else if(typeof options === "string") { options = { encoding: options, flag: 'w' }; @@ -9055,7 +9066,10 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr * Public API for FileSystem */ - FileSystem.prototype.open = function(path, flags, callback) { + FileSystem.prototype.open = function(path, flags, mode, callback) { + // We support the same signature as node with a `mode` arg, but + // ignore it. Find the callback. + callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -9066,13 +9080,14 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.close = function(fd, callback) { - _close(this, fd, callback); + _close(this, fd, maybeCallback(callback)); }; FileSystem.prototype.mkdir = function(path, mode, callback) { // Support passing a mode arg, but we ignore it internally for now. if(typeof mode === 'function') { callback = mode; } + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9083,6 +9098,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.rmdir = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9093,6 +9109,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.stat = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9103,6 +9120,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.fstat = function(fd, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9113,6 +9131,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.link = function(oldpath, newpath, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9123,6 +9142,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.unlink = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9133,16 +9153,22 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.read = function(fd, buffer, offset, length, position, callback) { + // Follow how node.js does this + function wrapper(err, bytesRead) { + // Retain a reference to buffer so that it can't be GC'ed too soon. + callback && callback(err, bytesRead || 0, buffer); + } var fs = this; var error = fs.queueOrRun( function() { var context = fs.provider.getReadWriteContext(); - _read(fs, context, fd, buffer, offset, length, position, callback); + _read(fs, context, fd, buffer, offset, length, position, wrapper); } ); if(error) callback(error); }; - FileSystem.prototype.readFile = function(path, options, callback) { + FileSystem.prototype.readFile = function(path, options, callback_) { + var callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -9153,6 +9179,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.write = function(fd, buffer, offset, length, position, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9163,7 +9190,8 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; - FileSystem.prototype.writeFile = function(path, data, options, callback) { + FileSystem.prototype.writeFile = function(path, data, options, callback_) { + var callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -9174,6 +9202,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.lseek = function(fd, offset, whence, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9184,6 +9213,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.readdir = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9194,6 +9224,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.rename = function(oldpath, newpath, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9204,6 +9235,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.readlink = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -9213,7 +9245,9 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr ); if(error) callback(error); }; - FileSystem.prototype.symlink = function(srcpath, dstpath, callback) { + FileSystem.prototype.symlink = function(srcpath, dstpath, type, callback_) { + // Follow node.js in allowing the `type` arg to be passed, but we ignore it. + var callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -9224,6 +9258,7 @@ define('src/fs',['require','lodash','encoding-indexes','encoding','src/path','sr if(error) callback(error); }; FileSystem.prototype.lstat = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { diff --git a/src/fs.js b/src/fs.js index 76ad549..03259b3 100644 --- a/src/fs.js +++ b/src/fs.js @@ -960,6 +960,19 @@ define(function(require) { return true; } + // node.js supports a calling pattern that leaves off a callback. + function maybeCallback(callback) { + if(typeof callback === "function") { + return callback; + } + return function(err) { + if(err) { + throw err; + } + }; + } + + /* * FileSystem * @@ -1227,7 +1240,6 @@ define(function(require) { if(!options) { options = { encoding: null, flag: 'r' }; } else if(typeof options === "function") { - callback = options; options = { encoding: null, flag: 'r' }; } else if(typeof options === "string") { options = { encoding: options, flag: 'r' }; @@ -1304,7 +1316,6 @@ define(function(require) { if(!options) { options = { encoding: 'utf8', flag: 'w' }; } else if(typeof options === "function") { - callback = options; options = { encoding: 'utf8', flag: 'w' }; } else if(typeof options === "string") { options = { encoding: options, flag: 'w' }; @@ -1506,7 +1517,10 @@ define(function(require) { * Public API for FileSystem */ - FileSystem.prototype.open = function(path, flags, callback) { + FileSystem.prototype.open = function(path, flags, mode, callback) { + // We support the same signature as node with a `mode` arg, but + // ignore it. Find the callback. + callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -1517,13 +1531,14 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.close = function(fd, callback) { - _close(this, fd, callback); + _close(this, fd, maybeCallback(callback)); }; FileSystem.prototype.mkdir = function(path, mode, callback) { // Support passing a mode arg, but we ignore it internally for now. if(typeof mode === 'function') { callback = mode; } + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1534,6 +1549,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.rmdir = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1544,6 +1560,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.stat = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1554,6 +1571,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.fstat = function(fd, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1564,6 +1582,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.link = function(oldpath, newpath, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1574,6 +1593,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.unlink = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1584,16 +1604,23 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.read = function(fd, buffer, offset, length, position, callback) { + // Follow how node.js does this + callback = maybeCallback(callback); + function wrapper(err, bytesRead) { + // Retain a reference to buffer so that it can't be GC'ed too soon. + callback(err, bytesRead || 0, buffer); + } var fs = this; var error = fs.queueOrRun( function() { var context = fs.provider.getReadWriteContext(); - _read(fs, context, fd, buffer, offset, length, position, callback); + _read(fs, context, fd, buffer, offset, length, position, wrapper); } ); if(error) callback(error); }; - FileSystem.prototype.readFile = function(path, options, callback) { + FileSystem.prototype.readFile = function(path, options, callback_) { + var callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -1604,6 +1631,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.write = function(fd, buffer, offset, length, position, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1614,7 +1642,8 @@ define(function(require) { if(error) callback(error); }; - FileSystem.prototype.writeFile = function(path, data, options, callback) { + FileSystem.prototype.writeFile = function(path, data, options, callback_) { + var callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -1625,6 +1654,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.lseek = function(fd, offset, whence, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1635,6 +1665,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.readdir = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1645,6 +1676,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.rename = function(oldpath, newpath, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1655,6 +1687,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.readlink = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { @@ -1664,7 +1697,9 @@ define(function(require) { ); if(error) callback(error); }; - FileSystem.prototype.symlink = function(srcpath, dstpath, callback) { + FileSystem.prototype.symlink = function(srcpath, dstpath, type, callback_) { + // Follow node.js in allowing the `type` arg to be passed, but we ignore it. + var callback = maybeCallback(arguments[arguments.length - 1]); var fs = this; var error = fs.queueOrRun( function() { @@ -1675,6 +1710,7 @@ define(function(require) { if(error) callback(error); }; FileSystem.prototype.lstat = function(path, callback) { + callback = maybeCallback(callback); var fs = this; var error = fs.queueOrRun( function() { diff --git a/tests/spec/node.spec.js b/tests/spec/node.spec.js index fe21914..c370a0f 100644 --- a/tests/spec/node.spec.js +++ b/tests/spec/node.spec.js @@ -108,9 +108,7 @@ describe("node.js tests from https://github.com/joyent/node/blob/master/test", f check(fs.symlink, 'foo\u0000bar', 'foobar'); check(fs.symlink, 'foobar', 'foo\u0000bar'); check(fs.unlink, 'foo\u0000bar'); - // NOTE: the node.js test doesn't pass anything for the data arg - // but this just seems wrong based on their docs. Here I use one. - check(fs.writeFile, 'foo\u0000bar', 'foobar'); + check(fs.writeFile, 'foo\u0000bar'); // TODO - need to be implemented still... // check(fs.appendFile, 'foo\u0000bar'); // check(fs.realpath, 'foo\u0000bar');