refactor(core): Remove the optional flag from Injector and all casts. (#60154)

Note that this does NOT use the retrieve method yet. I believe we need to move the logic for notFoundValue into the inject implementation.

PR Close #60154
This commit is contained in:
iteriani
2025-02-27 17:26:32 -08:00
committed by Andrew Kushnir
parent 6ea0318df6
commit ac94604ef2
20 changed files with 112 additions and 65 deletions
@@ -16,7 +16,7 @@ export interface InjectionToken<T> extends Type<T> {
// @public (undocumented)
export interface Injector {
// (undocumented)
retrieve?<T>(token: InjectionToken<T>, options?: unknown): T | NotFound;
retrieve<T>(token: InjectionToken<T>, options?: unknown): T | NotFound;
}
// @public
+1 -1
View File
@@ -10,7 +10,7 @@ import {InjectionToken} from './injection_token';
import {NotFound} from './not_found';
export interface Injector {
retrieve?<T>(token: InjectionToken<T>, options?: unknown): T | NotFound;
retrieve<T>(token: InjectionToken<T>, options?: unknown): T | NotFound;
}
/**
+7 -2
View File
@@ -14,8 +14,9 @@ import {
import {getInjectImplementation, setInjectImplementation} from './inject_switch';
import type {Injector} from './injector';
import {getCurrentInjector, setCurrentInjector} from './injector_compatibility';
import {getCurrentInjector, setCurrentInjector, RetrievingInjector} from './injector_compatibility';
import {assertNotDestroyed, R3Injector} from './r3_injector';
import {Injector as PrimitivesInjector} from '@angular/core/primitives/di';
/**
* Runs the given function in the [context](guide/di/dependency-injection-context) of the given
@@ -32,15 +33,19 @@ import {assertNotDestroyed, R3Injector} from './r3_injector';
* @publicApi
*/
export function runInInjectionContext<ReturnT>(injector: Injector, fn: () => ReturnT): ReturnT {
let internalInjector: PrimitivesInjector;
if (injector instanceof R3Injector) {
assertNotDestroyed(injector);
internalInjector = injector;
} else {
internalInjector = new RetrievingInjector(injector);
}
let prevInjectorProfilerContext: InjectorProfilerContext;
if (ngDevMode) {
prevInjectorProfilerContext = setInjectorProfilerContext({injector, token: null});
}
const prevInjector = setCurrentInjector(injector);
const prevInjector = setCurrentInjector(internalInjector);
const previousInjectImplementation = setInjectImplementation(undefined);
try {
return fn();
+24 -13
View File
@@ -24,18 +24,18 @@ import {
} from './interface/injector';
import {ProviderToken} from './provider_token';
import type {HostAttributeToken} from './host_attribute_token';
import * as di from '@angular/core/primitives/di';
import {
Injector as PrimitivesInjector,
NotFound,
NOT_FOUND,
InjectionToken as PrimitivesInjectionToken,
getCurrentInjector,
} from '@angular/core/primitives/di';
const _THROW_IF_NOT_FOUND = {};
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
export function getCurrentInjector(): Injector {
return di.getCurrentInjector() as unknown as Injector;
}
export function setCurrentInjector(injector: Injector | null | undefined): Injector {
return di.setCurrentInjector(injector as di.Injector) as unknown as Injector;
}
export {getCurrentInjector, setCurrentInjector} from '@angular/core/primitives/di';
/*
* Name of a property (that we patch onto DI decorator), which is used as an annotation of which
@@ -44,6 +44,14 @@ export function setCurrentInjector(injector: Injector | null | undefined): Injec
*/
const DI_DECORATOR_FLAG = '__NG_DI_FLAG__';
export class RetrievingInjector implements PrimitivesInjector {
constructor(readonly injector: Injector) {}
retrieve<T>(token: PrimitivesInjectionToken<T>, options: unknown): T | NotFound {
const ngOptions = options as InjectOptions;
return this.injector.get(token, ngOptions.optional ? NOT_FOUND : THROW_IF_NOT_FOUND, ngOptions);
}
}
export const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
const NG_TOKEN_PATH = 'ngTokenPath';
const NEW_LINE = /\n/gm;
@@ -65,11 +73,14 @@ export function injectInjectorOnly<T>(
} else if (getCurrentInjector() === null) {
return injectRootLimpMode(token, undefined, flags);
} else {
const value = getCurrentInjector().get(
token,
flags & InjectFlags.Optional ? null : undefined,
flags,
);
const currentInjector = getCurrentInjector();
let injector: Injector;
if (currentInjector instanceof RetrievingInjector) {
injector = currentInjector.injector;
} else {
injector = currentInjector as unknown as Injector;
}
const value = injector.get(token, flags & InjectFlags.Optional ? null : undefined, flags);
ngDevMode && emitInjectEvent(token as Type<unknown>, value, flags);
return value;
}
+12 -1
View File
@@ -74,6 +74,12 @@ import {
import {ProviderToken} from './provider_token';
import {INJECTOR_SCOPE, InjectorScope} from './scope';
import {setActiveConsumer} from '@angular/core/primitives/signals';
import {
Injector as PrimitivesInjector,
InjectionToken as PrimitivesInjectionToken,
NOT_FOUND,
NotFound,
} from '@angular/core/primitives/di';
/**
* Marker which indicates that a value has not yet been created from the factory function.
@@ -180,7 +186,7 @@ export abstract class EnvironmentInjector implements Injector {
abstract onDestroy(callback: () => void): () => void;
}
export class R3Injector extends EnvironmentInjector {
export class R3Injector extends EnvironmentInjector implements PrimitivesInjector {
/**
* Map of tokens to records which contain the instances of those tokens.
* - `null` value implies that we don't have the record. Used by tree-shakable injectors
@@ -235,6 +241,11 @@ export class R3Injector extends EnvironmentInjector {
this.injectorDefTypes = new Set(this.get(INJECTOR_DEF_TYPES, EMPTY_ARRAY, InjectFlags.Self));
}
retrieve<T>(token: PrimitivesInjectionToken<T>, options?: unknown): T | NotFound {
const ngOptions = options as InjectOptions;
return this.get(token, ngOptions.optional ? NOT_FOUND : THROW_IF_NOT_FOUND, ngOptions);
}
/**
* Destroy the injector and release references to every instance or provider associated with it.
*
@@ -107,6 +107,7 @@
"NG_INJ_DEF",
"NG_PIPE_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -140,6 +141,7 @@
"REMOVE_STYLES_ON_COMPONENT_DESTROY",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
"SELF_TOKEN_REGEX",
@@ -299,7 +301,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -457,7 +459,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -114,6 +114,7 @@
"NG_MOD_DEF",
"NG_PIPE_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -151,6 +152,7 @@
"REMOVE_STYLES_ON_COMPONENT_DESTROY",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RootComponent",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
@@ -320,7 +322,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -483,7 +485,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -83,6 +83,7 @@
"NG_MOD_DEF",
"NG_PIPE_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -115,6 +116,7 @@
"REMOVE_STYLES_ON_COMPONENT_DESTROY",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
"SIGNAL",
@@ -248,7 +250,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -391,7 +393,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -112,6 +112,7 @@
"NG_TEMPLATE_SELECTOR",
"NG_TEMP_TOKEN_PATH",
"NG_TOKEN_PATH",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -145,6 +146,7 @@
"REMOVE_STYLES_ON_COMPONENT_DESTROY",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
"SIGNAL",
@@ -300,7 +302,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -862,7 +864,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -119,6 +119,7 @@
"NG_PROV_DEF",
"NG_VALIDATORS",
"NG_VALUE_ACCESSOR",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -165,6 +166,7 @@
"Renderer2",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RootComponent",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
@@ -362,7 +364,7 @@
"getConstant",
"getControlAsyncValidators",
"getControlValidators",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -584,7 +586,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -111,6 +111,7 @@
"NG_PROV_DEF",
"NG_VALIDATORS",
"NG_VALUE_ACCESSOR",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -159,6 +160,7 @@
"RendererFactory2",
"RendererStyleFlags2",
"RequiredValidator",
"RetrievingInjector",
"RootComponent",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
@@ -349,7 +351,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -577,7 +579,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -58,6 +58,7 @@
"NG_INJ_DEF",
"NG_MOD_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -87,6 +88,7 @@
"REACTIVE_LVIEW_CONSUMER_NODE",
"REACTIVE_NODE",
"RendererFactory2",
"RetrievingInjector",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
"SIGNAL",
@@ -195,7 +197,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDeclarationTNode",
@@ -317,7 +319,7 @@
"setActiveConsumer",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setIncludeViewProviders",
"setInjectImplementation",
@@ -89,6 +89,7 @@
"NG_INJ_DEF",
"NG_PIPE_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -120,6 +121,7 @@
"RESPONSE_TYPE",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
"SIGNAL",
@@ -255,7 +257,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -421,7 +423,7 @@
"setActiveConsumer",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setIncludeViewProviders",
@@ -16,10 +16,12 @@
"NG_INJECTOR_DEF",
"NG_INJ_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_YET",
"NULL_INJECTOR",
"NullInjector",
"R3Injector",
"RetrievingInjector",
"RuntimeError",
"ScopedService",
"Subscription",
@@ -43,7 +45,7 @@
"forEachSingleProvider",
"forwardRef",
"getClosureSafeProperty",
"getCurrentInjector2",
"getCurrentInjector",
"getFactoryDef",
"getInjectableDef",
"getInjectorDef",
@@ -63,7 +65,7 @@
"processInjectorTypesWithProviders",
"resolveForwardRef",
"setActiveConsumer",
"setCurrentInjector2",
"setCurrentInjector",
"setInjectImplementation",
"stringify",
"walkProviderTree",
@@ -124,6 +124,7 @@
"NG_MOD_DEF",
"NG_PIPE_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -191,6 +192,7 @@
"RendererStyleFlags2",
"ResolveEnd",
"ResolveStart",
"RetrievingInjector",
"RouteConfigLoadEnd",
"RouteConfigLoadStart",
"RouteReuseStrategy",
@@ -429,7 +431,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentQueryIndex",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
@@ -668,7 +670,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -77,6 +77,7 @@
"NG_INJ_DEF",
"NG_PIPE_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -105,6 +106,7 @@
"REMOVE_STYLES_ON_COMPONENT_DESTROY",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
"SIGNAL",
@@ -222,7 +224,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -350,7 +352,7 @@
"setActiveConsumer",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setIncludeViewProviders",
@@ -85,6 +85,7 @@
"NG_MOD_DEF",
"NG_PIPE_DEF",
"NG_PROV_DEF",
"NOT_FOUND",
"NOT_FOUND2",
"NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",
"NOT_YET",
@@ -124,6 +125,7 @@
"REMOVE_STYLES_ON_COMPONENT_DESTROY",
"RendererFactory2",
"RendererStyleFlags2",
"RetrievingInjector",
"RuntimeError",
"SCHEDULE_IN_ROOT_ZONE",
"SIGNAL",
@@ -293,7 +295,7 @@
"getComponentDef",
"getComponentLViewByIndex",
"getConstant",
"getCurrentInjector2",
"getCurrentInjector",
"getCurrentTNode",
"getCurrentTNodePlaceholderOk",
"getDOM",
@@ -467,7 +469,7 @@
"setAllInputsForProperty",
"setBindingRootForHostBindings",
"setCurrentDirectiveIndex",
"setCurrentInjector2",
"setCurrentInjector",
"setCurrentQueryIndex",
"setCurrentTNode",
"setDirectiveInputsWhichShadowsStyling",
@@ -15,15 +15,18 @@ import {
ɵɵngDeclareFactory,
} from '@angular/core';
import {ɵɵdefineInjector} from '@angular/core/src/di';
import {setCurrentInjector} from '@angular/core/src/di/injector_compatibility';
import {RetrievingInjector, setCurrentInjector} from '@angular/core/src/di/injector_compatibility';
describe('Factory declaration jit compilation', () => {
let previousInjector: Injector | null | undefined;
let previousInjector: RetrievingInjector | null | undefined;
let previousInjectorProfilerContext: ɵInjectorProfilerContext;
beforeEach(() => {
const injector = ɵcreateInjector(TestInjector);
previousInjector = setCurrentInjector(injector);
previousInjectorProfilerContext = ɵsetInjectorProfilerContext({injector, token: null});
const injector = new RetrievingInjector(ɵcreateInjector(TestInjector));
previousInjector = setCurrentInjector(injector) as RetrievingInjector;
previousInjectorProfilerContext = ɵsetInjectorProfilerContext({
injector: injector.injector,
token: null,
});
});
afterEach(() => {
setCurrentInjector(previousInjector);
@@ -18,16 +18,19 @@ import {
ɵɵInjectableDeclaration,
ɵɵngDeclareInjectable,
ɵɵngDeclareInjector,
ɵɵngDeclareNgModule,
} from '@angular/core';
import {RetrievingInjector} from '@angular/core/src/di/injector_compatibility';
describe('Injectable declaration jit compilation', () => {
let previousInjector: Injector | null | undefined;
let previousInjector: RetrievingInjector | null | undefined;
let previousInjectorProfilerContext: ɵInjectorProfilerContext;
beforeEach(() => {
const injector = ɵcreateInjector(TestInjector);
previousInjector = ɵsetCurrentInjector(injector);
previousInjectorProfilerContext = ɵsetInjectorProfilerContext({injector, token: null});
const injector = new RetrievingInjector(ɵcreateInjector(TestInjector));
previousInjector = ɵsetCurrentInjector(injector) as RetrievingInjector;
previousInjectorProfilerContext = ɵsetInjectorProfilerContext({
injector: injector.injector,
token: null,
});
});
afterEach(() => {
ɵsetCurrentInjector(previousInjector);
+3 -13
View File
@@ -13,9 +13,7 @@ import {
InjectOptions,
Injector,
ProviderToken,
ɵInjectorProfilerContext,
ɵsetCurrentInjector as setCurrentInjector,
ɵsetInjectorProfilerContext,
runInInjectionContext,
} from '@angular/core';
class MockRootScopeInjector implements Injector {
@@ -27,17 +25,9 @@ class MockRootScopeInjector implements Injector {
flags: InjectFlags | InjectOptions = InjectFlags.Default,
): T {
if ((token as any).ɵprov && (token as any).ɵprov.providedIn === 'root') {
const old = setCurrentInjector(this);
const previousInjectorProfilerContext = ɵsetInjectorProfilerContext({
injector: this,
token: null,
});
try {
return runInInjectionContext(this, () => {
return (token as any).ɵprov.factory();
} finally {
setCurrentInjector(old);
ɵsetInjectorProfilerContext(previousInjectorProfilerContext);
}
});
}
return this.parent.get(token, defaultValue, flags);
}