twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

generators.js (7761B)


      1 "use strict";
      2 module.exports = function(Promise,
      3                           apiRejection,
      4                           INTERNAL,
      5                           tryConvertToPromise,
      6                           Proxyable,
      7                           debug) {
      8 var errors = require("./errors");
      9 var TypeError = errors.TypeError;
     10 var util = require("./util");
     11 var errorObj = util.errorObj;
     12 var tryCatch = util.tryCatch;
     13 var yieldHandlers = [];
     14 
     15 function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
     16     for (var i = 0; i < yieldHandlers.length; ++i) {
     17         traceParent._pushContext();
     18         var result = tryCatch(yieldHandlers[i])(value);
     19         traceParent._popContext();
     20         if (result === errorObj) {
     21             traceParent._pushContext();
     22             var ret = Promise.reject(errorObj.e);
     23             traceParent._popContext();
     24             return ret;
     25         }
     26         var maybePromise = tryConvertToPromise(result, traceParent);
     27         if (maybePromise instanceof Promise) return maybePromise;
     28     }
     29     return null;
     30 }
     31 
     32 function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
     33     if (debug.cancellation()) {
     34         var internal = new Promise(INTERNAL);
     35         var _finallyPromise = this._finallyPromise = new Promise(INTERNAL);
     36         this._promise = internal.lastly(function() {
     37             return _finallyPromise;
     38         });
     39         internal._captureStackTrace();
     40         internal._setOnCancel(this);
     41     } else {
     42         var promise = this._promise = new Promise(INTERNAL);
     43         promise._captureStackTrace();
     44     }
     45     this._stack = stack;
     46     this._generatorFunction = generatorFunction;
     47     this._receiver = receiver;
     48     this._generator = undefined;
     49     this._yieldHandlers = typeof yieldHandler === "function"
     50         ? [yieldHandler].concat(yieldHandlers)
     51         : yieldHandlers;
     52     this._yieldedPromise = null;
     53     this._cancellationPhase = false;
     54 }
     55 util.inherits(PromiseSpawn, Proxyable);
     56 
     57 PromiseSpawn.prototype._isResolved = function() {
     58     return this._promise === null;
     59 };
     60 
     61 PromiseSpawn.prototype._cleanup = function() {
     62     this._promise = this._generator = null;
     63     if (debug.cancellation() && this._finallyPromise !== null) {
     64         this._finallyPromise._fulfill();
     65         this._finallyPromise = null;
     66     }
     67 };
     68 
     69 PromiseSpawn.prototype._promiseCancelled = function() {
     70     if (this._isResolved()) return;
     71     var implementsReturn = typeof this._generator["return"] !== "undefined";
     72 
     73     var result;
     74     if (!implementsReturn) {
     75         var reason = new Promise.CancellationError(
     76             "generator .return() sentinel");
     77         Promise.coroutine.returnSentinel = reason;
     78         this._promise._attachExtraTrace(reason);
     79         this._promise._pushContext();
     80         result = tryCatch(this._generator["throw"]).call(this._generator,
     81                                                          reason);
     82         this._promise._popContext();
     83     } else {
     84         this._promise._pushContext();
     85         result = tryCatch(this._generator["return"]).call(this._generator,
     86                                                           undefined);
     87         this._promise._popContext();
     88     }
     89     this._cancellationPhase = true;
     90     this._yieldedPromise = null;
     91     this._continue(result);
     92 };
     93 
     94 PromiseSpawn.prototype._promiseFulfilled = function(value) {
     95     this._yieldedPromise = null;
     96     this._promise._pushContext();
     97     var result = tryCatch(this._generator.next).call(this._generator, value);
     98     this._promise._popContext();
     99     this._continue(result);
    100 };
    101 
    102 PromiseSpawn.prototype._promiseRejected = function(reason) {
    103     this._yieldedPromise = null;
    104     this._promise._attachExtraTrace(reason);
    105     this._promise._pushContext();
    106     var result = tryCatch(this._generator["throw"])
    107         .call(this._generator, reason);
    108     this._promise._popContext();
    109     this._continue(result);
    110 };
    111 
    112 PromiseSpawn.prototype._resultCancelled = function() {
    113     if (this._yieldedPromise instanceof Promise) {
    114         var promise = this._yieldedPromise;
    115         this._yieldedPromise = null;
    116         promise.cancel();
    117     }
    118 };
    119 
    120 PromiseSpawn.prototype.promise = function () {
    121     return this._promise;
    122 };
    123 
    124 PromiseSpawn.prototype._run = function () {
    125     this._generator = this._generatorFunction.call(this._receiver);
    126     this._receiver =
    127         this._generatorFunction = undefined;
    128     this._promiseFulfilled(undefined);
    129 };
    130 
    131 PromiseSpawn.prototype._continue = function (result) {
    132     var promise = this._promise;
    133     if (result === errorObj) {
    134         this._cleanup();
    135         if (this._cancellationPhase) {
    136             return promise.cancel();
    137         } else {
    138             return promise._rejectCallback(result.e, false);
    139         }
    140     }
    141 
    142     var value = result.value;
    143     if (result.done === true) {
    144         this._cleanup();
    145         if (this._cancellationPhase) {
    146             return promise.cancel();
    147         } else {
    148             return promise._resolveCallback(value);
    149         }
    150     } else {
    151         var maybePromise = tryConvertToPromise(value, this._promise);
    152         if (!(maybePromise instanceof Promise)) {
    153             maybePromise =
    154                 promiseFromYieldHandler(maybePromise,
    155                                         this._yieldHandlers,
    156                                         this._promise);
    157             if (maybePromise === null) {
    158                 this._promiseRejected(
    159                     new TypeError(
    160                         "A value %s was yielded that could not be treated as a promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", String(value)) +
    161                         "From coroutine:\u000a" +
    162                         this._stack.split("\n").slice(1, -7).join("\n")
    163                     )
    164                 );
    165                 return;
    166             }
    167         }
    168         maybePromise = maybePromise._target();
    169         var bitField = maybePromise._bitField;
    170         ;
    171         if (((bitField & 50397184) === 0)) {
    172             this._yieldedPromise = maybePromise;
    173             maybePromise._proxy(this, null);
    174         } else if (((bitField & 33554432) !== 0)) {
    175             Promise._async.invoke(
    176                 this._promiseFulfilled, this, maybePromise._value()
    177             );
    178         } else if (((bitField & 16777216) !== 0)) {
    179             Promise._async.invoke(
    180                 this._promiseRejected, this, maybePromise._reason()
    181             );
    182         } else {
    183             this._promiseCancelled();
    184         }
    185     }
    186 };
    187 
    188 Promise.coroutine = function (generatorFunction, options) {
    189     if (typeof generatorFunction !== "function") {
    190         throw new TypeError("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    191     }
    192     var yieldHandler = Object(options).yieldHandler;
    193     var PromiseSpawn$ = PromiseSpawn;
    194     var stack = new Error().stack;
    195     return function () {
    196         var generator = generatorFunction.apply(this, arguments);
    197         var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
    198                                       stack);
    199         var ret = spawn.promise();
    200         spawn._generator = generator;
    201         spawn._promiseFulfilled(undefined);
    202         return ret;
    203     };
    204 };
    205 
    206 Promise.coroutine.addYieldHandler = function(fn) {
    207     if (typeof fn !== "function") {
    208         throw new TypeError("expecting a function but got " + util.classString(fn));
    209     }
    210     yieldHandlers.push(fn);
    211 };
    212 
    213 Promise.spawn = function (generatorFunction) {
    214     debug.deprecated("Promise.spawn()", "Promise.coroutine()");
    215     if (typeof generatorFunction !== "function") {
    216         return apiRejection("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    217     }
    218     var spawn = new PromiseSpawn(generatorFunction, this);
    219     var ret = spawn.promise();
    220     spawn._run(Promise.spawn);
    221     return ret;
    222 };
    223 };