Initial commit
This commit is contained in:
412
node_modules/cps/lib/cps.js
generated
vendored
Normal file
412
node_modules/cps/lib/cps.js
generated
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
|
||||
var Tail = require('./tail');
|
||||
|
||||
module.exports = function() {
|
||||
var procedure = function(fn) {
|
||||
return function() {
|
||||
var cb = arguments[arguments.length - 1];
|
||||
|
||||
try {
|
||||
fn.apply(this, arguments);
|
||||
} catch(e) {
|
||||
handleError(e, cb);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var handleError = function(e, cb) {
|
||||
cb(e);
|
||||
};
|
||||
|
||||
var callback = function(cb, fn) {
|
||||
var called = false;
|
||||
|
||||
return function(err) {
|
||||
if (called) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
if (err.stack) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
}
|
||||
throw new Error('Continuation is being called more than once!');
|
||||
}
|
||||
called = true;
|
||||
try {
|
||||
if (err) {
|
||||
handleError(err, cb);
|
||||
} else {
|
||||
fn.apply(this, arguments);
|
||||
}
|
||||
} catch(e) {
|
||||
handleError(e, cb);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var _seq = procedure(function(procs, i, res, cb) {
|
||||
if (i >= procs.length) {
|
||||
return cb(null, res);
|
||||
}
|
||||
var proc = procs[i];
|
||||
proc(res, callback(cb, function(err, res) {
|
||||
// return _seq(procs, i+1, res, cb);
|
||||
return Tail.run(function() {
|
||||
_seq(procs, i+1, res, cb);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
var seq = function(procs, cb) {
|
||||
return _seq(procs, 0, null, cb);
|
||||
};
|
||||
|
||||
var rescue = procedure(function(procBundle, cb) {
|
||||
var tryProc = procBundle['try'];
|
||||
var catchProc = procBundle['catch'] || function(err, cb) {cb(err);};
|
||||
var finallyProc = procBundle['finally'] || function(cb) {cb();};
|
||||
|
||||
var applyTry = procedure(function(cb) {
|
||||
tryProc(cb);
|
||||
});
|
||||
|
||||
var applyCatch = procedure(function(err, cb) {
|
||||
catchProc(err, cb);
|
||||
});
|
||||
|
||||
var applyFinallyOk = procedure(function(res0, cb) {
|
||||
finallyProc(callback(cb, function(err, res) {
|
||||
cb(null, res0);
|
||||
}));
|
||||
});
|
||||
|
||||
var applyFinallyError = procedure(function(err0, cb) {
|
||||
finallyProc(callback(cb, function(err, res) {
|
||||
cb(err0);
|
||||
}));
|
||||
});
|
||||
|
||||
applyTry(function(err, res) {
|
||||
if (err) {
|
||||
applyCatch(err, function(err, res) {
|
||||
if (err) {
|
||||
applyFinallyError(err, cb);
|
||||
} else {
|
||||
applyFinallyOk(res, cb);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
applyFinallyOk(res, cb);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var pwhile = procedure(function(procBool, procBody, cb) {
|
||||
seq([
|
||||
function(_, cb) {
|
||||
procBool(cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
if (_) {
|
||||
seq([
|
||||
function(_, cb) {
|
||||
procBody(cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
pwhile(procBool, procBody, cb);
|
||||
}
|
||||
], cb);
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
|
||||
var peach = procedure(function(arr, proc, cb) {
|
||||
var i = 0;
|
||||
|
||||
pwhile(
|
||||
function(cb) {
|
||||
cb(null, i < arr.length);
|
||||
},
|
||||
function(cb) {
|
||||
seq([
|
||||
function(_, cb) {
|
||||
proc(arr[i], cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
i++;
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
},
|
||||
cb
|
||||
)
|
||||
});
|
||||
|
||||
var pfor = procedure(function(n, proc, cb) {
|
||||
var i = 0;
|
||||
|
||||
pwhile(
|
||||
function(cb) {
|
||||
cb(null, i < n);
|
||||
},
|
||||
function(cb) {
|
||||
seq([
|
||||
function(_, cb) {
|
||||
proc(i, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
i++;
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
},
|
||||
cb
|
||||
);
|
||||
});
|
||||
|
||||
var pmap = procedure(function(arr, proc, cb) {
|
||||
var l = [];
|
||||
|
||||
seq([
|
||||
function(_, cb) {
|
||||
peach(arr, function(e, cb) {
|
||||
seq([
|
||||
function(_, cb) {
|
||||
proc(e, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
l.push(_);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
}, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
cb(null, l);
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
|
||||
var _parallel2 = procedure(function(proc1, proc2, cb) {
|
||||
var state1 = 'start';
|
||||
var state2 = 'start';
|
||||
var res1;
|
||||
var res2;
|
||||
var err1;
|
||||
var err2;
|
||||
|
||||
var applyProc1 = procedure(function(cb) {
|
||||
proc1(cb);
|
||||
});
|
||||
|
||||
var applyProc2 = procedure(function(cb) {
|
||||
proc2(cb);
|
||||
});
|
||||
|
||||
applyProc1(function(err, res) {Tail.run(function() {
|
||||
if (err) {
|
||||
state1 = 'error';
|
||||
err1 = err;
|
||||
switch(state2) {
|
||||
case 'start':
|
||||
break;
|
||||
case 'done':
|
||||
cb(null, [
|
||||
{status: 'error', error: err1},
|
||||
{status: 'ok', data: res2}
|
||||
]);
|
||||
break;
|
||||
case 'error':
|
||||
cb(null, [
|
||||
{status: 'error', error: err1},
|
||||
{status: 'error', error: err2}
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
state1 = 'done';
|
||||
res1 = res;
|
||||
switch(state2) {
|
||||
case 'start':
|
||||
break;
|
||||
case 'done':
|
||||
cb(null, [
|
||||
{status: 'ok', data: res1},
|
||||
{status: 'ok', data: res2}
|
||||
]);
|
||||
break;
|
||||
case 'error':
|
||||
cb(null, [
|
||||
{status: 'ok', data: res1},
|
||||
{status: 'error', error: err2}
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
})});
|
||||
|
||||
applyProc2(function(err, res) {Tail.run(function() {
|
||||
if (err) {
|
||||
state2 = 'error';
|
||||
err2 = err;
|
||||
switch(state1) {
|
||||
case 'start':
|
||||
break;
|
||||
case 'done':
|
||||
cb(null, [
|
||||
{status: 'ok', data: res1},
|
||||
{status: 'error', error: err2}
|
||||
]);
|
||||
break;
|
||||
case 'error':
|
||||
cb(null, [
|
||||
{status: 'error', error: err1},
|
||||
{status: 'error', error: err2}
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
state2 = 'done';
|
||||
res2 = res;
|
||||
switch(state1) {
|
||||
case 'start':
|
||||
break;
|
||||
case 'done':
|
||||
cb(null, [
|
||||
{status: 'ok', data: res1},
|
||||
{status: 'ok', data: res2}
|
||||
]);
|
||||
break;
|
||||
case 'error':
|
||||
cb(null, [
|
||||
{status: 'error', error: err1},
|
||||
{status: 'ok', data: res2}
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
})});
|
||||
});
|
||||
|
||||
var _parallel = procedure(function(procs, i, cb) {
|
||||
if (procs.length == 0) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
if (i == procs.length - 1) {
|
||||
return procs[i](function(err, res) {
|
||||
if (err) {
|
||||
cb(null, [{status: 'error', error: err}]);
|
||||
} else {
|
||||
cb(null, [{status: 'ok', data: res}]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (i < procs.length) {
|
||||
_parallel2(
|
||||
procs[i],
|
||||
function(cb) {
|
||||
_parallel(procs, i+1, cb);
|
||||
},
|
||||
callback(cb, function(err, res) {
|
||||
cb(null, [res[0]].concat(res[1].data));
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var parallel = procedure(function(procs, cb) {
|
||||
_parallel(procs, 0, cb);
|
||||
});
|
||||
|
||||
var noFail = function() {
|
||||
var proc, handler, cb;
|
||||
|
||||
proc = arguments[0];
|
||||
cb = arguments[arguments.length - 1];
|
||||
|
||||
if (arguments.length == 2) {
|
||||
handler = function(err) {
|
||||
console.log('ERROR caught by cps.noFail: ', err);
|
||||
if (err.stack) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
};
|
||||
} else if (arguments.length == 3) {
|
||||
handler = arguments[1];
|
||||
} else {
|
||||
handleError(new Error('Incorrect number of arguments in calling cps.noFail.'), cb);
|
||||
}
|
||||
|
||||
rescue({
|
||||
'try': function(cb) {
|
||||
proc(cb);
|
||||
},
|
||||
'catch': function(err, cb) {
|
||||
handler(err);
|
||||
cb();
|
||||
}
|
||||
}, cb);
|
||||
};
|
||||
|
||||
var run = function(proc, cfg) {
|
||||
cfg = cfg || {};
|
||||
|
||||
var cb = function(err, res) {
|
||||
try {
|
||||
if (err) {
|
||||
if (cfg['error']) {
|
||||
cfg['error'](err);
|
||||
} else {
|
||||
console.log('cps.run ERROR: ', err);
|
||||
if (err.stack) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (cfg['ok']) {
|
||||
cfg['ok'](res);
|
||||
} else {
|
||||
console.log('cps.run OK: ', res);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
if (cfg['topLevelError']) {
|
||||
cfg['topLevelError'](e);
|
||||
} else {
|
||||
console.log('cps.run TOP_LEVEL_ERROR: ', e);
|
||||
}
|
||||
} finally {
|
||||
if (cfg['finally']) {
|
||||
try {
|
||||
cfg['finally']();
|
||||
} catch(e) {
|
||||
console.log('cps.run FINALLY_ERROR: ', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
proc(cb);
|
||||
};
|
||||
|
||||
return {
|
||||
seq: seq,
|
||||
peach: peach,
|
||||
pwhile: pwhile,
|
||||
pmap: pmap,
|
||||
pfor: pfor,
|
||||
rescue: rescue,
|
||||
parallel: parallel,
|
||||
noFail: noFail,
|
||||
run: run
|
||||
};
|
||||
}();
|
Reference in New Issue
Block a user