twitst4tz

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

using.js (7525B)


      1 "use strict";
      2 module.exports = function (Promise, apiRejection, tryConvertToPromise,
      3     createContext, INTERNAL, debug) {
      4     var util = require("./util");
      5     var TypeError = require("./errors").TypeError;
      6     var inherits = require("./util").inherits;
      7     var errorObj = util.errorObj;
      8     var tryCatch = util.tryCatch;
      9     var NULL = {};
     10 
     11     function thrower(e) {
     12         setTimeout(function(){throw e;}, 0);
     13     }
     14 
     15     function castPreservingDisposable(thenable) {
     16         var maybePromise = tryConvertToPromise(thenable);
     17         if (maybePromise !== thenable &&
     18             typeof thenable._isDisposable === "function" &&
     19             typeof thenable._getDisposer === "function" &&
     20             thenable._isDisposable()) {
     21             maybePromise._setDisposable(thenable._getDisposer());
     22         }
     23         return maybePromise;
     24     }
     25     function dispose(resources, inspection) {
     26         var i = 0;
     27         var len = resources.length;
     28         var ret = new Promise(INTERNAL);
     29         function iterator() {
     30             if (i >= len) return ret._fulfill();
     31             var maybePromise = castPreservingDisposable(resources[i++]);
     32             if (maybePromise instanceof Promise &&
     33                 maybePromise._isDisposable()) {
     34                 try {
     35                     maybePromise = tryConvertToPromise(
     36                         maybePromise._getDisposer().tryDispose(inspection),
     37                         resources.promise);
     38                 } catch (e) {
     39                     return thrower(e);
     40                 }
     41                 if (maybePromise instanceof Promise) {
     42                     return maybePromise._then(iterator, thrower,
     43                                               null, null, null);
     44                 }
     45             }
     46             iterator();
     47         }
     48         iterator();
     49         return ret;
     50     }
     51 
     52     function Disposer(data, promise, context) {
     53         this._data = data;
     54         this._promise = promise;
     55         this._context = context;
     56     }
     57 
     58     Disposer.prototype.data = function () {
     59         return this._data;
     60     };
     61 
     62     Disposer.prototype.promise = function () {
     63         return this._promise;
     64     };
     65 
     66     Disposer.prototype.resource = function () {
     67         if (this.promise().isFulfilled()) {
     68             return this.promise().value();
     69         }
     70         return NULL;
     71     };
     72 
     73     Disposer.prototype.tryDispose = function(inspection) {
     74         var resource = this.resource();
     75         var context = this._context;
     76         if (context !== undefined) context._pushContext();
     77         var ret = resource !== NULL
     78             ? this.doDispose(resource, inspection) : null;
     79         if (context !== undefined) context._popContext();
     80         this._promise._unsetDisposable();
     81         this._data = null;
     82         return ret;
     83     };
     84 
     85     Disposer.isDisposer = function (d) {
     86         return (d != null &&
     87                 typeof d.resource === "function" &&
     88                 typeof d.tryDispose === "function");
     89     };
     90 
     91     function FunctionDisposer(fn, promise, context) {
     92         this.constructor$(fn, promise, context);
     93     }
     94     inherits(FunctionDisposer, Disposer);
     95 
     96     FunctionDisposer.prototype.doDispose = function (resource, inspection) {
     97         var fn = this.data();
     98         return fn.call(resource, resource, inspection);
     99     };
    100 
    101     function maybeUnwrapDisposer(value) {
    102         if (Disposer.isDisposer(value)) {
    103             this.resources[this.index]._setDisposable(value);
    104             return value.promise();
    105         }
    106         return value;
    107     }
    108 
    109     function ResourceList(length) {
    110         this.length = length;
    111         this.promise = null;
    112         this[length-1] = null;
    113     }
    114 
    115     ResourceList.prototype._resultCancelled = function() {
    116         var len = this.length;
    117         for (var i = 0; i < len; ++i) {
    118             var item = this[i];
    119             if (item instanceof Promise) {
    120                 item.cancel();
    121             }
    122         }
    123     };
    124 
    125     Promise.using = function () {
    126         var len = arguments.length;
    127         if (len < 2) return apiRejection(
    128                         "you must pass at least 2 arguments to Promise.using");
    129         var fn = arguments[len - 1];
    130         if (typeof fn !== "function") {
    131             return apiRejection("expecting a function but got " + util.classString(fn));
    132         }
    133         var input;
    134         var spreadArgs = true;
    135         if (len === 2 && Array.isArray(arguments[0])) {
    136             input = arguments[0];
    137             len = input.length;
    138             spreadArgs = false;
    139         } else {
    140             input = arguments;
    141             len--;
    142         }
    143         var resources = new ResourceList(len);
    144         for (var i = 0; i < len; ++i) {
    145             var resource = input[i];
    146             if (Disposer.isDisposer(resource)) {
    147                 var disposer = resource;
    148                 resource = resource.promise();
    149                 resource._setDisposable(disposer);
    150             } else {
    151                 var maybePromise = tryConvertToPromise(resource);
    152                 if (maybePromise instanceof Promise) {
    153                     resource =
    154                         maybePromise._then(maybeUnwrapDisposer, null, null, {
    155                             resources: resources,
    156                             index: i
    157                     }, undefined);
    158                 }
    159             }
    160             resources[i] = resource;
    161         }
    162 
    163         var reflectedResources = new Array(resources.length);
    164         for (var i = 0; i < reflectedResources.length; ++i) {
    165             reflectedResources[i] = Promise.resolve(resources[i]).reflect();
    166         }
    167 
    168         var resultPromise = Promise.all(reflectedResources)
    169             .then(function(inspections) {
    170                 for (var i = 0; i < inspections.length; ++i) {
    171                     var inspection = inspections[i];
    172                     if (inspection.isRejected()) {
    173                         errorObj.e = inspection.error();
    174                         return errorObj;
    175                     } else if (!inspection.isFulfilled()) {
    176                         resultPromise.cancel();
    177                         return;
    178                     }
    179                     inspections[i] = inspection.value();
    180                 }
    181                 promise._pushContext();
    182 
    183                 fn = tryCatch(fn);
    184                 var ret = spreadArgs
    185                     ? fn.apply(undefined, inspections) : fn(inspections);
    186                 var promiseCreated = promise._popContext();
    187                 debug.checkForgottenReturns(
    188                     ret, promiseCreated, "Promise.using", promise);
    189                 return ret;
    190             });
    191 
    192         var promise = resultPromise.lastly(function() {
    193             var inspection = new Promise.PromiseInspection(resultPromise);
    194             return dispose(resources, inspection);
    195         });
    196         resources.promise = promise;
    197         promise._setOnCancel(resources);
    198         return promise;
    199     };
    200 
    201     Promise.prototype._setDisposable = function (disposer) {
    202         this._bitField = this._bitField | 131072;
    203         this._disposer = disposer;
    204     };
    205 
    206     Promise.prototype._isDisposable = function () {
    207         return (this._bitField & 131072) > 0;
    208     };
    209 
    210     Promise.prototype._getDisposer = function () {
    211         return this._disposer;
    212     };
    213 
    214     Promise.prototype._unsetDisposable = function () {
    215         this._bitField = this._bitField & (~131072);
    216         this._disposer = undefined;
    217     };
    218 
    219     Promise.prototype.disposer = function (fn) {
    220         if (typeof fn === "function") {
    221             return new FunctionDisposer(fn, this, createContext());
    222         }
    223         throw new TypeError();
    224     };
    225 
    226 };