diff --git a/modules/@angular/common/index.ts b/modules/@angular/common/index.ts
index ef9e7c4982..9ed2cda6e9 100644
--- a/modules/@angular/common/index.ts
+++ b/modules/@angular/common/index.ts
@@ -6,9 +6,25 @@
* found in the LICENSE file at https://angular.io/license
*/
+import {NgModule} from '@angular/core';
+import {COMMON_DIRECTIVES} from './src/common_directives';
+import {COMMON_PIPES} from './src/pipes';
+
export * from './src/pipes';
export * from './src/directives';
export * from './src/forms-deprecated';
export * from './src/common_directives';
export * from './src/location';
-export {NgLocalization} from './src/localization';
\ No newline at end of file
+export {NgLocalization} from './src/localization';
+
+// Note: This does not contain the location providers,
+// as they need some platform specific implementations to work.
+/**
+ * The module that includes all the basic Angular directives like {@link NgIf}, ${link NgFor}, ...
+ *
+ * @experimental
+ */
+@NgModule(
+ {declarations: [COMMON_DIRECTIVES, COMMON_PIPES], exports: [COMMON_DIRECTIVES, COMMON_PIPES]})
+export class CommonModule {
+}
diff --git a/modules/@angular/common/src/forms-deprecated.ts b/modules/@angular/common/src/forms-deprecated.ts
index d6484feaa9..a8f4c4dd11 100644
--- a/modules/@angular/common/src/forms-deprecated.ts
+++ b/modules/@angular/common/src/forms-deprecated.ts
@@ -18,7 +18,7 @@
* Forms providers are not included in default providers; you must import these providers
* explicitly.
*/
-import {AppModule, Type} from '@angular/core';
+import {NgModule, Type} from '@angular/core';
import {FORM_DIRECTIVES} from './forms-deprecated/directives';
import {RadioControlRegistry} from './forms-deprecated/directives/radio_control_value_accessor';
@@ -61,15 +61,15 @@ export const FORM_PROVIDERS: Type[] = /*@ts2dart_const*/[FormBuilder, RadioContr
/**
- * The app module for the deprecated forms API.
+ * The ng module for the deprecated forms API.
* @deprecated
*/
-@AppModule({
+@NgModule({
providers: [
FORM_PROVIDERS,
],
- directives: FORM_DIRECTIVES,
- pipes: []
+ declarations: FORM_DIRECTIVES,
+ exports: FORM_DIRECTIVES
})
export class DeprecatedFormsModule {
}
diff --git a/modules/@angular/common/test/forms-deprecated/integration_spec.ts b/modules/@angular/common/test/forms-deprecated/integration_spec.ts
index 56979f0f34..7b5f2755c7 100644
--- a/modules/@angular/common/test/forms-deprecated/integration_spec.ts
+++ b/modules/@angular/common/test/forms-deprecated/integration_spec.ts
@@ -22,7 +22,7 @@ import {PromiseWrapper} from '../../src/facade/promise';
export function main() {
describe('integration tests', () => {
- beforeEach(() => { configureModule({modules: [DeprecatedFormsModule]}); });
+ beforeEach(() => configureModule({imports: [DeprecatedFormsModule]}));
it('should initialize DOM elements with the given form object',
inject(
diff --git a/modules/@angular/compiler-cli/README.md b/modules/@angular/compiler-cli/README.md
index 75fa4d97e4..b626c34bbd 100644
--- a/modules/@angular/compiler-cli/README.md
+++ b/modules/@angular/compiler-cli/README.md
@@ -30,13 +30,14 @@ generated code:
main_module.ts
-------------
import {BrowserModule} from '@angular/platform-browser';
-import {Component, AppModule, ApplicationRef} from '@angular/core';
+import {Component, NgModule, ApplicationRef} from '@angular/core';
@Component(...)
export class MyComponent {}
-@AppModule({
- modules: [BrowserModule],
+@NgModule({
+ imports: [BrowserModule],
+ declarations: [MyComponent],
precompile: [MyComponent]
})
export class MainModule {
diff --git a/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts b/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts
index 854634661b..3204a30527 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts
+++ b/modules/@angular/compiler-cli/integrationtest/src/a/multiple_components.ts
@@ -8,10 +8,7 @@
import {Component} from '@angular/core';
-@Component({
- selector: 'my-comp',
- template: '
',
-})
+@Component({selector: 'my-comp', template: '
', directives: [NextComp]})
export class MultipleComponentsMyComp {
}
diff --git a/modules/@angular/compiler-cli/integrationtest/src/basic.html b/modules/@angular/compiler-cli/integrationtest/src/basic.html
index 4d1aebaf95..f36206577f 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/basic.html
+++ b/modules/@angular/compiler-cli/integrationtest/src/basic.html
@@ -1,4 +1,4 @@
{{ctxProp}}
-
+
diff --git a/modules/@angular/compiler-cli/integrationtest/src/basic.ts b/modules/@angular/compiler-cli/integrationtest/src/basic.ts
index 62cd26427a..8c06cf3798 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/basic.ts
+++ b/modules/@angular/compiler-cli/integrationtest/src/basic.ts
@@ -6,8 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {FORM_DIRECTIVES, NgFor, NgIf} from '@angular/common';
+import {NgFor, NgIf} from '@angular/common';
import {Component, Inject} from '@angular/core';
+import {FORM_DIRECTIVES} from '@angular/forms';
import {MultipleComponentsMyComp} from './a/multiple_components';
diff --git a/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts b/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts
index 49e82322c2..2d00a897e5 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts
+++ b/modules/@angular/compiler-cli/integrationtest/src/bootstrap.ts
@@ -10,4 +10,4 @@ import {browserPlatform} from '@angular/platform-browser';
import {BasicComp} from './basic';
import {MainModuleNgFactory} from './module.ngfactory';
-MainModuleNgFactory.create().instance.appRef.bootstrap(BasicComp);
+MainModuleNgFactory.create(null).instance.appRef.bootstrap(BasicComp);
diff --git a/modules/@angular/compiler-cli/integrationtest/src/module.ts b/modules/@angular/compiler-cli/integrationtest/src/module.ts
index c8469aade3..e6fec9aa31 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/module.ts
+++ b/modules/@angular/compiler-cli/integrationtest/src/module.ts
@@ -6,20 +6,29 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {AppModule, ApplicationRef} from '@angular/core';
+import {ApplicationRef, NgModule} from '@angular/core';
+import {FormsModule} from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser';
import {AnimateCmp} from './animate';
import {BasicComp} from './basic';
+import {CompWithProviders, CompWithReferences} from './features';
+import {CompUsingRootModuleDirectiveAndPipe, SomeDirectiveInRootModule, SomeLibModule, SomePipeInRootModule, SomeService} from './module_fixtures';
import {CompWithAnalyzePrecompileProvider, CompWithPrecompile} from './precompile';
import {ProjectingComp} from './projection';
-import {CompWithChildQuery} from './queries';
+import {CompWithChildQuery, CompWithDirectiveChild} from './queries';
-@AppModule({
- modules: [BrowserModule],
+@NgModule({
+ declarations: [
+ SomeDirectiveInRootModule, SomePipeInRootModule, AnimateCmp, BasicComp, CompWithPrecompile,
+ CompWithAnalyzePrecompileProvider, ProjectingComp, CompWithChildQuery, CompWithDirectiveChild,
+ CompUsingRootModuleDirectiveAndPipe, CompWithProviders, CompWithReferences
+ ],
+ imports: [BrowserModule, FormsModule, SomeLibModule],
+ providers: [SomeService],
precompile: [
AnimateCmp, BasicComp, CompWithPrecompile, CompWithAnalyzePrecompileProvider, ProjectingComp,
- CompWithChildQuery
+ CompWithChildQuery, CompUsingRootModuleDirectiveAndPipe
]
})
export class MainModule {
diff --git a/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts b/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts
index 469055d056..db3a01a91d 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts
+++ b/modules/@angular/compiler-cli/integrationtest/src/module_fixtures.ts
@@ -7,7 +7,7 @@
*/
import {LowerCasePipe, NgIf} from '@angular/common';
-import {ANALYZE_FOR_PRECOMPILE, AppModule, Component, ComponentFactoryResolver, Directive, Inject, Injectable, Input, OpaqueToken, Pipe} from '@angular/core';
+import {ANALYZE_FOR_PRECOMPILE, Component, ComponentFactoryResolver, Directive, Inject, Injectable, Input, NgModule, OpaqueToken, Pipe} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
@Injectable()
@@ -16,50 +16,37 @@ export class SomeService {
}
@Injectable()
-export class NestedService {
+export class ServiceUsingLibModule {
}
@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
-export class SomeDirective {
+export class SomeDirectiveInRootModule {
+ @Input()
+ someDir: string;
+}
+
+@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
+export class SomeDirectiveInLibModule {
@Input()
someDir: string;
}
@Pipe({name: 'somePipe'})
-export class SomePipe {
+export class SomePipeInRootModule {
transform(value: string): any { return `transformed ${value}`; }
}
-@Component({selector: 'cmp', template: `
`})
-export class SomeComp {
- constructor() {}
+@Pipe({name: 'somePipe'})
+export class SomePipeInLibModule {
+ transform(value: string): any { return `transformed ${value}`; }
}
-@Component({selector: 'parent', template: ` `, directives: [SomeComp]})
-export class ParentComp {
+@Component({selector: 'comp', template: `
`})
+export class CompUsingRootModuleDirectiveAndPipe {
}
-@AppModule({providers: [NestedService]})
-export class NestedModule {
-}
-
-@AppModule({
- directives: [SomeDirective],
- pipes: [SomePipe],
- providers: [SomeService],
- precompile: [SomeComp],
- modules: [NestedModule, BrowserModule]
-})
-export class SomeModule {
-}
-
-@AppModule({
- directives: [SomeDirective],
- pipes: [SomePipe],
- precompile: [ParentComp],
- modules: [BrowserModule]
-})
-export class SomeModuleUsingParentComp {
+@Component({selector: 'comp', template: `
`})
+export class CompUsingLibModuleDirectiveAndPipe {
}
export const SOME_TOKEN = new OpaqueToken('someToken');
@@ -71,7 +58,13 @@ export function provideValueWithPrecompile(value: any) {
];
}
-@AppModule({providers: [provideValueWithPrecompile([{a: 'b', component: SomeComp}])]})
-export class SomeModuleWithAnalyzePrecompileProvider {
- constructor(@Inject(SOME_TOKEN) public providedValue: any) {}
+@NgModule({
+ declarations: [SomeDirectiveInLibModule, SomePipeInLibModule, CompUsingLibModuleDirectiveAndPipe],
+ precompile: [CompUsingLibModuleDirectiveAndPipe],
+ providers: [
+ ServiceUsingLibModule,
+ provideValueWithPrecompile([{a: 'b', component: CompUsingLibModuleDirectiveAndPipe}])
+ ],
+})
+export class SomeLibModule {
}
diff --git a/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts
deleted file mode 100644
index 21c646406a..0000000000
--- a/modules/@angular/compiler-cli/integrationtest/test/app_module_spec.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * @license
- * Copyright Google Inc. All Rights Reserved.
- *
- * Use of this source code is governed by an MIT-style license that can be
- * found in the LICENSE file at https://angular.io/license
- */
-import './init';
-import {NestedModule, NestedService, ParentComp, SomeComp, SomeModule, SomeService} from '../src/module_fixtures';
-import {SomeModuleNgFactory, SomeModuleUsingParentCompNgFactory, SomeModuleWithAnalyzePrecompileProviderNgFactory} from '../src/module_fixtures.ngfactory';
-import {createComponent, createModule} from './util';
-
-describe('AppModule', () => {
- it('should support providers', () => {
- var moduleRef = createModule(SomeModuleNgFactory);
- expect(moduleRef.instance instanceof SomeModule).toBe(true);
- expect(moduleRef.injector.get(SomeModule) instanceof SomeModule).toBe(true);
- expect(moduleRef.injector.get(SomeService) instanceof SomeService).toBe(true);
- });
-
- it('should support precompile components', () => {
- var moduleRef = createModule(SomeModuleNgFactory);
- var cf = moduleRef.componentFactoryResolver.resolveComponentFactory(SomeComp);
- expect(cf.componentType).toBe(SomeComp);
- var compRef = cf.create(moduleRef.injector);
- expect(compRef.instance instanceof SomeComp).toBe(true);
- });
-
- it('should support precompile via the ANALYZE_FOR_PRECOMPILE provider and function providers in components',
- () => {
- const moduleRef = createModule(SomeModuleWithAnalyzePrecompileProviderNgFactory);
- const cf = moduleRef.componentFactoryResolver.resolveComponentFactory(SomeComp);
- expect(cf.componentType).toBe(SomeComp);
- // check that the function call that created the provider for ANALYZE_FOR_PRECOMPILE worked.
- expect(moduleRef.instance.providedValue).toEqual([{a: 'b', component: SomeComp}]);
- });
-
- it('should support module directives and pipes', () => {
- var compFixture = createComponent(SomeComp, SomeModuleNgFactory);
- compFixture.detectChanges();
-
- var debugElement = compFixture.debugElement;
- expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
- });
-
- it('should support module directives and pipes on nested components', () => {
- var compFixture = createComponent(ParentComp, SomeModuleUsingParentCompNgFactory);
- compFixture.detectChanges();
-
- var debugElement = compFixture.debugElement;
- debugElement = debugElement.children[0];
- expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
- });
-
- it('should support child moduless', () => {
- var moduleRef = createModule(SomeModuleNgFactory);
- expect(moduleRef.instance instanceof SomeModule).toBe(true);
- expect(moduleRef.injector.get(NestedModule) instanceof NestedModule).toBe(true);
- expect(moduleRef.injector.get(NestedService) instanceof NestedService).toBe(true);
- });
-
-});
diff --git a/modules/@angular/compiler-cli/integrationtest/test/ng_module_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/ng_module_spec.ts
new file mode 100644
index 0000000000..77e8dc14b4
--- /dev/null
+++ b/modules/@angular/compiler-cli/integrationtest/test/ng_module_spec.ts
@@ -0,0 +1,63 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+import './init';
+
+import {MainModule} from '../src/module';
+import {CompUsingLibModuleDirectiveAndPipe, CompUsingRootModuleDirectiveAndPipe, SOME_TOKEN, ServiceUsingLibModule, SomeLibModule, SomeService} from '../src/module_fixtures';
+
+import {createComponent, createModule} from './util';
+
+describe('NgModule', () => {
+ it('should support providers', () => {
+ const moduleRef = createModule();
+ expect(moduleRef.instance instanceof MainModule).toBe(true);
+ expect(moduleRef.injector.get(MainModule) instanceof MainModule).toBe(true);
+ expect(moduleRef.injector.get(SomeService) instanceof SomeService).toBe(true);
+ });
+
+ it('should support precompile components', () => {
+ const moduleRef = createModule();
+ const cf = moduleRef.componentFactoryResolver.resolveComponentFactory(
+ CompUsingRootModuleDirectiveAndPipe);
+ expect(cf.componentType).toBe(CompUsingRootModuleDirectiveAndPipe);
+ const compRef = cf.create(moduleRef.injector);
+ expect(compRef.instance instanceof CompUsingRootModuleDirectiveAndPipe).toBe(true);
+ });
+
+ it('should support precompile via the ANALYZE_FOR_PRECOMPILE provider and function providers in components',
+ () => {
+ const moduleRef = createModule();
+ const cf = moduleRef.componentFactoryResolver.resolveComponentFactory(
+ CompUsingRootModuleDirectiveAndPipe);
+ expect(cf.componentType).toBe(CompUsingRootModuleDirectiveAndPipe);
+ // check that the function call that created the provider for ANALYZE_FOR_PRECOMPILE worked.
+ expect(moduleRef.injector.get(SOME_TOKEN)).toEqual([
+ {a: 'b', component: CompUsingLibModuleDirectiveAndPipe}
+ ]);
+ });
+
+ it('should support module directives and pipes', () => {
+ const compFixture = createComponent(CompUsingRootModuleDirectiveAndPipe);
+ compFixture.detectChanges();
+
+ const debugElement = compFixture.debugElement;
+ expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
+ });
+
+ it('should support module directives and pipes on lib modules', () => {
+ const compFixture = createComponent(CompUsingLibModuleDirectiveAndPipe);
+ compFixture.detectChanges();
+
+ const debugElement = compFixture.debugElement;
+ expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
+
+ expect(debugElement.injector.get(SomeLibModule) instanceof SomeLibModule).toBe(true);
+ expect(debugElement.injector.get(ServiceUsingLibModule) instanceof ServiceUsingLibModule)
+ .toBe(true);
+ });
+});
diff --git a/modules/@angular/compiler-cli/integrationtest/test/util.ts b/modules/@angular/compiler-cli/integrationtest/test/util.ts
index 786dfe4cbb..681dacebd3 100644
--- a/modules/@angular/compiler-cli/integrationtest/test/util.ts
+++ b/modules/@angular/compiler-cli/integrationtest/test/util.ts
@@ -6,23 +6,19 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {AppModuleFactory, AppModuleRef, bootstrapModuleFactory} from '@angular/core';
+import {NgModuleFactory, NgModuleRef, bootstrapModuleFactory} from '@angular/core';
import {ComponentFixture} from '@angular/core/testing';
import {serverPlatform} from '@angular/platform-server';
+import {MainModule} from '../src/module';
import {MainModuleNgFactory} from '../src/module.ngfactory';
-export function createModule(factory: AppModuleFactory): AppModuleRef {
- return bootstrapModuleFactory(factory, serverPlatform());
+export function createModule(): NgModuleRef {
+ return bootstrapModuleFactory(MainModuleNgFactory, serverPlatform());
}
-export function createComponent(
- comp: {new (...args: any[]): C},
- moduleFactory: AppModuleFactory = null): ComponentFixture {
- if (!moduleFactory) {
- moduleFactory = MainModuleNgFactory;
- }
- const moduleRef = createModule(moduleFactory);
+export function createComponent(comp: {new (...args: any[]): C}): ComponentFixture {
+ const moduleRef = createModule();
const compRef =
moduleRef.componentFactoryResolver.resolveComponentFactory(comp).create(moduleRef.injector);
return new ComponentFixture(compRef, null, null);
diff --git a/modules/@angular/compiler-cli/src/codegen.ts b/modules/@angular/compiler-cli/src/codegen.ts
index 387cd9947f..bec68aef07 100644
--- a/modules/@angular/compiler-cli/src/codegen.ts
+++ b/modules/@angular/compiler-cli/src/codegen.ts
@@ -11,12 +11,12 @@
* Intended to be used in a build step.
*/
import * as compiler from '@angular/compiler';
-import {AppModuleMetadata, ComponentMetadata, ViewEncapsulation} from '@angular/core';
+import {ComponentMetadata, NgModuleMetadata, ViewEncapsulation} from '@angular/core';
import {AngularCompilerOptions} from '@angular/tsc-wrapped';
import * as path from 'path';
import * as ts from 'typescript';
-import {AppModuleCompiler, CompileMetadataResolver, DirectiveNormalizer, DomElementSchemaRegistry, HtmlParser, Lexer, Parser, StyleCompiler, TemplateParser, TypeScriptEmitter, ViewCompiler} from './compiler_private';
+import {CompileMetadataResolver, DirectiveNormalizer, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleCompiler, Parser, StyleCompiler, TemplateParser, TypeScriptEmitter, ViewCompiler} from './compiler_private';
import {ReflectorHost, ReflectorHostContext} from './reflector_host';
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
import {StaticReflector, StaticSymbol} from './static_reflector';
@@ -39,7 +39,7 @@ export class CodeGenerator {
private readFileMetadata(absSourcePath: string): FileMetadata {
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
- const result: FileMetadata = {components: [], appModules: [], fileUrl: absSourcePath};
+ const result: FileMetadata = {components: [], ngModules: [], fileUrl: absSourcePath};
if (!moduleMetadata) {
console.log(`WARNING: no metadata found for ${absSourcePath}`);
return result;
@@ -57,8 +57,8 @@ export class CodeGenerator {
const staticType = this.reflectorHost.findDeclaration(absSourcePath, symbol, absSourcePath);
const annotations = this.staticReflector.annotations(staticType);
annotations.forEach((annotation) => {
- if (annotation instanceof AppModuleMetadata) {
- result.appModules.push(staticType);
+ if (annotation instanceof NgModuleMetadata) {
+ result.ngModules.push(staticType);
} else if (annotation instanceof ComponentMetadata) {
result.components.push(staticType);
}
@@ -86,17 +86,17 @@ export class CodeGenerator {
let filePaths =
this.program.getSourceFiles().map(sf => sf.fileName).filter(f => !GENERATED_FILES.test(f));
let fileMetas = filePaths.map((filePath) => this.readFileMetadata(filePath));
- let appModules = fileMetas.reduce((appModules, fileMeta) => {
- appModules.push(...fileMeta.appModules);
- return appModules;
+ let ngModules = fileMetas.reduce((ngModules, fileMeta) => {
+ ngModules.push(...fileMeta.ngModules);
+ return ngModules;
}, []);
- let analyzedAppModules = this.compiler.analyzeModules(appModules);
+ let analyzedNgModules = this.compiler.analyzeModules(ngModules);
return Promise
.all(fileMetas.map(
(fileMeta) => this.compiler
.compile(
- fileMeta.fileUrl, analyzedAppModules, fileMeta.components,
- fileMeta.appModules)
+ fileMeta.fileUrl, analyzedNgModules, fileMeta.components,
+ fileMeta.ngModules)
.then((generatedModules) => {
generatedModules.forEach((generatedModule) => {
const sourceFile = this.program.getSourceFile(fileMeta.fileUrl);
@@ -139,11 +139,12 @@ export class CodeGenerator {
expressionParser, new DomElementSchemaRegistry(), htmlParser,
/*console*/ null, []);
const resolver = new CompileMetadataResolver(
+ new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
- new compiler.ViewResolver(staticReflector), config, staticReflector);
+ new compiler.ViewResolver(staticReflector), config, /*console*/ null, staticReflector);
const offlineCompiler = new compiler.OfflineCompiler(
resolver, normalizer, tmplParser, new StyleCompiler(urlResolver), new ViewCompiler(config),
- new AppModuleCompiler(), new TypeScriptEmitter(reflectorHost));
+ new NgModuleCompiler(), new TypeScriptEmitter(reflectorHost));
return new CodeGenerator(
options, program, compilerHost, staticReflector, offlineCompiler, reflectorHost);
@@ -153,5 +154,5 @@ export class CodeGenerator {
interface FileMetadata {
fileUrl: string;
components: StaticSymbol[];
- appModules: StaticSymbol[];
-}
\ No newline at end of file
+ ngModules: StaticSymbol[];
+}
diff --git a/modules/@angular/compiler-cli/src/compiler_private.ts b/modules/@angular/compiler-cli/src/compiler_private.ts
index 06617f3c16..cfc92777cf 100644
--- a/modules/@angular/compiler-cli/src/compiler_private.ts
+++ b/modules/@angular/compiler-cli/src/compiler_private.ts
@@ -61,8 +61,8 @@ export var StyleCompiler: typeof _c.StyleCompiler = _c.StyleCompiler;
export type ViewCompiler = _c.ViewCompiler;
export var ViewCompiler: typeof _c.ViewCompiler = _c.ViewCompiler;
-export type AppModuleCompiler = _c.AppModuleCompiler;
-export var AppModuleCompiler: typeof _c.AppModuleCompiler = _c.AppModuleCompiler;
+export type NgModuleCompiler = _c.NgModuleCompiler;
+export var NgModuleCompiler: typeof _c.NgModuleCompiler = _c.NgModuleCompiler;
export type TypeScriptEmitter = _c.TypeScriptEmitter;
export var TypeScriptEmitter: typeof _c.TypeScriptEmitter = _c.TypeScriptEmitter;
diff --git a/modules/@angular/compiler-cli/src/extract_i18n.ts b/modules/@angular/compiler-cli/src/extract_i18n.ts
index 759128cc7e..c0c7ba0680 100644
--- a/modules/@angular/compiler-cli/src/extract_i18n.ts
+++ b/modules/@angular/compiler-cli/src/extract_i18n.ts
@@ -76,7 +76,7 @@ class Extractor {
for (const symbol of symbols) {
const staticType = this._reflectorHost.findDeclaration(absSourcePath, symbol, absSourcePath);
let directive: compiler.CompileDirectiveMetadata;
- directive = this._resolver.maybeGetDirectiveMetadata(staticType);
+ directive = this._resolver.getDirectiveMetadata(staticType, false);
if (directive && directive.isComponent) {
let promise = this._normalizer.normalizeDirective(directive).asyncResult;
@@ -147,8 +147,9 @@ class Extractor {
const normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer());
const resolver = new CompileMetadataResolver(
+ new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
- new compiler.ViewResolver(staticReflector), config, staticReflector);
+ new compiler.ViewResolver(staticReflector), config, /*console*/ null, staticReflector);
// TODO(vicb): handle implicit
const extractor = new MessageExtractor(htmlParser, expressionParser, [], {});
diff --git a/modules/@angular/compiler-cli/src/static_reflector.ts b/modules/@angular/compiler-cli/src/static_reflector.ts
index 78f400f61a..8b9203faec 100644
--- a/modules/@angular/compiler-cli/src/static_reflector.ts
+++ b/modules/@angular/compiler-cli/src/static_reflector.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {AppModuleMetadata, AttributeMetadata, ComponentMetadata, ContentChildMetadata, ContentChildrenMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, HostMetadata, InjectMetadata, InjectableMetadata, InputMetadata, OptionalMetadata, OutputMetadata, PipeMetadata, Provider, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
+import {AttributeMetadata, ComponentMetadata, ContentChildMetadata, ContentChildrenMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, HostMetadata, InjectMetadata, InjectableMetadata, InputMetadata, NgModuleMetadata, OptionalMetadata, OutputMetadata, PipeMetadata, Provider, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
import {ReflectorReader} from './core_private';
@@ -217,7 +217,7 @@ export class StaticReflector implements ReflectorReader {
this.registerDecoratorOrConstructor(
this.host.findDeclaration(coreDecorators, 'Component'), ComponentMetadata);
this.registerDecoratorOrConstructor(
- this.host.findDeclaration(coreDecorators, 'AppModule'), AppModuleMetadata);
+ this.host.findDeclaration(coreDecorators, 'NgModule'), NgModuleMetadata);
// Note: Some metadata classes can be used directly with Provider.deps.
this.registerDecoratorOrConstructor(
@@ -619,4 +619,4 @@ function sameSymbol(a: StaticSymbol, b: StaticSymbol): boolean {
function shouldIgnore(value: any): boolean {
return value && value.__symbolic == 'ignore';
-}
\ No newline at end of file
+}
diff --git a/modules/@angular/compiler/compiler.ts b/modules/@angular/compiler/compiler.ts
index 9d0826b891..c4eef85043 100644
--- a/modules/@angular/compiler/compiler.ts
+++ b/modules/@angular/compiler/compiler.ts
@@ -11,7 +11,7 @@
* @description
* Starting point to import all compiler APIs.
*/
-export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompileMetadataWithType, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, OfflineCompiler, PipeResolver, RUNTIME_COMPILER_FACTORY, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, ViewResolver, XHR, createOfflineCompileUrlResolver} from './src/compiler';
+export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, ViewResolver, XHR, analyzeAppProvidersForDeprecatedConfiguration, coreDynamicPlatform, createOfflineCompileUrlResolver} from './src/compiler';
export {ElementSchemaRegistry} from './src/schema/element_schema_registry';
export * from './src/template_ast';
diff --git a/modules/@angular/compiler/core_private.ts b/modules/@angular/compiler/core_private.ts
index e9c70fbbce..590a9cffec 100644
--- a/modules/@angular/compiler/core_private.ts
+++ b/modules/@angular/compiler/core_private.ts
@@ -20,8 +20,6 @@ export var LifecycleHooks: typeof t.LifecycleHooks = r.LifecycleHooks;
export var LIFECYCLE_HOOKS_VALUES: typeof t.LIFECYCLE_HOOKS_VALUES = r.LIFECYCLE_HOOKS_VALUES;
export type ReflectorReader = t.ReflectorReader;
export var ReflectorReader: typeof t.ReflectorReader = r.ReflectorReader;
-export var ReflectorComponentResolver: typeof t.ReflectorComponentResolver =
- r.ReflectorComponentResolver;
export type AppElement = t.AppElement;
export var AppElement: typeof t.AppElement = r.AppElement;
export var CodegenComponentFactoryResolver: typeof t.CodegenComponentFactoryResolver =
@@ -29,7 +27,7 @@ export var CodegenComponentFactoryResolver: typeof t.CodegenComponentFactoryReso
export var AppView: typeof t.AppView = r.AppView;
export type DebugAppView = t.DebugAppView;
export var DebugAppView: typeof t.DebugAppView = r.DebugAppView;
-export var AppModuleInjector: typeof t.AppModuleInjector = r.AppModuleInjector;
+export var NgModuleInjector: typeof t.NgModuleInjector = r.NgModuleInjector;
export type ViewType = t.ViewType;
export var ViewType: typeof t.ViewType = r.ViewType;
export var MAX_INTERPOLATION_VALUES: typeof t.MAX_INTERPOLATION_VALUES = r.MAX_INTERPOLATION_VALUES;
@@ -68,6 +66,8 @@ export var Console: typeof t.Console = r.Console;
export var reflector: t.Reflector = r.reflector;
export var Reflector: typeof t.Reflector = r.Reflector;
export type Reflector = t.Reflector;
+export var ReflectionCapabilities: typeof t.ReflectionCapabilities = r.ReflectionCapabilities;
+export type ReflectionCapabilities = t.ReflectionCapabilities;
export type NoOpAnimationPlayer = t.NoOpAnimationPlayer;
export var NoOpAnimationPlayer: typeof t.NoOpAnimationPlayer = r.NoOpAnimationPlayer;
export type AnimationPlayer = t.AnimationPlayer;
diff --git a/modules/@angular/compiler/private_export.ts b/modules/@angular/compiler/private_export.ts
index be6557d3ab..73ee0575e7 100644
--- a/modules/@angular/compiler/private_export.ts
+++ b/modules/@angular/compiler/private_export.ts
@@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
-import * as app_module_compiler from './src/app_module_compiler';
import * as directive_normalizer from './src/directive_normalizer';
import * as lexer from './src/expression_parser/lexer';
import * as parser from './src/expression_parser/parser';
@@ -16,6 +15,7 @@ import * as i18n_message from './src/i18n/message';
import * as i18n_extractor from './src/i18n/message_extractor';
import * as xmb_serializer from './src/i18n/xmb_serializer';
import * as metadata_resolver from './src/metadata_resolver';
+import * as ng_module_compiler from './src/ng_module_compiler';
import * as path_util from './src/output/path_util';
import * as ts_emitter from './src/output/ts_emitter';
import * as parse_util from './src/parse_util';
@@ -99,8 +99,8 @@ export var StyleCompiler = style_compiler.StyleCompiler;
export type ViewCompiler = view_compiler.ViewCompiler;
export var ViewCompiler = view_compiler.ViewCompiler;
-export type AppModuleCompiler = app_module_compiler.AppModuleCompiler;
-export var AppModuleCompiler = app_module_compiler.AppModuleCompiler;
+export type NgModuleCompiler = ng_module_compiler.NgModuleCompiler;
+export var NgModuleCompiler = ng_module_compiler.NgModuleCompiler;
export type TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
export var TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
diff --git a/modules/@angular/compiler/src/compile_metadata.ts b/modules/@angular/compiler/src/compile_metadata.ts
index 993dcf15d8..6ca72057cc 100644
--- a/modules/@angular/compiler/src/compile_metadata.ts
+++ b/modules/@angular/compiler/src/compile_metadata.ts
@@ -22,139 +22,55 @@ import {sanitizeIdentifier, splitAtColon} from './util';
// group 1: "prop" from "[prop]"
// group 2: "event" from "(event)"
// group 3: "@trigger" from "@trigger"
-var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/g;
+const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/g;
+const UNDEFINED = new Object();
export abstract class CompileMetadataWithIdentifier {
- abstract toJson(): {[key: string]: any};
-
get identifier(): CompileIdentifierMetadata { return unimplemented(); }
-}
-export abstract class CompileMetadataWithType extends CompileMetadataWithIdentifier {
- abstract toJson(): {[key: string]: any};
+ get runtimeCacheKey(): any { return unimplemented(); }
- get type(): CompileTypeMetadata { return unimplemented(); }
+ get assetCacheKey(): any { return unimplemented(); }
- get identifier(): CompileIdentifierMetadata { return unimplemented(); }
-}
-
-export function metadataFromJson(data: {[key: string]: any}): any {
- return (_COMPILE_METADATA_FROM_JSON as any)[data['class']](data);
+ equalsTo(id2: CompileMetadataWithIdentifier): boolean { return unimplemented(); }
}
export class CompileAnimationEntryMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationEntryMetadata {
- var value = data['value'];
- var defs = _arrayFromJson(value['definitions'], metadataFromJson);
- return new CompileAnimationEntryMetadata(value['name'], defs);
- }
-
constructor(
public name: string = null, public definitions: CompileAnimationStateMetadata[] = null) {}
-
- toJson(): {[key: string]: any} {
- return {
- 'class': 'AnimationEntryMetadata',
- 'value': {'name': this.name, 'definitions': _arrayToJson(this.definitions)}
- };
- }
}
export abstract class CompileAnimationStateMetadata {}
export class CompileAnimationStateDeclarationMetadata extends CompileAnimationStateMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationStateDeclarationMetadata {
- var value = data['value'];
- var styles = _objFromJson(value['styles'], metadataFromJson);
- return new CompileAnimationStateDeclarationMetadata(value['stateNameExpr'], styles);
- }
-
constructor(public stateNameExpr: string, public styles: CompileAnimationStyleMetadata) {
super();
}
-
- toJson(): {[key: string]: any} {
- return {
- 'class': 'AnimationStateDeclarationMetadata',
- 'value': {'stateNameExpr': this.stateNameExpr, 'styles': this.styles.toJson()}
- };
- }
}
export class CompileAnimationStateTransitionMetadata extends CompileAnimationStateMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationStateTransitionMetadata {
- var value = data['value'];
- var steps = _objFromJson(value['steps'], metadataFromJson);
- return new CompileAnimationStateTransitionMetadata(value['stateChangeExpr'], steps);
- }
-
constructor(public stateChangeExpr: string, public steps: CompileAnimationMetadata) { super(); }
-
- toJson(): {[key: string]: any} {
- return {
- 'class': 'AnimationStateTransitionMetadata',
- 'value': {'stateChangeExpr': this.stateChangeExpr, 'steps': this.steps.toJson()}
- };
- }
}
-export abstract class CompileAnimationMetadata { abstract toJson(): {[key: string]: any}; }
+export abstract class CompileAnimationMetadata {}
export class CompileAnimationKeyframesSequenceMetadata extends CompileAnimationMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationKeyframesSequenceMetadata {
- var steps = _arrayFromJson(data['value'], metadataFromJson);
- return new CompileAnimationKeyframesSequenceMetadata(steps);
- }
-
constructor(public steps: CompileAnimationStyleMetadata[] = []) { super(); }
-
- toJson(): {[key: string]: any} {
- return {'class': 'AnimationKeyframesSequenceMetadata', 'value': _arrayToJson(this.steps)};
- }
}
export class CompileAnimationStyleMetadata extends CompileAnimationMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationStyleMetadata {
- var value = data['value'];
- var offsetVal = value['offset'];
- var offset = isPresent(offsetVal) ? NumberWrapper.parseFloat(offsetVal) : null;
- var styles = >value['styles'];
- return new CompileAnimationStyleMetadata(offset, styles);
- }
-
constructor(
public offset: number, public styles: Array = null) {
super();
}
-
- toJson(): {[key: string]: any} {
- return {
- 'class': 'AnimationStyleMetadata',
- 'value': {'offset': this.offset, 'styles': this.styles}
- };
- }
}
export class CompileAnimationAnimateMetadata extends CompileAnimationMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationAnimateMetadata {
- var value = data['value'];
- var timings = value['timings'];
- var styles = _objFromJson(value['styles'], metadataFromJson);
- return new CompileAnimationAnimateMetadata(timings, styles);
- }
-
constructor(
public timings: string|number = 0, public styles: CompileAnimationStyleMetadata|
CompileAnimationKeyframesSequenceMetadata = null) {
super();
}
-
- toJson(): {[key: string]: any} {
- return {
- 'class': 'AnimationAnimateMetadata',
- 'value': {'timings': this.timings, 'styles': _objToJson(this.styles)}
- };
- }
}
export abstract class CompileAnimationWithStepsMetadata extends CompileAnimationMetadata {
@@ -162,29 +78,11 @@ export abstract class CompileAnimationWithStepsMetadata extends CompileAnimation
}
export class CompileAnimationSequenceMetadata extends CompileAnimationWithStepsMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationSequenceMetadata {
- var steps = _arrayFromJson(data['value'], metadataFromJson);
- return new CompileAnimationSequenceMetadata(steps);
- }
-
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); }
-
- toJson(): {[key: string]: any} {
- return {'class': 'AnimationSequenceMetadata', 'value': _arrayToJson(this.steps)};
- }
}
export class CompileAnimationGroupMetadata extends CompileAnimationWithStepsMetadata {
- static fromJson(data: {[key: string]: any}): CompileAnimationGroupMetadata {
- var steps = _arrayFromJson(data['value'], metadataFromJson);
- return new CompileAnimationGroupMetadata(steps);
- }
-
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); }
-
- toJson(): {[key: string]: any} {
- return {'class': 'AnimationGroupMetadata', 'value': _arrayToJson(this.steps)};
- }
}
export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier {
@@ -193,6 +91,7 @@ export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier
prefix: string;
moduleUrl: string;
value: any;
+ private _assetCacheKey: any = UNDEFINED;
constructor(
{runtime, name, moduleUrl, prefix, value}:
@@ -204,26 +103,28 @@ export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier
this.value = value;
}
- static fromJson(data: {[key: string]: any}): CompileIdentifierMetadata {
- let value = isArray(data['value']) ? _arrayFromJson(data['value'], metadataFromJson) :
- _objFromJson(data['value'], metadataFromJson);
- return new CompileIdentifierMetadata(
- {name: data['name'], prefix: data['prefix'], moduleUrl: data['moduleUrl'], value: value});
- }
-
- toJson(): {[key: string]: any} {
- let value = isArray(this.value) ? _arrayToJson(this.value) : _objToJson(this.value);
- return {
- // Note: Runtime type can't be serialized...
- 'class': 'Identifier',
- 'name': this.name,
- 'moduleUrl': this.moduleUrl,
- 'prefix': this.prefix,
- 'value': value
- };
- }
-
get identifier(): CompileIdentifierMetadata { return this; }
+
+ get runtimeCacheKey(): any { return this.identifier.runtime; }
+
+ get assetCacheKey(): any {
+ if (this._assetCacheKey === UNDEFINED) {
+ if (isPresent(this.moduleUrl) && isPresent(getUrlScheme(this.moduleUrl))) {
+ var uri = reflector.importUri({'filePath': this.moduleUrl, 'name': this.name});
+ this._assetCacheKey = `${this.name}|${uri}`;
+ } else {
+ this._assetCacheKey = null;
+ }
+ }
+ return this._assetCacheKey;
+ }
+
+ equalsTo(id2: CompileIdentifierMetadata): boolean {
+ var rk = this.runtimeCacheKey;
+ var ak = this.assetCacheKey;
+ return (isPresent(rk) && rk == id2.runtimeCacheKey) ||
+ (isPresent(ak) && ak == id2.assetCacheKey);
+ }
}
export class CompileDiDependencyMetadata {
@@ -263,36 +164,6 @@ export class CompileDiDependencyMetadata {
this.token = token;
this.value = value;
}
-
- static fromJson(data: {[key: string]: any}): CompileDiDependencyMetadata {
- return new CompileDiDependencyMetadata({
- token: _objFromJson(data['token'], CompileTokenMetadata.fromJson),
- query: _objFromJson(data['query'], CompileQueryMetadata.fromJson),
- viewQuery: _objFromJson(data['viewQuery'], CompileQueryMetadata.fromJson),
- value: data['value'],
- isAttribute: data['isAttribute'],
- isSelf: data['isSelf'],
- isHost: data['isHost'],
- isSkipSelf: data['isSkipSelf'],
- isOptional: data['isOptional'],
- isValue: data['isValue']
- });
- }
-
- toJson(): {[key: string]: any} {
- return {
- 'token': _objToJson(this.token),
- 'query': _objToJson(this.query),
- 'viewQuery': _objToJson(this.viewQuery),
- 'value': this.value,
- 'isAttribute': this.isAttribute,
- 'isSelf': this.isSelf,
- 'isHost': this.isHost,
- 'isSkipSelf': this.isSkipSelf,
- 'isOptional': this.isOptional,
- 'isValue': this.isValue
- };
- }
}
export class CompileProviderMetadata {
@@ -321,41 +192,9 @@ export class CompileProviderMetadata {
this.deps = normalizeBlank(deps);
this.multi = normalizeBool(multi);
}
-
- static fromJson(data: {[key: string]: any}): CompileProviderMetadata {
- return new CompileProviderMetadata({
- token: _objFromJson(data['token'], CompileTokenMetadata.fromJson),
- useClass: _objFromJson(data['useClass'], CompileTypeMetadata.fromJson),
- useExisting: _objFromJson(data['useExisting'], CompileTokenMetadata.fromJson),
- useValue: _objFromJson(data['useValue'], CompileIdentifierMetadata.fromJson),
- useFactory: _objFromJson(data['useFactory'], CompileFactoryMetadata.fromJson),
- multi: data['multi'],
- deps: _arrayFromJson(data['deps'], CompileDiDependencyMetadata.fromJson)
- });
- }
-
- toJson(): {[key: string]: any} {
- return {
- // Note: Runtime type can't be serialized...
- 'class': 'Provider',
- 'token': _objToJson(this.token),
- 'useClass': _objToJson(this.useClass),
- 'useExisting': _objToJson(this.useExisting),
- 'useValue': _objToJson(this.useValue),
- 'useFactory': _objToJson(this.useFactory),
- 'multi': this.multi,
- 'deps': _arrayToJson(this.deps)
- };
- }
}
-export class CompileFactoryMetadata implements CompileIdentifierMetadata,
- CompileMetadataWithIdentifier {
- runtime: Function;
- name: string;
- prefix: string;
- moduleUrl: string;
- value: any;
+export class CompileFactoryMetadata extends CompileIdentifierMetadata {
diDeps: CompileDiDependencyMetadata[];
constructor({runtime, name, moduleUrl, prefix, diDeps, value}: {
@@ -366,45 +205,15 @@ export class CompileFactoryMetadata implements CompileIdentifierMetadata,
value?: boolean,
diDeps?: CompileDiDependencyMetadata[]
}) {
- this.runtime = runtime;
- this.name = name;
- this.prefix = prefix;
- this.moduleUrl = moduleUrl;
+ super({runtime: runtime, name: name, prefix: prefix, moduleUrl: moduleUrl, value: value});
this.diDeps = _normalizeArray(diDeps);
- this.value = value;
- }
-
- get identifier(): CompileIdentifierMetadata { return this; }
-
- static fromJson(data: {[key: string]: any}): CompileFactoryMetadata {
- return new CompileFactoryMetadata({
- name: data['name'],
- prefix: data['prefix'],
- moduleUrl: data['moduleUrl'],
- value: data['value'],
- diDeps: _arrayFromJson(data['diDeps'], CompileDiDependencyMetadata.fromJson)
- });
- }
-
- toJson(): {[key: string]: any} {
- return {
- 'class': 'Factory',
- 'name': this.name,
- 'prefix': this.prefix,
- 'moduleUrl': this.moduleUrl,
- 'value': this.value,
- 'diDeps': _arrayToJson(this.diDeps)
- };
}
}
-var UNDEFINED = new Object();
-
export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
value: any;
identifier: CompileIdentifierMetadata;
identifierIsInstance: boolean;
- private _assetCacheKey = UNDEFINED;
constructor(
{value, identifier, identifierIsInstance}:
@@ -414,46 +223,20 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
this.identifierIsInstance = normalizeBool(identifierIsInstance);
}
- static fromJson(data: {[key: string]: any}): CompileTokenMetadata {
- return new CompileTokenMetadata({
- value: data['value'],
- identifier: _objFromJson(data['identifier'], CompileIdentifierMetadata.fromJson),
- identifierIsInstance: data['identifierIsInstance']
- });
- }
-
- toJson(): {[key: string]: any} {
- return {
- 'value': this.value,
- 'identifier': _objToJson(this.identifier),
- 'identifierIsInstance': this.identifierIsInstance
- };
- }
-
get runtimeCacheKey(): any {
if (isPresent(this.identifier)) {
- return this.identifier.runtime;
+ return this.identifier.runtimeCacheKey;
} else {
return this.value;
}
}
get assetCacheKey(): any {
- if (this._assetCacheKey === UNDEFINED) {
- if (isPresent(this.identifier)) {
- if (isPresent(this.identifier.moduleUrl) &&
- isPresent(getUrlScheme(this.identifier.moduleUrl))) {
- var uri = reflector.importUri(
- {'filePath': this.identifier.moduleUrl, 'name': this.identifier.name});
- this._assetCacheKey = `${this.identifier.name}|${uri}|${this.identifierIsInstance}`;
- } else {
- this._assetCacheKey = null;
- }
- } else {
- this._assetCacheKey = this.value;
- }
+ if (isPresent(this.identifier)) {
+ return this.identifier.assetCacheKey;
+ } else {
+ return this.value;
}
- return this._assetCacheKey;
}
equalsTo(token2: CompileTokenMetadata): boolean {
@@ -468,15 +251,24 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
}
}
-export class CompileTokenMap {
+/**
+ * Note: We only need this in places where we need to support identifiers that
+ * don't have a `runtime` value given by the `StaticReflector`. E.g. see the `identifiers`
+ * file where we have some identifiers hard coded by name/module path.
+ *
+ * TODO(tbosch): Eventually, all of these places should go through the static reflector
+ * as well, providing them with a valid `StaticSymbol` that is again a singleton.
+ */
+export class CompileIdentifierMap {
private _valueMap = new Map();
private _values: VALUE[] = [];
- private _tokens: CompileTokenMetadata[] = [];
+ private _tokens: KEY[] = [];
- add(token: CompileTokenMetadata, value: VALUE) {
+ add(token: KEY, value: VALUE) {
var existing = this.get(token);
if (isPresent(existing)) {
- throw new BaseException(`Can only add to a TokenMap! Token: ${token.name}`);
+ throw new BaseException(
+ `Cannot overwrite in a CompileIdentifierMap! Token: ${token.identifier.name}`);
}
this._tokens.push(token);
this._values.push(value);
@@ -489,7 +281,7 @@ export class CompileTokenMap {
this._valueMap.set(ak, value);
}
}
- get(token: CompileTokenMetadata): VALUE {
+ get(token: KEY): VALUE {
var rk = token.runtimeCacheKey;
var ak = token.assetCacheKey;
var result: VALUE;
@@ -501,7 +293,7 @@ export class CompileTokenMap {
}
return result;
}
- keys(): CompileTokenMetadata[] { return this._tokens; }
+ keys(): KEY[] { return this._tokens; }
values(): VALUE[] { return this._values; }
get size(): number { return this._values.length; }
}
@@ -509,13 +301,8 @@ export class CompileTokenMap {
/**
* Metadata regarding compilation of a type.
*/
-export class CompileTypeMetadata implements CompileIdentifierMetadata, CompileMetadataWithType {
- runtime: Type;
- name: string;
- prefix: string;
- moduleUrl: string;
+export class CompileTypeMetadata extends CompileIdentifierMetadata {
isHost: boolean;
- value: any;
diDeps: CompileDiDependencyMetadata[];
constructor({runtime, name, moduleUrl, prefix, isHost, value, diDeps}: {
@@ -527,41 +314,10 @@ export class CompileTypeMetadata implements CompileIdentifierMetadata, CompileMe
value?: any,
diDeps?: CompileDiDependencyMetadata[]
} = {}) {
- this.runtime = runtime;
- this.name = name;
- this.moduleUrl = moduleUrl;
- this.prefix = prefix;
+ super({runtime: runtime, name: name, moduleUrl: moduleUrl, prefix: prefix, value: value});
this.isHost = normalizeBool(isHost);
- this.value = value;
this.diDeps = _normalizeArray(diDeps);
}
-
- static fromJson(data: {[key: string]: any}): CompileTypeMetadata {
- return new CompileTypeMetadata({
- name: data['name'],
- moduleUrl: data['moduleUrl'],
- prefix: data['prefix'],
- isHost: data['isHost'],
- value: data['value'],
- diDeps: _arrayFromJson(data['diDeps'], CompileDiDependencyMetadata.fromJson)
- });
- }
-
- get identifier(): CompileIdentifierMetadata { return this; }
- get type(): CompileTypeMetadata { return this; }
-
- toJson(): {[key: string]: any} {
- return {
- // Note: Runtime type can't be serialized...
- 'class': 'Type',
- 'name': this.name,
- 'moduleUrl': this.moduleUrl,
- 'prefix': this.prefix,
- 'isHost': this.isHost,
- 'value': this.value,
- 'diDeps': _arrayToJson(this.diDeps)
- };
- }
}
export class CompileQueryMetadata {
@@ -584,26 +340,6 @@ export class CompileQueryMetadata {
this.propertyName = propertyName;
this.read = read;
}
-
- static fromJson(data: {[key: string]: any}): CompileQueryMetadata {
- return new CompileQueryMetadata({
- selectors: _arrayFromJson(data['selectors'], CompileTokenMetadata.fromJson),
- descendants: data['descendants'],
- first: data['first'],
- propertyName: data['propertyName'],
- read: _objFromJson(data['read'], CompileTokenMetadata.fromJson)
- });
- }
-
- toJson(): {[key: string]: any} {
- return {
- 'selectors': _arrayToJson(this.selectors),
- 'descendants': this.descendants,
- 'first': this.first,
- 'propertyName': this.propertyName,
- 'read': _objToJson(this.read)
- };
- }
}
/**
@@ -620,15 +356,6 @@ export class CompileStylesheetMetadata {
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
}
-
- static fromJson(data: {[key: string]: any}): CompileStylesheetMetadata {
- return new CompileStylesheetMetadata(
- {moduleUrl: data['moduleUrl'], styles: data['styles'], styleUrls: data['styleUrls']});
- }
-
- toJson(): {[key: string]: any} {
- return {'moduleUrl': this.moduleUrl, 'styles': this.styles, 'styleUrls': this.styleUrls};
- }
}
/**
@@ -670,46 +397,12 @@ export class CompileTemplateMetadata {
}
this.interpolation = interpolation;
}
-
- static fromJson(data: {[key: string]: any}): CompileTemplateMetadata {
- var animations =
- _arrayFromJson(data['animations'], metadataFromJson);
- return new CompileTemplateMetadata({
- encapsulation: isPresent(data['encapsulation']) ?
- VIEW_ENCAPSULATION_VALUES[data['encapsulation']] :
- data['encapsulation'],
- template: data['template'],
- templateUrl: data['templateUrl'],
- styles: data['styles'],
- styleUrls: data['styleUrls'],
- externalStylesheets:
- _arrayFromJson(data['externalStylesheets'], CompileStylesheetMetadata.fromJson),
- animations: animations,
- ngContentSelectors: data['ngContentSelectors'],
- interpolation: data['interpolation']
- });
- }
-
- toJson(): {[key: string]: any} {
- return {
- 'encapsulation': isPresent(this.encapsulation) ? serializeEnum(this.encapsulation) :
- this.encapsulation,
- 'template': this.template,
- 'templateUrl': this.templateUrl,
- 'styles': this.styles,
- 'styleUrls': this.styleUrls,
- 'externalStylesheets': _objToJson(this.externalStylesheets),
- 'animations': _objToJson(this.animations),
- 'ngContentSelectors': this.ngContentSelectors,
- 'interpolation': this.interpolation
- };
- }
}
/**
* Metadata regarding compilation of a directive.
*/
-export class CompileDirectiveMetadata implements CompileMetadataWithType {
+export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
static create(
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
lifecycleHooks, providers, viewProviders, queries, viewQueries, precompile, template}: {
@@ -796,6 +489,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
viewProviders: CompileProviderMetadata[];
queries: CompileQueryMetadata[];
viewQueries: CompileQueryMetadata[];
+ // Note: Need to keep types here to prevent cycles!
precompile: CompileTypeMetadata[];
template: CompileTemplateMetadata;
@@ -844,68 +538,26 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
get identifier(): CompileIdentifierMetadata { return this.type; }
- static fromJson(data: {[key: string]: any}): CompileDirectiveMetadata {
- return new CompileDirectiveMetadata({
- isComponent: data['isComponent'],
- selector: data['selector'],
- exportAs: data['exportAs'],
- type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
- changeDetection: isPresent(data['changeDetection']) ?
- CHANGE_DETECTION_STRATEGY_VALUES[data['changeDetection']] :
- data['changeDetection'],
- inputs: data['inputs'],
- outputs: data['outputs'],
- hostListeners: data['hostListeners'],
- hostProperties: data['hostProperties'],
- hostAttributes: data['hostAttributes'],
- lifecycleHooks:
- (data['lifecycleHooks']).map(hookValue => LIFECYCLE_HOOKS_VALUES[hookValue]),
- template: isPresent(data['template']) ? CompileTemplateMetadata.fromJson(data['template']) :
- data['template'],
- providers: _arrayFromJson(data['providers'], metadataFromJson),
- viewProviders: _arrayFromJson(data['viewProviders'], metadataFromJson),
- queries: _arrayFromJson(data['queries'], CompileQueryMetadata.fromJson),
- viewQueries: _arrayFromJson(data['viewQueries'], CompileQueryMetadata.fromJson),
- precompile: _arrayFromJson(data['precompile'], CompileTypeMetadata.fromJson)
- });
- }
+ get runtimeCacheKey(): any { return this.type.runtimeCacheKey; }
- toJson(): {[key: string]: any} {
- return {
- 'class': 'Directive',
- 'isComponent': this.isComponent,
- 'selector': this.selector,
- 'exportAs': this.exportAs,
- 'type': isPresent(this.type) ? this.type.toJson() : this.type,
- 'changeDetection': isPresent(this.changeDetection) ? serializeEnum(this.changeDetection) :
- this.changeDetection,
- 'inputs': this.inputs,
- 'outputs': this.outputs,
- 'hostListeners': this.hostListeners,
- 'hostProperties': this.hostProperties,
- 'hostAttributes': this.hostAttributes,
- 'lifecycleHooks': this.lifecycleHooks.map(hook => serializeEnum(hook)),
- 'template': isPresent(this.template) ? this.template.toJson() : this.template,
- 'providers': _arrayToJson(this.providers),
- 'viewProviders': _arrayToJson(this.viewProviders),
- 'queries': _arrayToJson(this.queries),
- 'viewQueries': _arrayToJson(this.viewQueries),
- 'precompile': _arrayToJson(this.precompile)
- };
+ get assetCacheKey(): any { return this.type.assetCacheKey; }
+
+ equalsTo(other: CompileMetadataWithIdentifier): boolean {
+ return this.type.equalsTo(other.identifier);
}
}
/**
* Construct {@link CompileDirectiveMetadata} from {@link ComponentTypeMetadata} and a selector.
*/
-export function createHostComponentMeta(
- componentType: CompileTypeMetadata, componentSelector: string): CompileDirectiveMetadata {
- var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();
+export function createHostComponentMeta(compMeta: CompileDirectiveMetadata):
+ CompileDirectiveMetadata {
+ var template = CssSelector.parse(compMeta.selector)[0].getMatchingElementTemplate();
return CompileDirectiveMetadata.create({
type: new CompileTypeMetadata({
runtime: Object,
- name: `${componentType.name}_Host`,
- moduleUrl: componentType.moduleUrl,
+ name: `${compMeta.type.name}_Host`,
+ moduleUrl: compMeta.type.moduleUrl,
isHost: true
}),
template: new CompileTemplateMetadata({
@@ -931,7 +583,7 @@ export function createHostComponentMeta(
}
-export class CompilePipeMetadata implements CompileMetadataWithType {
+export class CompilePipeMetadata implements CompileMetadataWithIdentifier {
type: CompileTypeMetadata;
name: string;
pure: boolean;
@@ -949,114 +601,91 @@ export class CompilePipeMetadata implements CompileMetadataWithType {
this.lifecycleHooks = _normalizeArray(lifecycleHooks);
}
get identifier(): CompileIdentifierMetadata { return this.type; }
+ get runtimeCacheKey(): any { return this.type.runtimeCacheKey; }
- static fromJson(data: {[key: string]: any}): CompilePipeMetadata {
- return new CompilePipeMetadata({
- type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
- name: data['name'],
- pure: data['pure']
- });
- }
+ get assetCacheKey(): any { return this.type.assetCacheKey; }
- toJson(): {[key: string]: any} {
- return {
- 'class': 'Pipe',
- 'type': isPresent(this.type) ? this.type.toJson() : null,
- 'name': this.name,
- 'pure': this.pure
- };
+ equalsTo(other: CompileMetadataWithIdentifier): boolean {
+ return this.type.equalsTo(other.identifier);
}
}
/**
* Metadata regarding compilation of a directive.
*/
-export class CompileAppModuleMetadata implements CompileMetadataWithType {
+export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
type: CompileTypeMetadata;
- providers: CompileProviderMetadata[];
- directives: CompileTypeMetadata[];
- pipes: CompileTypeMetadata[];
+ declaredDirectives: CompileDirectiveMetadata[];
+ exportedDirectives: CompileDirectiveMetadata[];
+ declaredPipes: CompilePipeMetadata[];
+ exportedPipes: CompilePipeMetadata[];
+ // Note: See CompileDirectiveMetadata.precompile why this has to be a type.
precompile: CompileTypeMetadata[];
- modules: CompileTypeMetadata[];
+ providers: CompileProviderMetadata[];
- constructor({type, providers, directives, pipes, precompile, modules}: {
- type?: CompileTypeMetadata,
- providers?: Array,
- directives?: CompileTypeMetadata[],
- pipes?: CompileTypeMetadata[],
- precompile?: CompileTypeMetadata[],
- modules?: CompileTypeMetadata[]
- } = {}) {
+ importedModules: CompileNgModuleMetadata[];
+ exportedModules: CompileNgModuleMetadata[];
+
+ transitiveModule: TransitiveCompileNgModuleMetadata;
+
+ constructor(
+ {type, providers, declaredDirectives, exportedDirectives, declaredPipes, exportedPipes,
+ precompile, importedModules, exportedModules, transitiveModule}: {
+ type?: CompileTypeMetadata,
+ providers?:
+ Array,
+ declaredDirectives?: CompileDirectiveMetadata[],
+ exportedDirectives?: CompileDirectiveMetadata[],
+ declaredPipes?: CompilePipeMetadata[],
+ exportedPipes?: CompilePipeMetadata[],
+ precompile?: CompileTypeMetadata[],
+ importedModules?: CompileNgModuleMetadata[],
+ exportedModules?: CompileNgModuleMetadata[],
+ transitiveModule?: TransitiveCompileNgModuleMetadata
+ } = {}) {
this.type = type;
- this.directives = _normalizeArray(directives);
- this.pipes = _normalizeArray(pipes);
+ this.declaredDirectives = _normalizeArray(declaredDirectives);
+ this.exportedDirectives = _normalizeArray(exportedDirectives);
+ this.declaredPipes = _normalizeArray(declaredPipes);
+ this.exportedPipes = _normalizeArray(exportedPipes);
this.providers = _normalizeArray(providers);
this.precompile = _normalizeArray(precompile);
- this.modules = _normalizeArray(modules);
+ this.importedModules = _normalizeArray(importedModules);
+ this.exportedModules = _normalizeArray(exportedModules);
+ this.transitiveModule = transitiveModule;
}
get identifier(): CompileIdentifierMetadata { return this.type; }
+ get runtimeCacheKey(): any { return this.type.runtimeCacheKey; }
- static fromJson(data: {[key: string]: any}): CompileAppModuleMetadata {
- return new CompileAppModuleMetadata({
- type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
- providers: _arrayFromJson(data['providers'], metadataFromJson),
- directives: _arrayFromJson(data['directives'], metadataFromJson),
- pipes: _arrayFromJson(data['pipes'], metadataFromJson),
- precompile: _arrayFromJson(data['precompile'], CompileTypeMetadata.fromJson),
- modules: _arrayFromJson(data['modules'], CompileTypeMetadata.fromJson)
- });
- }
+ get assetCacheKey(): any { return this.type.assetCacheKey; }
- toJson(): {[key: string]: any} {
- return {
- 'class': 'AppModule',
- 'type': isPresent(this.type) ? this.type.toJson() : this.type,
- 'providers': _arrayToJson(this.providers),
- 'directives': _arrayToJson(this.directives),
- 'pipes': _arrayToJson(this.pipes),
- 'precompile': _arrayToJson(this.precompile),
- 'modules': _arrayToJson(this.modules)
- };
+ equalsTo(other: CompileMetadataWithIdentifier): boolean {
+ return this.type.equalsTo(other.identifier);
}
}
-var _COMPILE_METADATA_FROM_JSON = {
- 'AppModule': CompileAppModuleMetadata.fromJson,
- 'Directive': CompileDirectiveMetadata.fromJson,
- 'Pipe': CompilePipeMetadata.fromJson,
- 'Type': CompileTypeMetadata.fromJson,
- 'Provider': CompileProviderMetadata.fromJson,
- 'Identifier': CompileIdentifierMetadata.fromJson,
- 'Factory': CompileFactoryMetadata.fromJson,
- 'AnimationEntryMetadata': CompileAnimationEntryMetadata.fromJson,
- 'AnimationStateDeclarationMetadata': CompileAnimationStateDeclarationMetadata.fromJson,
- 'AnimationStateTransitionMetadata': CompileAnimationStateTransitionMetadata.fromJson,
- 'AnimationSequenceMetadata': CompileAnimationSequenceMetadata.fromJson,
- 'AnimationGroupMetadata': CompileAnimationGroupMetadata.fromJson,
- 'AnimationAnimateMetadata': CompileAnimationAnimateMetadata.fromJson,
- 'AnimationStyleMetadata': CompileAnimationStyleMetadata.fromJson,
- 'AnimationKeyframesSequenceMetadata': CompileAnimationKeyframesSequenceMetadata.fromJson
-};
-
-function _arrayFromJson(obj: any[], fn: (a: {[key: string]: any}) => any): any {
- return isBlank(obj) ? null : obj.map(o => _objFromJson(o, fn));
+export class TransitiveCompileNgModuleMetadata {
+ directivesSet = new Set();
+ pipesSet = new Set();
+ constructor(
+ public modules: CompileNgModuleMetadata[], public providers: CompileProviderMetadata[],
+ public precompile: CompileTypeMetadata[], public directives: CompileDirectiveMetadata[],
+ public pipes: CompilePipeMetadata[]) {
+ directives.forEach(dir => this.directivesSet.add(dir.type.runtime));
+ pipes.forEach(pipe => this.pipesSet.add(pipe.type.runtime));
+ }
}
-function _arrayToJson(obj: any[]): string|{[key: string]: any} {
- return isBlank(obj) ? null : obj.map(_objToJson);
-}
-
-function _objFromJson(obj: any, fn: (a: {[key: string]: any}) => any): any {
- if (isArray(obj)) return _arrayFromJson(obj, fn);
- if (isString(obj) || isBlank(obj) || isBoolean(obj) || isNumber(obj)) return obj;
- return fn(obj);
-}
-
-function _objToJson(obj: any): string|{[key: string]: any} {
- if (isArray(obj)) return _arrayToJson(obj);
- if (isString(obj) || isBlank(obj) || isBoolean(obj) || isNumber(obj)) return obj;
- return obj.toJson();
+export function removeIdentifierDuplicates(items: T[]):
+ T[] {
+ const map = new CompileIdentifierMap();
+ items.forEach((item) => {
+ if (!map.get(item)) {
+ map.add(item, item);
+ }
+ });
+ return map.keys();
}
function _normalizeArray(obj: any[]): any[] {
diff --git a/modules/@angular/compiler/src/compiler.ts b/modules/@angular/compiler/src/compiler.ts
index 0c3bb2fd30..50b83aeb08 100644
--- a/modules/@angular/compiler/src/compiler.ts
+++ b/modules/@angular/compiler/src/compiler.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {Compiler, CompilerFactory, CompilerOptions, ComponentResolver, Injectable, PLATFORM_DIRECTIVES, PLATFORM_PIPES, ReflectiveInjector, Type, ViewEncapsulation, isDevMode} from '@angular/core';
+import {Compiler, CompilerFactory, CompilerOptions, Component, ComponentResolver, Inject, Injectable, NgModule, PLATFORM_DIRECTIVES, PLATFORM_INITIALIZER, PLATFORM_PIPES, PlatformRef, ReflectiveInjector, Type, ViewEncapsulation, corePlatform, createPlatformFactory, disposePlatform, isDevMode} from '@angular/core';
export * from './template_ast';
export {TEMPLATE_TRANSFORMS} from './template_parser';
@@ -20,14 +20,17 @@ export * from './xhr';
export {ViewResolver} from './view_resolver';
export {DirectiveResolver} from './directive_resolver';
export {PipeResolver} from './pipe_resolver';
+export {NgModuleResolver} from './ng_module_resolver';
+import {stringify} from './facade/lang';
+import {ListWrapper} from './facade/collection';
import {TemplateParser} from './template_parser';
import {HtmlParser} from './html_parser';
import {DirectiveNormalizer} from './directive_normalizer';
import {CompileMetadataResolver} from './metadata_resolver';
import {StyleCompiler} from './style_compiler';
import {ViewCompiler} from './view_compiler/view_compiler';
-import {AppModuleCompiler} from './app_module_compiler';
+import {NgModuleCompiler} from './ng_module_compiler';
import {CompilerConfig} from './config';
import {RuntimeCompiler} from './runtime_compiler';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
@@ -38,19 +41,24 @@ import {Lexer} from './expression_parser/lexer';
import {ViewResolver} from './view_resolver';
import {DirectiveResolver} from './directive_resolver';
import {PipeResolver} from './pipe_resolver';
-import {Console, Reflector, reflector, ReflectorReader} from '../core_private';
+import {NgModuleResolver} from './ng_module_resolver';
+import {Console, Reflector, reflector, ReflectorReader, ReflectionCapabilities} from '../core_private';
import {XHR} from './xhr';
+const _NO_XHR: XHR = {
+ get(url: string): Promise{
+ throw new Error(`No XHR implementation has been provided. Can't read the url "${url}"`);}
+};
+
/**
* A set of providers that provide `RuntimeCompiler` and its dependencies to use for
* template compilation.
*/
export const COMPILER_PROVIDERS: Array =
/*@ts2dart_const*/[
- {provide: PLATFORM_DIRECTIVES, useValue: [], multi: true},
- {provide: PLATFORM_PIPES, useValue: [], multi: true},
{provide: Reflector, useValue: reflector},
{provide: ReflectorReader, useExisting: Reflector},
+ {provide: XHR, useValue: _NO_XHR},
Console,
Lexer,
Parser,
@@ -61,112 +69,153 @@ export const COMPILER_PROVIDERS: Array =
DEFAULT_PACKAGE_URL_PROVIDER,
StyleCompiler,
ViewCompiler,
- AppModuleCompiler,
+ NgModuleCompiler,
/*@ts2dart_Provider*/ {provide: CompilerConfig, useValue: new CompilerConfig()},
RuntimeCompiler,
- /*@ts2dart_Provider*/ {provide: ComponentResolver, useExisting: RuntimeCompiler},
/*@ts2dart_Provider*/ {provide: Compiler, useExisting: RuntimeCompiler},
DomElementSchemaRegistry,
/*@ts2dart_Provider*/ {provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
UrlResolver,
ViewResolver,
DirectiveResolver,
- PipeResolver
+ PipeResolver,
+ NgModuleResolver
];
+
+export function analyzeAppProvidersForDeprecatedConfiguration(appProviders: any[] = []):
+ {compilerOptions: CompilerOptions, moduleDeclarations: Type[], deprecationMessages: string[]} {
+ let platformDirectives: any[] = [];
+ let platformPipes: any[] = [];
+
+ let compilerProviders: any[] = [];
+ let useDebug: boolean;
+ let useJit: boolean;
+ let defaultEncapsulation: ViewEncapsulation;
+ const deprecationMessages: string[] = [];
+
+ // Note: This is a hack to still support the old way
+ // of configuring platform directives / pipes and the compiler xhr.
+ // This will soon be deprecated!
+ const tempInj = ReflectiveInjector.resolveAndCreate(appProviders);
+ const compilerConfig: CompilerConfig = tempInj.get(CompilerConfig, null);
+ if (compilerConfig) {
+ platformDirectives = compilerConfig.platformDirectives;
+ platformPipes = compilerConfig.platformPipes;
+ useJit = compilerConfig.useJit;
+ useDebug = compilerConfig.genDebugInfo;
+ defaultEncapsulation = compilerConfig.defaultEncapsulation;
+ deprecationMessages.push(
+ `Passing CompilerConfig as a regular provider is deprecated. Use the "compilerOptions" parameter of "bootstrap()" or use a custom "CompilerFactory" platform provider instead.`);
+ } else {
+ // If nobody provided a CompilerConfig, use the
+ // PLATFORM_DIRECTIVES / PLATFORM_PIPES values directly if existing
+ platformDirectives = tempInj.get(PLATFORM_DIRECTIVES, []);
+ platformPipes = tempInj.get(PLATFORM_PIPES, []);
+ }
+ platformDirectives = ListWrapper.flatten(platformDirectives);
+ platformPipes = ListWrapper.flatten(platformPipes);
+ const xhr = tempInj.get(XHR, null);
+ if (xhr) {
+ compilerProviders.push([{provide: XHR, useValue: xhr}]);
+ deprecationMessages.push(
+ `Passing XHR as regular provider is deprecated. Pass the provider via "compilerOptions" instead.`);
+ }
+
+ if (platformDirectives.length > 0) {
+ deprecationMessages.push(
+ `The PLATFORM_DIRECTIVES provider and CompilerConfig.platformDirectives is deprecated. Add the directives to an NgModule instead! ` +
+ `(Directives: ${platformDirectives.map(type => stringify(type))})`);
+ }
+ if (platformPipes.length > 0) {
+ deprecationMessages.push(
+ `The PLATFORM_PIPES provider and CompilerConfig.platformPipes is deprecated. Add the pipes to an NgModule instead! ` +
+ `(Pipes: ${platformPipes.map(type => stringify(type))})`);
+ }
+ const compilerOptions: CompilerOptions = {
+ useJit: useJit,
+ useDebug: useDebug,
+ defaultEncapsulation: defaultEncapsulation,
+ providers: compilerProviders
+ };
+
+ // Declare a component that uses @Component.directives / pipes as these
+ // will be added to the module declarations only if they are not already
+ // imported by other modules.
+ @Component({directives: platformDirectives, pipes: platformPipes, template: ''})
+ class DynamicComponent {
+ }
+
+ return {
+ compilerOptions,
+ moduleDeclarations: [DynamicComponent],
+ deprecationMessages: deprecationMessages
+ };
+}
+
@Injectable()
-export class _RuntimeCompilerFactory extends CompilerFactory {
- createCompiler(options: CompilerOptions): Compiler {
- const deprecationMessages: string[] = [];
- let platformDirectivesFromAppProviders: any[] = [];
- let platformPipesFromAppProviders: any[] = [];
- let compilerProvidersFromAppProviders: any[] = [];
- let useDebugFromAppProviders: boolean;
- let useJitFromAppProviders: boolean;
- let defaultEncapsulationFromAppProviders: ViewEncapsulation;
-
- if (options.deprecatedAppProviders && options.deprecatedAppProviders.length > 0) {
- // Note: This is a hack to still support the old way
- // of configuring platform directives / pipes and the compiler xhr.
- // This will soon be deprecated!
- const inj = ReflectiveInjector.resolveAndCreate(options.deprecatedAppProviders);
- const compilerConfig: CompilerConfig = inj.get(CompilerConfig, null);
- if (compilerConfig) {
- platformDirectivesFromAppProviders = compilerConfig.deprecatedPlatformDirectives;
- platformPipesFromAppProviders = compilerConfig.deprecatedPlatformPipes;
- useJitFromAppProviders = compilerConfig.useJit;
- useDebugFromAppProviders = compilerConfig.genDebugInfo;
- defaultEncapsulationFromAppProviders = compilerConfig.defaultEncapsulation;
- deprecationMessages.push(
- `Passing a CompilerConfig to "bootstrap()" as provider is deprecated. Pass the provider via the new parameter "compilerOptions" of "bootstrap()" instead.`);
- } else {
- // If nobody provided a CompilerConfig, use the
- // PLATFORM_DIRECTIVES / PLATFORM_PIPES values directly if existing
- platformDirectivesFromAppProviders = inj.get(PLATFORM_DIRECTIVES, []);
- if (platformDirectivesFromAppProviders.length > 0) {
- deprecationMessages.push(
- `Passing PLATFORM_DIRECTIVES to "bootstrap()" as provider is deprecated. Use the new parameter "directives" of "bootstrap()" instead.`);
- }
- platformPipesFromAppProviders = inj.get(PLATFORM_PIPES, []);
- if (platformPipesFromAppProviders.length > 0) {
- deprecationMessages.push(
- `Passing PLATFORM_PIPES to "bootstrap()" as provider is deprecated. Use the new parameter "pipes" of "bootstrap()" instead.`);
- }
- }
- const xhr = inj.get(XHR, null);
- if (xhr) {
- compilerProvidersFromAppProviders.push([{provide: XHR, useValue: xhr}]);
- deprecationMessages.push(
- `Passing an instance of XHR to "bootstrap()" as provider is deprecated. Pass the provider via the new parameter "compilerOptions" of "bootstrap()" instead.`);
- }
- // Need to copy console from deprecatedAppProviders to compiler providers
- // as well so that we can test the above deprecation messages in old style bootstrap
- // where we only have app providers!
- const console = inj.get(Console, null);
- if (console) {
- compilerProvidersFromAppProviders.push([{provide: Console, useValue: console}]);
- }
- }
-
+export class RuntimeCompilerFactory implements CompilerFactory {
+ private _defaultOptions: CompilerOptions[];
+ constructor(@Inject(CompilerOptions) defaultOptions: CompilerOptions[]) {
+ this._defaultOptions = [{
+ useDebug: isDevMode(),
+ useJit: true,
+ defaultEncapsulation: ViewEncapsulation.Emulated
+ }].concat(defaultOptions);
+ }
+ createCompiler(options: CompilerOptions[] = []): Compiler {
+ const mergedOptions = _mergeOptions(this._defaultOptions.concat(options));
const injector = ReflectiveInjector.resolveAndCreate([
COMPILER_PROVIDERS, {
provide: CompilerConfig,
- useFactory: (platformDirectives: any[], platformPipes: any[]) => {
+ useFactory: () => {
return new CompilerConfig({
- deprecatedPlatformDirectives:
- _mergeArrays(platformDirectivesFromAppProviders, platformDirectives),
- deprecatedPlatformPipes: _mergeArrays(platformPipesFromAppProviders, platformPipes),
// let explicit values from the compiler options overwrite options
// from the app providers. E.g. important for the testing platform.
- genDebugInfo: _firstDefined(options.useDebug, useDebugFromAppProviders, isDevMode()),
+ genDebugInfo: mergedOptions.useDebug,
// let explicit values from the compiler options overwrite options
// from the app providers
- useJit: _firstDefined(options.useJit, useJitFromAppProviders, true),
+ useJit: mergedOptions.useJit,
// let explicit values from the compiler options overwrite options
// from the app providers
- defaultEncapsulation: _firstDefined(
- options.defaultEncapsulation, defaultEncapsulationFromAppProviders,
- ViewEncapsulation.Emulated)
+ defaultEncapsulation: mergedOptions.defaultEncapsulation,
+ logBindingUpdate: mergedOptions.useDebug
});
},
- deps: [PLATFORM_DIRECTIVES, PLATFORM_PIPES]
+ deps: []
},
- // options.providers will always contain a provider for XHR as well
- // (added by platforms). So allow compilerProvidersFromAppProviders to overwrite this
- _mergeArrays(options.providers, compilerProvidersFromAppProviders)
+ mergedOptions.providers
]);
- const console: Console = injector.get(Console);
- deprecationMessages.forEach((msg) => { console.warn(msg); });
-
return injector.get(Compiler);
}
}
+function _initReflector() {
+ reflector.reflectionCapabilities = new ReflectionCapabilities();
+}
-export const RUNTIME_COMPILER_FACTORY = new _RuntimeCompilerFactory();
+/**
+ * A platform that included corePlatform and the compiler.
+ *
+ * @experimental
+ */
+export const coreDynamicPlatform = createPlatformFactory(corePlatform, 'coreDynamic', [
+ {provide: CompilerOptions, useValue: {}, multi: true},
+ {provide: CompilerFactory, useClass: RuntimeCompilerFactory},
+ {provide: PLATFORM_INITIALIZER, useValue: _initReflector, multi: true},
+]);
-function _firstDefined(...args: T[]): T {
- for (var i = 0; i < args.length; i++) {
+function _mergeOptions(optionsArr: CompilerOptions[]): CompilerOptions {
+ return {
+ useDebug: _lastDefined(optionsArr.map(options => options.useDebug)),
+ useJit: _lastDefined(optionsArr.map(options => options.useJit)),
+ defaultEncapsulation: _lastDefined(optionsArr.map(options => options.defaultEncapsulation)),
+ providers: _mergeArrays(optionsArr.map(options => options.providers))
+ };
+}
+
+function _lastDefined(args: T[]): T {
+ for (var i = args.length - 1; i >= 0; i--) {
if (args[i] !== undefined) {
return args[i];
}
@@ -174,7 +223,7 @@ function _firstDefined(...args: T[]): T {
return undefined;
}
-function _mergeArrays(...parts: any[][]): any[] {
+function _mergeArrays(parts: any[][]): any[] {
let result: any[] = [];
parts.forEach((part) => result.push(...part));
return result;
diff --git a/modules/@angular/compiler/src/config.ts b/modules/@angular/compiler/src/config.ts
index 4e7f74ae00..a765f34324 100644
--- a/modules/@angular/compiler/src/config.ts
+++ b/modules/@angular/compiler/src/config.ts
@@ -20,17 +20,15 @@ export class CompilerConfig {
private _logBindingUpdate: boolean;
public useJit: boolean;
/**
- * @deprecated Providing platform directives via the {@link CompilerConfig} deprecated. Provide
- * platform
- * directives via an {@link AppModule} instead.
+ * @deprecated Providing platform directives via the {@link CompilerConfig} is deprecated. Provide
+ * platform directives via an {@link NgModule} instead.
*/
- public deprecatedPlatformDirectives: any[];
+ public platformDirectives: any[];
/**
- * @deprecated Providing platform pipes via the {@link CompilerConfig} deprecated. Provide
- * platform pipes
- * via an {@link AppModule} instead.
+ * @deprecated Providing platform pipes via the {@link CompilerConfig} is deprecated. Provide
+ * platform pipes via an {@link NgModule} instead.
*/
- public deprecatedPlatformPipes: any[];
+ public platformPipes: any[];
constructor(
{renderTypes = new DefaultRenderTypes(), defaultEncapsulation = ViewEncapsulation.Emulated,
@@ -49,8 +47,8 @@ export class CompilerConfig {
this._genDebugInfo = genDebugInfo;
this._logBindingUpdate = logBindingUpdate;
this.useJit = useJit;
- this.deprecatedPlatformDirectives = deprecatedPlatformDirectives;
- this.deprecatedPlatformPipes = deprecatedPlatformPipes;
+ this.platformDirectives = deprecatedPlatformDirectives;
+ this.platformPipes = deprecatedPlatformPipes;
}
get genDebugInfo(): boolean {
diff --git a/modules/@angular/compiler/src/directive_resolver.ts b/modules/@angular/compiler/src/directive_resolver.ts
index 2c18904041..939541163c 100644
--- a/modules/@angular/compiler/src/directive_resolver.ts
+++ b/modules/@angular/compiler/src/directive_resolver.ts
@@ -33,7 +33,7 @@ export class DirectiveResolver {
/**
* Return {@link DirectiveMetadata} for a given `Type`.
*/
- resolve(type: Type): DirectiveMetadata {
+ resolve(type: Type, throwIfNotFound = true): DirectiveMetadata {
var typeMetadata = this._reflector.annotations(resolveForwardRef(type));
if (isPresent(typeMetadata)) {
var metadata = typeMetadata.find(_isDirectiveMetadata);
@@ -42,8 +42,10 @@ export class DirectiveResolver {
return this._mergeWithPropertyMetadata(metadata, propertyMetadata, type);
}
}
-
- throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
+ if (throwIfNotFound) {
+ throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
+ }
+ return null;
}
private _mergeWithPropertyMetadata(
diff --git a/modules/@angular/compiler/src/identifiers.ts b/modules/@angular/compiler/src/identifiers.ts
index bf07e272d4..304674fdc4 100644
--- a/modules/@angular/compiler/src/identifiers.ts
+++ b/modules/@angular/compiler/src/identifiers.ts
@@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {ANALYZE_FOR_PRECOMPILE, AppModuleFactory, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
+import {ANALYZE_FOR_PRECOMPILE, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
-import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppModuleInjector, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles} from '../core_private';
+import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NgModuleInjector, NoOpAnimationPlayer as NoOpAnimationPlayer_, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles} from '../core_private';
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
import {assetUrl} from './util';
@@ -118,15 +118,15 @@ export class Identifiers {
runtime: ComponentFactory,
moduleUrl: assetUrl('core', 'linker/component_factory')
});
- static AppModuleFactory = new CompileIdentifierMetadata({
- name: 'AppModuleFactory',
- runtime: AppModuleFactory,
- moduleUrl: assetUrl('core', 'linker/app_module_factory')
+ static NgModuleFactory = new CompileIdentifierMetadata({
+ name: 'NgModuleFactory',
+ runtime: NgModuleFactory,
+ moduleUrl: assetUrl('core', 'linker/ng_module_factory')
});
- static AppModuleInjector = new CompileIdentifierMetadata({
- name: 'AppModuleInjector',
- runtime: AppModuleInjector,
- moduleUrl: assetUrl('core', 'linker/app_module_factory')
+ static NgModuleInjector = new CompileIdentifierMetadata({
+ name: 'NgModuleInjector',
+ runtime: NgModuleInjector,
+ moduleUrl: assetUrl('core', 'linker/ng_module_factory')
});
static ValueUnwrapper = new CompileIdentifierMetadata(
{name: 'ValueUnwrapper', moduleUrl: CD_MODULE_URL, runtime: impValueUnwrapper});
diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts
index 278f9c7074..e8615891c5 100644
--- a/modules/@angular/compiler/src/metadata_resolver.ts
+++ b/modules/@angular/compiler/src/metadata_resolver.ts
@@ -6,10 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AppModuleMetadata, AttributeMetadata, ChangeDetectionStrategy, ComponentMetadata, HostMetadata, Inject, InjectMetadata, Injectable, Optional, OptionalMetadata, Provider, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewMetadata, ViewQueryMetadata, resolveForwardRef} from '@angular/core';
+import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AttributeMetadata, ChangeDetectionStrategy, ComponentMetadata, HostMetadata, Inject, InjectMetadata, Injectable, NgModule, NgModuleMetadata, Optional, OptionalMetadata, Provider, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewMetadata, ViewQueryMetadata, resolveForwardRef} from '@angular/core';
-import {LIFECYCLE_HOOKS_VALUES, ReflectorReader, createProvider, isProviderLiteral, reflector} from '../core_private';
-import {StringMapWrapper} from '../src/facade/collection';
+import {Console, LIFECYCLE_HOOKS_VALUES, ReflectorReader, createProvider, isProviderLiteral, reflector} from '../core_private';
+import {MapWrapper, StringMapWrapper} from '../src/facade/collection';
import {BaseException} from '../src/facade/exceptions';
import {Type, isArray, isBlank, isPresent, isString, isStringMap, stringify} from '../src/facade/lang';
@@ -19,6 +19,7 @@ import {CompilerConfig} from './config';
import {hasLifecycleHook} from './directive_lifecycle_reflector';
import {DirectiveResolver} from './directive_resolver';
import {Identifiers, identifierToken} from './identifiers';
+import {NgModuleResolver} from './ng_module_resolver';
import {PipeResolver} from './pipe_resolver';
import {getUrlScheme} from './url_resolver';
import {MODULE_SUFFIX, ValueTransformer, sanitizeIdentifier, visitValue} from './util';
@@ -28,13 +29,15 @@ import {ViewResolver} from './view_resolver';
export class CompileMetadataResolver {
private _directiveCache = new Map();
private _pipeCache = new Map();
- private _appModuleCache = new Map();
+ private _ngModuleCache = new Map();
+ private _ngModuleOfTypes = new Map();
private _anonymousTypes = new Map();
private _anonymousTypeIndex = 0;
constructor(
- private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver,
- private _viewResolver: ViewResolver, private _config: CompilerConfig,
+ private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
+ private _pipeResolver: PipeResolver, private _viewResolver: ViewResolver,
+ private _config: CompilerConfig, private _console: Console,
private _reflector: ReflectorReader = reflector) {}
private sanitizeTokenName(token: any): string {
@@ -54,13 +57,16 @@ export class CompileMetadataResolver {
clearCacheFor(type: Type) {
this._directiveCache.delete(type);
this._pipeCache.delete(type);
- this._appModuleCache.delete(type);
+ this._ngModuleOfTypes.delete(type);
+ // Clear all of the NgModuleMetadata as they contain transitive information!
+ this._ngModuleCache.clear();
}
clearCache() {
this._directiveCache.clear();
this._pipeCache.clear();
- this._appModuleCache.clear();
+ this._ngModuleCache.clear();
+ this._ngModuleOfTypes.clear();
}
getAnimationEntryMetadata(entry: AnimationEntryMetadata): cpl.CompileAnimationEntryMetadata {
@@ -105,11 +111,14 @@ export class CompileMetadataResolver {
return null;
}
- getDirectiveMetadata(directiveType: Type): cpl.CompileDirectiveMetadata {
+ getDirectiveMetadata(directiveType: Type, throwIfNotFound = true): cpl.CompileDirectiveMetadata {
directiveType = resolveForwardRef(directiveType);
var meta = this._directiveCache.get(directiveType);
if (isBlank(meta)) {
- var dirMeta = this._directiveResolver.resolve(directiveType);
+ var dirMeta = this._directiveResolver.resolve(directiveType, throwIfNotFound);
+ if (!dirMeta) {
+ return null;
+ }
var templateMeta: cpl.CompileTemplateMetadata = null;
var changeDetectionStrategy: ChangeDetectionStrategy = null;
var viewProviders: Array = [];
@@ -182,83 +191,254 @@ export class CompileMetadataResolver {
return meta;
}
- getAppModuleMetadata(moduleType: any, meta: AppModuleMetadata = null):
- cpl.CompileAppModuleMetadata {
- // Only cache if we read the metadata via the reflector,
- // as we use the moduleType as cache key.
- let useCache = !meta;
+ getNgModuleMetadata(moduleType: any, throwIfNotFound = true): cpl.CompileNgModuleMetadata {
moduleType = resolveForwardRef(moduleType);
- var compileMeta = this._appModuleCache.get(moduleType);
- if (isBlank(compileMeta) || !useCache) {
+ var compileMeta = this._ngModuleCache.get(moduleType);
+ if (!compileMeta) {
+ const meta = this._ngModuleResolver.resolve(moduleType, throwIfNotFound);
if (!meta) {
- meta = this._reflector.annotations(moduleType)
- .find((meta) => meta instanceof AppModuleMetadata);
+ return null;
}
- if (!meta) {
- throw new BaseException(
- `Could not compile '${stringify(moduleType)}' because it is not an AppModule.`);
- }
- let modules: cpl.CompileTypeMetadata[] = [];
- let providers: any[] = [];
- let directives: cpl.CompileTypeMetadata[] = [];
- let pipes: cpl.CompileTypeMetadata[] = [];
- let precompile: cpl.CompileTypeMetadata[] = [];
- if (meta.modules) {
- flattenArray(meta.modules).forEach((moduleType) => {
- var meta = this.getAppModuleMetadata(moduleType);
- providers.push(...meta.providers);
- directives.push(...meta.directives);
- pipes.push(...meta.pipes);
- precompile.push(...meta.precompile);
- modules.push(meta.type);
- modules.push(...meta.modules);
+ const declaredDirectives: cpl.CompileDirectiveMetadata[] = [];
+ const exportedDirectives: cpl.CompileDirectiveMetadata[] = [];
+ const declaredPipes: cpl.CompilePipeMetadata[] = [];
+ const exportedPipes: cpl.CompilePipeMetadata[] = [];
+ const importedModules: cpl.CompileNgModuleMetadata[] = [];
+ const exportedModules: cpl.CompileNgModuleMetadata[] = [];
+
+ if (meta.imports) {
+ flattenArray(meta.imports).forEach((importedType) => {
+ if (!isValidType(importedType)) {
+ throw new BaseException(
+ `Unexpected value '${stringify(importedType)}' imported by the module '${stringify(moduleType)}'`);
+ }
+ let importedModuleMeta: cpl.CompileNgModuleMetadata;
+ if (importedModuleMeta = this.getNgModuleMetadata(importedType, false)) {
+ importedModules.push(importedModuleMeta);
+ } else {
+ throw new BaseException(
+ `Unexpected value '${stringify(importedType)}' imported by the module '${stringify(moduleType)}'`);
+ }
});
}
+ if (meta.exports) {
+ flattenArray(meta.exports).forEach((exportedType) => {
+ if (!isValidType(exportedType)) {
+ throw new BaseException(
+ `Unexpected value '${stringify(exportedType)}' exported by the module '${stringify(moduleType)}'`);
+ }
+ let exportedDirMeta: cpl.CompileDirectiveMetadata;
+ let exportedPipeMeta: cpl.CompilePipeMetadata;
+ let exportedModuleMeta: cpl.CompileNgModuleMetadata;
+ if (exportedDirMeta = this.getDirectiveMetadata(exportedType, false)) {
+ exportedDirectives.push(exportedDirMeta);
+ } else if (exportedPipeMeta = this.getPipeMetadata(exportedType, false)) {
+ exportedPipes.push(exportedPipeMeta);
+ } else if (exportedModuleMeta = this.getNgModuleMetadata(exportedType, false)) {
+ exportedModules.push(exportedModuleMeta);
+ } else {
+ throw new BaseException(
+ `Unexpected value '${stringify(exportedType)}' exported by the module '${stringify(moduleType)}'`);
+ }
+ });
+ }
+
+ // Note: This will be modified later, so we rely on
+ // getting a new instance every time!
+ const transitiveModule =
+ this._getTransitiveNgModuleMetadata(importedModules, exportedModules);
+ if (meta.declarations) {
+ flattenArray(meta.declarations).forEach((declaredType) => {
+ if (!isValidType(declaredType)) {
+ throw new BaseException(
+ `Unexpected value '${stringify(declaredType)}' declared by the module '${stringify(moduleType)}'`);
+ }
+ let declaredDirMeta: cpl.CompileDirectiveMetadata;
+ let declaredPipeMeta: cpl.CompilePipeMetadata;
+ if (declaredDirMeta = this.getDirectiveMetadata(declaredType, false)) {
+ this._addDirectiveToModule(
+ declaredDirMeta, moduleType, transitiveModule, declaredDirectives, true);
+ // Collect @Component.directives/pipes/precompile into our declared directives/pipes.
+ this._getTransitiveViewDirectivesAndPipes(
+ declaredDirMeta, moduleType, transitiveModule, declaredDirectives, declaredPipes);
+ } else if (declaredPipeMeta = this.getPipeMetadata(declaredType, false)) {
+ this._addPipeToModule(
+ declaredPipeMeta, moduleType, transitiveModule, declaredPipes, true);
+ } else {
+ throw new BaseException(
+ `Unexpected value '${stringify(declaredType)}' declared by the module '${stringify(moduleType)}'`);
+ }
+ });
+ }
+
+ const providers: any[] = [];
+ const precompile: cpl.CompileTypeMetadata[] = [];
if (meta.providers) {
providers.push(...this.getProvidersMetadata(meta.providers, precompile));
}
- if (meta.directives) {
- directives.push(...flattenArray(meta.directives)
- .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
- }
- if (meta.pipes) {
- pipes.push(...flattenArray(meta.pipes)
- .map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
- }
if (meta.precompile) {
precompile.push(...flattenArray(meta.precompile)
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
}
- compileMeta = new cpl.CompileAppModuleMetadata({
+ transitiveModule.precompile.push(...precompile);
+ transitiveModule.providers.push(...providers);
+
+ compileMeta = new cpl.CompileNgModuleMetadata({
type: this.getTypeMetadata(moduleType, staticTypeModuleUrl(moduleType)),
providers: providers,
- directives: directives,
- pipes: pipes,
precompile: precompile,
- modules: modules
+ declaredDirectives: declaredDirectives,
+ exportedDirectives: exportedDirectives,
+ declaredPipes: declaredPipes,
+ exportedPipes: exportedPipes,
+ importedModules: importedModules,
+ exportedModules: exportedModules,
+ transitiveModule: transitiveModule
});
- if (useCache) {
- this._appModuleCache.set(moduleType, compileMeta);
- }
+ transitiveModule.modules.push(compileMeta);
+ this._verifyModule(compileMeta);
+ this._ngModuleCache.set(moduleType, compileMeta);
}
return compileMeta;
}
- /**
- * @param someType a symbol which may or may not be a directive type
- * @returns {cpl.CompileDirectiveMetadata} if possible, otherwise null.
- */
- maybeGetDirectiveMetadata(someType: Type): cpl.CompileDirectiveMetadata {
- try {
- return this.getDirectiveMetadata(someType);
- } catch (e) {
- if (e.message.indexOf('No Directive annotation') !== -1) {
- return null;
+ addComponentToModule(moduleType: Type, compType: Type) {
+ const moduleMeta = this.getNgModuleMetadata(moduleType);
+ // Collect @Component.directives/pipes/precompile into our declared directives/pipes.
+ const compMeta = this.getDirectiveMetadata(compType, false);
+ this._addDirectiveToModule(
+ compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
+ moduleMeta.declaredDirectives);
+ this._getTransitiveViewDirectivesAndPipes(
+ compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
+ moduleMeta.declaredDirectives, moduleMeta.declaredPipes);
+
+ moduleMeta.transitiveModule.precompile.push(compMeta.type);
+ moduleMeta.precompile.push(compMeta.type);
+
+ this._verifyModule(moduleMeta);
+ }
+
+ private _verifyModule(moduleMeta: cpl.CompileNgModuleMetadata) {
+ moduleMeta.exportedDirectives.forEach((dirMeta) => {
+ if (!moduleMeta.transitiveModule.directivesSet.has(dirMeta.type.runtime)) {
+ throw new BaseException(
+ `Can't export directive ${stringify(dirMeta.type.runtime)} from ${stringify(moduleMeta.type.runtime)} as it was neither declared nor imported!`);
}
- throw e;
+ });
+ moduleMeta.exportedPipes.forEach((pipeMeta) => {
+ if (!moduleMeta.transitiveModule.pipesSet.has(pipeMeta.type.runtime)) {
+ throw new BaseException(
+ `Can't export pipe ${stringify(pipeMeta.type.runtime)} from ${stringify(moduleMeta.type.runtime)} as it was neither declared nor imported!`);
+ }
+ });
+ moduleMeta.declaredDirectives.forEach((dirMeta) => {
+ dirMeta.precompile.forEach((precompileComp) => {
+ if (!moduleMeta.transitiveModule.directivesSet.has(precompileComp.runtime)) {
+ throw new BaseException(
+ `Component ${stringify(dirMeta.type.runtime)} in NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(precompileComp.runtime)} via "precompile" but it was neither declared nor imported into the module!`);
+ }
+ });
+ });
+ moduleMeta.precompile.forEach((precompileType) => {
+ if (!moduleMeta.transitiveModule.directivesSet.has(precompileType.runtime)) {
+ throw new BaseException(
+ `NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(precompileType.runtime)} via "precompile" but it was neither declared nor imported!`);
+ }
+ });
+ }
+
+ private _addTypeToModule(type: Type, moduleType: Type) {
+ const oldModule = this._ngModuleOfTypes.get(type);
+ if (oldModule && oldModule !== moduleType) {
+ throw new BaseException(
+ `Type ${stringify(type)} is part of the declarations of 2 modules: ${stringify(oldModule)} and ${stringify(moduleType)}!`);
}
+ this._ngModuleOfTypes.set(type, moduleType);
+ }
+
+
+ private _getTransitiveViewDirectivesAndPipes(
+ compMeta: cpl.CompileDirectiveMetadata, moduleType: any,
+ transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
+ declaredDirectives: cpl.CompileDirectiveMetadata[],
+ declaredPipes: cpl.CompilePipeMetadata[]) {
+ if (!compMeta.isComponent) {
+ return;
+ }
+ const addPipe = (pipeType: Type) => {
+ if (!pipeType) {
+ throw new BaseException(
+ `Unexpected pipe value '${pipeType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
+ }
+ const pipeMeta = this.getPipeMetadata(pipeType);
+ this._addPipeToModule(pipeMeta, moduleType, transitiveModule, declaredPipes);
+ };
+
+ const addDirective = (dirType: Type) => {
+ if (!dirType) {
+ throw new BaseException(
+ `Unexpected directive value '${dirType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
+ }
+ const dirMeta = this.getDirectiveMetadata(dirType);
+ if (this._addDirectiveToModule(dirMeta, moduleType, transitiveModule, declaredDirectives)) {
+ this._getTransitiveViewDirectivesAndPipes(
+ dirMeta, moduleType, transitiveModule, declaredDirectives, declaredPipes);
+ }
+ };
+ const view = this._viewResolver.resolve(compMeta.type.runtime);
+ if (view.pipes) {
+ flattenArray(view.pipes).forEach(addPipe);
+ }
+ if (view.directives) {
+ flattenArray(view.directives).forEach(addDirective);
+ }
+ }
+
+ private _getTransitiveNgModuleMetadata(
+ importedModules: cpl.CompileNgModuleMetadata[],
+ exportedModules: cpl.CompileNgModuleMetadata[]): cpl.TransitiveCompileNgModuleMetadata {
+ // collect `providers` / `precompile` from all imported and all exported modules
+ const transitiveModules = getTransitiveModules(importedModules.concat(exportedModules), true);
+ const providers = flattenArray(transitiveModules.map((ngModule) => ngModule.providers));
+ const precompile = flattenArray(transitiveModules.map((ngModule) => ngModule.precompile));
+
+ const transitiveExportedModules = getTransitiveModules(importedModules, false);
+ const directives =
+ flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedDirectives));
+ const pipes = flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedPipes));
+ return new cpl.TransitiveCompileNgModuleMetadata(
+ transitiveModules, providers, precompile, directives, pipes);
+ }
+
+ private _addDirectiveToModule(
+ dirMeta: cpl.CompileDirectiveMetadata, moduleType: any,
+ transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
+ declaredDirectives: cpl.CompileDirectiveMetadata[], force: boolean = false): boolean {
+ if (force || !transitiveModule.directivesSet.has(dirMeta.type.runtime)) {
+ transitiveModule.directivesSet.add(dirMeta.type.runtime);
+ transitiveModule.directives.push(dirMeta);
+ declaredDirectives.push(dirMeta);
+ this._addTypeToModule(dirMeta.type.runtime, moduleType);
+ return true;
+ }
+ return false;
+ }
+
+ private _addPipeToModule(
+ pipeMeta: cpl.CompilePipeMetadata, moduleType: any,
+ transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
+ declaredPipes: cpl.CompilePipeMetadata[], force: boolean = false): boolean {
+ if (force || !transitiveModule.pipesSet.has(pipeMeta.type.runtime)) {
+ transitiveModule.pipesSet.add(pipeMeta.type.runtime);
+ transitiveModule.pipes.push(pipeMeta);
+ declaredPipes.push(pipeMeta);
+ this._addTypeToModule(pipeMeta.type.runtime, moduleType);
+ return true;
+ }
+ return false;
}
getTypeMetadata(type: Type, moduleUrl: string, dependencies: any[] = null):
@@ -283,11 +463,14 @@ export class CompileMetadataResolver {
});
}
- getPipeMetadata(pipeType: Type): cpl.CompilePipeMetadata {
+ getPipeMetadata(pipeType: Type, throwIfNotFound = true): cpl.CompilePipeMetadata {
pipeType = resolveForwardRef(pipeType);
var meta = this._pipeCache.get(pipeType);
if (isBlank(meta)) {
- var pipeMeta = this._pipeResolver.resolve(pipeType);
+ var pipeMeta = this._pipeResolver.resolve(pipeType, throwIfNotFound);
+ if (!pipeMeta) {
+ return null;
+ }
meta = new cpl.CompilePipeMetadata({
type: this.getTypeMetadata(pipeType, staticTypeModuleUrl(pipeType)),
name: pipeMeta.name,
@@ -299,30 +482,6 @@ export class CompileMetadataResolver {
return meta;
}
- getViewDirectivesMetadata(component: Type): cpl.CompileDirectiveMetadata[] {
- var view = this._viewResolver.resolve(component);
- var directives = flattenDirectives(view, this._config.deprecatedPlatformDirectives);
- for (var i = 0; i < directives.length; i++) {
- if (!isValidType(directives[i])) {
- throw new BaseException(
- `Unexpected directive value '${stringify(directives[i])}' on the View of component '${stringify(component)}'`);
- }
- }
- return directives.map(type => this.getDirectiveMetadata(type));
- }
-
- getViewPipesMetadata(component: Type): cpl.CompilePipeMetadata[] {
- var view = this._viewResolver.resolve(component);
- var pipes = flattenPipes(view, this._config.deprecatedPlatformPipes);
- for (var i = 0; i < pipes.length; i++) {
- if (!isValidType(pipes[i])) {
- throw new BaseException(
- `Unexpected piped value '${stringify(pipes[i])}' on the View of component '${stringify(component)}'`);
- }
- }
- return pipes.map(type => this.getPipeMetadata(type));
- }
-
getDependenciesMetadata(typeOrFunc: Type|Function, dependencies: any[]):
cpl.CompileDiDependencyMetadata[] {
let hasUnknownDeps = false;
@@ -454,7 +613,7 @@ export class CompileMetadataResolver {
}
convertToCompileValue(provider.useValue, collectedIdentifiers);
collectedIdentifiers.forEach((identifier) => {
- let dirMeta = this.maybeGetDirectiveMetadata(identifier.runtime);
+ let dirMeta = this.getDirectiveMetadata(identifier.runtime, false);
if (dirMeta) {
components.push(dirMeta.type);
}
@@ -523,35 +682,35 @@ export class CompileMetadataResolver {
}
}
-function flattenDirectives(view: ViewMetadata, platformDirectives: any[]): Type[] {
- let directives: Type[] = [];
- if (isPresent(platformDirectives)) {
- flattenArray(platformDirectives, directives);
- }
- if (isPresent(view.directives)) {
- flattenArray(view.directives, directives);
- }
- return directives;
+function getTransitiveModules(
+ modules: cpl.CompileNgModuleMetadata[], includeImports: boolean,
+ targetModules: cpl.CompileNgModuleMetadata[] = [],
+ visitedModules = new Set()): cpl.CompileNgModuleMetadata[] {
+ modules.forEach((ngModule) => {
+ if (!visitedModules.has(ngModule.type.runtime)) {
+ visitedModules.add(ngModule.type.runtime);
+ const nestedModules = includeImports ?
+ ngModule.importedModules.concat(ngModule.exportedModules) :
+ ngModule.exportedModules;
+ getTransitiveModules(nestedModules, includeImports, targetModules, visitedModules);
+ // Add after recursing so imported/exported modules are before the module itself.
+ // This is important for overwriting providers of imported modules!
+ targetModules.push(ngModule);
+ }
+ });
+ return targetModules;
}
-function flattenPipes(view: ViewMetadata, platformPipes: any[]): Type[] {
- let pipes: Type[] = [];
- if (isPresent(platformPipes)) {
- flattenArray(platformPipes, pipes);
- }
- if (isPresent(view.pipes)) {
- flattenArray(view.pipes, pipes);
- }
- return pipes;
-}
-function flattenArray(tree: any[], out: Array = []): Array {
- for (var i = 0; i < tree.length; i++) {
- var item = resolveForwardRef(tree[i]);
- if (isArray(item)) {
- flattenArray(item, out);
- } else {
- out.push(item);
+function flattenArray(tree: any[], out: Array = []): Array {
+ if (tree) {
+ for (var i = 0; i < tree.length; i++) {
+ var item = resolveForwardRef(tree[i]);
+ if (isArray(item)) {
+ flattenArray(item, out);
+ } else {
+ out.push(item);
+ }
}
}
return out;
diff --git a/modules/@angular/compiler/src/app_module_compiler.ts b/modules/@angular/compiler/src/ng_module_compiler.ts
similarity index 79%
rename from modules/@angular/compiler/src/app_module_compiler.ts
rename to modules/@angular/compiler/src/ng_module_compiler.ts
index b0ac17ff1c..cfc7d56dcf 100644
--- a/modules/@angular/compiler/src/app_module_compiler.ts
+++ b/modules/@angular/compiler/src/ng_module_compiler.ts
@@ -8,13 +8,13 @@
import {Injectable} from '@angular/core';
-import {CompileAppModuleMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileProviderMetadata, CompileTokenMap, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
+import {CompileDiDependencyMetadata, CompileIdentifierMap, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata} from './compile_metadata';
import {isBlank, isPresent} from './facade/lang';
import {Identifiers, identifierToken} from './identifiers';
import * as o from './output/output_ast';
import {convertValueToOutputAst} from './output/value_util';
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
-import {AppModuleProviderParser} from './provider_parser';
+import {NgModuleProviderAnalyzer} from './provider_analyzer';
import {ProviderAst, ProviderAstType} from './template_ast';
import {createDiTokenExpression} from './util';
@@ -23,57 +23,58 @@ export class ComponentFactoryDependency {
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
}
-export class AppModuleCompileResult {
+export class NgModuleCompileResult {
constructor(
- public statements: o.Statement[], public appModuleFactoryVar: string,
+ public statements: o.Statement[], public ngModuleFactoryVar: string,
public dependencies: ComponentFactoryDependency[]) {}
}
@Injectable()
-export class AppModuleCompiler {
- compile(appModuleMeta: CompileAppModuleMetadata): AppModuleCompileResult {
- var sourceFileName = isPresent(appModuleMeta.type.moduleUrl) ?
- `in AppModule ${appModuleMeta.type.name} in ${appModuleMeta.type.moduleUrl}` :
- `in AppModule ${appModuleMeta.type.name}`;
+export class NgModuleCompiler {
+ compile(ngModuleMeta: CompileNgModuleMetadata, extraProviders: CompileProviderMetadata[]):
+ NgModuleCompileResult {
+ var sourceFileName = isPresent(ngModuleMeta.type.moduleUrl) ?
+ `in NgModule ${ngModuleMeta.type.name} in ${ngModuleMeta.type.moduleUrl}` :
+ `in NgModule ${ngModuleMeta.type.name}`;
var sourceFile = new ParseSourceFile('', sourceFileName);
var sourceSpan = new ParseSourceSpan(
new ParseLocation(sourceFile, null, null, null),
new ParseLocation(sourceFile, null, null, null));
var deps: ComponentFactoryDependency[] = [];
- var precompileComponents = appModuleMeta.precompile.map((precompileComp) => {
+ var precompileComponents = ngModuleMeta.transitiveModule.precompile.map((precompileComp) => {
var id = new CompileIdentifierMetadata({name: precompileComp.name});
deps.push(new ComponentFactoryDependency(precompileComp, id));
return id;
});
- var builder = new _InjectorBuilder(appModuleMeta, precompileComponents, sourceSpan);
+ var builder = new _InjectorBuilder(ngModuleMeta, precompileComponents, sourceSpan);
- var providerParser = new AppModuleProviderParser(appModuleMeta, sourceSpan);
+ var providerParser = new NgModuleProviderAnalyzer(ngModuleMeta, extraProviders, sourceSpan);
providerParser.parse().forEach((provider) => builder.addProvider(provider));
var injectorClass = builder.build();
- var appModuleFactoryVar = `${appModuleMeta.type.name}NgFactory`;
- var appModuleFactoryStmt =
- o.variable(appModuleFactoryVar)
- .set(o.importExpr(Identifiers.AppModuleFactory)
+ var ngModuleFactoryVar = `${ngModuleMeta.type.name}NgFactory`;
+ var ngModuleFactoryStmt =
+ o.variable(ngModuleFactoryVar)
+ .set(o.importExpr(Identifiers.NgModuleFactory)
.instantiate(
- [o.variable(injectorClass.name), o.importExpr(appModuleMeta.type)],
+ [o.variable(injectorClass.name), o.importExpr(ngModuleMeta.type)],
o.importType(
- Identifiers.AppModuleFactory, [o.importType(appModuleMeta.type)],
+ Identifiers.NgModuleFactory, [o.importType(ngModuleMeta.type)],
[o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]);
- return new AppModuleCompileResult(
- [injectorClass, appModuleFactoryStmt], appModuleFactoryVar, deps);
+ return new NgModuleCompileResult(
+ [injectorClass, ngModuleFactoryStmt], ngModuleFactoryVar, deps);
}
}
class _InjectorBuilder {
- private _instances = new CompileTokenMap();
+ private _instances = new CompileIdentifierMap();
private _fields: o.ClassField[] = [];
private _createStmts: o.Statement[] = [];
private _getters: o.ClassGetter[] = [];
constructor(
- private _appModuleMeta: CompileAppModuleMetadata,
+ private _ngModuleMeta: CompileNgModuleMetadata,
private _precompileComponents: CompileIdentifierMetadata[],
private _sourceSpan: ParseSourceSpan) {}
@@ -97,8 +98,8 @@ class _InjectorBuilder {
var methods = [
new o.ClassMethod(
'createInternal', [], this._createStmts.concat(
- new o.ReturnStatement(this._instances.get(identifierToken(this._appModuleMeta.type)))
- ), o.importType(this._appModuleMeta.type)
+ new o.ReturnStatement(this._instances.get(identifierToken(this._ngModuleMeta.type)))
+ ), o.importType(this._ngModuleMeta.type)
),
new o.ClassMethod(
'getInternal',
@@ -120,10 +121,10 @@ class _InjectorBuilder {
])
.toStmt()]);
- var injClassName = `${this._appModuleMeta.type.name}Injector`;
+ var injClassName = `${this._ngModuleMeta.type.name}Injector`;
return new o.ClassStmt(
injClassName,
- o.importExpr(Identifiers.AppModuleInjector, [o.importType(this._appModuleMeta.type)]),
+ o.importExpr(Identifiers.NgModuleInjector, [o.importType(this._ngModuleMeta.type)]),
this._fields, this._getters, ctor, methods);
}
diff --git a/modules/@angular/compiler/src/ng_module_resolver.ts b/modules/@angular/compiler/src/ng_module_resolver.ts
new file mode 100644
index 0000000000..d9f6851186
--- /dev/null
+++ b/modules/@angular/compiler/src/ng_module_resolver.ts
@@ -0,0 +1,39 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {Injectable, NgModuleMetadata} from '@angular/core';
+
+import {ReflectorReader, reflector} from '../core_private';
+import {BaseException} from '../src/facade/exceptions';
+import {Type, isBlank, isPresent, stringify} from '../src/facade/lang';
+
+function _isNgModuleMetadata(obj: any): obj is NgModuleMetadata {
+ return obj instanceof NgModuleMetadata;
+}
+
+/**
+ * Resolves types to {@link NgModuleMetadata}.
+ */
+@Injectable()
+export class NgModuleResolver {
+ constructor(private _reflector: ReflectorReader = reflector) {}
+
+ resolve(type: Type, throwIfNotFound = true): NgModuleMetadata {
+ const ngModuleMeta: NgModuleMetadata =
+ this._reflector.annotations(type).find(_isNgModuleMetadata);
+
+ if (isPresent(ngModuleMeta)) {
+ return ngModuleMeta;
+ } else {
+ if (throwIfNotFound) {
+ throw new BaseException(`No NgModule metadata found for '${stringify(type)}'.`);
+ }
+ return null;
+ }
+ }
+}
diff --git a/modules/@angular/compiler/src/offline_compiler.ts b/modules/@angular/compiler/src/offline_compiler.ts
index 9add04a270..66d8d7875d 100644
--- a/modules/@angular/compiler/src/offline_compiler.ts
+++ b/modules/@angular/compiler/src/offline_compiler.ts
@@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {AppModuleCompiler} from './app_module_compiler';
-import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
+import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
import {DirectiveNormalizer} from './directive_normalizer';
import {ListWrapper} from './facade/collection';
import {BaseException} from './facade/exceptions';
import {Identifiers} from './identifiers';
import {CompileMetadataResolver} from './metadata_resolver';
+import {NgModuleCompiler} from './ng_module_compiler';
import {OutputEmitter} from './output/abstract_emitter';
import * as o from './output/output_ast';
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
@@ -23,61 +23,29 @@ export class SourceModule {
constructor(public moduleUrl: string, public source: string) {}
}
-export class AppModulesSummary {
- private _compAppModule = new Map();
- private _hashKey(type: StaticSymbol) { return `${type.filePath}#${type.name}`; }
-
- hasComponent(component: StaticSymbol): boolean {
- return this._compAppModule.has(this._hashKey(component));
- }
-
- addComponent(module: StaticSymbol, component: StaticSymbol) {
- this._compAppModule.set(this._hashKey(component), module);
- }
-
- getModule(comp: StaticSymbol): StaticSymbol {
- return this._compAppModule.get(this._hashKey(comp));
- }
+export class NgModulesSummary {
+ constructor(public ngModuleByComponent: Map) {}
}
+
export class OfflineCompiler {
constructor(
private _metadataResolver: CompileMetadataResolver,
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
- private _appModuleCompiler: AppModuleCompiler, private _outputEmitter: OutputEmitter) {}
+ private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter) {}
- analyzeModules(appModules: StaticSymbol[]): AppModulesSummary {
- let result = new AppModulesSummary();
- appModules.forEach((appModule) => {
- let appModuleMeta = this._metadataResolver.getAppModuleMetadata(appModule);
- appModuleMeta.precompile.forEach(
- (precompileComp) =>
- this._getTransitiveComponents(appModule, precompileComp.runtime, result));
- });
- return result;
- }
+ analyzeModules(ngModules: StaticSymbol[]): NgModulesSummary {
+ const ngModuleByComponent = new Map();
- private _getTransitiveComponents(
- appModule: StaticSymbol, component: StaticSymbol,
- target: AppModulesSummary = new AppModulesSummary()): AppModulesSummary {
- var compMeta = this._metadataResolver.getDirectiveMetadata(component);
- // TODO(tbosch): preserve all modules per component, not just one.
- // Then run the template parser with the union and the intersection of the modules (regarding
- // directives/pipes)
- // and report an error if some directives/pipes are only matched with the union but not with the
- // intersection!
- // -> this means that a component is used in the wrong way!
- if (!compMeta.isComponent || target.hasComponent(component)) {
- return target;
- }
- target.addComponent(appModule, component);
- this._metadataResolver.getViewDirectivesMetadata(component).forEach((dirMeta) => {
- this._getTransitiveComponents(appModule, dirMeta.type.runtime);
+ ngModules.forEach((ngModule) => {
+ const ngModuleMeta = this._metadataResolver.getNgModuleMetadata(ngModule);
+ ngModuleMeta.declaredDirectives.forEach((dirMeta) => {
+ if (dirMeta.isComponent) {
+ ngModuleByComponent.set(dirMeta.type.runtime, ngModuleMeta);
+ }
+ });
});
- compMeta.precompile.forEach((precompileComp) => {
- this._getTransitiveComponents(appModule, precompileComp.type.runtime);
- });
- return target;
+ return new NgModulesSummary(ngModuleByComponent);
}
clearCache() {
@@ -86,55 +54,45 @@ export class OfflineCompiler {
}
compile(
- moduleUrl: string, appModulesSummary: AppModulesSummary, components: StaticSymbol[],
- appModules: StaticSymbol[]): Promise {
+ moduleUrl: string, ngModulesSummary: NgModulesSummary, components: StaticSymbol[],
+ ngModules: StaticSymbol[]): Promise {
let fileSuffix = _splitLastSuffix(moduleUrl)[1];
let statements: o.Statement[] = [];
let exportedVars: string[] = [];
let outputSourceModules: SourceModule[] = [];
- // compile app modules
+ // compile all ng modules
exportedVars.push(
- ...appModules.map((appModule) => this._compileAppModule(appModule, statements)));
+ ...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements)));
// compile components
return Promise
.all(components.map((compType) => {
- let appModule = appModulesSummary.getModule(compType);
- let appModuleDirectives: CompileDirectiveMetadata[] = [];
- let appModulePipes: CompilePipeMetadata[] = [];
- if (appModule) {
- let appModuleMeta = this._metadataResolver.getAppModuleMetadata(appModule);
- appModuleDirectives.push(...appModuleMeta.directives.map(
- type => this._metadataResolver.getDirectiveMetadata(type.runtime)));
- appModulePipes.push(...appModuleMeta.pipes.map(
- type => this._metadataResolver.getPipeMetadata(type.runtime)));
+ const compMeta = this._metadataResolver.getDirectiveMetadata(compType);
+ let ngModule = ngModulesSummary.ngModuleByComponent.get(compType);
+ if (!ngModule) {
+ throw new BaseException(
+ `Cannot determine the module for component ${compMeta.type.name}!`);
}
return Promise
- .all([
- this._metadataResolver.getDirectiveMetadata(compType), ...appModuleDirectives,
- ...this._metadataResolver.getViewDirectivesMetadata(compType)
- ].map(dirMeta => this._directiveNormalizer.normalizeDirective(dirMeta).asyncResult))
+ .all([compMeta, ...ngModule.transitiveModule.directives].map(
+ dirMeta => this._directiveNormalizer.normalizeDirective(dirMeta).asyncResult))
.then((normalizedCompWithDirectives) => {
- let compMeta = normalizedCompWithDirectives[0];
- let dirMetas = normalizedCompWithDirectives.slice(1);
+ const compMeta = normalizedCompWithDirectives[0];
+ const dirMetas = normalizedCompWithDirectives.slice(1);
_assertComponent(compMeta);
// compile styles
- let stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
+ const stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
stylesCompileResults.externalStylesheets.forEach((compiledStyleSheet) => {
outputSourceModules.push(this._codgenStyles(compiledStyleSheet, fileSuffix));
});
// compile components
exportedVars.push(this._compileComponentFactory(compMeta, fileSuffix, statements));
- let pipeMetas = [
- ...appModulePipes,
- ...this._metadataResolver.getViewPipesMetadata(compMeta.type.runtime)
- ];
exportedVars.push(this._compileComponent(
- compMeta, dirMetas, pipeMetas, stylesCompileResults.componentStylesheet,
- fileSuffix, statements));
+ compMeta, dirMetas, ngModule.transitiveModule.pipes,
+ stylesCompileResults.componentStylesheet, fileSuffix, statements));
});
}))
.then(() => {
@@ -146,21 +104,21 @@ export class OfflineCompiler {
});
}
- private _compileAppModule(appModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
- let appModuleMeta = this._metadataResolver.getAppModuleMetadata(appModuleType);
- let appCompileResult = this._appModuleCompiler.compile(appModuleMeta);
+ private _compileModule(ngModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
+ const ngModule = this._metadataResolver.getNgModuleMetadata(ngModuleType);
+ let appCompileResult = this._ngModuleCompiler.compile(ngModule, []);
appCompileResult.dependencies.forEach((dep) => {
dep.placeholder.name = _componentFactoryName(dep.comp);
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp.moduleUrl);
});
targetStatements.push(...appCompileResult.statements);
- return appCompileResult.appModuleFactoryVar;
+ return appCompileResult.ngModuleFactoryVar;
}
private _compileComponentFactory(
compMeta: CompileDirectiveMetadata, fileSuffix: string,
targetStatements: o.Statement[]): string {
- var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
+ var hostMeta = createHostComponentMeta(compMeta);
var hostViewFactoryVar =
this._compileComponent(hostMeta, [compMeta], [], null, fileSuffix, targetStatements);
var compFactoryVar = _componentFactoryName(compMeta.type);
diff --git a/modules/@angular/compiler/src/pipe_resolver.ts b/modules/@angular/compiler/src/pipe_resolver.ts
index bc85132677..d6c955e7db 100644
--- a/modules/@angular/compiler/src/pipe_resolver.ts
+++ b/modules/@angular/compiler/src/pipe_resolver.ts
@@ -30,7 +30,7 @@ export class PipeResolver {
/**
* Return {@link PipeMetadata} for a given `Type`.
*/
- resolve(type: Type): PipeMetadata {
+ resolve(type: Type, throwIfNotFound = true): PipeMetadata {
var metas = this._reflector.annotations(resolveForwardRef(type));
if (isPresent(metas)) {
var annotation = metas.find(_isPipeMetadata);
@@ -38,6 +38,9 @@ export class PipeResolver {
return annotation;
}
}
- throw new BaseException(`No Pipe decorator found on ${stringify(type)}`);
+ if (throwIfNotFound) {
+ throw new BaseException(`No Pipe decorator found on ${stringify(type)}`);
+ }
+ return null;
}
-}
\ No newline at end of file
+}
diff --git a/modules/@angular/compiler/src/provider_parser.ts b/modules/@angular/compiler/src/provider_analyzer.ts
similarity index 87%
rename from modules/@angular/compiler/src/provider_parser.ts
rename to modules/@angular/compiler/src/provider_analyzer.ts
index 4f45d10071..d54b4e9c13 100644
--- a/modules/@angular/compiler/src/provider_parser.ts
+++ b/modules/@angular/compiler/src/provider_analyzer.ts
@@ -10,7 +10,7 @@ import {ListWrapper} from '../src/facade/collection';
import {BaseException} from '../src/facade/exceptions';
import {isArray, isBlank, isPresent, normalizeBlank} from '../src/facade/lang';
-import {CompileAppModuleMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMap, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
+import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileIdentifierMap, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
import {Identifiers, identifierToken} from './identifiers';
import {ParseError, ParseSourceSpan} from './parse_util';
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, ReferenceAst, VariableAst} from './template_ast';
@@ -23,16 +23,16 @@ export class ProviderViewContext {
/**
* @internal
*/
- viewQueries: CompileTokenMap;
+ viewQueries: CompileIdentifierMap;
/**
* @internal
*/
- viewProviders: CompileTokenMap;
+ viewProviders: CompileIdentifierMap;
errors: ProviderError[] = [];
constructor(public component: CompileDirectiveMetadata, public sourceSpan: ParseSourceSpan) {
this.viewQueries = _getViewQueries(component);
- this.viewProviders = new CompileTokenMap();
+ this.viewProviders = new CompileIdentifierMap();
_normalizeProviders(component.viewProviders, sourceSpan, this.errors).forEach((provider) => {
if (isBlank(this.viewProviders.get(provider.token))) {
this.viewProviders.add(provider.token, true);
@@ -42,11 +42,11 @@ export class ProviderViewContext {
}
export class ProviderElementContext {
- private _contentQueries: CompileTokenMap;
+ private _contentQueries: CompileIdentifierMap;
- private _transformedProviders = new CompileTokenMap();
- private _seenProviders = new CompileTokenMap();
- private _allProviders: CompileTokenMap;
+ private _transformedProviders = new CompileIdentifierMap();
+ private _seenProviders = new CompileIdentifierMap();
+ private _allProviders: CompileIdentifierMap;
private _attrs: {[key: string]: string};
private _hasViewContainer: boolean = false;
@@ -60,7 +60,7 @@ export class ProviderElementContext {
this._allProviders =
_resolveProvidersFromDirectives(directivesMeta, _sourceSpan, _viewContext.errors);
this._contentQueries = _getContentQueries(directivesMeta);
- var queriedTokens = new CompileTokenMap();
+ var queriedTokens = new CompileIdentifierMap();
this._allProviders.values().forEach(
(provider) => { this._addQueryReadsTo(provider.token, queriedTokens); });
refs.forEach((refAst) => {
@@ -100,7 +100,9 @@ export class ProviderElementContext {
get transformedHasViewContainer(): boolean { return this._hasViewContainer; }
- private _addQueryReadsTo(token: CompileTokenMetadata, queryReadTokens: CompileTokenMap) {
+ private _addQueryReadsTo(
+ token: CompileTokenMetadata,
+ queryReadTokens: CompileIdentifierMap) {
this._getQueriesFor(token).forEach((query) => {
const queryReadToken = isPresent(query.read) ? query.read : token;
if (isBlank(queryReadTokens.get(queryReadToken))) {
@@ -272,24 +274,28 @@ export class ProviderElementContext {
}
-export class AppModuleProviderParser {
- private _transformedProviders = new CompileTokenMap();
- private _seenProviders = new CompileTokenMap();
+export class NgModuleProviderAnalyzer {
+ private _transformedProviders = new CompileIdentifierMap();
+ private _seenProviders = new CompileIdentifierMap();
private _unparsedProviders: any[] = [];
- private _allProviders: CompileTokenMap;
+ private _allProviders: CompileIdentifierMap;
private _errors: ProviderError[] = [];
- constructor(appModule: CompileAppModuleMetadata, sourceSpan: ParseSourceSpan) {
- this._allProviders = new CompileTokenMap();
- [appModule.type].concat(appModule.modules).forEach((appModuleType: CompileTypeMetadata) => {
- const appModuleProvider = new CompileProviderMetadata(
- {token: new CompileTokenMetadata({identifier: appModuleType}), useClass: appModuleType});
+ constructor(
+ ngModule: CompileNgModuleMetadata, extraProviders: CompileProviderMetadata[],
+ sourceSpan: ParseSourceSpan) {
+ this._allProviders = new CompileIdentifierMap();
+ const ngModuleTypes = ngModule.transitiveModule.modules.map((moduleMeta) => moduleMeta.type);
+ ngModuleTypes.forEach((ngModuleType: CompileTypeMetadata) => {
+ const ngModuleProvider = new CompileProviderMetadata(
+ {token: new CompileTokenMetadata({identifier: ngModuleType}), useClass: ngModuleType});
_resolveProviders(
- [appModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors,
+ [ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors,
this._allProviders);
});
_resolveProviders(
- _normalizeProviders(appModule.providers, sourceSpan, this._errors),
+ _normalizeProviders(
+ ngModule.transitiveModule.providers.concat(extraProviders), sourceSpan, this._errors),
ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders);
}
@@ -436,8 +442,8 @@ function _normalizeProviders(
function _resolveProvidersFromDirectives(
directives: CompileDirectiveMetadata[], sourceSpan: ParseSourceSpan,
- targetErrors: ParseError[]): CompileTokenMap {
- var providersByToken = new CompileTokenMap();
+ targetErrors: ParseError[]): CompileIdentifierMap {
+ var providersByToken = new CompileIdentifierMap();
directives.forEach((directive) => {
var dirProvider = new CompileProviderMetadata(
{token: new CompileTokenMetadata({identifier: directive.type}), useClass: directive.type});
@@ -464,7 +470,7 @@ function _resolveProvidersFromDirectives(
function _resolveProviders(
providers: CompileProviderMetadata[], providerType: ProviderAstType, eager: boolean,
sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
- targetProvidersByToken: CompileTokenMap) {
+ targetProvidersByToken: CompileIdentifierMap) {
providers.forEach((provider) => {
var resolvedProvider = targetProvidersByToken.get(provider.token);
if (isPresent(resolvedProvider) && resolvedProvider.multiProvider !== provider.multi) {
@@ -487,8 +493,8 @@ function _resolveProviders(
function _getViewQueries(component: CompileDirectiveMetadata):
- CompileTokenMap {
- var viewQueries = new CompileTokenMap();
+ CompileIdentifierMap {
+ var viewQueries = new CompileIdentifierMap();
if (isPresent(component.viewQueries)) {
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, query));
}
@@ -501,8 +507,8 @@ function _getViewQueries(component: CompileDirectiveMetadata):
}
function _getContentQueries(directives: CompileDirectiveMetadata[]):
- CompileTokenMap {
- var contentQueries = new CompileTokenMap();
+ CompileIdentifierMap {
+ var contentQueries = new CompileIdentifierMap();
directives.forEach(directive => {
if (isPresent(directive.queries)) {
directive.queries.forEach((query) => _addQueryToTokenMap(contentQueries, query));
@@ -517,7 +523,8 @@ function _getContentQueries(directives: CompileDirectiveMetadata[]):
}
function _addQueryToTokenMap(
- map: CompileTokenMap, query: CompileQueryMetadata) {
+ map: CompileIdentifierMap,
+ query: CompileQueryMetadata) {
query.selectors.forEach((token: CompileTokenMetadata) => {
var entry = map.get(token);
if (isBlank(entry)) {
diff --git a/modules/@angular/compiler/src/runtime_compiler.ts b/modules/@angular/compiler/src/runtime_compiler.ts
index 26a59646f7..273b99fe38 100644
--- a/modules/@angular/compiler/src/runtime_compiler.ts
+++ b/modules/@angular/compiler/src/runtime_compiler.ts
@@ -6,19 +6,19 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {AppModuleFactory, AppModuleMetadata, Compiler, ComponentFactory, ComponentResolver, ComponentStillLoadingError, Injectable, Injector, OptionalMetadata, Provider, SkipSelfMetadata} from '@angular/core';
-import {Console} from '../core_private';
+import {Compiler, ComponentFactory, ComponentResolver, ComponentStillLoadingError, Injectable, Injector, NgModule, NgModuleFactory, NgModuleMetadata, OptionalMetadata, Provider, SkipSelfMetadata} from '@angular/core';
+import {Console} from '../core_private';
import {BaseException} from '../src/facade/exceptions';
import {ConcreteType, IS_DART, Type, isBlank, isString, stringify} from '../src/facade/lang';
import {ListWrapper,} from '../src/facade/collection';
import {PromiseWrapper} from '../src/facade/async';
-import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata} from './compile_metadata';
+import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata} from './compile_metadata';
import {TemplateAst,} from './template_ast';
import {StyleCompiler, StylesCompileDependency, CompiledStylesheet} from './style_compiler';
import {ViewCompiler, ViewCompileResult, ViewFactoryDependency, ComponentFactoryDependency} from './view_compiler/view_compiler';
-import {AppModuleCompiler} from './app_module_compiler';
+import {NgModuleCompiler} from './ng_module_compiler';
import {TemplateParser} from './template_parser';
import {DirectiveNormalizer} from './directive_normalizer';
import {CompileMetadataResolver} from './metadata_resolver';
@@ -38,122 +38,123 @@ import {SyncAsyncResult} from './util';
* application to XSS risks. For more detail, see the [Security Guide](http://g.co/ng/security).
*/
@Injectable()
-export class RuntimeCompiler implements ComponentResolver, Compiler {
+export class RuntimeCompiler implements Compiler {
private _compiledTemplateCache = new Map();
private _compiledHostTemplateCache = new Map();
- private _compiledAppModuleCache = new Map>();
-
- private _warnOnComponentResolver = true;
+ private _compiledNgModuleCache = new Map>();
constructor(
private _injector: Injector, private _metadataResolver: CompileMetadataResolver,
private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
- private _appModuleCompiler: AppModuleCompiler, private _genConfig: CompilerConfig,
- private _console: Console) {
- const flatDeprecatedPlatformDirectives =
- ListWrapper.flatten(_genConfig.deprecatedPlatformDirectives);
- if (flatDeprecatedPlatformDirectives.length > 0) {
- this._console.warn(
- `Providing platform directives via the PLATFORM_DIRECTIVES provider or the "CompilerConfig" is deprecated. Provide platform directives via an @AppModule instead. Directives: ` +
- flatDeprecatedPlatformDirectives.map(stringify));
- }
- const flatDeprecatedPlatformPipes = ListWrapper.flatten(_genConfig.deprecatedPlatformPipes);
- if (flatDeprecatedPlatformPipes.length > 0) {
- this._console.warn(
- `Providing platform pipes via the PLATFORM_PIPES provider or the "CompilerConfig" is deprecated. Provide platform pipes via an @AppModule instead. Pipes: ` +
- flatDeprecatedPlatformPipes.map(stringify));
- }
- }
+ private _ngModuleCompiler: NgModuleCompiler, private _compilerConfig: CompilerConfig,
+ private _console: Console) {}
get injector(): Injector { return this._injector; }
- resolveComponent(component: Type|string): Promise> {
- if (isString(component)) {
- return PromiseWrapper.reject(
- new BaseException(`Cannot resolve component using '${component}'.`), null);
+ compileModuleSync(moduleType: ConcreteType): NgModuleFactory {
+ return this._compileModuleAndComponents(moduleType, true).syncResult;
+ }
+
+ compileModuleAsync(moduleType: ConcreteType): Promise> {
+ return this._compileModuleAndComponents(moduleType, false).asyncResult;
+ }
+
+ compileComponentAsync(compType: ConcreteType, ngModule: ConcreteType = null):
+ Promise> {
+ if (!ngModule) {
+ throw new BaseException(
+ `Calling compileComponentAsync on the root compiler without a module is not allowed! (Compiling component ${stringify(compType)})`);
}
- if (this._warnOnComponentResolver) {
- this._console.warn(ComponentResolver.DynamicCompilationDeprecationMsg);
- this._warnOnComponentResolver = false;
+ return this._compileComponentInModule(compType, false, ngModule).asyncResult;
+ }
+
+ compileComponentSync(compType: ConcreteType, ngModule: ConcreteType = null):
+ ComponentFactory {
+ if (!ngModule) {
+ throw new BaseException(
+ `Calling compileComponentSync on the root compiler without a module is not allowed! (Compiling component ${stringify(compType)})`);
}
- return this.compileComponentAsync(>component);
+ return this._compileComponentInModule(compType, true, ngModule).syncResult;
}
- compileAppModuleSync(moduleType: ConcreteType, metadata: AppModuleMetadata = null):
- AppModuleFactory {
- return this._compileAppModule(moduleType, true, metadata).syncResult;
+ private _compileModuleAndComponents(moduleType: ConcreteType, isSync: boolean):
+ SyncAsyncResult> {
+ const componentPromise = this._compileComponents(moduleType, isSync);
+ const ngModuleFactory = this._compileModule(moduleType);
+ return new SyncAsyncResult(ngModuleFactory, componentPromise.then(() => ngModuleFactory));
}
- compileAppModuleAsync(moduleType: ConcreteType, metadata: AppModuleMetadata = null):
- Promise> {
- return this._compileAppModule(moduleType, false, metadata).asyncResult;
- }
-
- private _compileAppModule(
- moduleType: ConcreteType, isSync: boolean,
- metadata: AppModuleMetadata = null): SyncAsyncResult> {
- // Only cache if we read the metadata via the reflector,
- // as we use the moduleType as cache key.
- let useCache = !metadata;
- let appModuleFactory = this._compiledAppModuleCache.get(moduleType);
- let componentCompilePromises: Promise[] = [];
- if (!appModuleFactory || !useCache) {
- var compileModuleMeta = this._metadataResolver.getAppModuleMetadata(moduleType, metadata);
- let boundCompilerFactory = (parentResolver: ComponentResolver) => new BoundCompiler(
- this, compileModuleMeta.directives.map(dir => dir.type.runtime),
- compileModuleMeta.pipes.map((pipe) => pipe.type.runtime), parentResolver);
+ private _compileModule(moduleType: ConcreteType): NgModuleFactory {
+ let ngModuleFactory = this._compiledNgModuleCache.get(moduleType);
+ if (!ngModuleFactory) {
+ const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType);
+ const transitiveModuleMeta = moduleMeta.transitiveModule;
+ let boundCompilerFactory = (parentResolver: ComponentResolver) =>
+ new ModuleBoundCompiler(this, moduleMeta.type.runtime, parentResolver, this._console);
// Always provide a bound Compiler and ComponentResolver
- compileModuleMeta.providers.push(
- this._metadataResolver.getProviderMetadata(new Provider(Compiler, {
- useFactory: boundCompilerFactory,
- deps: [[new OptionalMetadata(), new SkipSelfMetadata(), ComponentResolver]]
- })));
- compileModuleMeta.providers.push(this._metadataResolver.getProviderMetadata(
- new Provider(ComponentResolver, {useExisting: Compiler})));
- var compileResult = this._appModuleCompiler.compile(compileModuleMeta);
+ const extraProviders = [
+ this._metadataResolver.getProviderMetadata(new Provider(Compiler, {
+ useFactory: boundCompilerFactory,
+ deps: [[new OptionalMetadata(), new SkipSelfMetadata(), ComponentResolver]]
+ })),
+ this._metadataResolver.getProviderMetadata(
+ new Provider(ComponentResolver, {useExisting: Compiler}))
+ ];
+ var compileResult = this._ngModuleCompiler.compile(moduleMeta, extraProviders);
compileResult.dependencies.forEach((dep) => {
- let compileResult = this._compileComponent(
- dep.comp.runtime, isSync,
- compileModuleMeta.directives.map(compileType => compileType.runtime),
- compileModuleMeta.pipes.map(compileType => compileType.runtime));
- dep.placeholder.runtime = compileResult.syncResult;
- componentCompilePromises.push(compileResult.asyncResult);
+ dep.placeholder.runtime =
+ this._assertComponentKnown(dep.comp.runtime, true).proxyComponentFactory;
dep.placeholder.name = `compFactory_${dep.comp.name}`;
});
- if (IS_DART || !this._genConfig.useJit) {
- appModuleFactory =
- interpretStatements(compileResult.statements, compileResult.appModuleFactoryVar);
+ if (IS_DART || !this._compilerConfig.useJit) {
+ ngModuleFactory =
+ interpretStatements(compileResult.statements, compileResult.ngModuleFactoryVar);
} else {
- appModuleFactory = jitStatements(
- `${compileModuleMeta.type.name}.ngfactory.js`, compileResult.statements,
- compileResult.appModuleFactoryVar);
- }
- if (useCache) {
- this._compiledAppModuleCache.set(moduleType, appModuleFactory);
+ ngModuleFactory = jitStatements(
+ `${moduleMeta.type.name}.ngfactory.js`, compileResult.statements,
+ compileResult.ngModuleFactoryVar);
}
+ this._compiledNgModuleCache.set(moduleMeta.type.runtime, ngModuleFactory);
}
- return new SyncAsyncResult(
- appModuleFactory, Promise.all(componentCompilePromises).then(() => appModuleFactory));
+ return ngModuleFactory;
}
- compileComponentAsync(compType: ConcreteType): Promise> {
- return this._compileComponent(compType, false, [], []).asyncResult;
- }
+ private _compileComponentInModule(
+ compType: ConcreteType, isSync: boolean,
+ moduleType: ConcreteType): SyncAsyncResult> {
+ this._metadataResolver.addComponentToModule(moduleType, compType);
- compileComponentSync(compType: ConcreteType): ComponentFactory {
- return this._compileComponent(compType, true, [], []).syncResult;
+ const componentPromise = this._compileComponents(moduleType, isSync);
+ const componentFactory: ComponentFactory =
+ this._assertComponentKnown(compType, true).proxyComponentFactory;
+
+ return new SyncAsyncResult(componentFactory, componentPromise.then(() => componentFactory));
}
/**
* @internal
*/
- _compileComponent(
- compType: ConcreteType, isSync: boolean, moduleDirectives: ConcreteType[],
- modulePipes: ConcreteType[]): SyncAsyncResult> {
- var templates =
- this._getTransitiveCompiledTemplates(compType, true, moduleDirectives, modulePipes);
+ _compileComponents(mainModule: Type, isSync: boolean): Promise {
+ const templates = new Set();
var loadingPromises: Promise[] = [];
+
+ const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule);
+ ngModule.transitiveModule.modules.forEach((localModuleMeta) => {
+ localModuleMeta.declaredDirectives.forEach((dirMeta) => {
+ if (dirMeta.isComponent) {
+ templates.add(this._createCompiledTemplate(
+ dirMeta, localModuleMeta.transitiveModule.directives,
+ localModuleMeta.transitiveModule.pipes));
+ dirMeta.precompile.forEach((precompileType) => {
+ templates.add(this._createCompiledHostTemplate(precompileType.runtime));
+ });
+ }
+ });
+ localModuleMeta.precompile.forEach((precompileType) => {
+ templates.add(this._createCompiledHostTemplate(precompileType.runtime));
+ });
+ });
templates.forEach((template) => {
if (template.loading) {
if (isSync) {
@@ -167,16 +168,14 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
() => { templates.forEach((template) => { this._compileTemplate(template); }); };
if (isSync) {
compile();
+ return Promise.resolve(null);
+ } else {
+ return Promise.all(loadingPromises).then(compile);
}
- let result = this._compiledHostTemplateCache.get(compType).proxyComponentFactory;
- return new SyncAsyncResult(result, Promise.all(loadingPromises).then(() => {
- compile();
- return result;
- }));
}
clearCacheFor(type: Type) {
- this._compiledAppModuleCache.delete(type);
+ this._compiledNgModuleCache.delete(type);
this._metadataResolver.clearCacheFor(type);
this._compiledHostTemplateCache.delete(type);
var compiledTemplate = this._compiledTemplateCache.get(type);
@@ -191,71 +190,54 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
this._compiledTemplateCache.clear();
this._compiledHostTemplateCache.clear();
this._templateNormalizer.clearCache();
- this._compiledAppModuleCache.clear();
+ this._compiledNgModuleCache.clear();
}
- private _createCompiledHostTemplate(type: Type): CompiledTemplate {
- var compiledTemplate = this._compiledHostTemplateCache.get(type);
+ private _createCompiledHostTemplate(compType: Type): CompiledTemplate {
+ var compiledTemplate = this._compiledHostTemplateCache.get(compType);
if (isBlank(compiledTemplate)) {
- var compMeta = this._metadataResolver.getDirectiveMetadata(type);
+ var compMeta = this._metadataResolver.getDirectiveMetadata(compType);
assertComponent(compMeta);
- var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
+ var hostMeta = createHostComponentMeta(compMeta);
compiledTemplate = new CompiledTemplate(
- true, compMeta.selector, compMeta.type, [], [type], [], [],
+ true, compMeta.selector, compMeta.type, [compMeta], [],
this._templateNormalizer.normalizeDirective(hostMeta));
- this._compiledHostTemplateCache.set(type, compiledTemplate);
+ this._compiledHostTemplateCache.set(compType, compiledTemplate);
}
return compiledTemplate;
}
private _createCompiledTemplate(
- type: Type, moduleDirectives: ConcreteType[],
- modulePipes: ConcreteType[]): CompiledTemplate {
- var compiledTemplate = this._compiledTemplateCache.get(type);
+ compMeta: CompileDirectiveMetadata, directives: CompileDirectiveMetadata[],
+ pipes: CompilePipeMetadata[]): CompiledTemplate {
+ var compiledTemplate = this._compiledTemplateCache.get(compMeta.type.runtime);
if (isBlank(compiledTemplate)) {
- const compMeta = this._metadataResolver.getDirectiveMetadata(type);
assertComponent(compMeta);
- const viewDirectives: CompileDirectiveMetadata[] = [];
- moduleDirectives.forEach(
- (type) => viewDirectives.push(this._metadataResolver.getDirectiveMetadata(type)));
- const viewComponentTypes: Type[] = [];
- this._metadataResolver.getViewDirectivesMetadata(type).forEach(dirOrComp => {
- if (dirOrComp.isComponent) {
- viewComponentTypes.push(dirOrComp.type.runtime);
- } else {
- viewDirectives.push(dirOrComp);
- }
- });
- const precompileComponentTypes = compMeta.precompile.map((typeMeta) => typeMeta.runtime);
- const pipes = [
- ...modulePipes.map((type) => this._metadataResolver.getPipeMetadata(type)),
- ...this._metadataResolver.getViewPipesMetadata(type)
- ];
compiledTemplate = new CompiledTemplate(
- false, compMeta.selector, compMeta.type, viewDirectives, viewComponentTypes,
- precompileComponentTypes, pipes, this._templateNormalizer.normalizeDirective(compMeta));
- this._compiledTemplateCache.set(type, compiledTemplate);
+ false, compMeta.selector, compMeta.type, directives, pipes,
+ this._templateNormalizer.normalizeDirective(compMeta));
+ this._compiledTemplateCache.set(compMeta.type.runtime, compiledTemplate);
}
return compiledTemplate;
}
- private _getTransitiveCompiledTemplates(
- compType: Type, isHost: boolean, moduleDirectives: ConcreteType[],
- modulePipes: ConcreteType[],
- target: Set = new Set()): Set {
- const template = isHost ? this._createCompiledHostTemplate(compType) :
- this._createCompiledTemplate(compType, moduleDirectives, modulePipes);
- if (!target.has(template)) {
- target.add(template);
- template.viewComponentTypes.forEach((compType) => {
- this._getTransitiveCompiledTemplates(
- compType, false, moduleDirectives, modulePipes, target);
- });
- template.precompileHostComponentTypes.forEach((compType) => {
- this._getTransitiveCompiledTemplates(compType, true, moduleDirectives, modulePipes, target);
- });
+ private _assertComponentKnown(compType: any, isHost: boolean): CompiledTemplate {
+ const compiledTemplate = isHost ? this._compiledHostTemplateCache.get(compType) :
+ this._compiledTemplateCache.get(compType);
+ if (!compiledTemplate) {
+ throw new BaseException(
+ `Illegal state: CompiledTemplate for ${stringify(compType)} (isHost: ${isHost}) does not exist!`);
}
- return target;
+ return compiledTemplate;
+ }
+
+ private _assertComponentLoaded(compType: any, isHost: boolean): CompiledTemplate {
+ const compiledTemplate = this._assertComponentKnown(compType, isHost);
+ if (compiledTemplate.loading) {
+ throw new BaseException(
+ `Illegal state: CompiledTemplate for ${stringify(compType)} (isHost: ${isHost}) is still loading!`);
+ }
+ return compiledTemplate;
}
private _compileTemplate(template: CompiledTemplate) {
@@ -270,7 +252,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
this._resolveStylesCompileResult(
stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl);
const viewCompMetas = template.viewComponentTypes.map(
- (compType) => this._compiledTemplateCache.get(compType).normalizedCompMeta);
+ (compType) => this._assertComponentLoaded(compType, false).normalizedCompMeta);
const parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, template.viewDirectives.concat(viewCompMetas),
template.viewPipes, compMeta.type.name);
@@ -281,12 +263,12 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
let depTemplate: CompiledTemplate;
if (dep instanceof ViewFactoryDependency) {
let vfd = dep;
- depTemplate = this._compiledTemplateCache.get(vfd.comp.runtime);
+ depTemplate = this._assertComponentLoaded(vfd.comp.runtime, false);
vfd.placeholder.runtime = depTemplate.proxyViewFactory;
vfd.placeholder.name = `viewFactory_${vfd.comp.name}`;
} else if (dep instanceof ComponentFactoryDependency) {
let cfd = dep;
- depTemplate = this._compiledHostTemplateCache.get(cfd.comp.runtime);
+ depTemplate = this._assertComponentLoaded(cfd.comp.runtime, true);
cfd.placeholder.runtime = depTemplate.proxyComponentFactory;
cfd.placeholder.name = `compFactory_${cfd.comp.name}`;
}
@@ -294,7 +276,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
const statements =
stylesCompileResult.componentStylesheet.statements.concat(compileResult.statements);
let factory: any;
- if (IS_DART || !this._genConfig.useJit) {
+ if (IS_DART || !this._compilerConfig.useJit) {
factory = interpretStatements(statements, compileResult.viewFactoryVar);
} else {
factory = jitStatements(
@@ -318,7 +300,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
result: CompiledStylesheet,
externalStylesheetsByModuleUrl: Map): string[] {
this._resolveStylesCompileResult(result, externalStylesheetsByModuleUrl);
- if (IS_DART || !this._genConfig.useJit) {
+ if (IS_DART || !this._compilerConfig.useJit) {
return interpretStatements(result.statements, result.stylesVar);
} else {
return jitStatements(`${result.meta.moduleUrl}.css.js`, result.statements, result.stylesVar);
@@ -334,13 +316,28 @@ class CompiledTemplate {
private _normalizedCompMeta: CompileDirectiveMetadata = null;
isCompiled = false;
isCompiledWithDeps = false;
+ viewComponentTypes: Type[] = [];
+ viewDirectives: CompileDirectiveMetadata[] = [];
constructor(
public isHost: boolean, selector: string, public compType: CompileIdentifierMetadata,
- public viewDirectives: CompileDirectiveMetadata[], public viewComponentTypes: Type[],
- public precompileHostComponentTypes: Type[], public viewPipes: CompilePipeMetadata[],
+ viewDirectivesAndComponents: CompileDirectiveMetadata[],
+ public viewPipes: CompilePipeMetadata[],
_normalizeResult: SyncAsyncResult) {
- this.proxyViewFactory = (...args: any[]) => this._viewFactory.apply(null, args);
+ viewDirectivesAndComponents.forEach((dirMeta) => {
+ if (dirMeta.isComponent) {
+ this.viewComponentTypes.push(dirMeta.type.runtime);
+ } else {
+ this.viewDirectives.push(dirMeta);
+ }
+ });
+ this.proxyViewFactory = (...args: any[]) => {
+ if (!this._viewFactory) {
+ throw new BaseException(
+ `Illegal state: CompiledTemplate for ${stringify(this.compType)} is not compiled yet!`);
+ }
+ return this._viewFactory.apply(null, args);
+ };
this.proxyComponentFactory = isHost ?
new ComponentFactory(selector, this.proxyViewFactory, compType.runtime) :
null;
@@ -376,13 +373,15 @@ function assertComponent(meta: CompileDirectiveMetadata) {
}
/**
- * A wrapper around `Compiler` and `ComponentResolver` that
- * provides default patform directives / pipes.
+ * Implements `Compiler` and `ComponentResolver` by delegating
+ * to the RuntimeCompiler using a known module.
*/
-class BoundCompiler implements Compiler, ComponentResolver {
+class ModuleBoundCompiler implements Compiler, ComponentResolver {
+ private _warnOnComponentResolver = true;
+
constructor(
- private _delegate: RuntimeCompiler, private _directives: any[], private _pipes: any[],
- private _parentComponentResolver: ComponentResolver) {}
+ private _delegate: RuntimeCompiler, private _ngModule: ConcreteType,
+ private _parentComponentResolver: ComponentResolver, private _console: Console) {}
get injector(): Injector { return this._delegate.injector; }
@@ -395,27 +394,29 @@ class BoundCompiler implements Compiler, ComponentResolver {
new BaseException(`Cannot resolve component using '${component}'.`), null);
}
}
+ if (this._warnOnComponentResolver) {
+ this._console.warn(ComponentResolver.DynamicCompilationDeprecationMsg);
+ this._warnOnComponentResolver = false;
+ }
return this.compileComponentAsync(>component);
}
- compileComponentAsync(compType: ConcreteType): Promise> {
- return this._delegate._compileComponent(compType, false, this._directives, this._pipes)
- .asyncResult;
+ compileComponentAsync(compType: ConcreteType, ngModule: ConcreteType = null):
+ Promise> {
+ return this._delegate.compileComponentAsync(compType, ngModule ? ngModule : this._ngModule);
}
- compileComponentSync(compType: ConcreteType): ComponentFactory {
- return this._delegate._compileComponent(compType, true, this._directives, this._pipes)
- .syncResult;
+ compileComponentSync(compType: ConcreteType, ngModule: ConcreteType = null):
+ ComponentFactory {
+ return this._delegate.compileComponentSync(compType, ngModule ? ngModule : this._ngModule);
}
- compileAppModuleSync(moduleType: ConcreteType, metadata: AppModuleMetadata = null):
- AppModuleFactory {
- return this._delegate.compileAppModuleSync(moduleType, metadata);
+ compileModuleSync(moduleType: ConcreteType): NgModuleFactory {
+ return this._delegate.compileModuleSync(moduleType);
}
- compileAppModuleAsync(moduleType: ConcreteType, metadata: AppModuleMetadata = null):
- Promise> {
- return this._delegate.compileAppModuleAsync(moduleType, metadata);
+ compileModuleAsync(moduleType: ConcreteType): Promise> {
+ return this._delegate.compileModuleAsync(moduleType);
}
/**
@@ -429,7 +430,7 @@ class BoundCompiler implements Compiler, ComponentResolver {
}
/**
- * Clears the cache for the given component/appModule.
+ * Clears the cache for the given component/ngModule.
*/
clearCacheFor(type: Type) { this._delegate.clearCacheFor(type); }
-}
\ No newline at end of file
+}
diff --git a/modules/@angular/compiler/src/template_parser.ts b/modules/@angular/compiler/src/template_parser.ts
index 7ab90da12c..c22e91ee98 100644
--- a/modules/@angular/compiler/src/template_parser.ts
+++ b/modules/@angular/compiler/src/template_parser.ts
@@ -13,7 +13,7 @@ import {RegExpWrapper, isPresent, StringWrapper, isBlank} from '../src/facade/la
import {BaseException} from '../src/facade/exceptions';
import {AST, Interpolation, ASTWithSource, TemplateBinding, RecursiveAstVisitor, BindingPipe, ParserError} from './expression_parser/ast';
import {Parser} from './expression_parser/parser';
-import {CompileDirectiveMetadata, CompilePipeMetadata, CompileMetadataWithType, CompileTokenMetadata,} from './compile_metadata';
+import {CompileDirectiveMetadata, CompilePipeMetadata, CompileMetadataWithIdentifier, CompileTokenMetadata, CompileIdentifierMap, removeIdentifierDuplicates} from './compile_metadata';
import {HtmlParser, HtmlParseTreeResult} from './html_parser';
import {splitNsName, mergeNsAndName} from './html_tags';
import {ParseSourceSpan, ParseError, ParseErrorLevel} from './parse_util';
@@ -27,7 +27,7 @@ import {HtmlAstVisitor, HtmlElementAst, HtmlAttrAst, HtmlTextAst, HtmlCommentAst
import {splitAtColon} from './util';
import {identifierToken, Identifiers} from './identifiers';
import {expandNodes} from './expander';
-import {ProviderElementContext, ProviderViewContext} from './provider_parser';
+import {ProviderElementContext, ProviderViewContext} from './provider_analyzer';
// Group 1 = "bind-"
// Group 2 = "var-"
@@ -118,8 +118,8 @@ export class TemplateParser {
}
if (htmlAstWithErrors.rootNodes.length > 0) {
- const uniqDirectives = removeDuplicates(directives);
- const uniqPipes = removeDuplicates(pipes);
+ const uniqDirectives = removeIdentifierDuplicates(directives);
+ const uniqPipes = removeIdentifierDuplicates(pipes);
const providerViewContext =
new ProviderViewContext(component, htmlAstWithErrors.rootNodes[0].sourceSpan);
const parseVisitor = new TemplateParseVisitor(
@@ -181,7 +181,6 @@ class TemplateParseVisitor implements HtmlAstVisitor {
const tempMeta = providerViewContext.component.template;
- // TODO
if (isPresent(tempMeta) && isPresent(tempMeta.interpolation)) {
this._interpolationConfig = {
start: tempMeta.interpolation[0],
@@ -1015,18 +1014,3 @@ export class PipeCollector extends RecursiveAstVisitor {
return null;
}
}
-
-function removeDuplicates(items: CompileMetadataWithType[]): CompileMetadataWithType[] {
- let res: CompileMetadataWithType[] = [];
- items.forEach(item => {
- let hasMatch =
- res.filter(
- r => r.type.name == item.type.name && r.type.moduleUrl == item.type.moduleUrl &&
- r.type.runtime == item.type.runtime)
- .length > 0;
- if (!hasMatch) {
- res.push(item);
- }
- });
- return res;
-}
diff --git a/modules/@angular/compiler/src/view_compiler/compile_element.ts b/modules/@angular/compiler/src/view_compiler/compile_element.ts
index c1fbae1972..202c7ce4c3 100644
--- a/modules/@angular/compiler/src/view_compiler/compile_element.ts
+++ b/modules/@angular/compiler/src/view_compiler/compile_element.ts
@@ -18,7 +18,7 @@ import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../templa
import {CompileView} from './compile_view';
import {InjectMethodVars} from './constants';
-import {CompileTokenMap, CompileDirectiveMetadata, CompileTokenMetadata, CompileQueryMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata,} from '../compile_metadata';
+import {CompileIdentifierMap, CompileDirectiveMetadata, CompileTokenMetadata, CompileQueryMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata,} from '../compile_metadata';
import {getPropertyInView, injectFromViewParentInjector} from './util';
import {CompileQuery, createQueryList, addQueryToTokenMap} from './compile_query';
import {CompileMethod} from './compile_method';
@@ -43,11 +43,11 @@ export class CompileElement extends CompileNode {
public appElement: o.ReadPropExpr;
public elementRef: o.Expression;
public injector: o.Expression;
- private _instances = new CompileTokenMap();
- private _resolvedProviders: CompileTokenMap;
+ private _instances = new CompileIdentifierMap();
+ private _resolvedProviders: CompileIdentifierMap;
private _queryCount = 0;
- private _queries = new CompileTokenMap();
+ private _queries = new CompileIdentifierMap();
private _componentConstructorViewQueryLists: o.Expression[] = [];
public contentNodesByNgContentIndex: Array[] = null;
@@ -144,7 +144,7 @@ export class CompileElement extends CompileNode {
identifierToken(Identifiers.ViewContainerRef), this.appElement.prop('vcRef'));
}
- this._resolvedProviders = new CompileTokenMap();
+ this._resolvedProviders = new CompileIdentifierMap();
this._resolvedProvidersArray.forEach(
provider => this._resolvedProviders.add(provider.token, provider));
diff --git a/modules/@angular/compiler/src/view_compiler/compile_query.ts b/modules/@angular/compiler/src/view_compiler/compile_query.ts
index 29343485d3..f847ff0f4b 100644
--- a/modules/@angular/compiler/src/view_compiler/compile_query.ts
+++ b/modules/@angular/compiler/src/view_compiler/compile_query.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {CompileQueryMetadata, CompileTokenMap} from '../compile_metadata';
+import {CompileIdentifierMap, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata';
import {ListWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
import {Identifiers} from '../identifiers';
@@ -125,7 +125,8 @@ export function createQueryList(
return expr;
}
-export function addQueryToTokenMap(map: CompileTokenMap, query: CompileQuery) {
+export function addQueryToTokenMap(
+ map: CompileIdentifierMap, query: CompileQuery) {
query.meta.selectors.forEach((selector) => {
var entry = map.get(selector);
if (isBlank(entry)) {
diff --git a/modules/@angular/compiler/src/view_compiler/compile_view.ts b/modules/@angular/compiler/src/view_compiler/compile_view.ts
index 1220360fa3..1506be51a1 100644
--- a/modules/@angular/compiler/src/view_compiler/compile_view.ts
+++ b/modules/@angular/compiler/src/view_compiler/compile_view.ts
@@ -8,7 +8,7 @@
import {ViewType} from '../../core_private';
import {CompiledAnimation} from '../animation/animation_compiler';
-import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata, CompileTokenMap} from '../compile_metadata';
+import {CompileDirectiveMetadata, CompileIdentifierMap, CompileIdentifierMetadata, CompilePipeMetadata, CompileTokenMetadata} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {ListWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
@@ -27,7 +27,7 @@ import {createPureProxy, getPropertyInView, getViewFactoryName, injectFromViewPa
export class CompileView implements NameResolver {
public viewType: ViewType;
- public viewQueries: CompileTokenMap;
+ public viewQueries: CompileIdentifierMap;
public nodes: CompileNode[] = [];
// root nodes or AppElements for ViewContainers
@@ -98,7 +98,7 @@ export class CompileView implements NameResolver {
this.componentContext =
getPropertyInView(o.THIS_EXPR.prop('context'), this, this.componentView);
- var viewQueries = new CompileTokenMap();
+ var viewQueries = new CompileIdentifierMap();
if (this.viewType === ViewType.COMPONENT) {
var directiveInstance = o.THIS_EXPR.prop('context');
ListWrapper.forEachWithIndex(this.component.viewQueries, (queryMeta, queryIndex) => {
diff --git a/modules/@angular/compiler/src/view_resolver.ts b/modules/@angular/compiler/src/view_resolver.ts
index ddf566064d..99f1233b34 100644
--- a/modules/@angular/compiler/src/view_resolver.ts
+++ b/modules/@angular/compiler/src/view_resolver.ts
@@ -22,7 +22,7 @@ function _isComponentMetadata(obj: any): obj is ComponentMetadata {
export class ViewResolver {
constructor(private _reflector: ReflectorReader = reflector) {}
- resolve(component: Type): ViewMetadata {
+ resolve(component: Type, throwIfNotFound = true): ViewMetadata {
const compMeta: ComponentMetadata =
this._reflector.annotations(component).find(_isComponentMetadata);
@@ -45,8 +45,11 @@ export class ViewResolver {
});
}
} else {
- throw new BaseException(
- `Could not compile '${stringify(component)}' because it is not a component.`);
+ if (throwIfNotFound) {
+ throw new BaseException(
+ `Could not compile '${stringify(component)}' because it is not a component.`);
+ }
+ return null;
}
}
}
diff --git a/modules/@angular/compiler/test/compile_metadata_spec.ts b/modules/@angular/compiler/test/compile_metadata_spec.ts
deleted file mode 100644
index 883bdccdb2..0000000000
--- a/modules/@angular/compiler/test/compile_metadata_spec.ts
+++ /dev/null
@@ -1,256 +0,0 @@
-/**
- * @license
- * Copyright Google Inc. All Rights Reserved.
- *
- * Use of this source code is governed by an MIT-style license that can be
- * found in the LICENSE file at https://angular.io/license
- */
-
-import {beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
-
-import {CompileDirectiveMetadata, CompileTypeMetadata, CompileTemplateMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileQueryMetadata, CompileIdentifierMetadata, CompileFactoryMetadata, CompileTokenMetadata, CompileAnimationEntryMetadata, CompileAnimationStyleMetadata, CompileAnimationAnimateMetadata, CompileAnimationSequenceMetadata, CompileAnimationStateTransitionMetadata, CompileAnimationKeyframesSequenceMetadata, CompileAnimationGroupMetadata} from '@angular/compiler/src/compile_metadata';
-import {ViewEncapsulation} from '@angular/core/src/metadata/view';
-import {ChangeDetectionStrategy} from '@angular/core/src/change_detection';
-import {LifecycleHooks} from '@angular/core/src/metadata/lifecycle_hooks';
-
-export function main() {
- describe('CompileMetadata', () => {
- var fullTypeMeta: CompileTypeMetadata;
- var fullTemplateMeta: CompileTemplateMetadata;
- var fullDirectiveMeta: CompileDirectiveMetadata;
-
- beforeEach(() => {
- var diDep = new CompileDiDependencyMetadata({
- isAttribute: true,
- isSelf: true,
- isHost: true,
- isSkipSelf: true,
- isOptional: true,
- token: new CompileTokenMetadata({value: 'someToken'}),
- query: new CompileQueryMetadata({
- selectors: [new CompileTokenMetadata({value: 'one'})],
- descendants: true,
- first: true,
- propertyName: 'one'
- }),
- viewQuery: new CompileQueryMetadata({
- selectors: [new CompileTokenMetadata({value: 'one'})],
- descendants: true,
- first: true,
- propertyName: 'one'
- })
- });
-
- fullTypeMeta = new CompileTypeMetadata(
- {name: 'SomeType', moduleUrl: 'someUrl', isHost: true, diDeps: [diDep]});
- fullTemplateMeta = new CompileTemplateMetadata({
- encapsulation: ViewEncapsulation.Emulated,
- template: ' ',
- templateUrl: 'someTemplateUrl',
- styles: ['someStyle'],
- styleUrls: ['someStyleUrl'],
- animations: [new CompileAnimationEntryMetadata(
- 'animation',
- [new CompileAnimationStateTransitionMetadata(
- '* => *', new CompileAnimationSequenceMetadata([
- new CompileAnimationStyleMetadata(0, [{'opacity': 0}]),
- new CompileAnimationAnimateMetadata(
- 1000, new CompileAnimationStyleMetadata(0, [{'opacity': 1}]))
- ]))])],
- ngContentSelectors: ['*'],
- interpolation: ['{{', '}}']
- });
- fullDirectiveMeta = CompileDirectiveMetadata.create({
- selector: 'someSelector',
- isComponent: true,
- type: fullTypeMeta,
- template: fullTemplateMeta,
- changeDetection: ChangeDetectionStrategy.Default,
- inputs: ['someProp'],
- outputs: ['someEvent'],
- host: {'(event1)': 'handler1', '[prop1]': 'expr1', 'attr1': 'attrValue2'},
- lifecycleHooks: [LifecycleHooks.OnChanges],
- providers: [new CompileProviderMetadata({
- token: new CompileTokenMetadata({value: 'token'}),
- multi: true,
- useClass: fullTypeMeta,
- useExisting: new CompileTokenMetadata({
- identifier: new CompileIdentifierMetadata({name: 'someName'}),
- identifierIsInstance: true
- }),
- useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
- useValue: 'someValue',
- })],
- viewProviders: [new CompileProviderMetadata({
- token: new CompileTokenMetadata({value: 'token'}),
- useClass: fullTypeMeta,
- useExisting: new CompileTokenMetadata(
- {identifier: new CompileIdentifierMetadata({name: 'someName'})}),
- useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
- useValue: 'someValue'
- })],
- queries: [new CompileQueryMetadata({
- selectors: [new CompileTokenMetadata({value: 'selector'})],
- descendants: true,
- first: false,
- propertyName: 'prop',
- read: new CompileTokenMetadata({value: 'readToken'})
- })],
- viewQueries: [new CompileQueryMetadata({
- selectors: [new CompileTokenMetadata({value: 'selector'})],
- descendants: true,
- first: false,
- propertyName: 'prop',
- read: new CompileTokenMetadata({value: 'readToken'})
- })]
- });
-
- });
-
- describe('CompileIdentifierMetadata', () => {
- it('should serialize with full data', () => {
- let full = new CompileIdentifierMetadata(
- {name: 'name', moduleUrl: 'module', value: ['one', ['two']]});
- expect(CompileIdentifierMetadata.fromJson(full.toJson())).toEqual(full);
- });
-
- it('should serialize with no data', () => {
- let empty = new CompileIdentifierMetadata();
- expect(CompileIdentifierMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('DirectiveMetadata', () => {
- it('should serialize with full data', () => {
- expect(CompileDirectiveMetadata.fromJson(fullDirectiveMeta.toJson()))
- .toEqual(fullDirectiveMeta);
- });
-
- it('should serialize with no data', () => {
- var empty = CompileDirectiveMetadata.create();
- expect(CompileDirectiveMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('TypeMetadata', () => {
- it('should serialize with full data', () => {
- expect(CompileTypeMetadata.fromJson(fullTypeMeta.toJson())).toEqual(fullTypeMeta);
- });
-
- it('should serialize with no data', () => {
- var empty = new CompileTypeMetadata();
- expect(CompileTypeMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('TemplateMetadata', () => {
-
- it('should serialize with full data', () => {
- expect(CompileTemplateMetadata.fromJson(fullTemplateMeta.toJson()))
- .toEqual(fullTemplateMeta);
- });
-
- it('should serialize with no data', () => {
- var empty = new CompileTemplateMetadata();
- expect(CompileTemplateMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
-
- it('should throw an error with invalid interpolation symbols', () => {
- expect(() => new CompileTemplateMetadata({interpolation: ['{{']}))
- .toThrowError(`'interpolation' should have a start and an end symbol.`);
- });
- });
-
- describe('CompileAnimationStyleMetadata', () => {
- it('should serialize with full data', () => {
- let full = new CompileAnimationStyleMetadata(0, [{'opacity': 0, 'color': 'red'}]);
- expect(CompileAnimationStyleMetadata.fromJson(full.toJson())).toEqual(full);
- });
-
- it('should serialize with no data', () => {
- let empty = new CompileAnimationStyleMetadata(0, []);
- expect(CompileAnimationStyleMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('CompileAnimationAnimateMetadata', () => {
- it('should serialize with full data', () => {
- let full = new CompileAnimationAnimateMetadata(
- '1s linear', new CompileAnimationStyleMetadata(0, [{'opacity': 0.5, 'color': 'blue'}]));
- expect(CompileAnimationAnimateMetadata.fromJson(full.toJson())).toEqual(full);
- });
-
- it('should serialize with no data', () => {
- let empty = new CompileAnimationAnimateMetadata();
- expect(CompileAnimationAnimateMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('CompileAnimationSequenceMetadata', () => {
- it('should serialize with full data', () => {
- let full = new CompileAnimationSequenceMetadata([
- new CompileAnimationStyleMetadata(0, [{'opacity': 0.5, 'width': 100}]),
- new CompileAnimationAnimateMetadata(
- 1000, new CompileAnimationStyleMetadata(0, [{'opacity': 1, 'width': 0}]))
- ]);
- expect(CompileAnimationSequenceMetadata.fromJson(full.toJson())).toEqual(full);
- });
-
- it('should serialize with no data', () => {
- let empty = new CompileAnimationSequenceMetadata();
- expect(CompileAnimationSequenceMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('CompileAnimationGroupMetadata', () => {
- it('should serialize with full data', () => {
- let full = new CompileAnimationGroupMetadata([
- new CompileAnimationStyleMetadata(0, [{'width': 100, 'border': '1px solid red'}]),
- new CompileAnimationAnimateMetadata(
- 1000, new CompileAnimationStyleMetadata(
- 0, [{'width': 900, 'border': '10px solid blue'}]))
- ]);
- expect(CompileAnimationGroupMetadata.fromJson(full.toJson())).toEqual(full);
- });
-
- it('should serialize with no data', () => {
- let empty = new CompileAnimationGroupMetadata();
- expect(CompileAnimationGroupMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('CompileAnimationKeyframesSequenceMetadata', () => {
- it('should serialize with full data', () => {
- let full = new CompileAnimationKeyframesSequenceMetadata([
- new CompileAnimationStyleMetadata(0, [{'width': 0}]),
- new CompileAnimationStyleMetadata(0.5, [{'width': 100}]),
- new CompileAnimationStyleMetadata(1, [{'width': 200}]),
- ]);
- expect(CompileAnimationKeyframesSequenceMetadata.fromJson(full.toJson())).toEqual(full);
- });
-
- it('should serialize with no data', () => {
- let empty = new CompileAnimationKeyframesSequenceMetadata();
- expect(CompileAnimationKeyframesSequenceMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
-
- describe('CompileAnimationEntryMetadata', () => {
- it('should serialize with full data', () => {
- let full = new CompileAnimationEntryMetadata(
- 'name', [new CompileAnimationStateTransitionMetadata(
- 'key => value', new CompileAnimationSequenceMetadata([
- new CompileAnimationStyleMetadata(0, [{'color': 'red'}]),
- new CompileAnimationAnimateMetadata(
- 1000, new CompileAnimationStyleMetadata(0, [{'color': 'blue'}]))
- ]))]);
- expect(CompileAnimationEntryMetadata.fromJson(full.toJson())).toEqual(full);
- });
-
- it('should serialize with no data', () => {
- let empty = new CompileAnimationEntryMetadata();
- expect(CompileAnimationEntryMetadata.fromJson(empty.toJson())).toEqual(empty);
- });
- });
- });
-}
diff --git a/modules/@angular/compiler/test/metadata_resolver_spec.ts b/modules/@angular/compiler/test/metadata_resolver_spec.ts
index d4d8b350c8..9a3e53e97e 100644
--- a/modules/@angular/compiler/test/metadata_resolver_spec.ts
+++ b/modules/@angular/compiler/test/metadata_resolver_spec.ts
@@ -12,6 +12,7 @@ import {LIFECYCLE_HOOKS_VALUES} from '@angular/core/src/metadata/lifecycle_hooks
import {configureCompiler} from '@angular/core/testing';
import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
+import {CompileNgModuleMetadata} from '../src/compile_metadata';
import {IS_DART, stringify} from '../src/facade/lang';
import {CompileMetadataResolver} from '../src/metadata_resolver';
@@ -22,7 +23,7 @@ export function main() {
describe('CompileMetadataResolver', () => {
beforeEach(() => { configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
- describe('getMetadata', () => {
+ describe('getDirectiveMetadata', () => {
it('should read metadata',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
var meta = resolver.getDirectiveMetadata(ComponentWithEverything);
@@ -102,35 +103,6 @@ export function main() {
}));
});
- describe('getViewDirectivesMetadata', () => {
-
- it('should return the directive metadatas',
- inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
- expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
- .toContain(resolver.getDirectiveMetadata(SomeDirective));
- }));
-
- describe('platform directives', () => {
- beforeEach(() => {
- configureCompiler({
- providers: [{
- provide: CompilerConfig,
- useValue: new CompilerConfig(
- {genDebugInfo: true, deprecatedPlatformDirectives: [ADirective]})
- }]
- });
- });
-
- it('should include platform directives when available',
- inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
- expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
- .toContain(resolver.getDirectiveMetadata(ADirective));
- expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
- .toContain(resolver.getDirectiveMetadata(SomeDirective));
- }));
- });
- });
-
});
}
diff --git a/modules/@angular/compiler/test/ng_module_resolver_mock_spec.ts b/modules/@angular/compiler/test/ng_module_resolver_mock_spec.ts
new file mode 100644
index 0000000000..b1b2f88f95
--- /dev/null
+++ b/modules/@angular/compiler/test/ng_module_resolver_mock_spec.ts
@@ -0,0 +1,46 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {beforeEach, ddescribe, describe, expect, iit, it, inject,} from '@angular/core/testing/testing_internal';
+
+import {stringify, isBlank} from '../src/facade/lang';
+import {MockNgModuleResolver} from '../testing';
+import {NgModule, NgModuleMetadata, Injector} from '@angular/core';
+
+export function main() {
+ describe('MockNgModuleResolver', () => {
+ var ngModuleResolver: MockNgModuleResolver;
+
+ beforeEach(inject([Injector], (injector: Injector) => {
+ ngModuleResolver = new MockNgModuleResolver(injector);
+ }));
+
+ describe('NgModule overriding', () => {
+ it('should fallback to the default NgModuleResolver when templates are not overridden',
+ () => {
+ var ngModule = ngModuleResolver.resolve(SomeNgModule);
+ expect(ngModule.declarations).toEqual([SomeDirective]);
+ });
+
+ it('should allow overriding the @NgModule', () => {
+ ngModuleResolver.setNgModule(
+ SomeNgModule, new NgModuleMetadata({declarations: [SomeOtherDirective]}));
+ var ngModule = ngModuleResolver.resolve(SomeNgModule);
+ expect(ngModule.declarations).toEqual([SomeOtherDirective]);
+ });
+ });
+ });
+}
+
+class SomeDirective {}
+
+class SomeOtherDirective {}
+
+@NgModule({declarations: [SomeDirective]})
+class SomeNgModule {
+}
diff --git a/modules/@angular/compiler/test/ng_module_resolver_spec.ts b/modules/@angular/compiler/test/ng_module_resolver_spec.ts
new file mode 100644
index 0000000000..442766c508
--- /dev/null
+++ b/modules/@angular/compiler/test/ng_module_resolver_spec.ts
@@ -0,0 +1,53 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {NgModuleResolver} from '@angular/compiler/src/ng_module_resolver';
+import {NgModule, NgModuleMetadata} from '@angular/core/src/metadata';
+import {stringify} from '../src/facade/lang';
+
+class SomeClass1 {}
+class SomeClass2 {}
+class SomeClass3 {}
+class SomeClass4 {}
+class SomeClass5 {}
+
+@NgModule({
+ declarations: [SomeClass1],
+ imports: [SomeClass2],
+ exports: [SomeClass3],
+ providers: [SomeClass4],
+ precompile: [SomeClass5]
+})
+class SomeModule {
+}
+
+class SimpleClass {}
+
+export function main() {
+ describe('NgModuleResolver', () => {
+ var resolver: NgModuleResolver;
+
+ beforeEach(() => { resolver = new NgModuleResolver(); });
+
+ it('should read out the metadata from the class', () => {
+ var viewMetadata = resolver.resolve(SomeModule);
+ expect(viewMetadata).toEqual(new NgModuleMetadata({
+ declarations: [SomeClass1],
+ imports: [SomeClass2],
+ exports: [SomeClass3],
+ providers: [SomeClass4],
+ precompile: [SomeClass5]
+ }));
+ });
+
+ it('should throw when simple class has no component decorator', () => {
+ expect(() => resolver.resolve(SimpleClass))
+ .toThrowError(`No NgModule metadata found for '${stringify(SimpleClass)}'.`);
+ });
+ });
+}
diff --git a/modules/@angular/compiler/test/runtime_compiler_spec.ts b/modules/@angular/compiler/test/runtime_compiler_spec.ts
index 2f5b44b9b3..548b9be7ed 100644
--- a/modules/@angular/compiler/test/runtime_compiler_spec.ts
+++ b/modules/@angular/compiler/test/runtime_compiler_spec.ts
@@ -8,7 +8,7 @@
import {beforeEach, ddescribe, xdescribe, describe, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers';
-import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, AppModule, AppModuleMetadata, AppModuleFactory} from '@angular/core';
+import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, NgModule, NgModuleFactory} from '@angular/core';
import {ConcreteType, stringify} from '../src/facade/lang';
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture, configureCompiler} from '@angular/core/testing';
import {XHR, ViewResolver} from '@angular/compiler';
@@ -28,10 +28,6 @@ class SomeComp {
class SomeCompWithUrlTemplate {
}
-@AppModule({})
-class SomeModule {
-}
-
export function main() {
describe('RuntimeCompiler', () => {
let compiler: Compiler;
@@ -118,49 +114,61 @@ export function main() {
}));
});
- describe('compileAppModuleAsync', () => {
+ describe('compileModuleAsync', () => {
it('should allow to use templateUrl components', fakeAsync(() => {
+ @NgModule(
+ {declarations: [SomeCompWithUrlTemplate], precompile: [SomeCompWithUrlTemplate]})
+ class SomeModule {
+ }
+
xhr.spy('get').andCallFake(() => Promise.resolve('hello'));
- let appModuleFactory: AppModuleFactory;
- compiler
- .compileAppModuleAsync(
- SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]}))
- .then((f) => appModuleFactory = f);
+ let ngModuleFactory: NgModuleFactory;
+ compiler.compileModuleAsync(SomeModule).then((f) => ngModuleFactory = f);
tick();
- expect(appModuleFactory.moduleType).toBe(SomeModule);
+ expect(ngModuleFactory.moduleType).toBe(SomeModule);
}));
});
- describe('compileAppModuleSync', () => {
+ describe('compileModuleSync', () => {
it('should throw when using a templateUrl that has not been compiled before', () => {
+ @NgModule({declarations: [SomeCompWithUrlTemplate], precompile: [SomeCompWithUrlTemplate]})
+ class SomeModule {
+ }
+
xhr.spy('get').andCallFake(() => Promise.resolve(''));
- expect(
- () => compiler.compileAppModuleSync(
- SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]})))
+ expect(() => compiler.compileModuleSync(SomeModule))
.toThrowError(
`Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`);
});
it('should throw when using a templateUrl in a nested component that has not been compiled before',
() => {
+ @NgModule({declarations: [SomeComp], precompile: [SomeComp]})
+ class SomeModule {
+ }
+
xhr.spy('get').andCallFake(() => Promise.resolve(''));
viewResolver.setView(
SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
viewResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
- expect(
- () => compiler.compileAppModuleSync(
- SomeModule, new AppModuleMetadata({precompile: [SomeComp]})))
+ expect(() => compiler.compileModuleSync(SomeModule))
.toThrowError(
`Can't compile synchronously as ${stringify(ChildComp)} is still being loaded!`);
});
it('should allow to use templateUrl components that have been loaded before',
fakeAsync(() => {
+ @NgModule(
+ {declarations: [SomeCompWithUrlTemplate], precompile: [SomeCompWithUrlTemplate]})
+ class SomeModule {
+ }
+
xhr.spy('get').andCallFake(() => Promise.resolve('hello'));
- tcb.createFakeAsync(SomeCompWithUrlTemplate);
- let appModuleFactory = compiler.compileAppModuleSync(
- SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]}));
- expect(appModuleFactory).toBeTruthy();
+ compiler.compileModuleAsync(SomeModule);
+ tick();
+
+ let ngModuleFactory = compiler.compileModuleSync(SomeModule);
+ expect(ngModuleFactory).toBeTruthy();
}));
});
});
diff --git a/modules/@angular/compiler/test/test_component_builder_spec.ts b/modules/@angular/compiler/test/test_component_builder_spec.ts
index 9312d36d47..e9d469b3ea 100644
--- a/modules/@angular/compiler/test/test_component_builder_spec.ts
+++ b/modules/@angular/compiler/test/test_component_builder_spec.ts
@@ -9,7 +9,7 @@
import {AsyncTestCompleter, beforeEach, ddescribe, xdescribe, describe, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers';
import {TestComponentBuilder, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, withProviders} from '@angular/core/testing';
-import {Injectable, Component, Input, ViewMetadata} from '@angular/core';
+import {Injectable, Component, Input, ViewMetadata, Pipe, NgModule} from '@angular/core';
import {NgIf} from '@angular/common';
import {TimerWrapper} from '../src/facade/async';
import {PromiseWrapper} from '../src/facade/promise';
@@ -327,6 +327,27 @@ export function main() {
expect(componentFixture.nativeElement).toHaveText('Mock');
}));
+ it('should create components synchronously with a custom module',
+ inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
+ @Pipe({name: 'somePipe'})
+ class SomePipe {
+ transform(value: any) { return `transformed ${value}`; }
+ }
+
+ @NgModule({declarations: [SomePipe]})
+ class SomeModule {
+ }
+
+ @Component({selector: 'comp', template: `{{'hello' | somePipe}}`})
+ class SomeComponent {
+ }
+
+
+ let componentFixture = tcb.createSync(SomeComponent, SomeModule);
+ componentFixture.detectChanges();
+ expect(componentFixture.nativeElement).toHaveText('transformed hello');
+ }));
+
describe('ComponentFixture', () => {
it('should auto detect changes if autoDetectChanges is called',
inject(
diff --git a/modules/@angular/compiler/testing.ts b/modules/@angular/compiler/testing.ts
index fcc0ff94c1..3c1664e08a 100644
--- a/modules/@angular/compiler/testing.ts
+++ b/modules/@angular/compiler/testing.ts
@@ -10,3 +10,29 @@ export * from './testing/schema_registry_mock';
export * from './testing/view_resolver_mock';
export * from './testing/test_component_builder';
export * from './testing/directive_resolver_mock';
+export * from './testing/ng_module_resolver_mock';
+
+import {createPlatformFactory, CompilerOptions, PlatformRef} from '@angular/core';
+import {coreDynamicPlatform, DirectiveResolver, ViewResolver, NgModuleResolver} from './index';
+import {MockViewResolver} from './testing/view_resolver_mock';
+import {MockDirectiveResolver} from './testing/directive_resolver_mock';
+import {MockNgModuleResolver} from './testing/ng_module_resolver_mock';
+
+
+/**
+ * Platform for dynamic tests
+ *
+ * @experimental
+ */
+export const coreDynamicTestingPlatform =
+ createPlatformFactory(coreDynamicPlatform, 'coreDynamicTesting', [{
+ provide: CompilerOptions,
+ useValue: {
+ providers: [
+ {provide: DirectiveResolver, useClass: MockDirectiveResolver},
+ {provide: ViewResolver, useClass: MockViewResolver},
+ {provide: NgModuleResolver, useClass: MockNgModuleResolver}
+ ]
+ },
+ multi: true
+ }]);
diff --git a/modules/@angular/compiler/testing/directive_resolver_mock.ts b/modules/@angular/compiler/testing/directive_resolver_mock.ts
index 9a764f0e27..3a29439933 100644
--- a/modules/@angular/compiler/testing/directive_resolver_mock.ts
+++ b/modules/@angular/compiler/testing/directive_resolver_mock.ts
@@ -27,8 +27,11 @@ export class MockDirectiveResolver extends DirectiveResolver {
private get _compiler(): Compiler { return this._injector.get(Compiler); }
- resolve(type: Type): DirectiveMetadata {
- var dm = super.resolve(type);
+ resolve(type: Type, throwIfNotFound = true): DirectiveMetadata {
+ var dm = super.resolve(type, throwIfNotFound);
+ if (!dm) {
+ return null;
+ }
var providerOverrides = this._providerOverrides.get(type);
var viewProviderOverrides = this.viewProviderOverrides.get(type);
diff --git a/modules/@angular/compiler/testing/ng_module_resolver_mock.ts b/modules/@angular/compiler/testing/ng_module_resolver_mock.ts
new file mode 100644
index 0000000000..fc270f6b4e
--- /dev/null
+++ b/modules/@angular/compiler/testing/ng_module_resolver_mock.ts
@@ -0,0 +1,46 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {Compiler, Injectable, Injector, NgModuleMetadata, Type} from '@angular/core';
+
+import {NgModuleResolver} from '../index';
+import {Map} from '../src/facade/collection';
+
+@Injectable()
+export class MockNgModuleResolver extends NgModuleResolver {
+ /** @internal */
+ _ngModules = new Map();
+
+ constructor(private _injector: Injector) { super(); }
+
+ private get _compiler(): Compiler { return this._injector.get(Compiler); }
+
+ private _clearCacheFor(component: Type) { this._compiler.clearCacheFor(component); }
+
+ /**
+ * Overrides the {@link NgModuleMetadata} for a module.
+ */
+ setNgModule(type: Type, metadata: NgModuleMetadata): void {
+ this._ngModules.set(type, metadata);
+ this._clearCacheFor(type);
+ }
+
+ /**
+ * Returns the {@link NgModuleMetadata} for a module:
+ * - Set the {@link NgModuleMetadata} to the overridden view when it exists or fallback to the
+ * default
+ * `NgModuleResolver`, see `setNgModule`.
+ */
+ resolve(type: Type, throwIfNotFound = true): NgModuleMetadata {
+ var metadata = this._ngModules.get(type);
+ if (!metadata) {
+ metadata = super.resolve(type, throwIfNotFound);
+ }
+ return metadata;
+ }
+}
diff --git a/modules/@angular/compiler/testing/test_component_builder.ts b/modules/@angular/compiler/testing/test_component_builder.ts
index 76fa0202fb..2a28454900 100644
--- a/modules/@angular/compiler/testing/test_component_builder.ts
+++ b/modules/@angular/compiler/testing/test_component_builder.ts
@@ -87,14 +87,16 @@ export class OverridingTestComponentBuilder extends TestComponentBuilder {
return clone;
}
- createAsync(rootComponentType: ConcreteType): Promise> {
+ createAsync(rootComponentType: ConcreteType, ngModule: ConcreteType = null):
+ Promise> {
this._applyMetadataOverrides();
- return super.createAsync(rootComponentType);
+ return super.createAsync(rootComponentType, ngModule);
}
- createSync(rootComponentType: ConcreteType): ComponentFixture {
+ createSync(rootComponentType: ConcreteType, ngModule: ConcreteType = null):
+ ComponentFixture {
this._applyMetadataOverrides();
- return super.createSync(rootComponentType);
+ return super.createSync(rootComponentType, ngModule);
}
private _applyMetadataOverrides() {
diff --git a/modules/@angular/compiler/testing/view_resolver_mock.ts b/modules/@angular/compiler/testing/view_resolver_mock.ts
index 4b7b5090c1..7fe1ac6eb0 100644
--- a/modules/@angular/compiler/testing/view_resolver_mock.ts
+++ b/modules/@angular/compiler/testing/view_resolver_mock.ts
@@ -72,10 +72,13 @@ export class MockViewResolver extends ViewResolver {
* - Override the directives, see `overrideViewDirective`.
* - Override the @View definition, see `setInlineTemplate`.
*/
- resolve(component: Type): ViewMetadata {
+ resolve(component: Type, throwIfNotFound = true): ViewMetadata {
var view = this._views.get(component);
if (isBlank(view)) {
- view = super.resolve(component);
+ view = super.resolve(component, throwIfNotFound);
+ if (!view) {
+ return null;
+ }
}
var directives: any[] /** TODO #9100 */ = [];
diff --git a/modules/@angular/core/index.ts b/modules/@angular/core/index.ts
index 59013b965a..20c0ea3e4e 100644
--- a/modules/@angular/core/index.ts
+++ b/modules/@angular/core/index.ts
@@ -23,8 +23,8 @@ export {DebugElement, DebugNode, asNativeElements, getDebugNode} from './src/deb
export * from './src/testability/testability';
export * from './src/change_detection';
export * from './src/platform_directives_and_pipes';
-export * from './src/platform_common_providers';
-export {APPLICATION_COMMON_PROVIDERS} from './src/application_common_providers';
+export * from './src/platform_core_providers';
+export {APPLICATION_COMMON_PROVIDERS, ApplicationModule} from './src/application_module';
export {wtfCreateScope, wtfLeave, wtfStartTimeRange, wtfEndTimeRange, WtfScopeFn} from './src/profile/profile';
export {Type} from './src/facade/lang';
diff --git a/modules/@angular/core/private_export.ts b/modules/@angular/core/private_export.ts
index f46baf03cd..16d776d45c 100644
--- a/modules/@angular/core/private_export.ts
+++ b/modules/@angular/core/private_export.ts
@@ -20,11 +20,11 @@ import * as console from './src/console';
import * as debug from './src/debug/debug_renderer';
import * as provider_util from './src/di/provider_util';
import * as reflective_provider from './src/di/reflective_provider';
-import * as app_module_factory from './src/linker/app_module_factory';
import * as component_factory_resolver from './src/linker/component_factory_resolver';
import * as component_resolver from './src/linker/component_resolver';
import * as debug_context from './src/linker/debug_context';
import * as element from './src/linker/element';
+import * as ng_module_factory from './src/linker/ng_module_factory';
import * as template_ref from './src/linker/template_ref';
import * as view from './src/linker/view';
import * as view_type from './src/linker/view_type';
@@ -52,13 +52,12 @@ export declare namespace __core_private_types__ {
export var LIFECYCLE_HOOKS_VALUES: typeof lifecycle_hooks.LIFECYCLE_HOOKS_VALUES;
export type ReflectorReader = reflector_reader.ReflectorReader;
export var ReflectorReader: typeof reflector_reader.ReflectorReader;
- export var ReflectorComponentResolver: typeof component_resolver.ReflectorComponentResolver;
export var CodegenComponentFactoryResolver:
typeof component_factory_resolver.CodegenComponentFactoryResolver;
export type AppElement = element.AppElement;
export var AppElement: typeof element.AppElement;
export var AppView: typeof view.AppView;
- export var AppModuleInjector: typeof app_module_factory.AppModuleInjector;
+ export var NgModuleInjector: typeof ng_module_factory.NgModuleInjector;
export type DebugAppView = view.DebugAppView;
export var DebugAppView: typeof view.DebugAppView;
export type ViewType = view_type.ViewType;
@@ -136,12 +135,11 @@ export var __core_private__ = {
LifecycleHooks: lifecycle_hooks.LifecycleHooks,
LIFECYCLE_HOOKS_VALUES: lifecycle_hooks.LIFECYCLE_HOOKS_VALUES,
ReflectorReader: reflector_reader.ReflectorReader,
- ReflectorComponentResolver: component_resolver.ReflectorComponentResolver,
CodegenComponentFactoryResolver: component_factory_resolver.CodegenComponentFactoryResolver,
AppElement: element.AppElement,
AppView: view.AppView,
DebugAppView: view.DebugAppView,
- AppModuleInjector: app_module_factory.AppModuleInjector,
+ NgModuleInjector: ng_module_factory.NgModuleInjector,
ViewType: view_type.ViewType,
MAX_INTERPOLATION_VALUES: view_utils.MAX_INTERPOLATION_VALUES,
checkBinding: view_utils.checkBinding,
diff --git a/modules/@angular/core/src/application_common_providers.ts b/modules/@angular/core/src/application_common_providers.ts
deleted file mode 100644
index ccf8619759..0000000000
--- a/modules/@angular/core/src/application_common_providers.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * @license
- * Copyright Google Inc. All Rights Reserved.
- *
- * Use of this source code is governed by an MIT-style license that can be
- * found in the LICENSE file at https://angular.io/license
- */
-
-import {Type} from '../src/facade/lang';
-
-import {APPLICATION_CORE_PROVIDERS} from './application_ref';
-import {APP_ID_RANDOM_PROVIDER} from './application_tokens';
-import {IterableDiffers, KeyValueDiffers, defaultIterableDiffers, defaultKeyValueDiffers} from './change_detection/change_detection';
-import {ComponentFactoryResolver} from './linker/component_factory_resolver';
-import {ComponentResolver, ReflectorComponentResolver} from './linker/component_resolver';
-import {DynamicComponentLoader, DynamicComponentLoader_} from './linker/dynamic_component_loader';
-import {ViewUtils} from './linker/view_utils';
-
-let __unused: Type; // avoid unused import when Type union types are erased
-
-export function _componentFactoryResolverFactory() {
- return ComponentFactoryResolver.NULL;
-}
-
-export function _iterableDiffersFactory() {
- return defaultIterableDiffers;
-}
-
-export function _keyValueDiffersFactory() {
- return defaultKeyValueDiffers;
-}
-
-/**
- * A default set of providers which should be included in any Angular
- * application, regardless of the platform it runs onto.
- * @stable
- */
-export const APPLICATION_COMMON_PROVIDERS: Array =
- /*@ts2dart_const*/[
- APPLICATION_CORE_PROVIDERS,
- /* @ts2dart_Provider */ {provide: ComponentResolver, useClass: ReflectorComponentResolver},
- {provide: ComponentFactoryResolver, useFactory: _componentFactoryResolverFactory, deps: []},
- APP_ID_RANDOM_PROVIDER,
- ViewUtils,
- /* @ts2dart_Provider */ {
- provide: IterableDiffers,
- useFactory: _iterableDiffersFactory,
- deps: []
- },
- /* @ts2dart_Provider */ {
- provide: KeyValueDiffers,
- useFactory: _keyValueDiffersFactory,
- deps: []
- },
- /* @ts2dart_Provider */ {provide: DynamicComponentLoader, useClass: DynamicComponentLoader_},
- ];
diff --git a/modules/@angular/core/src/application_module.ts b/modules/@angular/core/src/application_module.ts
new file mode 100644
index 0000000000..91caaa9d75
--- /dev/null
+++ b/modules/@angular/core/src/application_module.ts
@@ -0,0 +1,84 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {Type} from '../src/facade/lang';
+
+import {ApplicationRef, ApplicationRef_, isDevMode} from './application_ref';
+import {APP_ID_RANDOM_PROVIDER} from './application_tokens';
+import {IterableDiffers, KeyValueDiffers, defaultIterableDiffers, defaultKeyValueDiffers} from './change_detection/change_detection';
+import {OptionalMetadata, SkipSelfMetadata} from './di';
+import {Compiler} from './linker/compiler';
+import {ComponentFactoryResolver} from './linker/component_factory_resolver';
+import {ComponentResolver} from './linker/component_resolver';
+import {DynamicComponentLoader, DynamicComponentLoader_} from './linker/dynamic_component_loader';
+import {ViewUtils} from './linker/view_utils';
+import {NgModule} from './metadata';
+import {NgZone} from './zone/ng_zone';
+
+let __unused: Type; // avoid unused import when Type union types are erased
+
+export function _componentFactoryResolverFactory() {
+ return ComponentFactoryResolver.NULL;
+}
+
+export function _iterableDiffersFactory() {
+ return defaultIterableDiffers;
+}
+
+export function _keyValueDiffersFactory() {
+ return defaultKeyValueDiffers;
+}
+
+export function createNgZone(parent: NgZone): NgZone {
+ // If an NgZone is already present in the parent injector,
+ // use that one. Creating the NgZone in the same injector as the
+ // application is dangerous as some services might get created before
+ // the NgZone has been created.
+ // We keep the NgZone factory in the application providers for
+ // backwards compatibility for now though.
+ if (parent) {
+ return parent;
+ }
+ return new NgZone({enableLongStackTrace: isDevMode()});
+}
+
+/**
+ * A default set of providers which should be included in any Angular
+ * application, regardless of the platform it runs onto.
+ *
+ * @deprecated Include `ApplicationModule` instead.
+ */
+export const APPLICATION_COMMON_PROVIDERS: Array = [];
+
+/**
+ * This module includes the providers of @angular/core that are needed
+ * to bootstrap components via `ApplicationRef`.
+ *
+ * @experimental
+ */
+@NgModule({
+ providers: [
+ {
+ provide: NgZone,
+ useFactory: createNgZone,
+ deps: [[new SkipSelfMetadata(), new OptionalMetadata(), NgZone]]
+ },
+ ApplicationRef_,
+ {provide: ApplicationRef, useExisting: ApplicationRef_},
+ Compiler,
+ {provide: ComponentResolver, useExisting: Compiler},
+ {provide: ComponentFactoryResolver, useFactory: _componentFactoryResolverFactory},
+ APP_ID_RANDOM_PROVIDER,
+ ViewUtils,
+ {provide: IterableDiffers, useFactory: _iterableDiffersFactory},
+ {provide: KeyValueDiffers, useFactory: _keyValueDiffersFactory},
+ {provide: DynamicComponentLoader, useClass: DynamicComponentLoader_},
+ ]
+})
+export class ApplicationModule {
+}
diff --git a/modules/@angular/core/src/application_ref.ts b/modules/@angular/core/src/application_ref.ts
index 11e607cf3a..f46aaa8e10 100644
--- a/modules/@angular/core/src/application_ref.ts
+++ b/modules/@angular/core/src/application_ref.ts
@@ -14,35 +14,16 @@ import {ConcreteType, IS_DART, Type, isBlank, isPresent, isPromise} from '../src
import {APP_INITIALIZER, PLATFORM_INITIALIZER} from './application_tokens';
import {ChangeDetectorRef} from './change_detection/change_detector_ref';
import {Console} from './console';
-import {Inject, Injectable, Injector, OpaqueToken, Optional, OptionalMetadata, ReflectiveInjector, SkipSelf, SkipSelfMetadata, forwardRef} from './di';
-import {AppModuleFactory, AppModuleRef} from './linker/app_module_factory';
+import {Inject, Injectable, Injector, OpaqueToken, Optional, ReflectiveInjector, SkipSelf, forwardRef} from './di';
import {Compiler, CompilerFactory, CompilerOptions} from './linker/compiler';
import {ComponentFactory, ComponentRef} from './linker/component_factory';
import {ComponentFactoryResolver} from './linker/component_factory_resolver';
import {ComponentResolver} from './linker/component_resolver';
+import {NgModuleFactory, NgModuleRef} from './linker/ng_module_factory';
import {WtfScopeFn, wtfCreateScope, wtfLeave} from './profile/profile';
import {Testability, TestabilityRegistry} from './testability/testability';
import {NgZone, NgZoneError} from './zone/ng_zone';
-
-
-/**
- * Create an Angular zone.
- * @experimental
- */
-export function createNgZone(parent: NgZone): NgZone {
- // If an NgZone is already present in the parent injector,
- // use that one. Creating the NgZone in the same injector as the
- // application is dangerous as some services might get created before
- // the NgZone has been created.
- // We keep the NgZone factory in the application providers for
- // backwards compatibility for now though.
- if (parent) {
- return parent;
- }
- return new NgZone({enableLongStackTrace: isDevMode()});
-}
-
var _devMode: boolean = true;
var _runModeLocked: boolean = false;
var _platform: PlatformRef;
@@ -113,17 +94,30 @@ export function createPlatform(injector: Injector): PlatformRef {
return _platform;
}
+/**
+ * Factory for a platform.
+ *
+ * @experimental
+ */
+export type PlatformFactory = (extraProviders?: any[]) => PlatformRef;
+
/**
* Creates a fatory for a platform
*
* @experimental APIs related to application bootstrap are currently under review.
*/
-export function createPlatformFactory(name: string, providers: any[]): () => PlatformRef {
+export function createPlatformFactory(
+ parentPlaformFactory: PlatformFactory, name: string, providers: any[] = []): PlatformFactory {
const marker = new OpaqueToken(`Platform: ${name}`);
- return () => {
+ return (extraProviders: any[] = []) => {
if (!getPlatform()) {
- createPlatform(
- ReflectiveInjector.resolveAndCreate(providers.concat({provide: marker, useValue: true})));
+ if (parentPlaformFactory) {
+ parentPlaformFactory(
+ providers.concat(extraProviders).concat({provide: marker, useValue: true}));
+ } else {
+ createPlatform(ReflectiveInjector.resolveAndCreate(
+ providers.concat(extraProviders).concat({provide: marker, useValue: true})));
+ }
}
return assertPlatform(marker);
};
@@ -168,7 +162,7 @@ export function getPlatform(): PlatformRef {
}
/**
- * Creates an instance of an `@AppModule` for the given platform
+ * Creates an instance of an `@NgModule` for the given platform
* for offline compilation.
*
* ## Simple Example
@@ -176,8 +170,8 @@ export function getPlatform(): PlatformRef {
* ```typescript
* my_module.ts:
*
- * @AppModule({
- * modules: [BrowserModule]
+ * @NgModule({
+ * imports: [BrowserModule]
* })
* class MyModule {}
*
@@ -192,11 +186,11 @@ export function getPlatform(): PlatformRef {
* @experimental APIs related to application bootstrap are currently under review.
*/
export function bootstrapModuleFactory(
- moduleFactory: AppModuleFactory, platform: PlatformRef): AppModuleRef {
+ moduleFactory: NgModuleFactory