@fnioc/di 2.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -28
- package/dist/index.d.ts +297 -242
- package/dist/index.js +203 -131
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,26 +1,54 @@
|
|
|
1
1
|
// ../core/src/store.ts
|
|
2
|
-
var hole = null;
|
|
3
2
|
var GLOBAL_KEY = Symbol.for("fnioc:deps");
|
|
4
3
|
var globals = globalThis;
|
|
5
4
|
var store = globals[GLOBAL_KEY] ??= new Map;
|
|
5
|
+
|
|
6
6
|
// ../core/src/defineDeps.ts
|
|
7
7
|
function isFactoryRef(slot) {
|
|
8
|
-
return typeof slot === "object" && slot !== null && typeof slot.
|
|
8
|
+
return typeof slot === "object" && slot !== null && typeof slot.type === "string";
|
|
9
9
|
}
|
|
10
10
|
function isScopeRef(slot) {
|
|
11
11
|
return typeof slot === "object" && slot !== null && slot.scope === true;
|
|
12
12
|
}
|
|
13
|
+
function isUnionSlot(slot) {
|
|
14
|
+
return typeof slot === "object" && slot !== null && Array.isArray(slot.union);
|
|
15
|
+
}
|
|
13
16
|
function slotsEqual(a, b) {
|
|
14
17
|
const aIsRef = isFactoryRef(a);
|
|
15
18
|
const bIsRef = isFactoryRef(b);
|
|
16
19
|
if (aIsRef || bIsRef) {
|
|
17
|
-
|
|
20
|
+
if (!aIsRef || !bIsRef)
|
|
21
|
+
return false;
|
|
22
|
+
if (a.type !== b.type)
|
|
23
|
+
return false;
|
|
24
|
+
const aParams = a.params ?? [];
|
|
25
|
+
const bParams = b.params ?? [];
|
|
26
|
+
if (aParams.length !== bParams.length)
|
|
27
|
+
return false;
|
|
28
|
+
for (let i = 0;i < aParams.length; i++) {
|
|
29
|
+
if (aParams[i] !== bParams[i])
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
18
33
|
}
|
|
19
34
|
const aIsScope = isScopeRef(a);
|
|
20
35
|
const bIsScope = isScopeRef(b);
|
|
21
36
|
if (aIsScope || bIsScope) {
|
|
22
37
|
return aIsScope && bIsScope;
|
|
23
38
|
}
|
|
39
|
+
const aIsUnion = isUnionSlot(a);
|
|
40
|
+
const bIsUnion = isUnionSlot(b);
|
|
41
|
+
if (aIsUnion || bIsUnion) {
|
|
42
|
+
if (!aIsUnion || !bIsUnion)
|
|
43
|
+
return false;
|
|
44
|
+
if (a.union.length !== b.union.length)
|
|
45
|
+
return false;
|
|
46
|
+
for (let i = 0;i < a.union.length; i++) {
|
|
47
|
+
if (!slotsEqual(a.union[i], b.union[i]))
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
24
52
|
return a === b;
|
|
25
53
|
}
|
|
26
54
|
function signaturesEqual(a, b) {
|
|
@@ -65,6 +93,12 @@ function forCtor(ctor) {
|
|
|
65
93
|
};
|
|
66
94
|
return builder;
|
|
67
95
|
}
|
|
96
|
+
|
|
97
|
+
// ../core/src/index.ts
|
|
98
|
+
function union(...slots) {
|
|
99
|
+
return { union: slots };
|
|
100
|
+
}
|
|
101
|
+
|
|
68
102
|
// src/errors.ts
|
|
69
103
|
class DiError extends Error {
|
|
70
104
|
constructor(message) {
|
|
@@ -134,6 +168,15 @@ class FactoryTargetError extends DiError {
|
|
|
134
168
|
}
|
|
135
169
|
}
|
|
136
170
|
|
|
171
|
+
class NoSatisfiableUnionError extends DiError {
|
|
172
|
+
members;
|
|
173
|
+
constructor(members) {
|
|
174
|
+
const memberList = members.map((m) => typeof m === "string" ? `"${m}"` : JSON.stringify(m)).join(", ");
|
|
175
|
+
super(`No satisfiable union member found. Tried: [${memberList}]. ` + `Register at least one of the union members before resolving.`);
|
|
176
|
+
this.members = members;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
137
180
|
class AsyncDisposalRequiredError extends DiError {
|
|
138
181
|
constructor() {
|
|
139
182
|
super(`Cannot dispose synchronously: this scope owns a Promise-valued ` + `instance (an async useFactory result). Awaiting it is required ` + `before disposal — call disposeAsync() instead of dispose().`);
|
|
@@ -150,108 +193,72 @@ function isAsyncDisposable(value) {
|
|
|
150
193
|
function isThenable(value) {
|
|
151
194
|
return value != null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
152
195
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
function isScopeRef2(slot) {
|
|
157
|
-
return slot !== null && typeof slot === "object" && slot.scope === true;
|
|
158
|
-
}
|
|
196
|
+
var isFactoryRef2 = isFactoryRef;
|
|
197
|
+
var isScopeRef2 = isScopeRef;
|
|
198
|
+
var isUnion = isUnionSlot;
|
|
159
199
|
|
|
160
200
|
class Scope {
|
|
161
201
|
name;
|
|
162
202
|
parent;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
ownedOrder = [];
|
|
167
|
-
disposed = false;
|
|
168
|
-
constructor(name, parent, baseRegistrations) {
|
|
203
|
+
cache = new Map;
|
|
204
|
+
owned = [];
|
|
205
|
+
constructor(name, parent) {
|
|
169
206
|
this.name = name;
|
|
170
207
|
this.parent = parent;
|
|
171
|
-
this.baseRegistrations = baseRegistrations;
|
|
172
208
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
class ServiceProvider {
|
|
212
|
+
registrations;
|
|
213
|
+
disposed = false;
|
|
214
|
+
frame;
|
|
215
|
+
constructor(registrations, frame) {
|
|
216
|
+
this.registrations = registrations;
|
|
217
|
+
this.frame = frame;
|
|
218
|
+
}
|
|
219
|
+
get name() {
|
|
220
|
+
if (this.frame === undefined) {
|
|
221
|
+
throw new TypeError("This ServiceProvider has no scope frame (unscoped root).");
|
|
179
222
|
}
|
|
223
|
+
return this.frame.name;
|
|
180
224
|
}
|
|
181
|
-
createScope(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Scope.appendTo(this.localRegistrations, token, base);
|
|
186
|
-
const map = this.localRegistrations;
|
|
187
|
-
return {
|
|
188
|
-
as(scope) {
|
|
189
|
-
if (scope === undefined)
|
|
190
|
-
return;
|
|
191
|
-
Scope.appendTo(map, token, { ...base, scope });
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
add(token, ctor) {
|
|
196
|
-
return this.appendScopedLocal(token, {
|
|
197
|
-
kind: "class",
|
|
198
|
-
ctor,
|
|
199
|
-
scope: undefined
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
addFactory(token, factory) {
|
|
203
|
-
return this.appendScopedLocal(token, {
|
|
204
|
-
kind: "factory",
|
|
205
|
-
factory,
|
|
206
|
-
scope: undefined
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
addValue(token, value) {
|
|
210
|
-
Scope.appendTo(this.localRegistrations, token, {
|
|
211
|
-
kind: "value",
|
|
212
|
-
useValue: value
|
|
213
|
-
});
|
|
214
|
-
return this;
|
|
225
|
+
createScope(...args) {
|
|
226
|
+
const name = args[0] ?? "scoped";
|
|
227
|
+
const childFrame = new Scope(name, this.frame);
|
|
228
|
+
return new ServiceProvider(this.registrations, childFrame);
|
|
215
229
|
}
|
|
216
230
|
resolve(token) {
|
|
217
231
|
if (token === undefined) {
|
|
218
232
|
throw new TypeError("resolve<T>() requires the @fnioc/transformer plugin (no token at " + "runtime). Without it, resolve with an explicit token: " + 'resolve<T>("my:token").');
|
|
219
233
|
}
|
|
220
|
-
return this.resolveWith(token, []);
|
|
234
|
+
return this.resolveWith(token, this.frame, []);
|
|
221
235
|
}
|
|
222
|
-
resolveFactory(
|
|
223
|
-
return this.makeFactory({
|
|
236
|
+
resolveFactory(type, params) {
|
|
237
|
+
return this.makeFactory({ type, params }, this.frame);
|
|
224
238
|
}
|
|
225
239
|
lookup(token) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const local = node.localRegistrations.get(token);
|
|
229
|
-
if (local !== undefined && local.length > 0)
|
|
230
|
-
return local[local.length - 1];
|
|
231
|
-
node = node.parent;
|
|
232
|
-
}
|
|
233
|
-
const base = this.baseRegistrations.get(token);
|
|
234
|
-
return base !== undefined && base.length > 0 ? base[base.length - 1] : undefined;
|
|
240
|
+
const list = this.registrations.get(token);
|
|
241
|
+
return list !== undefined && list.length > 0 ? list[list.length - 1] : undefined;
|
|
235
242
|
}
|
|
236
|
-
findOwner(
|
|
237
|
-
let node =
|
|
243
|
+
static findOwner(vantage, scopeName) {
|
|
244
|
+
let node = vantage;
|
|
238
245
|
while (node !== undefined) {
|
|
239
|
-
if (node.name ===
|
|
246
|
+
if (node.name === scopeName)
|
|
240
247
|
return node;
|
|
241
248
|
node = node.parent;
|
|
242
249
|
}
|
|
243
250
|
return;
|
|
244
251
|
}
|
|
245
|
-
chainNames() {
|
|
252
|
+
static chainNames(vantage) {
|
|
246
253
|
const names = [];
|
|
247
|
-
let node =
|
|
254
|
+
let node = vantage;
|
|
248
255
|
while (node !== undefined) {
|
|
249
256
|
names.push(node.name);
|
|
250
257
|
node = node.parent;
|
|
251
258
|
}
|
|
252
259
|
return names;
|
|
253
260
|
}
|
|
254
|
-
resolveWith(token, stack) {
|
|
261
|
+
resolveWith(token, vantage, stack) {
|
|
255
262
|
if (stack.includes(token)) {
|
|
256
263
|
throw new CircularDependencyError([...stack, token]);
|
|
257
264
|
}
|
|
@@ -265,65 +272,70 @@ class Scope {
|
|
|
265
272
|
if (registration.scope === undefined) {
|
|
266
273
|
stack.push(token);
|
|
267
274
|
try {
|
|
268
|
-
return this.instantiate(token, registration,
|
|
275
|
+
return this.instantiate(token, registration, vantage, stack);
|
|
269
276
|
} finally {
|
|
270
277
|
stack.pop();
|
|
271
278
|
}
|
|
272
279
|
}
|
|
273
|
-
const owner =
|
|
280
|
+
const owner = ServiceProvider.findOwner(vantage, registration.scope);
|
|
274
281
|
if (owner === undefined) {
|
|
275
|
-
throw new MissingScopeError(token, registration.scope,
|
|
282
|
+
throw new MissingScopeError(token, registration.scope, ServiceProvider.chainNames(vantage));
|
|
276
283
|
}
|
|
277
|
-
if (owner.
|
|
278
|
-
return owner.
|
|
284
|
+
if (owner.cache.has(token)) {
|
|
285
|
+
return owner.cache.get(token);
|
|
279
286
|
}
|
|
280
287
|
stack.push(token);
|
|
281
288
|
try {
|
|
282
|
-
const instance =
|
|
283
|
-
owner.
|
|
284
|
-
owner.
|
|
289
|
+
const instance = this.instantiate(token, registration, owner, stack);
|
|
290
|
+
owner.cache.set(token, instance);
|
|
291
|
+
owner.owned.push(instance);
|
|
285
292
|
return instance;
|
|
286
293
|
} finally {
|
|
287
294
|
stack.pop();
|
|
288
295
|
}
|
|
289
296
|
}
|
|
290
|
-
instantiate(token, registration,
|
|
297
|
+
instantiate(token, registration, owningFrame, stack) {
|
|
291
298
|
if (registration.kind === "factory") {
|
|
292
|
-
return
|
|
299
|
+
return this.invokeFactory(token, registration.factory, owningFrame, stack);
|
|
293
300
|
}
|
|
294
|
-
return
|
|
301
|
+
return this.construct(token, registration.ctor, owningFrame, stack);
|
|
295
302
|
}
|
|
296
|
-
|
|
297
|
-
const
|
|
298
|
-
|
|
303
|
+
makeProviderView(owningFrame, stack) {
|
|
304
|
+
const sp = this;
|
|
305
|
+
return {
|
|
299
306
|
resolve: (depToken) => {
|
|
300
307
|
if (depToken === undefined) {
|
|
301
308
|
throw new TypeError("resolve<T>() requires the @fnioc/transformer plugin (no token at " + "runtime).");
|
|
302
309
|
}
|
|
303
|
-
return
|
|
310
|
+
return sp.resolveWith(depToken, owningFrame, stack);
|
|
304
311
|
},
|
|
305
|
-
resolveFactory: (depToken) =>
|
|
306
|
-
createScope: (
|
|
312
|
+
resolveFactory: (depToken, depParams) => sp.makeFactory({ type: depToken, params: depParams }, owningFrame),
|
|
313
|
+
createScope: (...args) => {
|
|
314
|
+
const name = args[0] ?? "scoped";
|
|
315
|
+
const childFrame = new Scope(name, owningFrame);
|
|
316
|
+
return new ServiceProvider(sp.registrations, childFrame);
|
|
317
|
+
}
|
|
307
318
|
};
|
|
308
|
-
return view;
|
|
309
319
|
}
|
|
310
|
-
invokeFactory(token, factory, stack) {
|
|
311
|
-
const
|
|
320
|
+
invokeFactory(token, factory, owningFrame, stack) {
|
|
321
|
+
const providerView = this.makeProviderView(owningFrame, stack);
|
|
312
322
|
const record = getDeps(factory);
|
|
313
323
|
if (record === undefined || record.signatures.length === 0) {
|
|
314
|
-
return factory(
|
|
324
|
+
return factory(providerView);
|
|
315
325
|
}
|
|
316
|
-
const signature2 = this.selectSignature(token, factory.name, record.signatures);
|
|
326
|
+
const signature2 = this.selectSignature(token, factory.name, record.signatures, owningFrame);
|
|
317
327
|
const args = signature2.map((slot) => {
|
|
318
328
|
if (isScopeRef2(slot))
|
|
319
|
-
return
|
|
329
|
+
return providerView;
|
|
320
330
|
if (isFactoryRef2(slot))
|
|
321
|
-
return this.makeFactory(slot);
|
|
322
|
-
|
|
331
|
+
return this.makeFactory(slot, owningFrame);
|
|
332
|
+
if (isUnion(slot))
|
|
333
|
+
return this.resolveUnion(slot, owningFrame, stack);
|
|
334
|
+
return this.resolveWith(slot, owningFrame, stack);
|
|
323
335
|
});
|
|
324
336
|
return factory(...args);
|
|
325
337
|
}
|
|
326
|
-
construct(token, ctor, stack) {
|
|
338
|
+
construct(token, ctor, owningFrame, stack) {
|
|
327
339
|
const record = getDeps(ctor);
|
|
328
340
|
if (record === undefined || record.signatures.length === 0) {
|
|
329
341
|
if (ctor.length > 0) {
|
|
@@ -331,52 +343,69 @@ class Scope {
|
|
|
331
343
|
}
|
|
332
344
|
return new ctor;
|
|
333
345
|
}
|
|
334
|
-
const signature2 = this.selectSignature(token, ctor.name, record.signatures);
|
|
346
|
+
const signature2 = this.selectSignature(token, ctor.name, record.signatures, owningFrame);
|
|
347
|
+
const providerView = this.makeProviderView(owningFrame, stack);
|
|
335
348
|
const args = signature2.map((slot) => {
|
|
336
349
|
if (isScopeRef2(slot)) {
|
|
337
|
-
return
|
|
350
|
+
return providerView;
|
|
338
351
|
}
|
|
339
352
|
if (isFactoryRef2(slot)) {
|
|
340
|
-
return this.makeFactory(slot);
|
|
353
|
+
return this.makeFactory(slot, owningFrame);
|
|
354
|
+
}
|
|
355
|
+
if (isUnion(slot)) {
|
|
356
|
+
return this.resolveUnion(slot, owningFrame, stack);
|
|
341
357
|
}
|
|
342
|
-
return this.resolveWith(slot, stack);
|
|
358
|
+
return this.resolveWith(slot, owningFrame, stack);
|
|
343
359
|
});
|
|
344
360
|
return new ctor(...args);
|
|
345
361
|
}
|
|
346
|
-
makeFactory(ref) {
|
|
347
|
-
const
|
|
348
|
-
const target = this.lookup(ref.
|
|
362
|
+
makeFactory(ref, owningFrame) {
|
|
363
|
+
const sp = this;
|
|
364
|
+
const target = this.lookup(ref.type);
|
|
349
365
|
if (target === undefined) {
|
|
350
|
-
throw new FactoryTargetError(ref.
|
|
366
|
+
throw new FactoryTargetError(ref.type, "unregistered");
|
|
351
367
|
}
|
|
352
368
|
if (target.kind === "value") {
|
|
353
|
-
return () =>
|
|
369
|
+
return () => sp.resolveWith(ref.type, owningFrame, []);
|
|
370
|
+
}
|
|
371
|
+
const callerParams = ref.params !== undefined && ref.params.length > 0 ? ref.params : undefined;
|
|
372
|
+
if (callerParams === undefined) {
|
|
373
|
+
return () => sp.resolveWith(ref.type, owningFrame, []);
|
|
354
374
|
}
|
|
355
375
|
const depTarget = target.kind === "class" ? target.ctor : target.factory;
|
|
356
376
|
const record = getDeps(depTarget);
|
|
357
|
-
const targetSignature = record === undefined || record.signatures.length === 0 ? undefined :
|
|
358
|
-
|
|
359
|
-
if (!parameterized) {
|
|
360
|
-
return () => owningScope.resolveWith(ref.factory, []);
|
|
361
|
-
}
|
|
362
|
-
return (...callArgs) => owningScope.buildPartitioned(target, targetSignature, callArgs);
|
|
377
|
+
const targetSignature = record === undefined || record.signatures.length === 0 ? undefined : sp.selectTargetSignature(record.signatures);
|
|
378
|
+
return (...callArgs) => sp.buildPartitioned(target, targetSignature, callerParams, callArgs, owningFrame);
|
|
363
379
|
}
|
|
364
|
-
buildPartitioned(target, signature2,
|
|
380
|
+
buildPartitioned(target, signature2, callerParams, callArgs, owningFrame) {
|
|
365
381
|
const stack = [];
|
|
366
|
-
|
|
382
|
+
const providerView = this.makeProviderView(owningFrame, stack);
|
|
383
|
+
if (signature2 === undefined || signature2.length === 0) {
|
|
384
|
+
return target.kind === "class" ? new target.ctor : target.factory(providerView);
|
|
385
|
+
}
|
|
386
|
+
const remainingParamIndices = callerParams.map((_, i) => i);
|
|
367
387
|
const args = signature2.map((slot) => {
|
|
368
388
|
if (isScopeRef2(slot))
|
|
369
|
-
return
|
|
389
|
+
return providerView;
|
|
370
390
|
if (isFactoryRef2(slot))
|
|
371
|
-
return this.makeFactory(slot);
|
|
372
|
-
if (
|
|
373
|
-
return
|
|
391
|
+
return this.makeFactory(slot, owningFrame);
|
|
392
|
+
if (isUnion(slot))
|
|
393
|
+
return this.resolveUnion(slot, owningFrame, stack);
|
|
394
|
+
const token = slot;
|
|
395
|
+
const matchIdx = remainingParamIndices.findIndex((pi) => callerParams[pi] === token);
|
|
396
|
+
if (matchIdx !== -1) {
|
|
397
|
+
const paramIdx = remainingParamIndices[matchIdx];
|
|
398
|
+
remainingParamIndices.splice(matchIdx, 1);
|
|
399
|
+
return callArgs[paramIdx];
|
|
400
|
+
}
|
|
401
|
+
if (!this.isResolvable(token)) {
|
|
402
|
+
throw new NoSatisfiableSignatureError(token, token, [token]);
|
|
374
403
|
}
|
|
375
|
-
return this.resolveWith(
|
|
404
|
+
return this.resolveWith(token, owningFrame, stack);
|
|
376
405
|
});
|
|
377
406
|
return target.kind === "class" ? new target.ctor(...args) : target.factory(...args);
|
|
378
407
|
}
|
|
379
|
-
selectSignature(token, targetName, signatures) {
|
|
408
|
+
selectSignature(token, targetName, signatures, _owningFrame) {
|
|
380
409
|
const ordered = signatures.map((sig, index) => ({ sig, index })).sort((a, b) => b.sig.length !== a.sig.length ? b.sig.length - a.sig.length : a.index - b.index);
|
|
381
410
|
const unsatisfiable = new Set;
|
|
382
411
|
for (const { sig } of ordered) {
|
|
@@ -384,6 +413,12 @@ class Scope {
|
|
|
384
413
|
for (const slot of sig) {
|
|
385
414
|
if (isFactoryRef2(slot) || isScopeRef2(slot))
|
|
386
415
|
continue;
|
|
416
|
+
if (isUnion(slot)) {
|
|
417
|
+
if (!this.isResolvableSlot(slot)) {
|
|
418
|
+
satisfiable = false;
|
|
419
|
+
}
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
387
422
|
if (!this.isResolvable(slot)) {
|
|
388
423
|
satisfiable = false;
|
|
389
424
|
if (typeof slot === "string")
|
|
@@ -401,17 +436,43 @@ class Scope {
|
|
|
401
436
|
isResolvable(slot) {
|
|
402
437
|
return typeof slot === "string" && this.lookup(slot) !== undefined;
|
|
403
438
|
}
|
|
439
|
+
isResolvableSlot(slot) {
|
|
440
|
+
if (isFactoryRef2(slot) || isScopeRef2(slot))
|
|
441
|
+
return true;
|
|
442
|
+
if (isUnion(slot)) {
|
|
443
|
+
return slot.union.some((member) => this.isResolvableSlot(member));
|
|
444
|
+
}
|
|
445
|
+
return this.isResolvable(slot);
|
|
446
|
+
}
|
|
447
|
+
resolveUnion(slot, owningFrame, stack) {
|
|
448
|
+
for (const member of slot.union) {
|
|
449
|
+
if (this.isResolvableSlot(member)) {
|
|
450
|
+
return this.resolveSlot(member, owningFrame, stack);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
throw new NoSatisfiableUnionError(slot.union);
|
|
454
|
+
}
|
|
455
|
+
resolveSlot(slot, owningFrame, stack) {
|
|
456
|
+
if (isScopeRef2(slot))
|
|
457
|
+
return this.makeProviderView(owningFrame, stack);
|
|
458
|
+
if (isFactoryRef2(slot))
|
|
459
|
+
return this.makeFactory(slot, owningFrame);
|
|
460
|
+
if (isUnion(slot))
|
|
461
|
+
return this.resolveUnion(slot, owningFrame, stack);
|
|
462
|
+
return this.resolveWith(slot, owningFrame, stack);
|
|
463
|
+
}
|
|
404
464
|
dispose() {
|
|
405
465
|
if (this.disposed)
|
|
406
466
|
return;
|
|
407
|
-
|
|
467
|
+
const owned = this.frame?.owned ?? [];
|
|
468
|
+
for (const instance of owned) {
|
|
408
469
|
if (isThenable(instance)) {
|
|
409
470
|
throw new AsyncDisposalRequiredError;
|
|
410
471
|
}
|
|
411
472
|
}
|
|
412
473
|
this.disposed = true;
|
|
413
|
-
for (let i =
|
|
414
|
-
const instance =
|
|
474
|
+
for (let i = owned.length - 1;i >= 0; i--) {
|
|
475
|
+
const instance = owned[i];
|
|
415
476
|
if (isDisposable(instance)) {
|
|
416
477
|
instance[Symbol.dispose]();
|
|
417
478
|
}
|
|
@@ -422,8 +483,9 @@ class Scope {
|
|
|
422
483
|
if (this.disposed)
|
|
423
484
|
return;
|
|
424
485
|
this.disposed = true;
|
|
486
|
+
const owned = this.frame?.owned ?? [];
|
|
425
487
|
const settled = [];
|
|
426
|
-
for (const instance of
|
|
488
|
+
for (const instance of owned) {
|
|
427
489
|
settled.push(isThenable(instance) ? await instance : instance);
|
|
428
490
|
}
|
|
429
491
|
for (let i = settled.length - 1;i >= 0; i--) {
|
|
@@ -437,8 +499,10 @@ class Scope {
|
|
|
437
499
|
this.clear();
|
|
438
500
|
}
|
|
439
501
|
clear() {
|
|
440
|
-
this.
|
|
441
|
-
|
|
502
|
+
if (this.frame) {
|
|
503
|
+
this.frame.cache.clear();
|
|
504
|
+
this.frame.owned.length = 0;
|
|
505
|
+
}
|
|
442
506
|
}
|
|
443
507
|
[Symbol.dispose]() {
|
|
444
508
|
this.dispose();
|
|
@@ -500,16 +564,24 @@ class DiBuilder {
|
|
|
500
564
|
this.append(token, { kind: "value", useValue: value });
|
|
501
565
|
}
|
|
502
566
|
build() {
|
|
503
|
-
|
|
567
|
+
const sealed = new Map;
|
|
568
|
+
for (const [token, list] of this.registrations) {
|
|
569
|
+
sealed.set(token, Object.freeze([...list]));
|
|
570
|
+
}
|
|
571
|
+
Object.freeze(sealed);
|
|
572
|
+
const rootFrame = new Scope(this.rootName);
|
|
573
|
+
return new ServiceProvider(sealed, rootFrame);
|
|
504
574
|
}
|
|
505
575
|
}
|
|
506
576
|
export {
|
|
577
|
+
union,
|
|
507
578
|
signature,
|
|
508
|
-
hole,
|
|
509
579
|
forCtor,
|
|
510
580
|
defineDeps,
|
|
511
581
|
UnregisteredTokenError,
|
|
582
|
+
ServiceProvider,
|
|
512
583
|
Scope,
|
|
584
|
+
NoSatisfiableUnionError,
|
|
513
585
|
NoSatisfiableSignatureError,
|
|
514
586
|
MissingScopeError,
|
|
515
587
|
MissingMetadataError,
|
package/package.json
CHANGED