Skip to content

Commit 4812215

Browse files
JeanMechemmalerba
authored andcommittedFeb 27, 2025·
feat(core): Expose Injector.destroy on Injector created with Injector.create (#60054)
There is no implementation change, this only expose `destroy` in a case where the injector can be owned in userland. PR Close #60054
1 parent 0dbf693 commit 4812215

File tree

6 files changed

+44
-4
lines changed

6 files changed

+44
-4
lines changed
 

‎goldens/public-api/core/index.api.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,12 @@ export class DefaultIterableDiffer<V> implements IterableDiffer<V>, IterableChan
588588
// @public @deprecated (undocumented)
589589
export const defineInjectable: typeof ɵɵdefineInjectable;
590590

591+
// @public
592+
export interface DestroyableInjector extends Injector {
593+
// (undocumented)
594+
destroy(): void;
595+
}
596+
591597
// @public
592598
export function destroyPlatform(): void;
593599

@@ -949,7 +955,7 @@ export abstract class Injector {
949955
providers: Array<Provider | StaticProvider>;
950956
parent?: Injector;
951957
name?: string;
952-
}): Injector;
958+
}): DestroyableInjector;
953959
abstract get<T>(token: ProviderToken<T>, notFoundValue: undefined, options: InjectOptions & {
954960
optional?: false;
955961
}): T;

‎packages/core/src/di/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export {
2424
} from './interface/defs';
2525
export {forwardRef, resolveForwardRef, ForwardRefFn} from './forward_ref';
2626
export {Injectable, InjectableDecorator, InjectableProvider} from './injectable';
27-
export {Injector} from './injector';
27+
export {Injector, DestroyableInjector} from './injector';
2828
export {EnvironmentInjector} from './r3_injector';
2929
export {
3030
importProvidersFrom,

‎packages/core/src/di/injector.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export abstract class Injector {
117117
providers: Array<Provider | StaticProvider>;
118118
parent?: Injector;
119119
name?: string;
120-
}): Injector;
120+
}): DestroyableInjector;
121121

122122
static create(
123123
options:
@@ -146,3 +146,12 @@ export abstract class Injector {
146146
*/
147147
static __NG_ELEMENT_ID__ = InjectorMarkers.Injector;
148148
}
149+
150+
/**
151+
* An Injector that the owner can destroy and trigger the DestroyRef.destroy hooks.
152+
*
153+
* @publicApi
154+
*/
155+
export interface DestroyableInjector extends Injector {
156+
destroy(): void;
157+
}

‎packages/core/src/di/r3_injector.ts

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ interface Record<T> {
113113
/**
114114
* An `Injector` that's part of the environment injector hierarchy, which exists outside of the
115115
* component tree.
116+
*
117+
* @publicApi
116118
*/
117119
export abstract class EnvironmentInjector implements Injector {
118120
/**

‎packages/core/test/acceptance/di_spec.ts

+23
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import {
6060
ɵDEFAULT_LOCALE_ID as DEFAULT_LOCALE_ID,
6161
ɵINJECTOR_SCOPE,
6262
ɵInternalEnvironmentProviders as InternalEnvironmentProviders,
63+
DestroyRef,
6364
} from '@angular/core';
6465
import {RuntimeError, RuntimeErrorCode} from '@angular/core/src/errors';
6566
import {ViewRef as ViewRefInternal} from '@angular/core/src/render3/view_ref';
@@ -6494,4 +6495,26 @@ describe('di', () => {
64946495

64956496
expect(injector.get(token)).toBe('module');
64966497
});
6498+
6499+
it('should be able to destroy programmatically created injectors', () => {
6500+
@Injectable()
6501+
class Service {
6502+
ngOnDestroy() {}
6503+
}
6504+
6505+
const parentInjector = Injector.create({
6506+
providers: [Service],
6507+
parent: TestBed.inject(Injector),
6508+
});
6509+
6510+
const childInjector = Injector.create({providers: [Service], parent: parentInjector});
6511+
6512+
const instance = childInjector.get(Service);
6513+
const destroySpy = spyOn(instance, 'ngOnDestroy');
6514+
6515+
parentInjector.get(DestroyRef).onDestroy(() => childInjector.destroy());
6516+
parentInjector.destroy();
6517+
6518+
expect(destroySpy).toHaveBeenCalled();
6519+
});
64976520
});

‎packages/platform-browser/test/browser/tools/tools_spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('profiler', () => {
3434
deps: [],
3535
},
3636
],
37-
}),
37+
}) as Injector,
3838
} as ComponentRef<any>);
3939
});
4040

0 commit comments

Comments
 (0)
Please sign in to comment.