diff --git a/packages/core/src/di/r3_injector.ts b/packages/core/src/di/r3_injector.ts index 28742c19a2..e8dcdf42ef 100644 --- a/packages/core/src/di/r3_injector.ts +++ b/packages/core/src/di/r3_injector.ts @@ -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| InjectionToken): Record { const def = (token as InjectableType).ngInjectableDef as InjectableDef; 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)()); } return makeRecord(def.factory); } diff --git a/packages/core/test/di/r3_injector_spec.ts b/packages/core/test/di/r3_injector_spec.ts index 5e690b2f86..5f7a59124c 100644 --- a/packages/core/test/di/r3_injector_spec.ts +++ b/packages/core/test/di/r3_injector_spec.ts @@ -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(); + }); });