2 module.exports = function (Promise, apiRejection, tryConvertToPromise,
4 var TypeError = require("./errors.js").TypeError;
5 var inherits = require("./util.js").inherits;
6 var PromiseInspection = Promise.PromiseInspection;
8 function inspectionMapper(inspections) {
9 var len = inspections.length;
10 for (var i = 0; i < len; ++i) {
11 var inspection = inspections[i];
12 if (inspection.isRejected()) {
13 return Promise.reject(inspection.error());
15 inspections[i] = inspection._settledValue;
21 setTimeout(function(){throw e;}, 0);
24 function castPreservingDisposable(thenable) {
25 var maybePromise = tryConvertToPromise(thenable);
26 if (maybePromise !== thenable &&
27 typeof thenable._isDisposable === "function" &&
28 typeof thenable._getDisposer === "function" &&
29 thenable._isDisposable()) {
30 maybePromise._setDisposable(thenable._getDisposer());
34 function dispose(resources, inspection) {
36 var len = resources.length;
37 var ret = Promise.defer();
39 if (i >= len) return ret.resolve();
40 var maybePromise = castPreservingDisposable(resources[i++]);
41 if (maybePromise instanceof Promise &&
42 maybePromise._isDisposable()) {
44 maybePromise = tryConvertToPromise(
45 maybePromise._getDisposer().tryDispose(inspection),
50 if (maybePromise instanceof Promise) {
51 return maybePromise._then(iterator, thrower,
61 function disposerSuccess(value) {
62 var inspection = new PromiseInspection();
63 inspection._settledValue = value;
64 inspection._bitField = 268435456;
65 return dispose(this, inspection).thenReturn(value);
68 function disposerFail(reason) {
69 var inspection = new PromiseInspection();
70 inspection._settledValue = reason;
71 inspection._bitField = 134217728;
72 return dispose(this, inspection).thenThrow(reason);
75 function Disposer(data, promise, context) {
77 this._promise = promise;
78 this._context = context;
81 Disposer.prototype.data = function () {
85 Disposer.prototype.promise = function () {
89 Disposer.prototype.resource = function () {
90 if (this.promise().isFulfilled()) {
91 return this.promise().value();
96 Disposer.prototype.tryDispose = function(inspection) {
97 var resource = this.resource();
98 var context = this._context;
99 if (context !== undefined) context._pushContext();
100 var ret = resource !== null
101 ? this.doDispose(resource, inspection) : null;
102 if (context !== undefined) context._popContext();
103 this._promise._unsetDisposable();
108 Disposer.isDisposer = function (d) {
110 typeof d.resource === "function" &&
111 typeof d.tryDispose === "function");
114 function FunctionDisposer(fn, promise, context) {
115 this.constructor$(fn, promise, context);
117 inherits(FunctionDisposer, Disposer);
119 FunctionDisposer.prototype.doDispose = function (resource, inspection) {
120 var fn = this.data();
121 return fn.call(resource, resource, inspection);
124 function maybeUnwrapDisposer(value) {
125 if (Disposer.isDisposer(value)) {
126 this.resources[this.index]._setDisposable(value);
127 return value.promise();
132 Promise.using = function () {
133 var len = arguments.length;
134 if (len < 2) return apiRejection(
135 "you must pass at least 2 arguments to Promise.using");
136 var fn = arguments[len - 1];
137 if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a");
140 var spreadArgs = true;
141 if (len === 2 && Array.isArray(arguments[0])) {
142 input = arguments[0];
149 var resources = new Array(len);
150 for (var i = 0; i < len; ++i) {
151 var resource = input[i];
152 if (Disposer.isDisposer(resource)) {
153 var disposer = resource;
154 resource = resource.promise();
155 resource._setDisposable(disposer);
157 var maybePromise = tryConvertToPromise(resource);
158 if (maybePromise instanceof Promise) {
160 maybePromise._then(maybeUnwrapDisposer, null, null, {
161 resources: resources,
166 resources[i] = resource;
169 var promise = Promise.settle(resources)
170 .then(inspectionMapper)
171 .then(function(vals) {
172 promise._pushContext();
176 ? fn.apply(undefined, vals) : fn.call(undefined, vals);
178 promise._popContext();
183 disposerSuccess, disposerFail, undefined, resources, undefined);
184 resources.promise = promise;
188 Promise.prototype._setDisposable = function (disposer) {
189 this._bitField = this._bitField | 262144;
190 this._disposer = disposer;
193 Promise.prototype._isDisposable = function () {
194 return (this._bitField & 262144) > 0;
197 Promise.prototype._getDisposer = function () {
198 return this._disposer;
201 Promise.prototype._unsetDisposable = function () {
202 this._bitField = this._bitField & (~262144);
203 this._disposer = undefined;
206 Promise.prototype.disposer = function (fn) {
207 if (typeof fn === "function") {
208 return new FunctionDisposer(fn, this, createContext());
210 throw new TypeError();