UNPKG

2.59 kBJavaScriptView Raw
1/** @license MIT License (c) copyright 2010-2014 original author or authors */
2/** @author Brian Cavalier */
3/** @author John Hann */
4
5(function(define) { 'use strict';
6define(function(require) {
7
8 var when = require('./when');
9 var slice = Array.prototype.slice;
10 var Promise = when.Promise;
11 var reject = Promise.reject;
12
13 /**
14 * Lift a generator to create a function that can suspend and
15 * resume using the `yield` keyword to await promises.
16 * @param {function} generator
17 * @return {function}
18 */
19 function lift(generator) {
20 return function() {
21 return run(generator, this, arguments);
22 };
23 }
24
25 /**
26 * Immediately call a generator as a promise-aware coroutine
27 * that can suspend and resume using the `yield` keyword to
28 * await promises. Additional arguments after the first will
29 * be passed through to the generator.
30 * @param {function} generator
31 * @returns {Promise} promise for the ultimate value returned
32 * from the generator.
33 */
34 function call(generator /*x, y, z...*/) {
35 /*jshint validthis:true*/
36 return run(generator, this, slice.call(arguments, 1));
37 }
38
39 /**
40 * Immediately apply a generator, with the supplied args array,
41 * as a promise-aware coroutine that can suspend and resume
42 * using the `yield` keyword to await promises.
43 * @param {function} generator
44 * @param {Array} args arguments with which to initialize the generator
45 * @returns {Promise} promise for the ultimate value returned
46 * from the generator.
47 */
48 function apply(generator, args) {
49 /*jshint validthis:true*/
50 return run(generator, this, args || []);
51 }
52
53 /**
54 * Helper to initiate the provided generator as a coroutine
55 * @returns {*}
56 */
57 function run(generator, thisArg, args) {
58 return runNext(void 0, generator.apply(thisArg, args));
59 }
60
61 function runNext(x, iterator) {
62 try {
63 return handle(iterator.next(x), iterator);
64 } catch(e) {
65 return reject(e);
66 }
67 }
68
69 function next(x) {
70 /*jshint validthis:true*/
71 return runNext(x, this);
72 }
73
74 function error(e) {
75 /*jshint validthis:true*/
76 try {
77 return handle(this.throw(e), this);
78 } catch(e) {
79 return reject(e);
80 }
81 }
82
83 function handle(result, iterator) {
84 if(result.done) {
85 return result.value;
86 }
87
88 var h = Promise._handler(result.value);
89 if(h.state() > 0) {
90 return runNext(h.value, iterator);
91 }
92
93 var p = Promise._defer();
94 h.chain(p._handler, iterator, next, error);
95 return p;
96 }
97
98 return {
99 lift: lift,
100 call: call,
101 apply: apply
102 };
103
104});
105}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));