2 module.exports = function(Promise,
6 var errors = require("./errors.js");
7 var TypeError = errors.TypeError;
8 var util = require("./util.js");
9 var errorObj = util.errorObj;
10 var tryCatch = util.tryCatch;
11 var yieldHandlers = [];
13 function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
14 for (var i = 0; i < yieldHandlers.length; ++i) {
15 traceParent._pushContext();
16 var result = tryCatch(yieldHandlers[i])(value);
17 traceParent._popContext();
18 if (result === errorObj) {
19 traceParent._pushContext();
20 var ret = Promise.reject(errorObj.e);
21 traceParent._popContext();
24 var maybePromise = tryConvertToPromise(result, traceParent);
25 if (maybePromise instanceof Promise) return maybePromise;
30 function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
31 var promise = this._promise = new Promise(INTERNAL);
32 promise._captureStackTrace();
34 this._generatorFunction = generatorFunction;
35 this._receiver = receiver;
36 this._generator = undefined;
37 this._yieldHandlers = typeof yieldHandler === "function"
38 ? [yieldHandler].concat(yieldHandlers)
42 PromiseSpawn.prototype.promise = function () {
46 PromiseSpawn.prototype._run = function () {
47 this._generator = this._generatorFunction.call(this._receiver);
49 this._generatorFunction = undefined;
50 this._next(undefined);
53 PromiseSpawn.prototype._continue = function (result) {
54 if (result === errorObj) {
55 return this._promise._rejectCallback(result.e, false, true);
58 var value = result.value;
59 if (result.done === true) {
60 this._promise._resolveCallback(value);
62 var maybePromise = tryConvertToPromise(value, this._promise);
63 if (!(maybePromise instanceof Promise)) {
65 promiseFromYieldHandler(maybePromise,
68 if (maybePromise === null) {
71 "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) +
72 "From coroutine:\u000a" +
73 this._stack.split("\n").slice(1, -7).join("\n")
89 PromiseSpawn.prototype._throw = function (reason) {
90 this._promise._attachExtraTrace(reason);
91 this._promise._pushContext();
92 var result = tryCatch(this._generator["throw"])
93 .call(this._generator, reason);
94 this._promise._popContext();
95 this._continue(result);
98 PromiseSpawn.prototype._next = function (value) {
99 this._promise._pushContext();
100 var result = tryCatch(this._generator.next).call(this._generator, value);
101 this._promise._popContext();
102 this._continue(result);
105 Promise.coroutine = function (generatorFunction, options) {
106 if (typeof generatorFunction !== "function") {
107 throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a");
109 var yieldHandler = Object(options).yieldHandler;
110 var PromiseSpawn$ = PromiseSpawn;
111 var stack = new Error().stack;
113 var generator = generatorFunction.apply(this, arguments);
114 var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
116 spawn._generator = generator;
117 spawn._next(undefined);
118 return spawn.promise();
122 Promise.coroutine.addYieldHandler = function(fn) {
123 if (typeof fn !== "function") throw new TypeError("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a");
124 yieldHandlers.push(fn);
127 Promise.spawn = function (generatorFunction) {
128 if (typeof generatorFunction !== "function") {
129 return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/6Vqhm0\u000a");
131 var spawn = new PromiseSpawn(generatorFunction, this);
132 var ret = spawn.promise();
133 spawn._run(Promise.spawn);