corrade-nucleus-nucleons – Blame information for rev 20

Subversion Repositories:
Rev:
Rev Author Line No. Line
20 office 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 };