Do not use Promise in 'fs' module
authorRyan Dahl <ry@tinyclouds.org>
Sat, 20 Feb 2010 00:02:30 +0000 (16:02 -0800)
committerRyan Dahl <ry@tinyclouds.org>
Sat, 20 Feb 2010 00:02:30 +0000 (16:02 -0800)
12 files changed:
doc/api.txt
src/node.js
test/mjsunit/test-eio-race.js
test/mjsunit/test-eio-race2.js
test/mjsunit/test-eio-race4.js
test/mjsunit/test-file-read-noexist.js
test/mjsunit/test-fs-chmod.js
test/mjsunit/test-fs-stat.js
test/mjsunit/test-fs-write.js
test/mjsunit/test-mkdir-rmdir.js
test/mjsunit/test-module-loading.js
test/mjsunit/test-readdir.js

index a3e5082..e3a408a 100644 (file)
@@ -236,9 +236,6 @@ Events are represented by a camel-cased string. Here are some examples:
 Functions can be then be attached to objects, to be executed when an event
 is emitted. These functions are called _listeners_.
 
-Some asynchronous file operations return an +EventEmitter+ called a
-_promise_.  A promise emits just a single event when the operation is
-complete.
 
 === +events.EventEmitter+
 
@@ -586,60 +583,96 @@ will be sent +"SIGTERM"+. See signal(7) for a list of available signals.
 == File System
 
 File I/O is provided by simple wrappers around standard POSIX functions.  To
-use this module do +require("fs")+. All the methods have a similar form.
-They return a promise (+events.Promise+). Example of deleting a file:
+use this module do +require("fs")+. All the methods have asynchornous and
+synchronous forms. 
 
-------------------------------------------------------------------------------
+The asynchronous form always take a completion callback as its last
+argument. The arguments passed to the completion callback depend on the
+method, but the first argument is always reserved for an exception. If the
+operation was completed successfully, then the first argument will be +null+
+or +undefined+.
+
+Here is an example of the asynchornous version:
+
+-------------------------------------------------------
 var fs = require("fs"),
     sys = require("sys");
 
