Skip to content

Commit 4ca596b

Browse files
committed
refactor(di): keep the deferred-loader provider internal to the container
A record carrying only a lazy-require loader resolves to an error until the loader registers something onto it, so the form is not one callers should be offered: drop ILazyRequireProvider from the exported Provider union and keep it in an InternalProvider alias the container accepts. Add hasResolver() so the deferred paths can tell a record that a loader has filled in from one it left empty.
1 parent c57a29d commit 4ca596b

3 files changed

Lines changed: 29 additions & 6 deletions

File tree

lib/common/di/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type { IContractOptions } from "./contract";
1212
export { provide, provideLazy } from "./providers";
1313
export type {
1414
Provider,
15+
InternalProvider,
1516
ProviderToken,
1617
Type,
1718
AbstractType,

lib/common/di/injector.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { annotate } from "../helpers";
22
import { getContractName } from "./contract";
33
import { resolveForwardRef } from "./forward-ref";
44
import { runInInjectionContext } from "./inject";
5-
import type { Provider, ProviderToken, Type } from "./providers";
5+
import type {
6+
InternalProvider,
7+
Provider,
8+
ProviderToken,
9+
Type,
10+
} from "./providers";
611

712
type TokenKey = string | Function;
813

@@ -131,7 +136,7 @@ export class Injector {
131136
}
132137

133138
/** Merge-mutate: re-registering a key updates the existing record in place. */
134-
public register(providers: Provider | Provider[]): void {
139+
public register(providers: InternalProvider | InternalProvider[]): void {
135140
const list = Array.isArray(providers) ? providers : [providers];
136141
for (const provider of list) {
137142
const keys = this.keysFor(provider.provide);
@@ -172,6 +177,16 @@ export class Injector {
172177
return !!this.findRecord(token);
173178
}
174179

180+
/**
181+
* Whether the token can actually produce a value. A record carrying only a
182+
* pending loader answers `has()` but resolves to an error, so the deferred
183+
* paths use this to tell "loaded and registered" from "loaded and silent".
184+
*/
185+
protected hasResolver(token: ProviderToken): boolean {
186+
const found = this.findRecord(token);
187+
return !!found && found.record.kind !== undefined;
188+
}
189+
175190
/** First cached instance for a token, without triggering construction. */
176191
public peek(token: ProviderToken): any {
177192
const found = this.findRecord(token);
@@ -230,7 +245,10 @@ export class Injector {
230245
return name !== undefined ? [token, name] : [token];
231246
}
232247

233-
private applyProvider(record: IProviderRecord, provider: Provider): void {
248+
private applyProvider(
249+
record: IProviderRecord,
250+
provider: InternalProvider,
251+
): void {
234252
record.shared = provider.shared === undefined ? true : provider.shared;
235253

236254
if ("useLazyRequire" in provider) {

lib/common/di/providers.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ export interface ILegacyClassProvider extends IBaseProvider<any> {
3737

3838
/**
3939
* Deferred side-effect loader (Yok's `require(name, path)`): running it is
40-
* expected to register the real resolver onto this same record.
40+
* expected to register the real resolver onto this same record. Container
41+
* internals only — a record left with nothing but a loader resolves to an
42+
* error, so it is deliberately kept out of `Provider`.
4143
*/
4244
export interface ILazyRequireProvider extends IBaseProvider<any> {
4345
useLazyRequire: () => void;
@@ -48,8 +50,10 @@ export type Provider<T = any> =
4850
| IValueProvider<T>
4951
| IFactoryProvider<T>
5052
| ILazyClassProvider<T>
51-
| ILegacyClassProvider
52-
| ILazyRequireProvider;
53+
| ILegacyClassProvider;
54+
55+
/** The provider forms the container accepts, including the unpublished ones. */
56+
export type InternalProvider<T = any> = Provider<T> | ILazyRequireProvider;
5357

5458
/** Enforces at compile time that the implementation satisfies the token. */
5559
export const provide = <T>(

0 commit comments

Comments
 (0)