| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 | "use strict";module.exports = function (Promise, apiRejection, tryConvertToPromise,    createContext, INTERNAL, debug) {    var util = require("./util");    var TypeError = require("./errors").TypeError;    var inherits = require("./util").inherits;    var errorObj = util.errorObj;    var tryCatch = util.tryCatch;    var NULL = {};    function thrower(e) {        setTimeout(function(){throw e;}, 0);    }    function castPreservingDisposable(thenable) {        var maybePromise = tryConvertToPromise(thenable);        if (maybePromise !== thenable &&            typeof thenable._isDisposable === "function" &&            typeof thenable._getDisposer === "function" &&            thenable._isDisposable()) {            maybePromise._setDisposable(thenable._getDisposer());        }        return maybePromise;    }    function dispose(resources, inspection) {        var i = 0;        var len = resources.length;        var ret = new Promise(INTERNAL);        function iterator() {            if (i >= len) return ret._fulfill();            var maybePromise = castPreservingDisposable(resources[i++]);            if (maybePromise instanceof Promise &&                maybePromise._isDisposable()) {                try {                    maybePromise = tryConvertToPromise(                        maybePromise._getDisposer().tryDispose(inspection),                        resources.promise);                } catch (e) {                    return thrower(e);                }                if (maybePromise instanceof Promise) {                    return maybePromise._then(iterator, thrower,                                              null, null, null);                }            }            iterator();        }        iterator();        return ret;    }    function Disposer(data, promise, context) {        this._data = data;        this._promise = promise;        this._context = context;    }    Disposer.prototype.data = function () {        return this._data;    };    Disposer.prototype.promise = function () {        return this._promise;    };    Disposer.prototype.resource = function () {        if (this.promise().isFulfilled()) {            return this.promise().value();        }        return NULL;    };    Disposer.prototype.tryDispose = function(inspection) {        var resource = this.resource();        var context = this._context;        if (context !== undefined) context._pushContext();        var ret = resource !== NULL            ? this.doDispose(resource, inspection) : null;        if (context !== undefined) context._popContext();        this._promise._unsetDisposable();        this._data = null;        return ret;    };    Disposer.isDisposer = function (d) {        return (d != null &&                typeof d.resource === "function" &&                typeof d.tryDispose === "function");    };    function FunctionDisposer(fn, promise, context) {        this.constructor$(fn, promise, context);    }    inherits(FunctionDisposer, Disposer);    FunctionDisposer.prototype.doDispose = function (resource, inspection) {        var fn = this.data();        return fn.call(resource, resource, inspection);    };    function maybeUnwrapDisposer(value) {        if (Disposer.isDisposer(value)) {            this.resources[this.index]._setDisposable(value);            return value.promise();        }        return value;    }    function ResourceList(length) {        this.length = length;        this.promise = null;        this[length-1] = null;    }    ResourceList.prototype._resultCancelled = function() {        var len = this.length;        for (var i = 0; i < len; ++i) {            var item = this[i];            if (item instanceof Promise) {                item.cancel();            }        }    };    Promise.using = function () {        var len = arguments.length;        if (len < 2) return apiRejection(                        "you must pass at least 2 arguments to Promise.using");        var fn = arguments[len - 1];        if (typeof fn !== "function") {            return apiRejection("expecting a function but got " + util.classString(fn));        }        var input;        var spreadArgs = true;        if (len === 2 && Array.isArray(arguments[0])) {            input = arguments[0];            len = input.length;            spreadArgs = false;        } else {            input = arguments;            len--;        }        var resources = new ResourceList(len);        for (var i = 0; i < len; ++i) {            var resource = input[i];            if (Disposer.isDisposer(resource)) {                var disposer = resource;                resource = resource.promise();                resource._setDisposable(disposer);            } else {                var maybePromise = tryConvertToPromise(resource);                if (maybePromise instanceof Promise) {                    resource =                        maybePromise._then(maybeUnwrapDisposer, null, null, {                            resources: resources,                            index: i                    }, undefined);                }            }            resources[i] = resource;        }        var reflectedResources = new Array(resources.length);        for (var i = 0; i < reflectedResources.length; ++i) {            reflectedResources[i] = Promise.resolve(resources[i]).reflect();        }        var resultPromise = Promise.all(reflectedResources)            .then(function(inspections) {                for (var i = 0; i < inspections.length; ++i) {                    var inspection = inspections[i];                    if (inspection.isRejected()) {                        errorObj.e = inspection.error();                        return errorObj;                    } else if (!inspection.isFulfilled()) {                        resultPromise.cancel();                        return;                    }                    inspections[i] = inspection.value();                }                promise._pushContext();                fn = tryCatch(fn);                var ret = spreadArgs                    ? fn.apply(undefined, inspections) : fn(inspections);                var promiseCreated = promise._popContext();                debug.checkForgottenReturns(                    ret, promiseCreated, "Promise.using", promise);                return ret;            });        var promise = resultPromise.lastly(function() {            var inspection = new Promise.PromiseInspection(resultPromise);            return dispose(resources, inspection);        });        resources.promise = promise;        promise._setOnCancel(resources);        return promise;    };    Promise.prototype._setDisposable = function (disposer) {        this._bitField = this._bitField | 131072;        this._disposer = disposer;    };    Promise.prototype._isDisposable = function () {        return (this._bitField & 131072) > 0;    };    Promise.prototype._getDisposer = function () {        return this._disposer;    };    Promise.prototype._unsetDisposable = function () {        this._bitField = this._bitField & (~131072);        this._disposer = undefined;    };    Promise.prototype.disposer = function (fn) {        if (typeof fn === "function") {            return new FunctionDisposer(fn, this, createContext());        }        throw new TypeError();    };};
 |