Initial commit
This commit is contained in:
3
node_modules/cps/.npmignore
generated
vendored
Normal file
3
node_modules/cps/.npmignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.idea
|
||||
cps.iml
|
||||
npm-debug.log
|
19
node_modules/cps/LICENSE
generated
vendored
Normal file
19
node_modules/cps/LICENSE
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013 Chiyan Chen
|
||||
|
||||
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.
|
348
node_modules/cps/README.md
generated
vendored
Normal file
348
node_modules/cps/README.md
generated
vendored
Normal file
@ -0,0 +1,348 @@
|
||||
|
||||
# cps
|
||||
|
||||
A CPS (Continuation Passing Style) library to ease the
|
||||
event-driven/asynchronized coding style in node.js. There seems to be
|
||||
enough node.js libs (e.g. async) doing the same thing, why yet
|
||||
another? This lib is notably different from other libs in
|
||||
exception handling. Using cps:
|
||||
|
||||
* Any "throw" statements in the procedures will be transformed to an
|
||||
application of the callback onto the error object.
|
||||
* A "rescue" function is provided, which can be used to catch such
|
||||
exceptions pass through the callbacks.
|
||||
|
||||
This consistently recovers the try/catch functionality in continuation
|
||||
passing style programming.
|
||||
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```text
|
||||
npm install cps
|
||||
```
|
||||
|
||||
## Terminologies
|
||||
|
||||
### Callback
|
||||
|
||||
We call a function of the following form a callback:
|
||||
|
||||
```javascript
|
||||
function(err, res) {
|
||||
// process the err and res
|
||||
}
|
||||
```
|
||||
|
||||
A callback is a function that takes two arguments, "err" and "res".
|
||||
Semantically, a non-null "err" corresponds to a program exception;
|
||||
while a null "err" corresponds to normal return without any
|
||||
exceptions.
|
||||
|
||||
### Procedure
|
||||
|
||||
We call a function of the following form a procedure:
|
||||
|
||||
```javascript
|
||||
function(arg1, arg2, ..., callback) {
|
||||
// do some work with the arguments and then invoke the callback to continue
|
||||
}
|
||||
```
|
||||
|
||||
A procedure is a function that takes a callback as the last argument.
|
||||
Semantically, a procedure does some work with the input arguments and
|
||||
at some point, call the callback to continue. Note that a call to the
|
||||
"callback" argument MUST always be a tail call. In particular, the
|
||||
following is a procedure:
|
||||
|
||||
```javascript
|
||||
function(callback) {
|
||||
// do some work and then invoke the callback to continue
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## API Document
|
||||
|
||||
* [seq](#seq)
|
||||
* [pwhile](#pwhile)
|
||||
* [peach](#peach)
|
||||
* [pmap](#pmap)
|
||||
* [pfor](#pfor)
|
||||
* [rescue](#rescue)
|
||||
* [parallel](#parallel)
|
||||
|
||||
<a name="seq"/>
|
||||
### seq(array_of_procedures, callback)
|
||||
|
||||
Sequence a list of procedures. Note that the result of each procedure
|
||||
is fed into the next procedure in the listed order.
|
||||
|
||||
__Example__
|
||||
|
||||
```javascript
|
||||
var concatFile = function(f1, f2, resFile, cb) {
|
||||
var contentOfA, contentOfB;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
fs.readFile(f1, cb);
|
||||
},
|
||||
function(res, cb) {
|
||||
contentOfA = res;
|
||||
fs.readFile(f2, cb);
|
||||
},
|
||||
function(res, cb) {
|
||||
contentOfB = res;
|
||||
fs.writeFile(resFile, contentA + contentB, cb);
|
||||
}
|
||||
], cb);
|
||||
};
|
||||
```
|
||||
|
||||
<a name="pwhile">
|
||||
### pwhile(bool_procedure, repeat_body_procedure, cb)
|
||||
|
||||
An asynchronized version of while loop.
|
||||
|
||||
__Example__
|
||||
|
||||
Consider a world in which arithmatic operations do not exists and must
|
||||
be accomplished through alien technology. Then the Fibonacci function
|
||||
needs to be written in the following way:
|
||||
|
||||
```javascript
|
||||
var alienAdd = function(a, b, cb) {
|
||||
setTimeout(function() {
|
||||
cb(null, a + b);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
var asyncFib = function(n, cb) {
|
||||
if (n < 0) {
|
||||
throw new Error('fib input error');
|
||||
}
|
||||
if (n == 0) {return cb(null, 1);}
|
||||
if (n == 1) {return cb(null, 1);}
|
||||
|
||||
var a = 1,
|
||||
b = 1,
|
||||
i = 2;
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.pwhile(
|
||||
function(cb) {
|
||||
cb(null, i <= n);
|
||||
},
|
||||
function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
alienAdd(a, b, cb);
|
||||
},
|
||||
function(res, cb) {
|
||||
a = b;
|
||||
b = res;
|
||||
alienAdd(i, 1, cb);
|
||||
},
|
||||
function(res, cb) {
|
||||
i = res;
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
},
|
||||
cb
|
||||
);
|
||||
},
|
||||
function(_, cb) {
|
||||
cb(null, b);
|
||||
}
|
||||
], cb);
|
||||
};
|
||||
```
|
||||
|
||||
<a name="peach"/>
|
||||
### peach(arr, procedure_for_each_element, callback)
|
||||
|
||||
Apply a procedure on an array sequentially.
|
||||
|
||||
__Example__
|
||||
|
||||
Then in the same "arithmetic-less" world, print out the first 10 Fibonacci numbers.
|
||||
|
||||
```javascript
|
||||
cps.peach(
|
||||
[1,2,3,4,5,6,7,8,9,10],
|
||||
function(el, cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
asyncFib(el, cb);
|
||||
},
|
||||
function(res, cb) {
|
||||
console.log(res);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
|
||||
},
|
||||
cb
|
||||
);
|
||||
```
|
||||
|
||||
<a name="pmap" />
|
||||
### pmap(arr, procedure_for_each_element, callback)
|
||||
|
||||
Apply a procedure on an array sequentially, and record the results in another array, which is pass to the callback.
|
||||
|
||||
__Example__
|
||||
|
||||
You can also map it out first and then log the result list.
|
||||
|
||||
```javascript
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.pmap(
|
||||
[1,2,3,4,5,6,7,8,9,10],
|
||||
function(el, cb) {
|
||||
asyncFib(el, cb);
|
||||
},
|
||||
cb
|
||||
);
|
||||
},
|
||||
function(res, cb) {
|
||||
console.log(res);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
```
|
||||
|
||||
<a name="pfor" />
|
||||
### pfor(number_of_iterations, procedure_for_each_index, callback)
|
||||
|
||||
Apply a procedure on a sequence of consecutive indices, starting of 0.
|
||||
|
||||
__Example__
|
||||
|
||||
|
||||
```javascript
|
||||
var sum = 0;
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
console.log('here');
|
||||
cps.pfor(10, function(i, cb) {
|
||||
setTimeout(function() {
|
||||
sum += i;
|
||||
console.log(sum);
|
||||
cb();
|
||||
}, 1000);
|
||||
}, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
console.log(sum);
|
||||
cb(null, 'ok');
|
||||
}
|
||||
], cb);
|
||||
```
|
||||
|
||||
<a name="rescue"/>
|
||||
### rescue(try_clause_procedure, catch_clause_procedure, callback)
|
||||
|
||||
An asyned version of try/catch. It take two procedures as arguments. If the first one fails, the second is executed to rescue.
|
||||
|
||||
__Example__
|
||||
|
||||
What if there's some invalid input? Let's catch it without disturbing the overall flow.
|
||||
|
||||
```javascript
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.pmap(
|
||||
[1,2,3,4,5,6,7,8,9,10, -1],
|
||||
function(el, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) { // try clause
|
||||
asyncFib(el, cb);
|
||||
},
|
||||
'catch': function(err, cb) { // catch clause
|
||||
console.log(err);
|
||||
cb(null, -1);
|
||||
},
|
||||
'finally': function(cb) { // finally
|
||||
console.log("always print this whether it's good or bad.");
|
||||
cb();
|
||||
}
|
||||
}, cb);
|
||||
},
|
||||
cb
|
||||
);
|
||||
},
|
||||
function(res, cb) {
|
||||
console.log(res);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
```
|
||||
|
||||
<a name="parallel"/>
|
||||
### parallel(array_of_procedures, callback)
|
||||
|
||||
Parallel a list of procedures. The top level callback is only called
|
||||
after each parallel procedure finishes, regardless the procedure
|
||||
succeeds or fails. The callback will never take a non-null error
|
||||
parameter; the result parameter is an array of the following form:
|
||||
|
||||
```js
|
||||
[
|
||||
{"status": "ok", "data": res}, /* in case the procedure in the
|
||||
corresponding position succeeds
|
||||
with result res
|
||||
*/
|
||||
{"status": "error", "error": err} /* in case the procedure in the
|
||||
corresponding position fails
|
||||
with error err
|
||||
*/
|
||||
// ...
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
__Example__
|
||||
|
||||
See "thread b" being printed out before "thread a":
|
||||
|
||||
```javascript
|
||||
var parallelTest = function(cb) {
|
||||
cps.parallel([
|
||||
function(cb) {
|
||||
setTimeout(function() {
|
||||
console.log('3');
|
||||
cb(new Error('kaz'));
|
||||
}, 3000);
|
||||
},
|
||||
function(cb) {
|
||||
setTimeout(function() {
|
||||
console.log('1');
|
||||
cb(null, 'ok');
|
||||
}, 2000);
|
||||
},
|
||||
function(cb) {
|
||||
setTimeout(function() {
|
||||
console.log('2');
|
||||
cb(new Error('foobar'));
|
||||
}, 1000);
|
||||
}
|
||||
], cb);
|
||||
};
|
||||
```
|
||||
|
||||
Running this procedure will yield the following output:
|
||||
|
||||
```text
|
||||
2
|
||||
1
|
||||
3
|
||||
[ { status: 'error', error: [Error: kaz] },
|
||||
{ status: 'ok', data: 'ok' },
|
||||
{ status: 'error', error: [Error: foobar] } ]
|
||||
```
|
||||
|
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
|
||||
};
|
||||
}();
|
30
node_modules/cps/lib/tail.js
generated
vendored
Normal file
30
node_modules/cps/lib/tail.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
var Tail = function() {
|
||||
this._q = [];
|
||||
this._running = false;
|
||||
};
|
||||
|
||||
Tail.prototype = {
|
||||
run: function(fn) {
|
||||
this._q.push(fn);
|
||||
if (!this._running) {
|
||||
this._run();
|
||||
}
|
||||
},
|
||||
|
||||
_run: function() {
|
||||
while(true) {
|
||||
var fn = this._q.shift();
|
||||
if (fn) {
|
||||
this._running = true;
|
||||
fn();
|
||||
} else {
|
||||
this._running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = new Tail();
|
||||
|
56
node_modules/cps/package.json
generated
vendored
Normal file
56
node_modules/cps/package.json
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"_from": "cps@*",
|
||||
"_id": "cps@1.0.2",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-LNCyXYDxCQljfghWrZumNM4E/x0=",
|
||||
"_location": "/cps",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "cps@*",
|
||||
"name": "cps",
|
||||
"escapedName": "cps",
|
||||
"rawSpec": "*",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "*"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/node-mysql"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/cps/-/cps-1.0.2.tgz",
|
||||
"_shasum": "2cd0b25d80f10909637e0856ad9ba634ce04ff1d",
|
||||
"_spec": "cps@*",
|
||||
"_where": "E:\\IntellijProjects\\woam-antispam-bot\\node_modules\\node-mysql",
|
||||
"author": {
|
||||
"name": "Chiyan Chen"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/redblaze/cps/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "A continuation passing style library to help the coding of asynced programs in Javascript/Node.js.",
|
||||
"homepage": "https://github.com/redblaze/cps#readme",
|
||||
"jam": {
|
||||
"main": "lib/cps.js",
|
||||
"include": [
|
||||
"lib/cps.js",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
]
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/redblaze/cps/raw/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"main": "./lib/cps",
|
||||
"name": "cps",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/redblaze/cps.git"
|
||||
},
|
||||
"version": "1.0.2"
|
||||
}
|
51
node_modules/cps/test/fib.js
generated
vendored
Normal file
51
node_modules/cps/test/fib.js
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
var cps = require('../lib/cps.js');
|
||||
|
||||
var alienAdd = function(a, b, cb) {
|
||||
setTimeout(function() {
|
||||
cb(null, a + b);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
var asyncFib = function(n, cb) {
|
||||
if (n < 0) {
|
||||
throw new Error('fib input error');
|
||||
// return cb(new Error('fib input error'));
|
||||
}
|
||||
if (n == 0) {return cb(null, 1);}
|
||||
if (n == 1) {return cb(null, 1);}
|
||||
|
||||
var a = 1,
|
||||
b = 1,
|
||||
i = 2;
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.pwhile(
|
||||
function(cb) {
|
||||
cb(null, i <= n);
|
||||
},
|
||||
function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
alienAdd(a, b, cb);
|
||||
},
|
||||
function(res, cb) {
|
||||
a = b;
|
||||
b = res;
|
||||
alienAdd(i, 1, cb);
|
||||
},
|
||||
function(res, cb) {
|
||||
i = res;
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
},
|
||||
cb
|
||||
);
|
||||
},
|
||||
function(_, cb) {
|
||||
cb(null, b);
|
||||
}
|
||||
], cb);
|
||||
};
|
||||
|
||||
module.exports = asyncFib;
|
417
node_modules/cps/test/test.js
generated
vendored
Normal file
417
node_modules/cps/test/test.js
generated
vendored
Normal file
@ -0,0 +1,417 @@
|
||||
|
||||
var cps = require('../lib/cps.js');
|
||||
var fib = require('./fib');
|
||||
var assert = require("assert");
|
||||
|
||||
describe('cps', function() {
|
||||
describe('seq', function() {
|
||||
it('should return 3 for 1+2', function(cb) {
|
||||
var a, b;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
setTimeout(function() {
|
||||
cb(null, 1);
|
||||
}, 0);
|
||||
},
|
||||
function(_, cb) {
|
||||
a = _;
|
||||
setTimeout(function() {
|
||||
cb(null, 2);
|
||||
}, 0);
|
||||
},
|
||||
function(_, cb) {
|
||||
b = _;
|
||||
cb(null, a + b);
|
||||
},
|
||||
function(_, cb) {
|
||||
assert.equal(_, 3);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pwhile', function() {
|
||||
it('should return 2 for fib(2)', function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
fib(5, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
assert.equal(_, 8);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
|
||||
it('should not fail for huge loops', function(cb) {
|
||||
this.timeout(0);
|
||||
var i;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
i = 0;
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
cps.pwhile(
|
||||
function(cb) {
|
||||
cb(null, i < 10000);
|
||||
},
|
||||
function(cb) {
|
||||
i++;
|
||||
cb();
|
||||
},
|
||||
cb
|
||||
)
|
||||
},
|
||||
'catch': function(e, cb) {
|
||||
console.log('ERROR: ', e);
|
||||
throw e;
|
||||
}
|
||||
}, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
console.log('i is: ', i);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pfor', function() {
|
||||
it('should return 45 for the sum of 0 through 9', function(cb) {
|
||||
var sum = 0;
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.pfor(10, function(i, cb) {
|
||||
setTimeout(function() {
|
||||
sum += i;
|
||||
cb();
|
||||
}, 0);
|
||||
}, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
assert.equal(sum, 45);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('peach', function() {
|
||||
it('should return 55 for the sum of 1 through 10', function(cb) {
|
||||
var sum = 0;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.peach(
|
||||
[1,2,3,4,5,6,7,8,9,10],
|
||||
function(el, cb) {
|
||||
sum += el;
|
||||
cb();
|
||||
},
|
||||
cb
|
||||
);
|
||||
},
|
||||
function(_, cb) {
|
||||
assert.equal(sum, 55);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pmap', function() {
|
||||
it('should return the list of squares of [1..10]', function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.pmap(
|
||||
[1,2,3,4,5,6,7,8,9,10],
|
||||
function(el, cb) {
|
||||
setTimeout(function() {
|
||||
cb(null, el*el);
|
||||
}, 0);
|
||||
},
|
||||
cb
|
||||
);
|
||||
},
|
||||
function(_, cb) {
|
||||
for (var i = 1; i <= 10; i++) {
|
||||
assert.equal(_[i-1], i*i);
|
||||
}
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parallel', function() {
|
||||
it('should work for 3 parallel threads', function(cb) {
|
||||
this.timeout(0);
|
||||
|
||||
var output = [];
|
||||
var start, end;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
start = new Date();
|
||||
|
||||
cps.parallel([
|
||||
function(cb) {
|
||||
setTimeout(function() {
|
||||
output.push(3);
|
||||
cb(new Error('kaz'));
|
||||
}, 3000);
|
||||
},
|
||||
function(cb) {
|
||||
setTimeout(function() {
|
||||
output.push(2);
|
||||
cb(null, 'ok');
|
||||
}, 2000);
|
||||
},
|
||||
function(cb) {
|
||||
setTimeout(function() {
|
||||
output.push(1);
|
||||
cb(new Error('foobar'));
|
||||
}, 1000);
|
||||
}
|
||||
], cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
end = new Date();
|
||||
|
||||
assert(end-start < 3100, 'parallel is taking too long to run');
|
||||
|
||||
for (var i = 1; i <= 3; i++) {
|
||||
assert.equal(output[i-1], i);
|
||||
}
|
||||
|
||||
assert.equal(_[0].status, 'error');
|
||||
assert.equal(_[0].error.message, 'kaz');
|
||||
|
||||
assert.equal(_[1].status, 'ok');
|
||||
assert.equal(_[1].data, 'ok');
|
||||
|
||||
assert.equal(_[2].status, 'error');
|
||||
assert.equal(_[2].error.message, 'foobar');
|
||||
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('noFail', function() {
|
||||
it('should not fail on success', function(cb) {
|
||||
cps.noFail(function(cb) {
|
||||
cb(null, 1);
|
||||
}, cb);
|
||||
});
|
||||
|
||||
it('should not fail on failure', function(cb) {
|
||||
cps.noFail(function(cb) {
|
||||
cb(new Error('foobar'));
|
||||
}, cb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rescue', function() {
|
||||
it('should catch errors', function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(new Error('foobar'));
|
||||
}, 0);
|
||||
},
|
||||
'catch': function(err, cb) {
|
||||
cb(null, 'ok');
|
||||
}
|
||||
}, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
assert.equal(_, 'ok');
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
|
||||
it('should be able to throw errors', function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(new Error('foobar'));
|
||||
}, 0);
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
], function(err, res) {
|
||||
try {
|
||||
assert.equal(err.message, 'foobar');
|
||||
cb();
|
||||
} catch(e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to rethrow errors', function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(new Error('foobar'));
|
||||
}, 0);
|
||||
},
|
||||
'catch': function(err, cb) {
|
||||
throw new Error('kaz');
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
], function(err, res) {
|
||||
try {
|
||||
assert.equal(err.message, 'kaz');
|
||||
cb();
|
||||
} catch(e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should execute finally clause on success', function(cb) {
|
||||
var finallyDone = false;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(null, 'ok');
|
||||
}, 0);
|
||||
},
|
||||
'finally': function(cb) {
|
||||
finallyDone = true;
|
||||
cb();
|
||||
}
|
||||
}, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
assert.equal(_, 'ok');
|
||||
assert(finallyDone);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
|
||||
it('should execute finally clause on exception being caught', function(cb) {
|
||||
var finallyDone = false;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(new Error('foobar'));
|
||||
}, 0);
|
||||
},
|
||||
'catch': function(err, cb) {
|
||||
cb(null, 'exception caught');
|
||||
},
|
||||
'finally': function(cb) {
|
||||
finallyDone = true;
|
||||
cb();
|
||||
}
|
||||
}, cb);
|
||||
},
|
||||
function(_, cb) {
|
||||
assert.equal(_, 'exception caught');
|
||||
assert(finallyDone);
|
||||
cb();
|
||||
}
|
||||
], cb);
|
||||
});
|
||||
|
||||
it('should execute finally clause on exception', function(cb) {
|
||||
var finallyDone = false;
|
||||
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(new Error('foobar'));
|
||||
}, 0);
|
||||
},
|
||||
'finally': function(cb) {
|
||||
finallyDone = true;
|
||||
cb();
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
], function(err, res) {
|
||||
try{
|
||||
assert.equal(err.message, 'foobar');
|
||||
assert(finallyDone);
|
||||
cb();
|
||||
} catch(e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw exception in finally clause on success', function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(null, 'ok');
|
||||
}, 0);
|
||||
},
|
||||
'finally': function(cb) {
|
||||
throw new Error('error in finally');
|
||||
cb();
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
], function(err, res) {
|
||||
try{
|
||||
assert.equal(err.message, 'error in finally');
|
||||
cb();
|
||||
} catch(e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw exception in finally clause on exception', function(cb) {
|
||||
cps.seq([
|
||||
function(_, cb) {
|
||||
cps.rescue({
|
||||
'try': function(cb) {
|
||||
setTimeout(function() {
|
||||
cb(new Error('foobar'));
|
||||
}, 0);
|
||||
},
|
||||
'finally': function(cb) {
|
||||
throw new Error('error in finally');
|
||||
cb();
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
], function(err, res) {
|
||||
try{
|
||||
assert.equal(err.message, 'error in finally');
|
||||
cb();
|
||||
} catch(e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user