Skip to content
Browse files

Initial version.

  • Loading branch information...
1 parent 0ca150c commit f5041c64e7ce37b5e4798f3347e79120c527c733 @lm1 committed Jan 23, 2011
Showing with 362 additions and 0 deletions.
  1. +128 −0 fiberize.js
  2. +11 −0 package.json
  3. +110 −0 test/callback_args_test.js
  4. +24 −0 test/childp_test.js
  5. +23 −0 test/fs_test.js
  6. +22 −0 test/proto_test.js
  7. +15 −0 test/run-all
  8. +13 −0 test/sleep_test.js
  9. +16 −0 test/this_test.js
View
128 fiberize.js
@@ -0,0 +1,128 @@
+/*
+ Copyright 2011 Lukasz Mielicki <mielicki@gmail.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+*/
+
+require('fibers');
+
+module.exports = fiberize;
+
+module.exports.wrapf = wrapf;
+
+module.exports.require = function(path) {
+ return fiberize(require(path));
+};
+
+function build_result(result, cb_args) {
+ var ret = {};
+ if (result !== undefined) {
+ ret.value = [result].concat(cb_args);
+ } else {
+ if (cb_args[0]) {
+ ret.error = cb_args[0];
+ } else {
+ ret.value = cb_args.slice(1);
+ if (ret.value.length == 1) ret.value = ret.value[0];
+ }
+ }
+ return ret;
+}
+
+function wrapf(fn) {
+ return function() {
+ var self = this;
+ var args = Array.prototype.slice.call(arguments);
+ var fiber = Fiber.current;
+ var returned = false;
+ var result;
+ var cb_args;
+ var cb = function(err) {
+ cb_args = Array.prototype.slice.call(arguments);
+ if (!returned) return true;
+ var ret = build_result(result, cb_args);
+ if (ret.error) {
+ fiber.throwInto(ret.error);
+ return false;
+ } else {
+ fiber.run(ret.value);
+ return true;
+ }
+ };
+ var len = fn.__length || fn.length;
+ if (args.length >= len) args.push(cb);
+ else args[len - 1] = cb;
+ var value = fn.apply(self, args);
+ returned = true;
+ if (value !== self) result = value;
+ if (cb_args) {
+ var ret = build_result(result, cb_args);
+ if (ret.error) throw (ret.error);
+ else return ret.value;
+ }
+ return yield();
+ }
+}
+
+function fiberizeObject(obj) {
+ if (obj.__fiberized) return obj;
+ for (var f in obj) {
+ var fn = obj[f];
+ console.log('Found:', f, typeof fn);
+ if (typeof fn !== 'function' || /^_.*|.*_$/.test(f)) continue;
+
+ var body = obj[f].toString(); // stringify function body
+ // extract arguments, also the commented ones
+ var args = /function [\w$]*\((.*)\)\s*{/.exec(body)[1]
+ .replace(/\/\*|\*\//g, ', ')
+ .replace(/\s*/g, '')
+ .replace(/,,/g, ',')
+ .replace(/,$/, '')
+ .split(',');
+ var lastarg = args.slice(-1).toString();
+ if (lastarg == 'callback' || obj[f].__hasCallback) {
+ console.log('Wrapping', f, '(', args, ')');
+ fn.__length = args.length;
+ if (obj[f + 'W'] === undefined) {
+ obj[f + 'W'] = wrapf(fn);
+ } else {
+ console.error('(fiberize) Warning:', f + 'W', 'already defined.');
+ }
+ }
+ if (fn.prototype) fiberizeObject(fn.prototype);
+ }
+ obj.__fiberized = true;
+ return obj;
+}
+
+function fiberize(mod, proto) {
+ return fiberizeObject(mod, proto);
+}
+
+module.exports.start = function(f) {
+ return Fiber(f).run();
+};
+
+module.exports.sleep = function(ms) {
+ var fiber = Fiber.current;
+ setTimeout(function() { fiber.run(); }, ms);
+ yield();
+};
+
+require('fs').readFile.__hasCallback = true;
View
11 package.json
@@ -0,0 +1,11 @@
+{
+ "name": "fiberize",
+ "description": "Node API wrapper for node-fibers.",
+ "version": "0.0.0",
+ "url": "http://github.com/lm1/node-fiberize",
+ "author": "Lukasz Mielicki <mielicki@gmail.com>",
+ "main": "fiberize",
+ "engines": {
+ "node": ">=0.3.6"
+ }
+}
View
110 test/callback_args_test.js
@@ -0,0 +1,110 @@
+var fiberize = require('fiberize');
+var assert = require('assert');
+
+var mod = {};
+//
+// Direct callback, no result
+//
+mod.f0 = function(callback) {
+ callback();
+};
+
+mod.f1 = function(a, callback) {
+ callback(false, a);
+};
+mod.f1.args = [1];
+mod.f1.result = 1;
+
+mod.f2 = function(a, b, callback) {
+ callback(false, a, b);
+};
+mod.f2.args = [1, 2];
+mod.f2.result = [1, 2];
+
+mod.ferr = function(callback) {
+ callback(true);
+};
+mod.ferr.throws = true;
+
+//
+// Delayed callback, no result
+//
+mod.f0d = function(callback) {
+ process.nextTick(function() {callback();});
+};
+
+mod.f1d = function(a, callback) {
+ process.nextTick(function() {callback(false, a);});
+};
+mod.f1d.args = [1];
+mod.f1d.result = 1;
+
+mod.f2d = function(a, b, callback) {
+ process.nextTick(function() {callback(false, a, b);});
+};
+mod.f2d.args = [1, 2];
+mod.f2d.result = [1, 2];
+
+mod.ferrd = function(callback) {
+ process.nextTick(function() {callback(true);});
+};
+mod.ferrd.throws = true;
+
+//
+// Direct callback with result
+//
+mod.fr0 = function(callback) {
+ callback();
+ return 1;
+};
+mod.fr0.result = [1];
+
+mod.fr1 = function(a, callback) {
+ callback(a);
+ return 1;
+};
+mod.fr1.args = [2];
+mod.fr1.result = [1, 2];
+
+//
+// Delayed callback with result
+//
+mod.fr1d = function(callback) {
+ process.nextTick(function() {callback(2);});
+ return 1;
+};
+mod.fr1d.result = [1, 2];
+
+mod.fr2d = function(callback) {
+ process.nextTick(function() {callback(2, 3);});
+ return 1;
+};
+mod.fr2d.result = [1, 2, 3];
+
+
+fiberize(mod);
+
+fiberize.start(function() {
+ for (fn in mod) {
+ var f = mod[fn];
+ var fw = mod[fn + 'W'];
+ if (!fw) continue;
+
+ console.log(fn, f.args, f.result, f.throws ? 'throws' : '');
+
+ var args = f.args || [];
+ var result;
+ if (f.throws) {
+ assert.throws(function() {
+ result = fw.apply(null, args);
+ });
+ } else {
+ result = fw.apply(null, args);
+ }
+ if (f.result) {
+ assert.deepEqual(result, f.result);
+ }
+ }
+
+ process.nextTick(function() { console.log('_END_');});
+});
View
24 test/childp_test.js
@@ -0,0 +1,24 @@
+var fiberize = require('fiberize');
+var child_process = fiberize.require('child_process');
+var assert = require('assert');
+
+fiberize.start(function() {
+ // Run command and wait for result
+ var result = child_process.execW('cat ' + __filename + ' |wc -l');
+
+ assert.equal(result.length, 4);
+
+ // result[0] is a returned child object
+ assert.equal(typeof result[0].kill, 'function');
+
+ // result[1] is 1st callabck argument (error code)
+ assert.equal(result[1], null);
+
+ // result[2] is 2ns callback argument (stdout)
+ assert.equal(result[2], '24\n'); // :)
+
+ // result[3] is 3rd callback argument (stderr)
+ assert.equal(result[3], '');
+
+ process.nextTick(function() { console.log('_END_');});
+});
View
23 test/fs_test.js
@@ -0,0 +1,23 @@
+var fiberize = require('fiberize');
+var fs = fiberize.require('fs');
+var assert = require('assert');
+
+fiberize.start(function() {
+ var file = __filename;
+ var fd = fs.openW(file, 'r');
+ var info = fs.fstatW(fd);
+ var buf = new Buffer(info.size);
+ var read = fs.readW(fd, buf, 0, info.size, null);
+ fs.closeW(fd);
+ assert.ok(read == info.size);
+ //console.log(buf.toString('utf8'));
+
+ var txt = fs.readFileW(file, 'utf8');
+ assert.ok(txt.length == info.size);
+
+ assert.throws(function() {
+ fs.writeFileW('.', 'ABC', 'utf8');
+ });
+
+ process.nextTick(function() { console.log('_END_');});
+});
View
22 test/proto_test.js
@@ -0,0 +1,22 @@
+var fiberize = require('fiberize');
+var assert = require('assert');
+
+var mod = { };
+mod.MyClass = function() {
+ this.a = 1;
+};
+mod.MyClass.prototype.get_a = function(callback) {
+ callback(null, this.a);
+ //return this;
+};
+
+fiberize(mod);
+
+fiberize.start(function() {
+
+ var obj = new mod.MyClass();
+ var val = obj.get_aW();
+ assert.equal(val, 1);
+
+ process.nextTick(function() { console.log('_END_');});
+});
View
15 test/run-all
@@ -0,0 +1,15 @@
+#!/bin/bash
+for TEST in *_test.js; do
+ echo -n "$TEST "
+
+ exec 3>&1 4>&2
+ RESULT=$( { node-fibers $TEST|grep _END_ 1>&3 2>&4; } 3>&1)
+ exec 3>&- 4>&-
+
+ if [[ $RESULT == "_END_" ]]; then
+ echo -e "\E[32m\E[1mOK\033[0m"
+ else
+ echo -e "\E[31m\E[1mFAIL\033[0m"
+ fi;
+done;
+
View
13 test/sleep_test.js
@@ -0,0 +1,13 @@
+var fiberize = require('fiberize');
+var assert = require('assert');
+
+fiberize.start(function() {
+
+ var timeout = 50;
+ var before = new Date();
+ fiberize.sleep(timeout);
+ var after = new Date();
+ assert.ok((after - before) >= timeout);
+
+ process.nextTick(function() { console.log('_END_');});
+});
View
16 test/this_test.js
@@ -0,0 +1,16 @@
+var fiberize = require('fiberize');
+var assert = require('assert');
+
+var obj = {
+ f: function(callback) {
+ callback();
+ assert.ok(this === obj);
+ }
+};
+
+fiberize(obj);
+
+fiberize.start(function() {
+ obj.fW();
+ process.nextTick(function() { console.log('_END_');});
+});

0 comments on commit f5041c6

Please sign in to comment.
Something went wrong with that request. Please try again.