-var promise = fs.unlink("/tmp/hello");
-
-promise.addCallback(function () {
+fs.unlink("/tmp/hello", function (err) {
+  if (err) throw err;
   sys.puts("successfully deleted /tmp/hello");
 });
-------------------------------------------------------------------------------
+-------------------------------------------------------
+
+Here is the synchronous version:
+
+-------------------------------------------------------
+var fs = require("fs"),
+    sys = require("sys");
+
+fs.unlinkSync("/tmp/hello")
+sys.puts("successfully deleted /tmp/hello");
+-------------------------------------------------------
 
-This is asynchornous, there is no guaranteed ordering. The following is
-prone to error
+With the asynchronous methods there is no guaranteed ordering. So the
+following is prone to error:
 
-------------------------------------------------------------------------------
-fs.rename("/tmp/hello", "/tmp/world");
-fs.stat("/tmp/world").addCallback(function (stats) {
+------------------------------------------------------
+fs.rename("/tmp/hello", "/tmp/world", function (err) {
+  if (err) throw err;
+  sys.puts("renamed complete");
+});
+fs.stat("/tmp/world", function (err, stats) {
+  if (err) throw err;
   sys.puts("stats: " + JSON.stringify(stats));
 });
-------------------------------------------------------------------------------
+------------------------------------------------------
 
 It could be that +fs.stat+ is executed before +fs.rename+.
-The correct way to do this is to chain the promises.
+The correct way to do this is to chain the callbacks.
 
-------------------------------------------------------------------------------
-fs.rename("/tmp/hello", "/tmp/world").addCallback(function () {
-  fs.stat("/tmp/world").addCallback(function (stats) {
+------------------------------------------------------
+fs.rename("/tmp/hello", "/tmp/world", function (err) {
+  if (err) throw err;
+  fs.stat("/tmp/world", function (err, stats) {
+    if (err) throw err;
     sys.puts("stats: " + JSON.stringify(stats));
   });
 });
-------------------------------------------------------------------------------
+------------------------------------------------------
+
+In busy processes, the programmer is _strongly encouraged_ to use the
+asynchronous versions of these calls. The synchronous versions will block
+the entire process until they complete--halting all connections.
 
 
-+fs.rename(path1, path2)+ ::
-  See rename(2).
-  - on success: no parameters.
-  - on error: no parameters.
++fs.rename(path1, path2, callback)+ ::
+Asynchronous rename(2). 
+No arguments other than a possible exception are given to the completion callback.
 
-+fs.truncate(fd, len)+ ::
-  See ftruncate(2).
-  - on success: no parameters.
-  - on error: no parameters.
++fs.renameSync(path1, path2)+ ::
+Synchronous rename(2).
+
+
++fs.truncate(fd, len, callback)+ ::
+  Asynchronous ftruncate(2).
+  No arguments other than a possible exception are given to the completion callback.
+
++fs.truncateSync(fd, len)+ ::
+  Synchronous ftruncate(2).
+
+
++fs.chmod(path, mode, callback)+ ::
+  Asynchronous chmod(2).
+  No arguments other than a possible exception are given to the completion callback.
+
++fs.chmodSync(path, mode)+ ::
+  Synchronous chmod(2).
 
-+fs.chmod(path, mode)+ ::
-  See chmod(1)
-  - on success: no parameters.
-  - on error: no parameters.
   
-+fs.stat(path)+ ::
-See stat(2).
-- on success: Returns +fs.Stats+ object. It looks like this:
++fs.stat(path, callback)+ ::
+Asynchronous stat(2). The callback gets two arguments +(err, stats)+ where
++stats+ is a +fs.Stats+ object. It looks like this:
 +
 ---------------------------------
 { dev: 2049
@@ -660,91 +693,116 @@ See stat(2).
 +
 See the +fs.Stats+ section below for more information.
 
-- on error: no parameters.
++fs.statSync(path)+ ::
+Synchronous stat(2). Returns an instance of +fs.Stats+.
 
 
-+fs.unlink(path)+ ::
-  See unlink(2)
-  - on success: no parameters.
-  - on error: no parameters.
++fs.unlink(path, callback)+ ::
+Asynchronous unlink(2).
+No arguments other than a possible exception are given to the completion callback.
 
++fs.unlinkSync(path)+ ::
+Synchronous unlink(2).
 
-+fs.rmdir(path)+ ::
-  See rmdir(2)
-  - on success: no parameters.
-  - on error: no parameters.
 
++fs.rmdir(path, callback)+ ::
+Asynchronous rmdir(2).
+No arguments other than a possible exception are given to the completion callback.
 
-+fs.mkdir(path, mode)+ ::
-  See mkdir(2)
-  - on success: no parameters.
-  - on error: no parameters.
++fs.rmdirSync(path)+ ::
+Synchronous rmdir(2).
 
 
-+fs.readdir(path)+ ::
-  Reads the contents of a directory.
-  - on success: One argument, an array containing the names (strings) of the
-    files in the directory (excluding "." and "..").
-  - on error: no parameters.
++fs.mkdir(path, mode, callback)+ ::
+Asynchronous mkdir(2).
+No arguments other than a possible exception are given to the completion callback.
 
++fs.mkdirSync(path, mode)+ ::
+Synchronous mkdir(2).
 
-+fs.close(fd)+ ::
-  See close(2)
-  - on success: no parameters.
-  - on error: no parameters.
 
++fs.readdir(path, callback)+ ::
+Asynchronous readdir(3).  Reads the contents of a directory.
+The callback gets two arguments +(err, files)+ where +files+ is an array of
+the names of the files in the directory excluding +"."+ and +".."+.
 
-+fs.open(path, flags, mode=0666)+::
-  See open(2). The constants like +O_CREAT+ are defined at +process.O_CREAT+.
-  Also you can use the strings "r", "r+", "w", "w+", "a", or "a+" as aliases
-  to the common flag combinations.
-  - on success: +fd+ is given as the parameter.
-  - on error: no parameters.
 
++fs.close(fd, callback)+ ::
+Asynchronous close(2).
+No arguments other than a possible exception are given to the completion callback.
 
-+fs.write(fd, data, position, encoding)+::
-  Write data to the file specified by +fd+.  +position+ refers to the offset
-  from the beginning of the file where this data should be written. If
-  +position+ is +null+, the data will be written at the current position.
-  See pwrite(2).
-  - on success: returns an integer +written+ which specifies how many _bytes_ were written.
-  - on error: no parameters.
++fs.closeSync(fd)+ ::
+Synchronous close(2).
 
-+fs.read(fd, length, position, encoding)+::
-  Read data from the file specified by +fd+.
-  +
-  +length+ is an integer specifying the number of
-  bytes to read.
-  +
-  +position+ is an integer specifying where to begin
-  reading from in the file.
-  +
-  - on success: returns +data, bytes_read+, what was read from the file.
-  - on error: no parameters.
 
-+fs.readFile(filename, encoding="utf8")+::
-Outputs the entire contents of a file. Example:
++fs.open(path, flags, mode, callback)+::
+Asynchronous file open. See open(2). Flags can be "r", "r+", "w", "w+", "a",
+or "a+". The callback gets two arguments +(err, fd)+. 
+
++fs.openSync(path, flags, mode)+::
+Synchronous open(2). 
+
+
++fs.write(fd, data, position, encoding, callback)+::
+Write data to the file specified by +fd+.  +position+ refers to the offset
+from the beginning of the file where this data should be written. If
++position+ is +null+, the data will be written at the current position.
+See pwrite(2).
++
+The callback will be given two arguments +(err, written)+ where +written+
+specifies how many _bytes_ were written.
+
++fs.writeSync(fd, data, position, encoding)+::
+Synchronous version of +fs.write()+. Returns the number of bytes written.
+
+
++fs.read(fd, length, position, encoding, callback)+::
+Read data from the file specified by +fd+.
++
++length+ is an integer specifying the number of
+bytes to read.
++
++position+ is an integer specifying where to begin
+reading from in the file.
++
+The callback is given three arguments, +(err, data, bytesRead)+ where +data+
+is a string--what was read--and +bytesRead+ is the number of bytes read.
+
++fs.readSync(fd, length, position, encoding)+::
+Synchronous version of +fs.read+. Returns an array +[data, bytesRead]+.
+
++fs.readFile(filename, encoding="utf8", callback)+::
+Asynchronously reads the entire contents of a file. Example:
 +
 --------------------------------
-fs.readFile("/etc/passwd").addCallback(function (content) {
+fs.readFile("/etc/passwd", function (err, data) {
+  if (err) throw err;
   sys.puts(content);
 });
 --------------------------------
 +
-- on success: returns +data+, what was read from the file.
-- on error: no parameters.
+The callback is passed two arguments +(err, data)+, where +data+ is the
+contents of the file.
+
++fs.readFileSync(filename, encoding="utf8")+::
+Synchronous version of +fs.readFile+. Returns the contents of the
++filename+.
+
 
-+fs.writeFile(filename, data, encoding="utf8")+::
-Writes data to a file. Example:
++fs.writeFile(filename, data, encoding="utf8", callback)+::
+Asynchronously writes data to a file. Example:
 +
 --------------------------------
-fs.writeFile("message.txt", "Hello Node").addCallback(function () {
+fs.writeFile("message.txt", "Hello Node", function (err) {
+  if (err) throw err;
   sys.puts("It's saved!");
 });
 --------------------------------
-+
-- on success: no parameters.
-- on error: no parameters.
+
++fs.writeFileSync(filename, data, encoding="utf8")+::
+The synchronous version of +fs.writeFile+.
+
+
 
 === +fs.Stats+
 
index 01686b0..4f07c7d 100644 (file)
@@ -453,17 +453,6 @@ function debug (x) {
 
 var fsModule = createInternalModule("fs", function (exports) {
   exports.Stats = process.Stats;
-
-  function callback (promise) {
-    return function (error) {
-      if (error) {
-        promise.emitError.apply(promise, arguments);
-      } else {
-        promise.emitSuccess.apply(promise,
-                                  Array.prototype.slice.call(arguments, 1));
-      }
-    };
-  }
   
   // Used by fs.open and friends
   function stringToFlags(flag) {
@@ -482,24 +471,22 @@ var fsModule = createInternalModule("fs", function (exports) {
     }
   }
 
+  function noop () {}
+
   // Yes, the follow could be easily DRYed up but I provide the explicit
   // list to make the arguments clear.
 
-  exports.close = function (fd) {
-    var promise = new events.Promise();
-    process.fs.close(fd, callback(promise));
-    return promise;
+  exports.close = function (fd, callback) {
+    process.fs.close(fd, callback || noop);
   };
 
   exports.closeSync = function (fd) {
     return process.fs.close(fd);
   };
 
-  exports.open = function (path, flags, mode) {
+  exports.open = function (path, flags, mode, callback) {
     if (mode === undefined) { mode = 0666; }
-    var promise = new events.Promise();
-    process.fs.open(path, stringToFlags(flags), mode, callback(promise));
-    return promise;
+    process.fs.open(path, stringToFlags(flags), mode, callback || noop);
   };
 
   exports.openSync = function (path, flags, mode) {
@@ -507,11 +494,9 @@ var fsModule = createInternalModule("fs", function (exports) {
     return process.fs.open(path, stringToFlags(flags), mode);
   };
 
-  exports.read = function (fd, length, position, encoding) {
-    var promise = new events.Promise();
+  exports.read = function (fd, length, position, encoding, callback) {
     encoding = encoding || "binary";
-    process.fs.read(fd, length, position, encoding, callback(promise));
-    return promise;
+    process.fs.read(fd, length, position, encoding, callback || noop);
   };
 
   exports.readSync = function (fd, length, position, encoding) {
@@ -519,11 +504,9 @@ var fsModule = createInternalModule("fs", function (exports) {
     return process.fs.read(fd, length, position, encoding);
   };
 
-  exports.write = function (fd, data, position, encoding) {
-    var promise = new events.Promise();
+  exports.write = function (fd, data, position, encoding, callback) {
     encoding = encoding || "binary";
-    process.fs.write(fd, data, position, encoding, callback(promise));
-    return promise;
+    process.fs.write(fd, data, position, encoding, callback || noop);
   };
 
   exports.writeSync = function (fd, data, position, encoding) {
@@ -531,160 +514,149 @@ var fsModule = createInternalModule("fs", function (exports) {
     return process.fs.write(fd, data, position, encoding);
   };
 
-  exports.rename = function (oldPath, newPath) {
-    var promise = new events.Promise();
-    process.fs.rename(oldPath, newPath, callback(promise));
-    return promise;
+  exports.rename = function (oldPath, newPath, callback) {
+    process.fs.rename(oldPath, newPath, callback || noop);
   };
 
   exports.renameSync = function (oldPath, newPath) {
     return process.fs.rename(oldPath, newPath);
   };
 
-  exports.truncate = function (fd, len) {
-    var promise = new events.Promise();
-    process.fs.truncate(fd, len, callback(promise));
-    return promise;
+  exports.truncate = function (fd, len, callback) {
+    process.fs.truncate(fd, len, callback || noop);
   };
 
   exports.truncateSync = function (fd, len) {
     return process.fs.truncate(fd, len);
   };
 
-  exports.rmdir = function (path) {
-    var promise = new events.Promise();
-    process.fs.rmdir(path, callback(promise));
-    return promise;
+  exports.rmdir = function (path, callback) {
+    process.fs.rmdir(path, callback || noop);
   };
 
   exports.rmdirSync = function (path) {
     return process.fs.rmdir(path);
   };
 
-  exports.mkdir = function (path, mode) {
-    var promise = new events.Promise();
-    process.fs.mkdir(path, mode, callback(promise));
-    return promise;
+  exports.mkdir = function (path, mode, callback) {
+    process.fs.mkdir(path, mode, callback || noop);
   };
 
   exports.mkdirSync = function (path, mode) {
     return process.fs.mkdir(path, mode);
   };
 
-  exports.sendfile = function (outFd, inFd, inOffset, length) {
-    var promise = new events.Promise();
-    process.fs.sendfile(outFd, inFd, inOffset, length, callback(promise));
-    return promise;
+  exports.sendfile = function (outFd, inFd, inOffset, length, callback) {
+    process.fs.sendfile(outFd, inFd, inOffset, length, callback || noop);
   };
 
   exports.sendfileSync = function (outFd, inFd, inOffset, length) {
     return process.fs.sendfile(outFd, inFd, inOffset, length);
   };
 
-  exports.readdir = function (path) {
-    var promise = new events.Promise();
-    process.fs.readdir(path, callback(promise));
-    return promise;
+  exports.readdir = function (path, callback) {
+    process.fs.readdir(path, callback || noop);
   };
 
   exports.readdirSync = function (path) {
     return process.fs.readdir(path);
   };
 
-  exports.stat = function (path) {
-    var promise = new events.Promise();
-    process.fs.stat(path, callback(promise));
-    return promise;
+  exports.stat = function (path, callback) {
+    process.fs.stat(path, callback || noop);
   };
 
   exports.statSync = function (path) {
     return process.fs.stat(path);
   };
 
-  exports.unlink = function (path) {
-    var promise = new events.Promise();
-    process.fs.unlink(path, callback(promise));
-    return promise;
+  exports.unlink = function (path, callback) {
+    process.fs.unlink(path, callback || noop);
   };
 
   exports.unlinkSync = function (path) {
     return process.fs.unlink(path);
   };
+  
+  exports.chmod = function (path, mode, callback) {
+    process.fs.chmod(path, mode, callback || noop);
+  };
+  
+  exports.chmodSync = function (path, mode) {
+    return process.fs.chmod(path, mode);
+  };
 
-  exports.writeFile = function (path, data, encoding) {
-    var promise = new events.Promise();
-    encoding = encoding || "utf8"; // default to utf8
-
-    fs.open(path, "w")
-      .addCallback(function (fd) {
-        function doWrite (_data) {
-          fs.write(fd, _data, 0, encoding)
-            .addErrback(function () {
-              fs.close(fd);
-              promise.emitError();
-            })
-            .addCallback(function (written) {
-              if (written === _data.length) {
-                fs.close(fd);
-                promise.emitSuccess();
-              } else {
-                doWrite(_data.slice(written));
-              }
-            });
+  function writeAll (fd, data, encoding, callback) {
+    exports.write(fd, data, 0, encoding, function (writeErr, written) {
+      if (writeErr) {
+        exports.close(fd, function () {
+          if (callback) callback(writeErr);
+        });
+      } else {
+        if (written === _data.length) {
+          exports.close(fd, callback);
+        } else {
+          writeAll(fd, data.slice(written), encoding, callback);
         }
-        doWrite(data);
-      })
-      .addErrback(function () {
-        promise.emitError();
-      });
+      }
+    });
+  }
 
-    return promise;
-    
+  exports.writeFile = function (path, data, encoding_) {
+    var encoding = (typeof(encoding) == 'string' ? encoding_ : 'utf8');
+    var callback_ = arguments[arguments.length - 1];
+    var callback = (typeof(callback_) == 'function' ? callback_ : null);
+    exports.open(path, 'w', 0666, function (openErr, fd) {
+      if (openErr) {
+        if (callback) callback(openErr);
+      } else {
+        writeAll(fd, data, encoding, callback);
+      }
+    });
   };
   
   exports.writeFileSync = function (path, data, encoding) {
     encoding = encoding || "utf8"; // default to utf8
     var fd = exports.openSync(path, "w");
-    return process.fs.write(fd, data, 0, encoding);
+    var written = 0;
+    while (written < data.length) {
+      written += exports.writeSync(fd, data, 0, encoding);
+      data = data.slice(written);
+    }
+    exports.closeSync(fd);
   };
   
-  
   exports.cat = function () {
     throw new Error("fs.cat is deprecated. Please use fs.readFile instead.");
   };
 
-  exports.readFile = function (path, encoding) {
-    var promise = new events.Promise();
-
-    encoding = encoding || "utf8"; // default to utf8
-
-    exports.open(path, "r").addCallback(function (fd) {
-      var content = "", pos = 0;
-
-      function readChunk () {
-        exports.read(fd, 16*1024, pos, encoding).addCallback(function (chunk, bytes_read) {
-          if (chunk) {
-            if (chunk.constructor === String) {
-              content += chunk;
-            } else {
-              content = content.concat(chunk);
-            }
-
-            pos += bytes_read;
-            readChunk();
-          } else {
-            promise.emitSuccess(content);
-            exports.close(fd);
-          }
-        }).addErrback(function () {
-          promise.emitError.apply(promise, arguments);
+  function readAll (fd, pos, content, encoding, callback) {
+    exports.read(fd, 4*1024, pos, encoding, function (err, chunk, bytesRead) {
+      if (err) {
+        if (callback) callback(err);
+      } else if (chunk) {
+        content += chunk;
+        pos += bytesRead;
+        readAll(fd, pos, content, encoding, callback);
+      } else {
+        process.fs.close(fd, function (err) {
+          if (callback) callback(err, content);
         });
       }
-      readChunk();
-    }).addErrback(function () {
-      promise.emitError.apply(promise, arguments);
     });
-    return promise;
+  }
+
+  exports.readFile = function (path, encoding_) {
+    var encoding = typeof(encoding_) == 'string' ? encoding : 'utf8';
+    var callback_ = arguments[arguments.length - 1];
+    var callback = (typeof(callback_) == 'function' ? callback_ : null);
+    exports.open(path, 'r', 0666, function (err, fd) {
+      if (err) {
+        if (callback) callback(err); 
+      } else {
+        readAll(fd, 0, "", encoding, callback);
+      }
+    });
   };
 
   exports.catSync = function () {
@@ -694,30 +666,27 @@ var fsModule = createInternalModule("fs", function (exports) {
   exports.readFileSync = function (path, encoding) {
     encoding = encoding || "utf8"; // default to utf8
 
-    var
-      fd = exports.openSync(path, "r"),
-      content = '',
-      pos = 0,
-      r;
+    debug('readFileSync open');
+
+    var fd = exports.openSync(path, "r");
+    var content = '';
+    var pos = 0;
+    var r;
 
-    while ((r = exports.readSync(fd, 16*1024, pos, encoding)) && r[0]) {
+    while ((r = exports.readSync(fd, 4*1024, pos, encoding)) && r[0]) {
+      debug('readFileSync read ' + r[1]);
       content += r[0];
       pos += r[1]
     }
 
+    debug('readFileSync close');
+
+    exports.closeSync(fd);
+
+    debug('readFileSync done');
+
     return content;
   };
-  
-  exports.chmod = function(path, mode){
-    var promise = new events.Promise();
-    process.fs.chmod(path, mode, callback(promise));
-    return promise;
-  };
-  
-  exports.chmodSync = function(path, mode){
-    return process.fs.chmod(path, mode);
-  };
-  
 });
 
 var fs = fsModule.exports;
@@ -782,9 +751,9 @@ var pathModule = createInternalModule("path", function (exports) {
   };
 
   exports.exists = function (path, callback) {
-    var p = fs.stat(path);
-    p.addCallback(function () { callback(true); });
-    p.addErrback(function () { callback(false); });
+    fs.stat(path, function (err, stats) {
+      if (callback) callback(err ? false : true);
+    });
   };
 });
 
@@ -1017,13 +986,7 @@ function cat (id, callback) {
       }
     });
   } else {
-    fs.readFile(id)
-      .addCallback(function(content) {
-        if (callback) callback(null, content);
-      })
-      .addErrback(function(err) {
-        if (callback) callback(err);
-      });
+    fs.readFile(id, callback);
   }
 }
 
@@ -1075,6 +1038,7 @@ Module.prototype._loadScriptSync = function (filename) {
 Module.prototype._loadScript = function (filename, callback) {
   var self = this;
   cat(filename, function (err, content) {
+    debug('cat done');
     if (err) {
       if (callback) callback(err);
     } else {
@@ -1130,7 +1094,9 @@ if (process.argv[1].charAt(0) != "/" && !(/^http:\/\//).exec(process.argv[1])) {
 
 // Load the main module--the command line argument.
 process.mainModule = new Module(".");
-process.mainModule.load(process.argv[1]);
+process.mainModule.load(process.argv[1], function (err) {
+  if (err) throw err;
+});
 
 // All our arguments are loaded. We've evaluated all of the scripts. We
 // might even have created TCP servers. Now we enter the main eventloop. If
index cae4bc7..0245d5d 100644 (file)
@@ -1,18 +1,20 @@
 process.mixin(require("./common"));
 
-var
-  count = 100,
-  fs = require('fs');
+var count = 100;
+var fs = require('fs');
 
 function tryToKillEventLoop() {
   puts('trying to kill event loop ...');
 
-  fs.stat(__filename)
-    .addCallback(function() {
+  fs.stat(__filename, function (err) {
+    if (err) {
+      throw new Exception('first fs.stat failed')
+    } else {
       puts('first fs.stat succeeded ...');
-
-      fs.stat(__filename)
-        .addCallback(function() {
+      fs.stat(__filename, function (err) {
+        if (err) {
+          throw new Exception('second fs.stat failed')
+        } else {
           puts('second fs.stat succeeded ...');
           puts('could not kill event loop, retrying...');
 
@@ -23,37 +25,31 @@ function tryToKillEventLoop() {
               process.exit(0);
             }
           }, 1);
-        })
-        .addErrback(function() {
-          throw new Exception('second fs.stat failed')
-        })
-
-    })
-    .addErrback(function() {
-      throw new Exception('first fs.stat failed')
-    });
+        }
+      });
+    }
+  });
 }
 
 // Generate a lot of thread pool events
 var pos = 0;
-fs.open('/dev/zero', "r").addCallback(function (rd) {
+fs.open('/dev/zero', "r", 0666, function (err, fd) {
+  if (err) throw err;
+
   function readChunk () {
-    fs.read(rd, 1024, pos, 'binary').addCallback(function (chunk, bytesRead) {
+    fs.read(fd, 1024, pos, 'binary', function (err, chunk, bytesRead) {
+      if (err) throw err;
       if (chunk) {
         pos += bytesRead;
         //puts(pos);
         readChunk();
       } else {
-        fs.close(rd);
-        throw new Exception(BIG_FILE+' should not end before the issue shows up');
+        fs.closeSync(fd);
+        throw new Exception('/dev/zero should not end before the issue shows up');
       }
-    }).addErrback(function () {
-      throw new Exception('could not read from '+BIG_FILE);
     });
   }
   readChunk();
-}).addErrback(function () {
-  throw new Exception('could not open '+BIG_FILE);
 });
 
 tryToKillEventLoop();
index d11f5be..d41f37c 100644 (file)
@@ -8,11 +8,13 @@ setTimeout(function () {
   N = 30;
   for (var i=0; i < N; i++) {
     puts("start " + i);
-    fs.readFile(testTxt).addCallback(function(data) {
-      puts("finish");
-    }).addErrback(function (e) {
-      puts("error! " + e);
-      process.exit(1);
+    fs.readFile(testTxt, function(err, data) {
+      if (err) {
+        puts("error! " + e);
+        process.exit(1);
+      } else {
+        puts("finish");
+      }
     });
   }
 }, 100);
index 3dea273..7004ee8 100644 (file)
@@ -4,14 +4,15 @@ var N = 100;
 var j = 0;
 
 for (var i = 0; i < N; i++) {
-  fs.stat("does-not-exist-" + i) // these files don't exist
-  .addErrback(function (e) {
-    j++; // only makes it to about 17
-    puts("finish " + j);
-  })
-  .addCallback(function () {
-    puts("won't be called");
-  });
+  // these files don't exist
+  fs.stat("does-not-exist-" + i, function (err) {
+    if (err) {
+      j++; // only makes it to about 17
+      puts("finish " + j);
+    } else {
+      throw new Error("this shouldn't be called");
+    }
+  }); 
 }
 
 process.addListener("exit", function () {
index 9e2b2ae..da28964 100644 (file)
@@ -2,16 +2,14 @@ process.mixin(require("./common"));
 var got_error = false;
 
 var filename = path.join(fixturesDir, "does_not_exist.txt");
-var promise = fs.readFile(filename, "raw");
-
-promise.addCallback(function (content) {
-  debug("cat returned some content: " + content);
-  debug("this shouldn't happen as the file doesn't exist...");
-  assert.equal(true, false);
-});
-
-promise.addErrback(function () {
-  got_error = true;
+fs.readFile(filename, "raw", function (err, content) {
+  if (err) {
+    got_error = true;
+  } else {
+    debug("cat returned some content: " + content);
+    debug("this shouldn't happen as the file doesn't exist...");
+    assert.equal(true, false);
+  }
 });
 
 process.addListener("exit", function () {
index e4a012c..71bd5b7 100644 (file)
@@ -3,21 +3,19 @@ process.mixin(require("./common"));
 var got_error = false;
 var success_count = 0;
 
-var __file = path.join(fixturesDir, "a.js");
+var file = path.join(fixturesDir, "a.js");
 
-var promise = fs.chmod(__file, 0777);
-
-promise.addCallback(function () {
-  puts(fs.statSync(__file).mode);
-  assert.equal("777", (fs.statSync(__file).mode & 0777).toString(8));
-  
-  fs.chmodSync(__file, 0644);
-  assert.equal("644", (fs.statSync(__file).mode & 0777).toString(8));
-  success_count++;
-});
-
-promise.addErrback(function () {
-  got_error = true;
+fs.chmod(file, 0777, function (err) {
+  if (err) {
+    got_error = true;
+  } else {
+    puts(fs.statSync(file).mode);
+    assert.equal(0777, fs.statSync(file).mode & 0777);
+    
+    fs.chmodSync(file, 0644);
+    assert.equal(0644, fs.statSync(file).mode & 0777);
+    success_count++;
+  }
 });
 
 process.addListener("exit", function () {
index 94b2f3f..7b5fa4e 100644 (file)
@@ -2,53 +2,52 @@ process.mixin(require("./common"));
 
 var got_error = false;
 var success_count = 0;
-var stats;
 
-var promise = fs.stat(".");
-
-promise.addCallback(function (_stats) {
-  stats = _stats;
-  p(stats);
-  success_count++;
-});
-
-promise.addErrback(function () {
-  got_error = true;
+fs.stat(".", function (err, stats) {
+  if (err) {
+    got_error = true;
+  } else {
+    p(stats);
+    assert.ok(stats.mtime instanceof Date);
+    success_count++;
+  }
 });
 
 puts("stating: " + __filename);
-fs.stat(__filename).addCallback(function (s) {
-  p(s);
-  success_count++;
+fs.stat(__filename, function (err, s) {
+  if (err) {
+    got_error = true;
+  } else {
+    p(s);
+    success_count++;
 
-  puts("isDirectory: " + JSON.stringify( s.isDirectory() ) );
-  assert.equal(false, s.isDirectory());
+    puts("isDirectory: " + JSON.stringify( s.isDirectory() ) );
+    assert.equal(false, s.isDirectory());
 
-  puts("isFile: " + JSON.stringify( s.isFile() ) );
-  assert.equal(true, s.isFile());
+    puts("isFile: " + JSON.stringify( s.isFile() ) );
+    assert.equal(true, s.isFile());
 
-  puts("isSocket: " + JSON.stringify( s.isSocket() ) );
-  assert.equal(false, s.isSocket());
+    puts("isSocket: " + JSON.stringify( s.isSocket() ) );
+    assert.equal(false, s.isSocket());
 
-  puts("isBlockDevice: " + JSON.stringify( s.isBlockDevice() ) );
-  assert.equal(false, s.isBlockDevice());
+    puts("isBlockDevice: " + JSON.stringify( s.isBlockDevice() ) );
+    assert.equal(false, s.isBlockDevice());
 
-  puts("isCharacterDevice: " + JSON.stringify( s.isCharacterDevice() ) );
-  assert.equal(false, s.isCharacterDevice());
+    puts("isCharacterDevice: " + JSON.stringify( s.isCharacterDevice() ) );
+    assert.equal(false, s.isCharacterDevice());
 
-  puts("isFIFO: " + JSON.stringify( s.isFIFO() ) );
-  assert.equal(false, s.isFIFO());
+    puts("isFIFO: " + JSON.stringify( s.isFIFO() ) );
+    assert.equal(false, s.isFIFO());
 
-  puts("isSymbolicLink: " + JSON.stringify( s.isSymbolicLink() ) );
-  assert.equal(false, s.isSymbolicLink());
-}).addErrback(function () {
-  got_error = true;
-});
+    puts("isSymbolicLink: " + JSON.stringify( s.isSymbolicLink() ) );
+    assert.equal(false, s.isSymbolicLink());
 
+    assert.ok(s.mtime instanceof Date);
+  }
+});
 
 process.addListener("exit", function () {
   assert.equal(2, success_count);
   assert.equal(false, got_error);
-  assert.equal(true, stats.mtime instanceof Date);
 });
 
index 0211a82..33b6d01 100644 (file)
@@ -4,14 +4,18 @@ var fn = path.join(fixturesDir, "write.txt");
 var expected = "hello";
 var found;
 
-fs.open(fn, 'w', 0644).addCallback(function (file) {
-  fs.write(file, expected, 0, "utf8").addCallback(function() {
-    fs.close(file).addCallback(function() {
-      fs.readFile(fn, process.UTF8).addCallback(function(contents) {
-        found = contents;
-        fs.unlinkSync(fn);
-      });
-    });
+fs.open(fn, 'w', 0644, function (err, fd) {
+  if (err) throw err;
+  puts('open done');
+  fs.write(fd, expected, 0, "utf8", function (err, written) {
+    puts('write done');
+    if (err) throw err;
+    assert.equal(expected.length, written);
+    fs.closeSync(fd);
+    found = fs.readFileSync(fn, 'utf8');
+    puts('expected: ' + expected.toJSON());
+    puts('found: ' + found.toJSON());
+    fs.unlinkSync(fn);
   });
 });
 
index 9eb78ce..9e3f787 100644 (file)
@@ -7,20 +7,21 @@ var d = path.join(fixtures, "dir");
 var mkdir_error = false;
 var rmdir_error = false;
 
-fs.mkdir(d, 0x666).addCallback(function () {
-  puts("mkdir okay!");
-
-  fs.rmdir(d).addCallback(function () {
-    puts("rmdir okay!");
-
-  }).addErrback(function (e) {
-    puts("rmdir error: " + e.message);
-    rmdir_error = true;
-  });
-
-}).addErrback(function (e) {
-  puts("mkdir error: " + e.message);
-  mkdir_error = true;
+fs.mkdir(d, 0666, function (err) {
+  if (err) {
+    puts("mkdir error: " + err.message);
+    mkdir_error = true;
+  } else {
+    puts("mkdir okay!");
+    fs.rmdir(d, function (err) {
+      if (err) {
+        puts("rmdir error: " + err.message);
+        rmdir_error = true;
+      } else {
+        puts("rmdir okay!");
+      }
+    });
+  }
 });
 
 process.addListener("exit", function () {
index 3a042fc..8058cb2 100644 (file)
@@ -57,13 +57,10 @@ try {
 
 assert.equal(require('path').dirname(__filename), __dirname);
 
-require.async('./fixtures/a')
-  .addCallback(function(a) {
-    assert.equal("A", a.A());
-  })
-  .addErrback(function() {
-    assert.ok(false, 'async loading broken?');
-  });
+require.async('./fixtures/a', function (err, a) {
+  if (err) throw err;
+  assert.equal("A", a.A());
+});
 
 process.addListener("exit", function () {
   assert.equal(true, a.A instanceof Function);
index 09b4575..f740560 100644 (file)
@@ -2,30 +2,28 @@ process.mixin(require("./common"));
 
 var got_error = false;
 
-var promise = fs.readdir(fixturesDir);
-puts("readdir " + fixturesDir);
-
-promise.addCallback(function (files) {
-  p(files);
-  assert.deepEqual(['a.js'
-                   , 'b'
-                   , 'cycles'
-                   , 'echo.js'
-                   , 'multipart.js'
-                   , 'nested-index'
-                   , 'print-chars.js'
-                   , 'test_ca.pem'
-                   , 'test_cert.pem'
-                   , 'test_key.pem'
-                   , 'throws_error.js'
-                   , 'x.txt'
-                   ], files.sort());
-});
-
-promise.addErrback(function () {
-  puts("error");
-  got_error = true;
+fs.readdir(fixturesDir, function (err, files) {
+  if (err) {
+    puts("error");
+    got_error = true;
+  } else {
+    p(files);
+    assert.deepEqual(['a.js'
+                     , 'b'
+                     , 'cycles'
+                     , 'echo.js'
+                     , 'multipart.js'
+                     , 'nested-index'
+                     , 'print-chars.js'
+                     , 'test_ca.pem'
+                     , 'test_cert.pem'
+                     , 'test_key.pem'
+                     , 'throws_error.js'
+                     , 'x.txt'
+                     ], files.sort());
+  }
 });
+puts("readdir " + fixturesDir);
 
 process.addListener("exit", function () {
   assert.equal(false, got_error);