| /** @license MIT License (c) copyright 2010-2014 original author or authors */ |
| /** @author Brian Cavalier */ |
| /** @author John Hann */ |
| |
| (function(define) { 'use strict'; |
| define(function(require) { |
| |
| var when = require('./when'); |
| var slice = Array.prototype.slice; |
| var Promise = when.Promise; |
| var reject = Promise.reject; |
| |
| /** |
| * Lift a generator to create a function that can suspend and |
| * resume using the `yield` keyword to await promises. |
| * @param {function} generator |
| * @return {function} |
| */ |
| function lift(generator) { |
| return function() { |
| return run(generator, this, arguments); |
| }; |
| } |
| |
| /** |
| * Immediately call a generator as a promise-aware coroutine |
| * that can suspend and resume using the `yield` keyword to |
| * await promises. Additional arguments after the first will |
| * be passed through to the generator. |
| * @param {function} generator |
| * @returns {Promise} promise for the ultimate value returned |
| * from the generator. |
| */ |
| function call(generator /*x, y, z...*/) { |
| /*jshint validthis:true*/ |
| return run(generator, this, slice.call(arguments, 1)); |
| } |
| |
| /** |
| * Immediately apply a generator, with the supplied args array, |
| * as a promise-aware coroutine that can suspend and resume |
| * using the `yield` keyword to await promises. |
| * @param {function} generator |
| * @param {Array} args arguments with which to initialize the generator |
| * @returns {Promise} promise for the ultimate value returned |
| * from the generator. |
| */ |
| function apply(generator, args) { |
| /*jshint validthis:true*/ |
| return run(generator, this, args || []); |
| } |
| |
| /** |
| * Helper to initiate the provided generator as a coroutine |
| * @returns {*} |
| */ |
| function run(generator, thisArg, args) { |
| return runNext(void 0, generator.apply(thisArg, args)); |
| } |
| |
| function runNext(x, iterator) { |
| try { |
| return handle(iterator.next(x), iterator); |
| } catch(e) { |
| return reject(e); |
| } |
| } |
| |
| function next(x) { |
| /*jshint validthis:true*/ |
| return runNext(x, this); |
| } |
| |
| function error(e) { |
| /*jshint validthis:true*/ |
| try { |
| return handle(this.throw(e), this); |
| } catch(e) { |
| return reject(e); |
| } |
| } |
| |
| function handle(result, iterator) { |
| if(result.done) { |
| return result.value; |
| } |
| |
| var h = Promise._handler(result.value); |
| if(h.state() > 0) { |
| return runNext(h.value, iterator); |
| } |
| |
| var p = Promise._defer(); |
| h.chain(p._handler, iterator, next, error); |
| return p; |
| } |
| |
| return { |
| lift: lift, |
| call: call, |
| apply: apply |
| }; |
| |
| }); |
| }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); |