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;
11 setTimeout(function(){throw e;}, 0);
14 function castPreservingDisposable(thenable) {
15 var maybePromise = tryConvertToPromise(thenable);
16 if (maybePromise !== thenable &&
17 typeof thenable._isDisposable === "function" &&
18 typeof thenable._getDisposer === "function" &&
19 thenable._isDisposable()) {
20 maybePromise._setDisposable(thenable._getDisposer());
24 function dispose(resources, inspection) {
26 var len = resources.length;
27 var ret = new Promise(INTERNAL);
29 if (i >= len) return ret._fulfill();
30 var maybePromise = castPreservingDisposable(resources[i++]);
31 if (maybePromise instanceof Promise &&
32 maybePromise._isDisposable()) {
34 maybePromise = tryConvertToPromise(
35 maybePromise._getDisposer().tryDispose(inspection),
40 if (maybePromise instanceof Promise) {
41 return maybePromise._then(iterator, thrower,
51 function Disposer(data, promise, context) {
53 this._promise = promise;
54 this._context = context;
57 Disposer.prototype.data = function () {
61 Disposer.prototype.promise = function () {
65 Disposer.prototype.resource = function () {
66 if (this.promise().isFulfilled()) {
67 return this.promise().value();
72 Disposer.prototype.tryDispose = function(inspection) {
73 var resource = this.resource();
74 var context = this._context;
75 if (context !== undefined) context._pushContext();
76 var ret = resource !== null
77 ? this.doDispose(resource, inspection) : null;
78 if (context !== undefined) context._popContext();
79 this._promise._unsetDisposable();
84 Disposer.isDisposer = function (d) {
86 typeof d.resource === "function" &&
87 typeof d.tryDispose === "function");
90 function FunctionDisposer(fn, promise, context) {
91 this.constructor$(fn, promise, context);
93 inherits(FunctionDisposer, Disposer);
95 FunctionDisposer.prototype.doDispose = function (resource, inspection) {
97 return fn.call(resource, resource, inspection);
100 function maybeUnwrapDisposer(value) {
101 if (Disposer.isDisposer(value)) {
102 this.resources[this.index]._setDisposable(value);
103 return value.promise();
108 function ResourceList(length) {
109 this.length = length;
111 this[length-1] = null;
114 ResourceList.prototype._resultCancelled = function() {
115 var len = this.length;
116 for (var i = 0; i < len; ++i) {
118 if (item instanceof Promise) {
124 Promise.using = function () {
125 var len = arguments.length;
126 if (len < 2) return apiRejection(
127 "you must pass at least 2 arguments to Promise.using");
128 var fn = arguments[len - 1];
129 if (typeof fn !== "function") {
130 return apiRejection("expecting a function but got " + util.classString(fn));
133 var spreadArgs = true;
134 if (len === 2 && Array.isArray(arguments[0])) {
135 input = arguments[0];
142 var resources = new ResourceList(len);
143 for (var i = 0; i < len; ++i) {
144 var resource = input[i];
145 if (Disposer.isDisposer(resource)) {
146 var disposer = resource;
147 resource = resource.promise();
148 resource._setDisposable(disposer);
150 var maybePromise = tryConvertToPromise(resource);
151 if (maybePromise instanceof Promise) {
153 maybePromise._then(maybeUnwrapDisposer, null, null, {
154 resources: resources,
159 resources[i] = resource;
162 var reflectedResources = new Array(resources.length);
163 for (var i = 0; i < reflectedResources.length; ++i) {
164 reflectedResources[i] = Promise.resolve(resources[i]).reflect();
167 var resultPromise = Promise.all(reflectedResources)
168 .then(function(inspections) {
169 for (var i = 0; i < inspections.length; ++i) {
170 var inspection = inspections[i];
171 if (inspection.isRejected()) {
172 errorObj.e = inspection.error();
174 } else if (!inspection.isFulfilled()) {
175 resultPromise.cancel();
178 inspections[i] = inspection.value();
180 promise._pushContext();
184 ? fn.apply(undefined, inspections) : fn(inspections);
185 var promiseCreated = promise._popContext();
186 debug.checkForgottenReturns(
187 ret, promiseCreated, "Promise.using", promise);
191 var promise = resultPromise.lastly(function() {
192 var inspection = new Promise.PromiseInspection(resultPromise);
193 return dispose(resources, inspection);
195 resources.promise = promise;
196 promise._setOnCancel(resources);
200 Promise.prototype._setDisposable = function (disposer) {
201 this._bitField = this._bitField | 131072;
202 this._disposer = disposer;
205 Promise.prototype._isDisposable = function () {
206 return (this._bitField & 131072) > 0;
209 Promise.prototype._getDisposer = function () {
210 return this._disposer;
213 Promise.prototype._unsetDisposable = function () {
214 this._bitField = this._bitField & (~131072);
215 this._disposer = undefined;
218 Promise.prototype.disposer = function (fn) {
219 if (typeof fn === "function") {
220 return new FunctionDisposer(fn, this, createContext());
222 throw new TypeError();