Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81160 views
1
"use strict";
2
module.exports = function (Promise, apiRejection, tryConvertToPromise,
3
createContext) {
4
var TypeError = require("./errors.js").TypeError;
5
var inherits = require("./util.js").inherits;
6
var PromiseInspection = Promise.PromiseInspection;
7
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());
14
}
15
inspections[i] = inspection._settledValue;
16
}
17
return inspections;
18
}
19
20
function thrower(e) {
21
setTimeout(function(){throw e;}, 0);
22
}
23
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());
31
}
32
return maybePromise;
33
}
34
function dispose(resources, inspection) {
35
var i = 0;
36
var len = resources.length;
37
var ret = Promise.defer();
38
function iterator() {
39
if (i >= len) return ret.resolve();
40
var maybePromise = castPreservingDisposable(resources[i++]);
41
if (maybePromise instanceof Promise &&
42
maybePromise._isDisposable()) {
43
try {
44
maybePromise = tryConvertToPromise(
45
maybePromise._getDisposer().tryDispose(inspection),
46
resources.promise);
47
} catch (e) {
48
return thrower(e);
49
}
50
if (maybePromise instanceof Promise) {
51
return maybePromise._then(iterator, thrower,
52
null, null, null);
53
}
54
}
55
iterator();
56
}
57
iterator();
58
return ret.promise;
59
}
60
61
function disposerSuccess(value) {
62
var inspection = new PromiseInspection();
63
inspection._settledValue = value;
64
inspection._bitField = 268435456;
65
return dispose(this, inspection).thenReturn(value);
66
}
67
68
function disposerFail(reason) {
69
var inspection = new PromiseInspection();
70
inspection._settledValue = reason;
71
inspection._bitField = 134217728;
72
return dispose(this, inspection).thenThrow(reason);
73
}
74
75
function Disposer(data, promise, context) {
76
this._data = data;
77
this._promise = promise;
78
this._context = context;
79
}
80
81
Disposer.prototype.data = function () {
82
return this._data;
83
};
84
85
Disposer.prototype.promise = function () {
86
return this._promise;
87
};
88
89
Disposer.prototype.resource = function () {
90
if (this.promise().isFulfilled()) {
91
return this.promise().value();
92
}
93
return null;
94
};
95
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();
104
this._data = null;
105
return ret;
106
};
107
108
Disposer.isDisposer = function (d) {
109
return (d != null &&
110
typeof d.resource === "function" &&
111
typeof d.tryDispose === "function");
112
};
113
114
function FunctionDisposer(fn, promise, context) {
115
this.constructor$(fn, promise, context);
116
}
117
inherits(FunctionDisposer, Disposer);
118
119
FunctionDisposer.prototype.doDispose = function (resource, inspection) {
120
var fn = this.data();
121
return fn.call(resource, resource, inspection);
122
};
123
124
function maybeUnwrapDisposer(value) {
125
if (Disposer.isDisposer(value)) {
126
this.resources[this.index]._setDisposable(value);
127
return value.promise();
128
}
129
return value;
130
}
131
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");
138
len--;
139
var resources = new Array(len);
140
for (var i = 0; i < len; ++i) {
141
var resource = arguments[i];
142
if (Disposer.isDisposer(resource)) {
143
var disposer = resource;
144
resource = resource.promise();
145
resource._setDisposable(disposer);
146
} else {
147
var maybePromise = tryConvertToPromise(resource);
148
if (maybePromise instanceof Promise) {
149
resource =
150
maybePromise._then(maybeUnwrapDisposer, null, null, {
151
resources: resources,
152
index: i
153
}, undefined);
154
}
155
}
156
resources[i] = resource;
157
}
158
159
var promise = Promise.settle(resources)
160
.then(inspectionMapper)
161
.then(function(vals) {
162
promise._pushContext();
163
var ret;
164
try {
165
ret = fn.apply(undefined, vals);
166
} finally {
167
promise._popContext();
168
}
169
return ret;
170
})
171
._then(
172
disposerSuccess, disposerFail, undefined, resources, undefined);
173
resources.promise = promise;
174
return promise;
175
};
176
177
Promise.prototype._setDisposable = function (disposer) {
178
this._bitField = this._bitField | 262144;
179
this._disposer = disposer;
180
};
181
182
Promise.prototype._isDisposable = function () {
183
return (this._bitField & 262144) > 0;
184
};
185
186
Promise.prototype._getDisposer = function () {
187
return this._disposer;
188
};
189
190
Promise.prototype._unsetDisposable = function () {
191
this._bitField = this._bitField & (~262144);
192
this._disposer = undefined;
193
};
194
195
Promise.prototype.disposer = function (fn) {
196
if (typeof fn === "function") {
197
return new FunctionDisposer(fn, this, createContext());
198
}
199
throw new TypeError();
200
};
201
202
};
203
204