123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- "use strict";
- module.exports = function(Promise,
- apiRejection,
- INTERNAL,
- tryConvertToPromise) {
- var errors = require("./errors.js");
- var TypeError = errors.TypeError;
- var util = require("./util.js");
- var errorObj = util.errorObj;
- var tryCatch = util.tryCatch;
- var yieldHandlers = [];
- function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
- for (var i = 0; i < yieldHandlers.length; ++i) {
- traceParent._pushContext();
- var result = tryCatch(yieldHandlers[i])(value);
- traceParent._popContext();
- if (result === errorObj) {
- traceParent._pushContext();
- var ret = Promise.reject(errorObj.e);
- traceParent._popContext();
- return ret;
- }
- var maybePromise = tryConvertToPromise(result, traceParent);
- if (maybePromise instanceof Promise) return maybePromise;
- }
- return null;
- }
- function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
- var promise = this._promise = new Promise(INTERNAL);
- promise._captureStackTrace();
- this._stack = stack;
- this._generatorFunction = generatorFunction;
- this._receiver = receiver;
- this._generator = undefined;
- this._yieldHandlers = typeof yieldHandler === "function"
- ? [yieldHandler].concat(yieldHandlers)
- : yieldHandlers;
- }
- PromiseSpawn.prototype.promise = function () {
- return this._promise;
- };
- PromiseSpawn.prototype._run = function () {
- this._generator = this._generatorFunction.call(this._receiver);
- this._receiver =
- this._generatorFunction = undefined;
- this._next(undefined);
- };
- PromiseSpawn.prototype._continue = function (result) {
- if (result === errorObj) {
- return this._promise._rejectCallback(result.e, false, true);
- }
- var value = result.value;
- if (result.done === true) {
- this._promise._resolveCallback(value);
- } else {
- var maybePromise = tryConvertToPromise(value, this._promise);
- if (!(maybePromise instanceof Promise)) {
- maybePromise =
- promiseFromYieldHandler(maybePromise,
- this._yieldHandlers,
- this._promise);
- if (maybePromise === null) {
- this._throw(
- new TypeError(
- "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/4Y4pDk\u000a\u000a".replace("%s", value) +
- "From coroutine:\u000a" +
- this._stack.split("\n").slice(1, -7).join("\n")
- )
- );
- return;
- }
- }
- maybePromise._then(
- this._next,
- this._throw,
- undefined,
- this,
- null
- );
- }
- };
- PromiseSpawn.prototype._throw = function (reason) {
- this._promise._attachExtraTrace(reason);
- this._promise._pushContext();
- var result = tryCatch(this._generator["throw"])
- .call(this._generator, reason);
- this._promise._popContext();
- this._continue(result);
- };
- PromiseSpawn.prototype._next = function (value) {
- this._promise._pushContext();
- var result = tryCatch(this._generator.next).call(this._generator, value);
- this._promise._popContext();
- this._continue(result);
- };
- Promise.coroutine = function (generatorFunction, options) {
- if (typeof generatorFunction !== "function") {
- throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a");
- }
- var yieldHandler = Object(options).yieldHandler;
- var PromiseSpawn$ = PromiseSpawn;
- var stack = new Error().stack;
- return function () {
- var generator = generatorFunction.apply(this, arguments);
- var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
- stack);
- spawn._generator = generator;
- spawn._next(undefined);
- return spawn.promise();
- };
- };
- Promise.coroutine.addYieldHandler = function(fn) {
- if (typeof fn !== "function") throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a");
- yieldHandlers.push(fn);
- };
- Promise.spawn = function (generatorFunction) {
- if (typeof generatorFunction !== "function") {
- return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a");
- }
- var spawn = new PromiseSpawn(generatorFunction, this);
- var ret = spawn.promise();
- spawn._run(Promise.spawn);
- return ret;
- };
- };
|