UNPKG

axos

Version:

JIT-friendly, multiparadigm asynchronous programming

217 lines (198 loc) 5.82 kB
(function() { var CATCH, Cell, FINAL_ERROR, FINAL_VALUE, NO_MORE, Promise, Strategy, TRY, TRY1, axos, empty, getThen, io_send, promiseResolver, ref, runInitializer, send; ref = axos = require('./'), Cell = ref.Cell, Strategy = ref.Strategy, NO_MORE = ref.NO_MORE, FINAL_VALUE = ref.FINAL_VALUE, FINAL_ERROR = ref.FINAL_ERROR, TRY = ref.TRY, CATCH = ref.CATCH, send = ref.send, io_send = ref.io_send; empty = new Strategy(); Cell.prototype.then = function(onF, onR) { return promiseResolver.cell(this, onF, onR); }; module.exports = axos.Promise = Promise = (function() { var arrayResolver; function Promise(init) { if (init == null) { init = empty.cell(); } if (init instanceof Cell) { this.__cell__ = init; } else if (typeof init === "function") { runInitializer(init, null, this.__cell__ = empty.cell(), 1); } else { throw new TypeError("Promise must be created from cell or function"); } } Promise.prototype.then = function(onF, onR) { return new Promise(promiseResolver.cell(this.__cell__, onF, onR)); }; Promise.deferred = function() { var d; d = {}; d.promise = empty.cell(); runInitializer((function(res, rej) { d.resolve = res; return d.reject = rej; }), null, d.promise, 1); return d; }; Promise.promisify = function(fn) { return function() { var a, args, cell, i, j, len; cell = empty.cell(); args = Array(arguments.length + 1); for (i = j = 0, len = arguments.length; j < len; i = ++j) { a = arguments[i]; args[i] = a; } args[arguments.length] = function(e, v) { if (e) { return send(cell, 1, FINAL_ERROR, e); } else { return send(cell, 1, FINAL_VALUE, v); } }; fn.apply(this, args); return cell; }; }; Promise.prototype["catch"] = function(onR) { return this.then(null, onR); }; Promise.all = function(promises) { return new arrayResolver.cell(promises).state; }; arrayResolver = new Strategy({ onDispose: function() { return this.seen = this.result = null; }, initState: function(promises) { var i, j, len, p, state; state = new Promise(this); state.seen = new Array(state.pending = promises.length); state.result = new Array(state.pending); for (i = j = 0, len = promises.length; j < len; i = ++j) { p = promises[i]; p.__cell__.addSink(this, i); } return state; }, onReceive: function(cell, tag, op, arg) { if (!this.seen[tag]) { if (op.isError) { return cell.abort(arg); } this.seen[tag] = true; this.result[tag] = arg; if (!--this.pending) { return cell.finish(this.result); } } return NO_MORE; } }); return Promise; })(); promiseResolver = new Strategy({ onReceive: function(cell, tag, op, arg) { var ref1, ref2, thenF; if (typeof tag === "function") { if (op.isError) { return cell.abort(arg); } arg = TRY1(tag, arg); if (arg === CATCH) { return cell.abort(CATCH.err); } op = FINAL_VALUE; } else if (typeof tag === "object") { tag = op.isError ? tag.onR : tag.onF; if (typeof tag === "function") { arg = TRY1(tag, arg); if (arg === CATCH) { return cell.abort(CATCH.err); } op = FINAL_VALUE; } } if (op.isError) { return cell.abort(arg); } if (arg instanceof Promise) { arg = arg.__cell__; } while (arg instanceof Cell) { if (arg === cell) { return cell.abort(new TypeError("Can't resolve promise to itself")); } else { if (arg.op == null) { arg.addSink(cell, 0); return NO_MORE; } ref1 = arg, op = ref1.op, arg = ref1.arg; if (op.isError) { return cell.abort(arg); } if (arg instanceof Promise) { arg = arg.__cell__; } } } if (((ref2 = typeof arg) === "object" || ref2 === "function") && arg !== null) { if ((thenF = TRY1(getThen, arg)) === CATCH) { return cell.abort(CATCH.err); } if (typeof thenF === "function") { runInitializer(thenF, arg, cell, 0); return NO_MORE; } } return cell.finish(arg); }, initState: function(other, onF, onR) { var tag; if (other instanceof Cell) { if (typeof onR !== "function") { if (typeof onF !== "function") { tag = 0; } else { tag = onF; } } else { tag = { onF: onF, onR: onR }; } other.addSink(this, tag); } } }); getThen = function(x) { return x.then; }; runInitializer = function(init, rcv, cell, step) { var reject, resolve; resolve = function(v) { if (cell !== null) { send(cell, step, FINAL_VALUE, v); return cell = null; } }; reject = function(e) { if (cell !== null) { send(cell, step, FINAL_ERROR, e); return cell = null; } }; if (TRY(init).call(rcv, resolve, reject) === CATCH && cell !== null) { cell.abort(CATCH.err); } }; TRY1 = function(cb, arg) { var e; try { return cb(arg); } catch (_error) { e = _error; CATCH.err = e; return CATCH; } }; }).call(this);