fix(ivy): ignore imports without ngInjectorDef in r3_injector (#24862)
ngInjectorDef.imports is generated from @NgModule.imports plus @NgModule.exports. A problem arises as a result, because @NgModule exports contain not only other modules (which will have ngInjectorDef fields), but components, directives, and pipes as well. Because of locality, it's difficult for the compiler to filter these out at build time. It's not impossible, but for now filtering them out at runtime will allow testing of the compiler against complex applications. PR Close #24862
This commit is contained in:
parent
ae4563202c
commit
9644873023
|
@ -231,9 +231,9 @@ export class R3Injector {
|
|||
def = ngModule.ngInjectorDef;
|
||||
}
|
||||
|
||||
// If no definition was found, throw.
|
||||
// If no definition was found, it might be from exports. Remove it.
|
||||
if (def == null) {
|
||||
throw new Error(`Type ${stringify(defType)} is missing an ngInjectorDef definition.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for circular dependencies.
|
||||
|
@ -333,7 +333,12 @@ export class R3Injector {
|
|||
function injectableDefRecord(token: Type<any>| InjectionToken<any>): Record<any> {
|
||||
const def = (token as InjectableType<any>).ngInjectableDef as InjectableDef<any>;
|
||||
if (def === undefined) {
|
||||
throw new Error(`Type ${stringify(token)} is missing an ngInjectableDef definition.`);
|
||||
if (token instanceof InjectionToken) {
|
||||
throw new Error(`Token ${stringify(token)} is missing an ngInjectableDef definition.`);
|
||||
}
|
||||
// TODO(alxhub): there should probably be a strict mode which throws here instead of assuming a
|
||||
// no-args constructor.
|
||||
return makeRecord(() => new (token as Type<any>)());
|
||||
}
|
||||
return makeRecord(def.factory);
|
||||
}
|
||||
|
|
|
@ -143,6 +143,16 @@ describe('InjectorDef-based createInjector()', () => {
|
|||
});
|
||||
}
|
||||
|
||||
class NotAModule {}
|
||||
|
||||
class ImportsNotAModule {
|
||||
static ngInjectorDef = defineInjector({
|
||||
factory: () => new ImportsNotAModule(),
|
||||
imports: [NotAModule],
|
||||
providers: [],
|
||||
});
|
||||
}
|
||||
|
||||
class ScopedService {
|
||||
static ngInjectableDef = defineInjectable({
|
||||
providedIn: Module,
|
||||
|
@ -241,4 +251,9 @@ describe('InjectorDef-based createInjector()', () => {
|
|||
expect(() => (injector as R3Injector).destroy())
|
||||
.toThrowError('Injector has already been destroyed.');
|
||||
});
|
||||
|
||||
it('should not crash when importing something that has no ngInjectorDef', () => {
|
||||
injector = createInjector(ImportsNotAModule);
|
||||
expect(injector.get(ImportsNotAModule)).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue