diff --git a/packages/compiler/src/metadata_resolver.ts b/packages/compiler/src/metadata_resolver.ts index fb58976059..bbbb0c3722 100644 --- a/packages/compiler/src/metadata_resolver.ts +++ b/packages/compiler/src/metadata_resolver.ts @@ -933,7 +933,7 @@ export class CompileMetadataResolver { } if (token == null) { hasUnknownDeps = true; - return null !; + return {}; } return { @@ -949,7 +949,7 @@ export class CompileMetadataResolver { if (hasUnknownDeps) { const depsTokens = - dependenciesMetadata.map((dep) => dep ? stringifyType(dep.token) : '?').join(', '); + dependenciesMetadata.map((dep) => dep.token ? stringifyType(dep.token) : '?').join(', '); const message = `Can't resolve all parameters for ${stringifyType(typeOrFunc)}: (${depsTokens}).`; if (throwOnUnknownDeps || this._config.strictInjectionParameters) { diff --git a/packages/compiler/test/metadata_resolver_spec.ts b/packages/compiler/test/metadata_resolver_spec.ts index 2ef89defb0..406b8755b0 100644 --- a/packages/compiler/test/metadata_resolver_spec.ts +++ b/packages/compiler/test/metadata_resolver_spec.ts @@ -10,7 +10,7 @@ import {LIFECYCLE_HOOKS_VALUES, LifecycleHooks} from '@angular/compiler/src/life import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, Component, Directive, DoCheck, Injectable, NgModule, OnChanges, OnDestroy, OnInit, Pipe, SimpleChanges, ViewEncapsulation, ɵstringify as stringify} from '@angular/core'; import {TestBed, async, inject} from '@angular/core/testing'; -import {identifierName} from '../src/compile_metadata'; +import {CompileDiDependencyMetadata, identifierName} from '../src/compile_metadata'; import {CompileMetadataResolver} from '../src/metadata_resolver'; import {ResourceLoader} from '../src/resource_loader'; import {MockResourceLoader} from '../testing/src/resource_loader_mock'; @@ -371,6 +371,38 @@ import {TEST_COMPILER_PROVIDERS} from './test_bindings'; .toThrowError(`SimpleService cannot be used as an entry component.`); })); + it('should generate an error when a dependency could not be resolved', + inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { + + // Override the errorCollector so that error gets collected instead of + // being thrown. + (resolver as any)._errorCollector = (error: Error, type?: any) => { + expect(error.message).toBe(`Can't resolve all parameters for MyComponent: (?).`); + }; + + @Component({template: ''}) + class MyComponent { + // @ts-ignore UserService is a non-existent class. + constructor(service: UserService) {} + } + + @NgModule({declarations: [MyComponent]}) + class AppModule { + } + + const moduleMetadata = resolver.getNgModuleMetadata(AppModule) !; + expect(moduleMetadata).toBeTruthy(); + expect(moduleMetadata.declaredDirectives.length).toBe(1); + const directive = moduleMetadata.declaredDirectives[0]; + const directiveMetadata = + resolver.getNonNormalizedDirectiveMetadata(directive.reference) !; + expect(directiveMetadata).toBeTruthy(); + const {metadata} = directiveMetadata; + const diDeps: CompileDiDependencyMetadata[] = metadata.type.diDeps; + // 'null' does not conform to the shape of `CompileDiDependencyMetadata` + expect(diDeps.every(d => d !== null)).toBe(true); + })); + it(`should throw an error when a Directive is added to module's bootstrap list`, inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {