Skip to content

Commit

Permalink
work around eager callback apis (in this case less.js)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomyan committed Jul 27, 2013
1 parent 7636a28 commit 5d59f4a
Showing 1 changed file with 60 additions and 8 deletions.
68 changes: 60 additions & 8 deletions lib/coro.js
Expand Up @@ -10,10 +10,15 @@ function currentCoro () {
exports.resume = function () {
var coro = currentCoro();
return function (error) {
var result = error ? null : Array.prototype.slice.call(arguments, 1);
if (coros.length && coro === coros[coros.length - 1]) {
coro.save(error, result);
return;
}
var val, err;
coros.push(coro);
try {
val = error ? coro.generator.throw(error) : coro.generator.next(Array.prototype.slice.call(arguments, 1));
val = error ? coro.generator.throw(error) : coro.generator.next(result);
}
catch (e) {
err = e;
Expand All @@ -24,11 +29,15 @@ exports.resume = function () {

exports.resumeFirst = function () {
var coro = currentCoro();
return function (error, res) {
return function (error, result) {
if (coros.length && coro === coros[coros.length - 1]) {
coro.save(error, result);
return;
}
var val, err;
coros.push(coro);
try {
val = error ? coro.generator.throw(error) : coro.generator.next(res);
val = error ? coro.generator.throw(error) : coro.generator.next(result);
}
catch (e) {
err = e;
Expand All @@ -40,10 +49,15 @@ exports.resumeFirst = function () {
exports.resumeNth = function (n) {
var coro = currentCoro();
return function (error) {
var result = error ? null : arguments[n];
if (coros.length && coro === coros[coros.length - 1]) {
coro.save(error, result);
return;
}
var val, err;
coros.push(coro);
try {
val = error ? coro.generator.throw(error) : coro.generator.next(arguments[n]);
val = error ? coro.generator.throw(error) : coro.generator.next(result);
}
catch (e) {
err = e;
Expand All @@ -55,10 +69,15 @@ exports.resumeNth = function (n) {
exports.resumeNoThrow = function () {
var coro = currentCoro();
return function () {
var result = Array.prototype.slice.call(arguments, 0);
if (coros.length && coro === coros[coros.length - 1]) {
coro.save(null, result);
return;
}
var val, err;
coros.push(coro);
try {
val = coro.generator.next(Array.prototype.slice.call(arguments, 0));
val = coro.generator.next(result);
}
catch (e) {
err = e;
Expand All @@ -70,6 +89,10 @@ exports.resumeNoThrow = function () {
exports.resumeNoThrowFirst = function () {
var coro = currentCoro();
return function (first) {
if (coros.length && coro === coros[coros.length - 1]) {
coro.save(null, first);
return;
}
var val, err;
coros.push(coro);
try {
Expand All @@ -85,10 +108,15 @@ exports.resumeNoThrowFirst = function () {
exports.resumeNoThrowNth = function (n) {
var coro = currentCoro();
return function () {
var result = arguments[n];
if (coros.length && coro === coros[coros.length - 1]) {
coro.save(null, result);
return;
}
var val, err;
coros.push(coro);
try {
val = coro.generator.next(arguments[n]);
val = coro.generator.next(result);
}
catch (e) {
err = e;
Expand All @@ -100,6 +128,10 @@ exports.resumeNoThrowNth = function (n) {
exports.resumeThrow = function () {
var coro = currentCoro();
return function (error) {
if (coros.length && coro === coros[coros.length - 1]) {
coro.save(error);
return;
}
var val, err;
coros.push(coro);
try {
Expand All @@ -119,13 +151,25 @@ var Coro = function (generator, deferred, callback) {
};

Coro.prototype.handle = function (err, result) {
var val, err;
coros.pop();
if (err || result.done) {
this.handleResult(err, result);
if (err || this.savedError || result.done) {
this.handleResult(err || this.savedError, result);
}
else if (result.value && result.value.then) {
this.handlePromise(result.value);
}
else if (this.savedResult) {
coros.push(this);
try {
val = this.generator.next(this.savedResult);
}
catch (e) {
err = e;
}
this.savedResult = null;
this.handle(err, val);
}
};

Coro.prototype.handleResult = function (err, result) {
Expand Down Expand Up @@ -168,6 +212,14 @@ Coro.prototype.handlePromise = function (promise) {
);
};

Coro.prototype.save = function (error, result) {
if (this.savedResult || this.savedError) {
throw new Error('more than one coro callback called without yield');
}
this.savedError = error;
this.savedResult = result;
};

exports.run = function (makeGenerator, args, callback) {

var deferred = callback ? null : p.defer(),
Expand Down

0 comments on commit 5d59f4a

Please sign in to comment.