@codefast/di 0.7.1 → 0.8.1
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/CHANGELOG.md +40 -0
- package/README.md +242 -159
- package/dist/ambient/active-container.d.ts +1 -2
- package/dist/ambient/active-container.js +1 -2
- package/dist/container/binding-builders.d.ts +1 -2
- package/dist/container/binding-builders.js +5 -7
- package/dist/container/container.d.ts +1 -2
- package/dist/container/container.js +4 -6
- package/dist/core/binding-scope.d.ts +1 -2
- package/dist/core/binding-scope.js +1 -2
- package/dist/core/binding.d.ts +16 -4
- package/dist/core/binding.js +30 -6
- package/dist/core/constraint-requirement.d.ts +1 -2
- package/dist/core/constraint-requirement.js +1 -2
- package/dist/core/constructor-type.d.ts +1 -2
- package/dist/core/constructor-type.js +1 -2
- package/dist/core/map-upsert.d.ts +1 -2
- package/dist/core/map-upsert.js +1 -2
- package/dist/core/module.d.ts +1 -2
- package/dist/core/module.js +1 -2
- package/dist/core/registry.d.ts +1 -5
- package/dist/core/registry.js +15 -63
- package/dist/core/tag.d.ts +27 -2
- package/dist/core/tag.js +55 -13
- package/dist/core/token.d.ts +1 -2
- package/dist/core/token.js +1 -2
- package/dist/core/types.d.ts +1 -2
- package/dist/core/types.js +1 -2
- package/dist/decorators/inject.d.ts +1 -2
- package/dist/decorators/inject.js +1 -2
- package/dist/decorators/injectable.d.ts +1 -2
- package/dist/decorators/injectable.js +1 -2
- package/dist/decorators/lifecycle-decorators.d.ts +1 -2
- package/dist/decorators/lifecycle-decorators.js +1 -2
- package/dist/errors/diagnostics.d.ts +1 -2
- package/dist/errors/diagnostics.js +1 -2
- package/dist/errors/errors.d.ts +1 -2
- package/dist/errors/errors.js +29 -5
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -3
- package/dist/injection/descriptor.d.ts +1 -2
- package/dist/injection/descriptor.js +1 -2
- package/dist/injection/resolve-options.d.ts +18 -14
- package/dist/injection/resolve-options.js +70 -17
- package/dist/introspection/dependency-graph.d.ts +1 -2
- package/dist/introspection/dependency-graph.js +23 -11
- package/dist/introspection/graph-adapters/cytoscape.d.ts +1 -2
- package/dist/introspection/graph-adapters/cytoscape.js +1 -2
- package/dist/introspection/graph-adapters/dot.d.ts +1 -2
- package/dist/introspection/graph-adapters/dot.js +1 -2
- package/dist/introspection/graph-adapters/mermaid.d.ts +1 -2
- package/dist/introspection/graph-adapters/mermaid.js +1 -2
- package/dist/introspection/graph-adapters/reactflow.d.ts +1 -2
- package/dist/introspection/graph-adapters/reactflow.js +1 -2
- package/dist/introspection/inspector.d.ts +1 -2
- package/dist/introspection/inspector.js +1 -2
- package/dist/lifecycle/lifecycle-manager.d.ts +1 -2
- package/dist/lifecycle/lifecycle-manager.js +1 -2
- package/dist/lifecycle/scope-manager.d.ts +1 -2
- package/dist/lifecycle/scope-manager.js +1 -2
- package/dist/metadata/metadata-keys.d.ts +1 -2
- package/dist/metadata/metadata-keys.js +1 -2
- package/dist/metadata/metadata-reader-token.d.ts +1 -2
- package/dist/metadata/metadata-reader-token.js +1 -2
- package/dist/metadata/metadata-types.d.ts +1 -2
- package/dist/metadata/metadata-types.js +1 -2
- package/dist/metadata/symbol-metadata-reader.d.ts +1 -2
- package/dist/metadata/symbol-metadata-reader.js +1 -2
- package/dist/metadata/verifying-metadata-reader.d.ts +1 -2
- package/dist/metadata/verifying-metadata-reader.js +1 -2
- package/dist/resolution/cache/activation-need.d.ts +1 -2
- package/dist/resolution/cache/activation-need.js +1 -2
- package/dist/resolution/cache/binding-lookup-cache.d.ts +2 -5
- package/dist/resolution/cache/binding-lookup-cache.js +2 -40
- package/dist/resolution/cache/class-introspector.d.ts +1 -2
- package/dist/resolution/cache/class-introspector.js +1 -2
- package/dist/resolution/context.d.ts +1 -2
- package/dist/resolution/context.js +1 -2
- package/dist/resolution/path/resolution-path.d.ts +1 -2
- package/dist/resolution/path/resolution-path.js +1 -2
- package/dist/resolution/plan/instantiation-plan.d.ts +5 -14
- package/dist/resolution/plan/instantiation-plan.js +10 -29
- package/dist/resolution/resolver.d.ts +13 -7
- package/dist/resolution/resolver.js +107 -143
- package/dist/resolution/select/binding-select.d.ts +5 -7
- package/dist/resolution/select/binding-select.js +19 -22
- package/dist/resolution/select/constraints.d.ts +1 -2
- package/dist/resolution/select/constraints.js +1 -2
- package/package.json +6 -58
- package/dist/ambient/active-container.d.ts.map +0 -1
- package/dist/ambient/active-container.js.map +0 -1
- package/dist/container/binding-builders.d.ts.map +0 -1
- package/dist/container/binding-builders.js.map +0 -1
- package/dist/container/container.d.ts.map +0 -1
- package/dist/container/container.js.map +0 -1
- package/dist/core/binding-scope.d.ts.map +0 -1
- package/dist/core/binding-scope.js.map +0 -1
- package/dist/core/binding.d.ts.map +0 -1
- package/dist/core/binding.js.map +0 -1
- package/dist/core/constraint-requirement.d.ts.map +0 -1
- package/dist/core/constraint-requirement.js.map +0 -1
- package/dist/core/constructor-type.d.ts.map +0 -1
- package/dist/core/constructor-type.js.map +0 -1
- package/dist/core/map-upsert.d.ts.map +0 -1
- package/dist/core/map-upsert.js.map +0 -1
- package/dist/core/module.d.ts.map +0 -1
- package/dist/core/module.js.map +0 -1
- package/dist/core/registry.d.ts.map +0 -1
- package/dist/core/registry.js.map +0 -1
- package/dist/core/tag.d.ts.map +0 -1
- package/dist/core/tag.js.map +0 -1
- package/dist/core/token.d.ts.map +0 -1
- package/dist/core/token.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/decorators/inject.d.ts.map +0 -1
- package/dist/decorators/inject.js.map +0 -1
- package/dist/decorators/injectable.d.ts.map +0 -1
- package/dist/decorators/injectable.js.map +0 -1
- package/dist/decorators/lifecycle-decorators.d.ts.map +0 -1
- package/dist/decorators/lifecycle-decorators.js.map +0 -1
- package/dist/errors/diagnostics.d.ts.map +0 -1
- package/dist/errors/diagnostics.js.map +0 -1
- package/dist/errors/errors.d.ts.map +0 -1
- package/dist/errors/errors.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/injection/descriptor.d.ts.map +0 -1
- package/dist/injection/descriptor.js.map +0 -1
- package/dist/injection/resolve-options.d.ts.map +0 -1
- package/dist/injection/resolve-options.js.map +0 -1
- package/dist/introspection/dependency-graph.d.ts.map +0 -1
- package/dist/introspection/dependency-graph.js.map +0 -1
- package/dist/introspection/graph-adapters/cytoscape.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/cytoscape.js.map +0 -1
- package/dist/introspection/graph-adapters/dot.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/dot.js.map +0 -1
- package/dist/introspection/graph-adapters/mermaid.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/mermaid.js.map +0 -1
- package/dist/introspection/graph-adapters/reactflow.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/reactflow.js.map +0 -1
- package/dist/introspection/inspector.d.ts.map +0 -1
- package/dist/introspection/inspector.js.map +0 -1
- package/dist/lifecycle/lifecycle-manager.d.ts.map +0 -1
- package/dist/lifecycle/lifecycle-manager.js.map +0 -1
- package/dist/lifecycle/scope-manager.d.ts.map +0 -1
- package/dist/lifecycle/scope-manager.js.map +0 -1
- package/dist/metadata/metadata-keys.d.ts.map +0 -1
- package/dist/metadata/metadata-keys.js.map +0 -1
- package/dist/metadata/metadata-reader-token.d.ts.map +0 -1
- package/dist/metadata/metadata-reader-token.js.map +0 -1
- package/dist/metadata/metadata-types.d.ts.map +0 -1
- package/dist/metadata/metadata-types.js.map +0 -1
- package/dist/metadata/symbol-metadata-reader.d.ts.map +0 -1
- package/dist/metadata/symbol-metadata-reader.js.map +0 -1
- package/dist/metadata/verifying-metadata-reader.d.ts.map +0 -1
- package/dist/metadata/verifying-metadata-reader.js.map +0 -1
- package/dist/resolution/cache/activation-need.d.ts.map +0 -1
- package/dist/resolution/cache/activation-need.js.map +0 -1
- package/dist/resolution/cache/binding-lookup-cache.d.ts.map +0 -1
- package/dist/resolution/cache/binding-lookup-cache.js.map +0 -1
- package/dist/resolution/cache/class-introspector.d.ts.map +0 -1
- package/dist/resolution/cache/class-introspector.js.map +0 -1
- package/dist/resolution/context.d.ts.map +0 -1
- package/dist/resolution/context.js.map +0 -1
- package/dist/resolution/path/resolution-path.d.ts.map +0 -1
- package/dist/resolution/path/resolution-path.js.map +0 -1
- package/dist/resolution/plan/instantiation-plan.d.ts.map +0 -1
- package/dist/resolution/plan/instantiation-plan.js.map +0 -1
- package/dist/resolution/resolver.d.ts.map +0 -1
- package/dist/resolution/resolver.js.map +0 -1
- package/dist/resolution/select/binding-select.d.ts.map +0 -1
- package/dist/resolution/select/binding-select.js.map +0 -1
- package/dist/resolution/select/constraints.d.ts.map +0 -1
- package/dist/resolution/select/constraints.js.map +0 -1
- package/src/ambient/active-container.ts +0 -69
- package/src/container/binding-builders.ts +0 -332
- package/src/container/container.ts +0 -973
- package/src/core/binding-scope.ts +0 -15
- package/src/core/binding.ts +0 -477
- package/src/core/constraint-requirement.ts +0 -94
- package/src/core/constructor-type.ts +0 -18
- package/src/core/map-upsert.ts +0 -53
- package/src/core/module.ts +0 -117
- package/src/core/registry.ts +0 -371
- package/src/core/tag.ts +0 -158
- package/src/core/token.ts +0 -31
- package/src/core/types.ts +0 -149
- package/src/decorators/inject.ts +0 -101
- package/src/decorators/injectable.ts +0 -134
- package/src/decorators/lifecycle-decorators.ts +0 -43
- package/src/errors/diagnostics.ts +0 -45
- package/src/errors/errors.ts +0 -476
- package/src/index.ts +0 -139
- package/src/injection/descriptor.ts +0 -218
- package/src/injection/resolve-options.ts +0 -144
- package/src/introspection/dependency-graph.ts +0 -282
- package/src/introspection/graph-adapters/cytoscape.ts +0 -78
- package/src/introspection/graph-adapters/dot.ts +0 -32
- package/src/introspection/graph-adapters/mermaid.ts +0 -61
- package/src/introspection/graph-adapters/reactflow.ts +0 -84
- package/src/introspection/inspector.ts +0 -134
- package/src/lifecycle/lifecycle-manager.ts +0 -272
- package/src/lifecycle/scope-manager.ts +0 -158
- package/src/metadata/metadata-keys.ts +0 -28
- package/src/metadata/metadata-reader-token.ts +0 -10
- package/src/metadata/metadata-types.ts +0 -57
- package/src/metadata/symbol-metadata-reader.ts +0 -126
- package/src/metadata/verifying-metadata-reader.ts +0 -41
- package/src/resolution/cache/activation-need.ts +0 -87
- package/src/resolution/cache/binding-lookup-cache.ts +0 -209
- package/src/resolution/cache/class-introspector.ts +0 -256
- package/src/resolution/context.ts +0 -331
- package/src/resolution/path/resolution-path.ts +0 -167
- package/src/resolution/plan/instantiation-plan.ts +0 -617
- package/src/resolution/resolver.ts +0 -1675
- package/src/resolution/select/binding-select.ts +0 -210
- package/src/resolution/select/constraints.ts +0 -146
|
@@ -56,5 +56,4 @@ export declare class BindingChain<Value> implements AliasBindingBuilder, Binding
|
|
|
56
56
|
onActivation(fn: ActivationHandler<Value>): this;
|
|
57
57
|
onDeactivation(fn: DeactivationHandler<Value>): this;
|
|
58
58
|
id(): BindingIdentifier;
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=binding-builders.d.ts.map
|
|
59
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { clearBindingFrame, createBinding, DEFAULT_BINDING_SLOT, refinableFields } from "#/core/binding";
|
|
1
|
+
import { clearBindingFrame, createBinding, createBindingSlot, DEFAULT_BINDING_SLOT, refinableFields, } from "#/core/binding";
|
|
2
2
|
import { mergingConstraintRequirements } from "#/core/constraint-requirement";
|
|
3
|
-
import {
|
|
3
|
+
import { slotName } from "#/core/tag";
|
|
4
4
|
import { tokenName } from "#/core/token";
|
|
5
5
|
import { ChainNotRegisteredError, SelfBindingRequiresClassError } from "#/errors/errors";
|
|
6
6
|
import { normalizeToDescriptor } from "#/injection/descriptor";
|
|
@@ -14,8 +14,7 @@ function updateSlotTag(slot, criterion) {
|
|
|
14
14
|
else {
|
|
15
15
|
tags[existingIndex] = criterion;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
return { ...slot, tags: Object.freeze(tags), keyMask: tagKeyMaskOf(tags) };
|
|
17
|
+
return createBindingSlot(tags);
|
|
19
18
|
}
|
|
20
19
|
/** Record a module's binding id, dropping the id the chain re-slotted away from. */
|
|
21
20
|
function trackBindingForModule(ids, id, previousId) {
|
|
@@ -140,7 +139,7 @@ export class BindingChain {
|
|
|
140
139
|
return this.#reslot(binding.slot, composed);
|
|
141
140
|
}
|
|
142
141
|
whenNamed(name) {
|
|
143
|
-
return this
|
|
142
|
+
return this.whenTagged(slotName.of(name));
|
|
144
143
|
}
|
|
145
144
|
whenTagged(criterion) {
|
|
146
145
|
const binding = this.#registered();
|
|
@@ -226,5 +225,4 @@ export class BindingChain {
|
|
|
226
225
|
}
|
|
227
226
|
}
|
|
228
227
|
}
|
|
229
|
-
}
|
|
230
|
-
//# sourceMappingURL=binding-builders.js.map
|
|
228
|
+
}
|
|
@@ -67,9 +67,6 @@ class DefaultContainer {
|
|
|
67
67
|
if (this.#moduleRefs !== undefined || this.#moduleBindingIds !== undefined) {
|
|
68
68
|
builtSubsystems.push("container.moduleTables");
|
|
69
69
|
}
|
|
70
|
-
if (this.#registry.isNamedIndexBuilt) {
|
|
71
|
-
builtSubsystems.push("registry.namedIndex");
|
|
72
|
-
}
|
|
73
70
|
if (this.#registry.isTaggedIndexBuilt) {
|
|
74
71
|
builtSubsystems.push("registry.taggedIndex");
|
|
75
72
|
}
|
|
@@ -516,8 +513,10 @@ class DefaultContainer {
|
|
|
516
513
|
!this.#lifecycle.hasActivationHandlers(binding.token)) {
|
|
517
514
|
continue;
|
|
518
515
|
}
|
|
516
|
+
// Warm the binding itself — re-selecting by its own criteria could pick a different
|
|
517
|
+
// candidate whose criteria are a subset of them.
|
|
519
518
|
const slotOptions = bindingSlotToResolveOptions(binding.slot);
|
|
520
|
-
await this.
|
|
519
|
+
await this.#resolver.warmBindingAsync(binding, slotOptions);
|
|
521
520
|
}
|
|
522
521
|
}
|
|
523
522
|
}
|
|
@@ -744,5 +743,4 @@ export const Container = {
|
|
|
744
743
|
await container.loadAsync(...modules);
|
|
745
744
|
return container;
|
|
746
745
|
},
|
|
747
|
-
};
|
|
748
|
-
//# sourceMappingURL=container.js.map
|
|
746
|
+
};
|
|
@@ -9,5 +9,4 @@ import type { BindingScope } from "#/core/types";
|
|
|
9
9
|
*
|
|
10
10
|
* @since 0.3.16-canary.0
|
|
11
11
|
*/
|
|
12
|
-
export declare function effectiveBindingScope(binding: Binding): BindingScope;
|
|
13
|
-
//# sourceMappingURL=binding-scope.d.ts.map
|
|
12
|
+
export declare function effectiveBindingScope(binding: Binding): BindingScope;
|
package/dist/core/binding.d.ts
CHANGED
|
@@ -3,18 +3,31 @@ import type { Token } from "#/core/token";
|
|
|
3
3
|
import type { ActivationHandler, BindingIdentifier, BindingScope, Constructor, DeactivationHandler, ResolutionContext, ResolutionFrame, BindingConstraint } from "#/core/types";
|
|
4
4
|
import type { InjectableDependency, InjectionDescriptor, ResolvedDependencyValue } from "#/injection/descriptor";
|
|
5
5
|
/**
|
|
6
|
-
* The
|
|
6
|
+
* The criterion set a binding registers under and a request matches against.
|
|
7
7
|
*
|
|
8
8
|
* @since 0.3.16-canary.0
|
|
9
9
|
*/
|
|
10
10
|
export interface BindingSlot {
|
|
11
|
+
/** Derived view of the reserved `slotName` criterion — `undefined` when the slot carries none. */
|
|
11
12
|
readonly name: string | undefined;
|
|
13
|
+
/** The whole criterion set, the reserved name criterion included. */
|
|
12
14
|
readonly tags: ReadonlyArray<BindingTag>;
|
|
13
15
|
/** OR of this slot's tag keys, so the subset test is one word compare. */
|
|
14
16
|
readonly keyMask: TagKeyMask;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* Builds a slot from its criterion set, deriving the name view and key mask.
|
|
20
|
+
*
|
|
21
|
+
* @remarks The one place the derived `name` is computed — a slot assembled any other way can carry
|
|
22
|
+
* a name criterion the readers of the view never see.
|
|
23
|
+
*
|
|
24
|
+
* @since 0.8.0
|
|
25
|
+
*/
|
|
26
|
+
export declare function createBindingSlot(tags: ReadonlyArray<BindingTag>): BindingSlot;
|
|
27
|
+
/**
|
|
28
|
+
* Returns whether two slots carry the same criterion set, in any order.
|
|
29
|
+
*
|
|
30
|
+
* @remarks The derived `name` is not compared — the criterion set alone is the identity.
|
|
18
31
|
*
|
|
19
32
|
* @since 0.3.16-canary.0
|
|
20
33
|
*/
|
|
@@ -323,5 +336,4 @@ export interface SingletonLifecycleBuilder<Value> {
|
|
|
323
336
|
onDeactivation(fn: DeactivationHandler<Value>): this;
|
|
324
337
|
id(): BindingIdentifier;
|
|
325
338
|
}
|
|
326
|
-
export {};
|
|
327
|
-
//# sourceMappingURL=binding.d.ts.map
|
|
339
|
+
export {};
|
package/dist/core/binding.js
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
|
-
import { NO_TAG_KEYS } from "#/core/tag";
|
|
1
|
+
import { NO_TAG_KEYS, slotName, tagKeyMaskOf } from "#/core/tag";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Builds a slot from its criterion set, deriving the name view and key mask.
|
|
4
|
+
*
|
|
5
|
+
* @remarks The one place the derived `name` is computed — a slot assembled any other way can carry
|
|
6
|
+
* a name criterion the readers of the view never see.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.8.0
|
|
9
|
+
*/
|
|
10
|
+
export function createBindingSlot(tags) {
|
|
11
|
+
let name;
|
|
12
|
+
for (const criterion of tags) {
|
|
13
|
+
if (criterion.key === slotName) {
|
|
14
|
+
name = criterion.value;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Frozen like DEFAULT_BINDING_SLOT's list: frames and snapshots alias a slot's tags.
|
|
19
|
+
return { name, tags: Object.freeze([...tags]), keyMask: tagKeyMaskOf(tags) };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns whether two slots carry the same criterion set, in any order.
|
|
23
|
+
*
|
|
24
|
+
* @remarks The derived `name` is not compared — the criterion set alone is the identity.
|
|
4
25
|
*
|
|
5
26
|
* @since 0.3.16-canary.0
|
|
6
27
|
*/
|
|
7
28
|
export function bindingSlotEquals(left, right) {
|
|
8
|
-
if (left.
|
|
29
|
+
if (left.keyMask !== right.keyMask || left.tags.length !== right.tags.length) {
|
|
9
30
|
return false;
|
|
10
31
|
}
|
|
11
32
|
for (const criterion of left.tags) {
|
|
@@ -37,7 +58,7 @@ export const DEFAULT_BINDING_SLOT = { name: undefined, tags: Object.freeze([]),
|
|
|
37
58
|
* @since 0.3.16-canary.0
|
|
38
59
|
*/
|
|
39
60
|
export function bindingSlotToString(slot) {
|
|
40
|
-
if (slot.
|
|
61
|
+
if (slot.tags.length === 0) {
|
|
41
62
|
return "default";
|
|
42
63
|
}
|
|
43
64
|
const parts = [];
|
|
@@ -45,6 +66,10 @@ export function bindingSlotToString(slot) {
|
|
|
45
66
|
parts.push(`name:${slot.name}`);
|
|
46
67
|
}
|
|
47
68
|
for (const criterion of slot.tags) {
|
|
69
|
+
// The reserved criterion already printed as the `name:` part.
|
|
70
|
+
if (criterion.key === slotName) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
48
73
|
parts.push(`tag:${criterion.key.name}=${String(criterion.value)}`);
|
|
49
74
|
}
|
|
50
75
|
return parts.join(",");
|
|
@@ -112,5 +137,4 @@ export function refinableFields(binding) {
|
|
|
112
137
|
*/
|
|
113
138
|
export function clearBindingFrame(binding) {
|
|
114
139
|
binding.frame = undefined;
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=binding.js.map
|
|
140
|
+
}
|
|
@@ -49,5 +49,4 @@ export declare function constraintRequirementsOf(predicate: BindingConstraint):
|
|
|
49
49
|
*
|
|
50
50
|
* @since 0.6.1
|
|
51
51
|
*/
|
|
52
|
-
export declare function mergingConstraintRequirements(composite: BindingConstraint, left: BindingConstraint, right: BindingConstraint): BindingConstraint;
|
|
53
|
-
//# sourceMappingURL=constraint-requirement.d.ts.map
|
|
52
|
+
export declare function mergingConstraintRequirements(composite: BindingConstraint, left: BindingConstraint, right: BindingConstraint): BindingConstraint;
|
|
@@ -14,5 +14,4 @@ export type Constructor<out Value = unknown> = new (...args: Array<never>) => Va
|
|
|
14
14
|
*
|
|
15
15
|
* @since 0.3.16-canary.0
|
|
16
16
|
*/
|
|
17
|
-
export type ConstructorInvocation = new (...args: Array<unknown>) => unknown;
|
|
18
|
-
//# sourceMappingURL=constructor-type.d.ts.map
|
|
17
|
+
export type ConstructorInvocation = new (...args: Array<unknown>) => unknown;
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {};
|
|
2
|
-
//# sourceMappingURL=constructor-type.js.map
|
|
1
|
+
export {};
|
|
@@ -25,5 +25,4 @@ export declare function getOrInsert<Key, Value extends {} | null>(map: Map<Key,
|
|
|
25
25
|
*
|
|
26
26
|
* @since 0.7.0
|
|
27
27
|
*/
|
|
28
|
-
export declare function getOrInsertComputed<Key, Value extends {} | null>(map: Map<Key, Value>, key: NoInfer<Key>, create: (key: NoInfer<Key>) => NoInfer<Value>): Value;
|
|
29
|
-
//# sourceMappingURL=map-upsert.d.ts.map
|
|
28
|
+
export declare function getOrInsertComputed<Key, Value extends {} | null>(map: Map<Key, Value>, key: NoInfer<Key>, create: (key: NoInfer<Key>) => NoInfer<Value>): Value;
|
package/dist/core/map-upsert.js
CHANGED
package/dist/core/module.d.ts
CHANGED
package/dist/core/module.js
CHANGED
package/dist/core/registry.d.ts
CHANGED
|
@@ -41,7 +41,6 @@ export declare class BindingRegistry {
|
|
|
41
41
|
clear(): ReadonlyArray<Binding>;
|
|
42
42
|
/** Whether a slot-based binding currently occupies `binding`'s slot, so adding it would displace. */
|
|
43
43
|
hasSlotOccupant(binding: Binding): boolean;
|
|
44
|
-
getSimpleNamed(token: Token<unknown> | Constructor, name: string): Binding | undefined;
|
|
45
44
|
/**
|
|
46
45
|
* The binding indexed under one criterion.
|
|
47
46
|
*
|
|
@@ -59,9 +58,6 @@ export declare class BindingRegistry {
|
|
|
59
58
|
getFastDefault(token: Token<unknown> | Constructor): Binding | undefined;
|
|
60
59
|
/** Summarize available slot strings for a token (for error messages). */
|
|
61
60
|
availableSlotStrings(token: Token<unknown> | Constructor): Array<string>;
|
|
62
|
-
/** Whether the deferred named-slot index has had to be built. */
|
|
63
|
-
get isNamedIndexBuilt(): boolean;
|
|
64
61
|
/** Whether the deferred tagged-slot index has had to be built. */
|
|
65
62
|
get isTaggedIndexBuilt(): boolean;
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=registry.d.ts.map
|
|
63
|
+
}
|
package/dist/core/registry.js
CHANGED
|
@@ -12,15 +12,13 @@ export class BindingRegistry {
|
|
|
12
12
|
#bindings = new Map();
|
|
13
13
|
// Fast lookup by binding ID
|
|
14
14
|
#byId = new Map();
|
|
15
|
-
// Fast lookup for slot { name, tags: [] } — unallocated until a named binding is registered.
|
|
16
|
-
#simpleNamed;
|
|
17
15
|
// Fast path for one default slot binding with no predicate
|
|
18
16
|
#fastDefault = new Map();
|
|
19
|
-
// Fast lookup for a slot carrying exactly one
|
|
20
|
-
// the
|
|
17
|
+
// Fast lookup for a slot carrying exactly one criterion (a lone name folds here too) — keyed by
|
|
18
|
+
// the interned criterion itself, so the pair is one hash. Unallocated until such a slot lands.
|
|
21
19
|
#simpleTagged;
|
|
22
|
-
//
|
|
23
|
-
//
|
|
20
|
+
// Slots with two or more criteria, bucketed by their FIRST criterion. A matching slot's every
|
|
21
|
+
// criterion is in the request, so walking the request's buckets finds each candidate exactly once.
|
|
24
22
|
#multiTagged;
|
|
25
23
|
// Set on the first constant registered and never cleared. Teardown only needs the negative answer
|
|
26
24
|
// to be exact, and that is what lets a container holding no constant skip its sweep entirely.
|
|
@@ -67,7 +65,6 @@ export class BindingRegistry {
|
|
|
67
65
|
if (existingIndex !== -1) {
|
|
68
66
|
displacedBinding = bindingsForToken[existingIndex];
|
|
69
67
|
this.#byId.delete(displacedBinding.id);
|
|
70
|
-
this.#deindexSimpleNamedBinding(key, displacedBinding);
|
|
71
68
|
this.#deindexSimpleTaggedBinding(key, displacedBinding);
|
|
72
69
|
this.#deindexMultiTaggedBinding(key, displacedBinding);
|
|
73
70
|
}
|
|
@@ -79,7 +76,6 @@ export class BindingRegistry {
|
|
|
79
76
|
}
|
|
80
77
|
this.#bindings.set(key, nextBindings);
|
|
81
78
|
this.#byId.set(binding.id, binding);
|
|
82
|
-
this.#indexSimpleNamedBinding(key, binding);
|
|
83
79
|
this.#indexSimpleTaggedBinding(key, binding);
|
|
84
80
|
this.#indexMultiTaggedBinding(key, binding);
|
|
85
81
|
this.#refreshFastDefaultForToken(key);
|
|
@@ -91,7 +87,6 @@ export class BindingRegistry {
|
|
|
91
87
|
const key = token;
|
|
92
88
|
const bindingsForToken = this.#bindings.get(key) ?? [];
|
|
93
89
|
this.#bindings.delete(key);
|
|
94
|
-
this.#simpleNamed?.delete(key);
|
|
95
90
|
this.#simpleTagged?.delete(key);
|
|
96
91
|
this.#multiTagged?.delete(key);
|
|
97
92
|
this.#fastDefault.delete(key);
|
|
@@ -114,12 +109,10 @@ export class BindingRegistry {
|
|
|
114
109
|
const bindingIndex = bindingsForToken.findIndex((candidate) => candidate.id === id);
|
|
115
110
|
// Copy-on-write, like `add`: a walk holding the current array must not lose its place.
|
|
116
111
|
const remaining = bindingIndex === -1 ? bindingsForToken : bindingsForToken.toSpliced(bindingIndex, 1);
|
|
117
|
-
this.#deindexSimpleNamedBinding(key, binding);
|
|
118
112
|
this.#deindexSimpleTaggedBinding(key, binding);
|
|
119
113
|
this.#deindexMultiTaggedBinding(key, binding);
|
|
120
114
|
if (remaining.length === 0) {
|
|
121
115
|
this.#bindings.delete(key);
|
|
122
|
-
this.#simpleNamed?.delete(key);
|
|
123
116
|
this.#simpleTagged?.delete(key);
|
|
124
117
|
this.#multiTagged?.delete(key);
|
|
125
118
|
this.#fastDefault.delete(key);
|
|
@@ -159,7 +152,6 @@ export class BindingRegistry {
|
|
|
159
152
|
const all = this.allBindings();
|
|
160
153
|
this.#bindings.clear();
|
|
161
154
|
this.#byId.clear();
|
|
162
|
-
this.#simpleNamed?.clear();
|
|
163
155
|
this.#simpleTagged?.clear();
|
|
164
156
|
this.#multiTagged?.clear();
|
|
165
157
|
this.#fastDefault.clear();
|
|
@@ -176,9 +168,6 @@ export class BindingRegistry {
|
|
|
176
168
|
}
|
|
177
169
|
return candidates.some((candidate) => !isPurePredicateBinding(candidate) && bindingSlotEquals(candidate.slot, binding.slot));
|
|
178
170
|
}
|
|
179
|
-
getSimpleNamed(token, name) {
|
|
180
|
-
return this.#simpleNamed?.get(token)?.get(name);
|
|
181
|
-
}
|
|
182
171
|
/**
|
|
183
172
|
* The binding indexed under one criterion.
|
|
184
173
|
*
|
|
@@ -255,31 +244,6 @@ export class BindingRegistry {
|
|
|
255
244
|
bucket.splice(bindingIndex, 1);
|
|
256
245
|
}
|
|
257
246
|
}
|
|
258
|
-
#indexSimpleNamedBinding(tokenKey, binding) {
|
|
259
|
-
const name = simpleNameOf(binding);
|
|
260
|
-
if (name === undefined) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
this.#simpleNamed ??= new Map();
|
|
264
|
-
const bindingsByName = getOrInsert(this.#simpleNamed, tokenKey, new Map());
|
|
265
|
-
bindingsByName.set(name, binding);
|
|
266
|
-
}
|
|
267
|
-
#deindexSimpleNamedBinding(tokenKey, binding) {
|
|
268
|
-
const name = simpleNameOf(binding);
|
|
269
|
-
if (name === undefined) {
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
const bindingsByName = this.#simpleNamed?.get(tokenKey);
|
|
273
|
-
if (bindingsByName === undefined) {
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
if (bindingsByName.get(name)?.id === binding.id) {
|
|
277
|
-
bindingsByName.delete(name);
|
|
278
|
-
if (bindingsByName.size === 0) {
|
|
279
|
-
this.#simpleNamed.delete(tokenKey);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
247
|
#refreshFastDefaultForToken(tokenKey) {
|
|
284
248
|
const bindingsForToken = this.#bindings.get(tokenKey);
|
|
285
249
|
const onlyBinding = bindingsForToken?.length === 1 ? bindingsForToken[0] : undefined;
|
|
@@ -289,43 +253,31 @@ export class BindingRegistry {
|
|
|
289
253
|
}
|
|
290
254
|
this.#fastDefault.delete(tokenKey);
|
|
291
255
|
}
|
|
292
|
-
/** Whether the deferred named-slot index has had to be built. */
|
|
293
|
-
get isNamedIndexBuilt() {
|
|
294
|
-
return this.#simpleNamed !== undefined;
|
|
295
|
-
}
|
|
296
256
|
/** Whether the deferred tagged-slot index has had to be built. */
|
|
297
257
|
get isTaggedIndexBuilt() {
|
|
298
258
|
return this.#simpleTagged !== undefined;
|
|
299
259
|
}
|
|
300
260
|
}
|
|
301
|
-
/** The name a binding is indexed under, or `undefined` when its slot is more than a plain name. */
|
|
302
|
-
function simpleNameOf(binding) {
|
|
303
|
-
const { name, tags } = binding.slot;
|
|
304
|
-
return name !== undefined && tags.length === 0 ? name : undefined;
|
|
305
|
-
}
|
|
306
261
|
/**
|
|
307
|
-
* The
|
|
262
|
+
* The criterion a binding is indexed under, or `undefined` when its slot carries more than one.
|
|
308
263
|
*
|
|
309
|
-
* @remarks Carries predicate-bearing bindings too
|
|
310
|
-
*
|
|
264
|
+
* @remarks Carries predicate-bearing bindings too: every lane that reads this index already
|
|
265
|
+
* re-checks what it finds, so an indexed hit was never unconditional.
|
|
311
266
|
*/
|
|
312
267
|
function simpleTagOf(binding) {
|
|
313
|
-
const {
|
|
314
|
-
return
|
|
268
|
+
const { tags } = binding.slot;
|
|
269
|
+
return tags.length === 1 ? tags[0] : undefined;
|
|
315
270
|
}
|
|
316
|
-
/** The first criterion a multi-
|
|
271
|
+
/** The first criterion a multi-criterion slot is bucketed under, or `undefined` for any other shape. */
|
|
317
272
|
function multiTagFirstOf(binding) {
|
|
318
|
-
const {
|
|
319
|
-
return
|
|
273
|
+
const { tags } = binding.slot;
|
|
274
|
+
return tags.length >= 2 ? tags[0] : undefined;
|
|
320
275
|
}
|
|
321
276
|
/** A binding nothing has to be matched against: the default slot, no predicate. */
|
|
322
277
|
function isDefaultSlotBinding(binding) {
|
|
323
|
-
|
|
324
|
-
return name === undefined && tags.length === 0 && binding.predicate === undefined;
|
|
278
|
+
return binding.slot.tags.length === 0 && binding.predicate === undefined;
|
|
325
279
|
}
|
|
326
280
|
/** A predicate with no slot constraint: last-wins does not apply to it. */
|
|
327
281
|
function isPurePredicateBinding(binding) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
//# sourceMappingURL=registry.js.map
|
|
282
|
+
return binding.predicate !== undefined && binding.slot.tags.length === 0;
|
|
283
|
+
}
|
package/dist/core/tag.d.ts
CHANGED
|
@@ -47,6 +47,14 @@ export interface TagKey<Value = unknown> {
|
|
|
47
47
|
readonly mask: TagKeyMask;
|
|
48
48
|
/** The criterion for one value, interned: the same value always yields the same object. */
|
|
49
49
|
of(value: Value): BindingTag<Value>;
|
|
50
|
+
/**
|
|
51
|
+
* The interned criterion for a value, or `undefined` when none was ever minted.
|
|
52
|
+
*
|
|
53
|
+
* @remarks Reading without minting is what keeps a request-side value from being retained for
|
|
54
|
+
* the process lifetime: a value no binding ever declared has no criterion, so a lookup can
|
|
55
|
+
* answer "no match" without inserting one.
|
|
56
|
+
*/
|
|
57
|
+
peek(value: Value): BindingTag<Value> | undefined;
|
|
50
58
|
}
|
|
51
59
|
/**
|
|
52
60
|
* Declares a tag key, whose `of()` builds the criteria a `whenTagged` and a resolve both take.
|
|
@@ -64,6 +72,24 @@ export interface TagKey<Value = unknown> {
|
|
|
64
72
|
* @since 0.6.0
|
|
65
73
|
*/
|
|
66
74
|
export declare function tag<Value = unknown>(name: string): TagKey<Value>;
|
|
75
|
+
/**
|
|
76
|
+
* The reserved key a slot's name is a criterion of.
|
|
77
|
+
*
|
|
78
|
+
* @remarks `whenNamed(n)` and a request's `name` are sugar for `slotName.of(n)`, so one selection
|
|
79
|
+
* model serves both spellings — a name takes part in key masks, indexes and specificity like any
|
|
80
|
+
* criterion. What reserves the key is its identity; diagnostics render its criteria as `name:<value>`.
|
|
81
|
+
*
|
|
82
|
+
* @since 0.8.0
|
|
83
|
+
*/
|
|
84
|
+
export declare const slotName: TagKey<string>;
|
|
85
|
+
/**
|
|
86
|
+
* The reserved criterion for a name, or `undefined` while no binding has declared it.
|
|
87
|
+
*
|
|
88
|
+
* @remarks Reads without minting, so a request-side name no binding declared is never retained.
|
|
89
|
+
*
|
|
90
|
+
* @since 0.8.0
|
|
91
|
+
*/
|
|
92
|
+
export declare function slotNameCriterionOf(name: string): BindingTag<string> | undefined;
|
|
67
93
|
/**
|
|
68
94
|
* The key set a list of criteria covers.
|
|
69
95
|
*
|
|
@@ -76,5 +102,4 @@ export declare function tagKeyMaskOf(tags: ReadonlyArray<BindingTag>): TagKeyMas
|
|
|
76
102
|
* @since 0.6.0
|
|
77
103
|
*/
|
|
78
104
|
export declare function coversTagKeys(requestMask: TagKeyMask, slotMask: TagKeyMask): boolean;
|
|
79
|
-
export {};
|
|
80
|
-
//# sourceMappingURL=tag.d.ts.map
|
|
105
|
+
export {};
|
package/dist/core/tag.js
CHANGED
|
@@ -49,6 +49,22 @@ export function tag(name) {
|
|
|
49
49
|
// split and `NaN` hits itself, with no `internKeyFor` detour.
|
|
50
50
|
let lastValue;
|
|
51
51
|
let lastPair;
|
|
52
|
+
// The miss paths live outside `of()`/`peek()` so the hot wrappers stay small enough to inline.
|
|
53
|
+
const internPair = (value) => {
|
|
54
|
+
const cacheKey = internKeyFor(value);
|
|
55
|
+
const existing = interned.get(cacheKey);
|
|
56
|
+
if (existing !== undefined) {
|
|
57
|
+
lastValue = value;
|
|
58
|
+
lastPair = existing;
|
|
59
|
+
return existing;
|
|
60
|
+
}
|
|
61
|
+
const pair = { key, value, mask };
|
|
62
|
+
interned.set(cacheKey, pair);
|
|
63
|
+
lastValue = value;
|
|
64
|
+
lastPair = pair;
|
|
65
|
+
return pair;
|
|
66
|
+
};
|
|
67
|
+
const peekInterned = (value) => interned.get(internKeyFor(value));
|
|
52
68
|
const key = {
|
|
53
69
|
name,
|
|
54
70
|
id,
|
|
@@ -57,22 +73,49 @@ export function tag(name) {
|
|
|
57
73
|
if (lastPair !== undefined && Object.is(value, lastValue)) {
|
|
58
74
|
return lastPair;
|
|
59
75
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
lastPair
|
|
65
|
-
return existing;
|
|
76
|
+
return internPair(value);
|
|
77
|
+
},
|
|
78
|
+
peek(value) {
|
|
79
|
+
if (lastPair !== undefined && Object.is(value, lastValue)) {
|
|
80
|
+
return lastPair;
|
|
66
81
|
}
|
|
67
|
-
|
|
68
|
-
interned.set(cacheKey, pair);
|
|
69
|
-
lastValue = value;
|
|
70
|
-
lastPair = pair;
|
|
71
|
-
return pair;
|
|
82
|
+
return peekInterned(value);
|
|
72
83
|
},
|
|
73
84
|
};
|
|
74
85
|
return key;
|
|
75
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* The reserved key a slot's name is a criterion of.
|
|
89
|
+
*
|
|
90
|
+
* @remarks `whenNamed(n)` and a request's `name` are sugar for `slotName.of(n)`, so one selection
|
|
91
|
+
* model serves both spellings — a name takes part in key masks, indexes and specificity like any
|
|
92
|
+
* criterion. What reserves the key is its identity; diagnostics render its criteria as `name:<value>`.
|
|
93
|
+
*
|
|
94
|
+
* @since 0.8.0
|
|
95
|
+
*/
|
|
96
|
+
export const slotName = tag("di:name");
|
|
97
|
+
// One-entry front for the reserved key's read: a name's criterion never changes once minted, so a
|
|
98
|
+
// hit is sound forever, and a miss is never cached so a later `whenNamed` bind is still seen.
|
|
99
|
+
let lastPeekedName;
|
|
100
|
+
let lastPeekedCriterion;
|
|
101
|
+
/**
|
|
102
|
+
* The reserved criterion for a name, or `undefined` while no binding has declared it.
|
|
103
|
+
*
|
|
104
|
+
* @remarks Reads without minting, so a request-side name no binding declared is never retained.
|
|
105
|
+
*
|
|
106
|
+
* @since 0.8.0
|
|
107
|
+
*/
|
|
108
|
+
export function slotNameCriterionOf(name) {
|
|
109
|
+
if (name === lastPeekedName) {
|
|
110
|
+
return lastPeekedCriterion;
|
|
111
|
+
}
|
|
112
|
+
const criterion = slotName.peek(name);
|
|
113
|
+
if (criterion !== undefined) {
|
|
114
|
+
lastPeekedName = name;
|
|
115
|
+
lastPeekedCriterion = criterion;
|
|
116
|
+
}
|
|
117
|
+
return criterion;
|
|
118
|
+
}
|
|
76
119
|
/**
|
|
77
120
|
* The key set a list of criteria covers.
|
|
78
121
|
*
|
|
@@ -92,5 +135,4 @@ export function tagKeyMaskOf(tags) {
|
|
|
92
135
|
*/
|
|
93
136
|
export function coversTagKeys(requestMask, slotMask) {
|
|
94
137
|
return (requestMask & slotMask) === slotMask;
|
|
95
|
-
}
|
|
96
|
-
//# sourceMappingURL=tag.js.map
|
|
138
|
+
}
|
package/dist/core/token.d.ts
CHANGED
package/dist/core/token.js
CHANGED
package/dist/core/types.d.ts
CHANGED
|
@@ -112,5 +112,4 @@ export interface ResolutionContext {
|
|
|
112
112
|
*
|
|
113
113
|
* @since 0.3.16-canary.0
|
|
114
114
|
*/
|
|
115
|
-
export type TokenValue<Type> = Type extends Token<infer Value> ? Value : Type extends Constructor<infer Value> ? Value : never;
|
|
116
|
-
//# sourceMappingURL=types.d.ts.map
|
|
115
|
+
export type TokenValue<Type> = Type extends Token<infer Value> ? Value : Type extends Constructor<infer Value> ? Value : never;
|
package/dist/core/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {};
|
|
2
|
-
//# sourceMappingURL=types.js.map
|
|
1
|
+
export {};
|
|
@@ -9,5 +9,4 @@ type ClassAccessorDecorator<This, Value> = (target: ClassAccessorDecoratorTarget
|
|
|
9
9
|
* @since 0.3.16-canary.0
|
|
10
10
|
*/
|
|
11
11
|
export declare function inject<Value>(token: Token<Value> | Constructor<Value>, options?: InjectOptions): InjectionDescriptor<Value> & ClassAccessorDecorator<unknown, Value>;
|
|
12
|
-
export {};
|
|
13
|
-
//# sourceMappingURL=inject.d.ts.map
|
|
12
|
+
export {};
|
|
@@ -54,5 +54,4 @@ export declare function injectable(): (target: unknown, context: ClassDecoratorC
|
|
|
54
54
|
* @since 0.3.16-canary.0
|
|
55
55
|
*/
|
|
56
56
|
export declare function injectable<const Deps extends ReadonlyArray<InjectableDependency>>(deps: Deps, options?: InjectableOptions): <Target extends abstract new (...args: InjectedParameters<Deps>) => unknown>(target: Target & (number extends Deps["length"] ? unknown : Deps["length"] extends ConstructorParameters<Target>["length"] ? unknown : never), context: ClassDecoratorContext) => void;
|
|
57
|
-
export type { InjectableDependency };
|
|
58
|
-
//# sourceMappingURL=injectable.d.ts.map
|
|
57
|
+
export type { InjectableDependency };
|