refactor(core): change module semantics

This contains major changes to the compiler, bootstrap of the platforms
and test environment initialization.

Main part of #10043
Closes #10164

BREAKING CHANGE:
- Semantics and name of `@AppModule` (now `@NgModule`) changed quite a bit.
  This is actually not breaking as `@AppModules` were not part of rc.4.
  We will have detailed docs on `@NgModule` separately.
- `coreLoadAndBootstrap` and `coreBootstrap` can't be used any more (without migration support).
  Use `bootstrapModule` / `bootstrapModuleFactory` instead.
- All Components listed in routes have to be part of the `declarations` of an NgModule.
  Either directly on the bootstrap module / lazy loaded module, or in an NgModule imported by them.
This commit is contained in:
Tobias Bosch 2016-07-18 03:50:31 -07:00
parent ca16fc29a6
commit 46b212706b
129 changed files with 3580 additions and 3366 deletions

View File

@ -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';
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 {
}

View File

@ -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 {
}

View File

@ -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(

View File

@ -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 {

View File

@ -8,10 +8,7 @@
import {Component} from '@angular/core';
@Component({
selector: 'my-comp',
template: '<div></div>',
})
@Component({selector: 'my-comp', template: '<div></div>', directives: [NextComp]})
export class MultipleComponentsMyComp {
}

View File

@ -1,4 +1,4 @@
<div [attr.array]="[0]" [attr.map]="{a:1}" title="translate me" i18n-title="meaning|desc">{{ctxProp}}</div>
<form><input type="button" [(ngModel)]="ctxProp"/></form>
<form><input type="button" [(ngModel)]="ctxProp" name="first"/></form>
<my-comp *ngIf="ctxBool"></my-comp>
<div *ngFor="let x of ctxArr" [attr.value]="x"></div>

View File

@ -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';

View File

@ -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);

View File

@ -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 {

View File

@ -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: `<div [someDir]="'someValue' | somePipe"></div>`})
export class SomeComp {
constructor() {}
@Pipe({name: 'somePipe'})
export class SomePipeInLibModule {
transform(value: string): any { return `transformed ${value}`; }
}
@Component({selector: 'parent', template: `<cmp></cmp>`, directives: [SomeComp]})
export class ParentComp {
@Component({selector: 'comp', template: `<div [someDir]="'someValue' | somePipe"></div>`})
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: `<div [someDir]="'someValue' | somePipe"></div>`})
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 {
}

View File

@ -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);
});
});

View File

@ -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);
});
});

View File

@ -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<M>(factory: AppModuleFactory<M>): AppModuleRef<M> {
return bootstrapModuleFactory(factory, serverPlatform());
export function createModule(): NgModuleRef<MainModule> {
return bootstrapModuleFactory(MainModuleNgFactory, serverPlatform());
}
export function createComponent<C>(
comp: {new (...args: any[]): C},
moduleFactory: AppModuleFactory<any> = null): ComponentFixture<C> {
if (!moduleFactory) {
moduleFactory = MainModuleNgFactory;
}
const moduleRef = createModule(moduleFactory);
export function createComponent<C>(comp: {new (...args: any[]): C}): ComponentFixture<C> {
const moduleRef = createModule();
const compRef =
moduleRef.componentFactoryResolver.resolveComponentFactory(comp).create(moduleRef.injector);
return new ComponentFixture(compRef, null, null);

View File

@ -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;
}, <StaticSymbol[]>[]);
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[];
}
ngModules: StaticSymbol[];
}

View File

@ -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;

View File

@ -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(<any>staticType);
directive = this._resolver.getDirectiveMetadata(<any>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, [], {});

View File

@ -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';
}
}

View File

@ -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';

View File

@ -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> = t.DebugAppView<T>;
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;

View File

@ -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;

View File

@ -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 <CompileIdentifierMetadata>unimplemented(); }
}
export abstract class CompileMetadataWithType extends CompileMetadataWithIdentifier {
abstract toJson(): {[key: string]: any};
get runtimeCacheKey(): any { return unimplemented(); }
get type(): CompileTypeMetadata { return <CompileTypeMetadata>unimplemented(); }
get assetCacheKey(): any { return unimplemented(); }
get identifier(): CompileIdentifierMetadata { return <CompileIdentifierMetadata>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(<CompileAnimationStyleMetadata[]>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 = <Array<string|{[key: string]: string | number}>>value['styles'];
return new CompileAnimationStyleMetadata(offset, styles);
}
constructor(
public offset: number, public styles: Array<string|{[key: string]: string | number}> = 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 = <string|number>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<VALUE> {
/**
* 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<KEY extends CompileMetadataWithIdentifier, VALUE> {
private _valueMap = new Map<any, VALUE>();
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<VALUE> {
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<VALUE> {
}
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<VALUE> {
/**
* 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 =
<CompileAnimationEntryMetadata[]>_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:
(<any[]>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<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
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<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
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<Type>();
pipesSet = new Set<Type>();
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<T extends CompileMetadataWithIdentifier>(items: T[]):
T[] {
const map = new CompileIdentifierMap<T, T>();
items.forEach((item) => {
if (!map.get(item)) {
map.add(item, item);
}
});
return map.keys();
}
function _normalizeArray(obj: any[]): any[] {

View File

@ -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<string>{
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<any|Type|{[k: string]: any}|any[]> =
/*@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<any|Type|{[k: string]: any}|any[]> =
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 = [<CompilerOptions>{
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<T>(...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<T>(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<T>(...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;

View File

@ -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 {

View File

@ -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(

View File

@ -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});

View File

@ -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<Type, cpl.CompileDirectiveMetadata>();
private _pipeCache = new Map<Type, cpl.CompilePipeMetadata>();
private _appModuleCache = new Map<Type, cpl.CompileAppModuleMetadata>();
private _ngModuleCache = new Map<Type, cpl.CompileNgModuleMetadata>();
private _ngModuleOfTypes = new Map<Type, Type>();
private _anonymousTypes = new Map<Object, number>();
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<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
@ -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<Type>()): 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<Type> = []): Array<Type> {
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<any> = []): Array<any> {
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;

View File

@ -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<o.Expression>();
private _instances = new CompileIdentifierMap<CompileTokenMetadata, o.Expression>();
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);
}

View File

@ -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;
}
}
}

View File

@ -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<string, StaticSymbol>();
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<StaticSymbol, CompileNgModuleMetadata>) {}
}
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, <any>precompileComp.runtime, result));
});
return result;
}
analyzeModules(ngModules: StaticSymbol[]): NgModulesSummary {
const ngModuleByComponent = new Map<StaticSymbol, CompileNgModuleMetadata>();
private _getTransitiveComponents(
appModule: StaticSymbol, component: StaticSymbol,
target: AppModulesSummary = new AppModulesSummary()): AppModulesSummary {
var compMeta = this._metadataResolver.getDirectiveMetadata(<any>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(<any>component).forEach((dirMeta) => {
this._getTransitiveComponents(appModule, <any>dirMeta.type.runtime);
ngModules.forEach((ngModule) => {
const ngModuleMeta = this._metadataResolver.getNgModuleMetadata(<any>ngModule);
ngModuleMeta.declaredDirectives.forEach((dirMeta) => {
if (dirMeta.isComponent) {
ngModuleByComponent.set(dirMeta.type.runtime, ngModuleMeta);
}
});
});
compMeta.precompile.forEach((precompileComp) => {
this._getTransitiveComponents(appModule, <any>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<SourceModule[]> {
moduleUrl: string, ngModulesSummary: NgModulesSummary, components: StaticSymbol[],
ngModules: StaticSymbol[]): Promise<SourceModule[]> {
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(<any>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(<any>compType), ...appModuleDirectives,
...this._metadataResolver.getViewDirectivesMetadata(<any>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(<any>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);

View File

@ -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;
}
}
}

View File

@ -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<CompileQueryMetadata[]>;
viewQueries: CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>;
/**
* @internal
*/
viewProviders: CompileTokenMap<boolean>;
viewProviders: CompileIdentifierMap<CompileTokenMetadata, boolean>;
errors: ProviderError[] = [];
constructor(public component: CompileDirectiveMetadata, public sourceSpan: ParseSourceSpan) {
this.viewQueries = _getViewQueries(component);
this.viewProviders = new CompileTokenMap<boolean>();
this.viewProviders = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
_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<CompileQueryMetadata[]>;
private _contentQueries: CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>;
private _transformedProviders = new CompileTokenMap<ProviderAst>();
private _seenProviders = new CompileTokenMap<boolean>();
private _allProviders: CompileTokenMap<ProviderAst>;
private _transformedProviders = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
private _seenProviders = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
private _allProviders: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>;
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<boolean>();
var queriedTokens = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
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<boolean>) {
private _addQueryReadsTo(
token: CompileTokenMetadata,
queryReadTokens: CompileIdentifierMap<CompileTokenMetadata, boolean>) {
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<ProviderAst>();
private _seenProviders = new CompileTokenMap<boolean>();
export class NgModuleProviderAnalyzer {
private _transformedProviders = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
private _seenProviders = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
private _unparsedProviders: any[] = [];
private _allProviders: CompileTokenMap<ProviderAst>;
private _allProviders: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>;
private _errors: ProviderError[] = [];
constructor(appModule: CompileAppModuleMetadata, sourceSpan: ParseSourceSpan) {
this._allProviders = new CompileTokenMap<ProviderAst>();
[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<CompileTokenMetadata, ProviderAst>();
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<ProviderAst> {
var providersByToken = new CompileTokenMap<ProviderAst>();
targetErrors: ParseError[]): CompileIdentifierMap<CompileTokenMetadata, ProviderAst> {
var providersByToken = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
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<ProviderAst>) {
targetProvidersByToken: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>) {
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<CompileQueryMetadata[]> {
var viewQueries = new CompileTokenMap<CompileQueryMetadata[]>();
CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]> {
var viewQueries = new CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>();
if (isPresent(component.viewQueries)) {
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, query));
}
@ -501,8 +507,8 @@ function _getViewQueries(component: CompileDirectiveMetadata):
}
function _getContentQueries(directives: CompileDirectiveMetadata[]):
CompileTokenMap<CompileQueryMetadata[]> {
var contentQueries = new CompileTokenMap<CompileQueryMetadata[]>();
CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]> {
var contentQueries = new CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>();
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<CompileQueryMetadata[]>, query: CompileQueryMetadata) {
map: CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>,
query: CompileQueryMetadata) {
query.selectors.forEach((token: CompileTokenMetadata) => {
var entry = map.get(token);
if (isBlank(entry)) {

View File

@ -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<Type, CompiledTemplate>();
private _compiledHostTemplateCache = new Map<Type, CompiledTemplate>();
private _compiledAppModuleCache = new Map<Type, AppModuleFactory<any>>();
private _warnOnComponentResolver = true;
private _compiledNgModuleCache = new Map<Type, NgModuleFactory<any>>();
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<ComponentFactory<any>> {
if (isString(component)) {
return PromiseWrapper.reject(
new BaseException(`Cannot resolve component using '${component}'.`), null);
compileModuleSync<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
return this._compileModuleAndComponents(moduleType, true).syncResult;
}
compileModuleAsync<T>(moduleType: ConcreteType<T>): Promise<NgModuleFactory<T>> {
return this._compileModuleAndComponents(moduleType, false).asyncResult;
}
compileComponentAsync<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
Promise<ComponentFactory<T>> {
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<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
ComponentFactory<T> {
if (!ngModule) {
throw new BaseException(
`Calling compileComponentSync on the root compiler without a module is not allowed! (Compiling component ${stringify(compType)})`);
}
return this.compileComponentAsync(<ConcreteType<any>>component);
return this._compileComponentInModule(compType, true, ngModule).syncResult;
}
compileAppModuleSync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
AppModuleFactory<T> {
return this._compileAppModule(moduleType, true, metadata).syncResult;
private _compileModuleAndComponents<T>(moduleType: ConcreteType<T>, isSync: boolean):
SyncAsyncResult<NgModuleFactory<T>> {
const componentPromise = this._compileComponents(moduleType, isSync);
const ngModuleFactory = this._compileModule(moduleType);
return new SyncAsyncResult(ngModuleFactory, componentPromise.then(() => ngModuleFactory));
}
compileAppModuleAsync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
Promise<AppModuleFactory<T>> {
return this._compileAppModule(moduleType, false, metadata).asyncResult;
}
private _compileAppModule<T>(
moduleType: ConcreteType<T>, isSync: boolean,
metadata: AppModuleMetadata = null): SyncAsyncResult<AppModuleFactory<T>> {
// 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<any>[] = [];
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<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
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 => <any>compileType.runtime),
compileModuleMeta.pipes.map(compileType => <any>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<T>(compType: ConcreteType<T>): Promise<ComponentFactory<T>> {
return this._compileComponent(compType, false, [], []).asyncResult;
}
private _compileComponentInModule<T>(
compType: ConcreteType<T>, isSync: boolean,
moduleType: ConcreteType<any>): SyncAsyncResult<ComponentFactory<T>> {
this._metadataResolver.addComponentToModule(moduleType, compType);
compileComponentSync<T>(compType: ConcreteType<T>): ComponentFactory<T> {
return this._compileComponent(compType, true, [], []).syncResult;
const componentPromise = this._compileComponents(moduleType, isSync);
const componentFactory: ComponentFactory<T> =
this._assertComponentKnown(compType, true).proxyComponentFactory;
return new SyncAsyncResult(componentFactory, componentPromise.then(() => componentFactory));
}
/**
* @internal
*/
_compileComponent<T>(
compType: ConcreteType<T>, isSync: boolean, moduleDirectives: ConcreteType<any>[],
modulePipes: ConcreteType<any>[]): SyncAsyncResult<ComponentFactory<T>> {
var templates =
this._getTransitiveCompiledTemplates(compType, true, moduleDirectives, modulePipes);
_compileComponents(mainModule: Type, isSync: boolean): Promise<any> {
const templates = new Set<CompiledTemplate>();
var loadingPromises: Promise<any>[] = [];
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<any>[],
modulePipes: ConcreteType<any>[]): 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<any>[],
modulePipes: ConcreteType<any>[],
target: Set<CompiledTemplate> = new Set<CompiledTemplate>()): Set<CompiledTemplate> {
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 = <ViewFactoryDependency>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 = <ComponentFactoryDependency>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, CompiledStylesheet>): 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<CompileDirectiveMetadata>) {
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<any>(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<any>,
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(<ConcreteType<any>>component);
}
compileComponentAsync<T>(compType: ConcreteType<T>): Promise<ComponentFactory<T>> {
return this._delegate._compileComponent(compType, false, this._directives, this._pipes)
.asyncResult;
compileComponentAsync<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
Promise<ComponentFactory<T>> {
return this._delegate.compileComponentAsync(compType, ngModule ? ngModule : this._ngModule);
}
compileComponentSync<T>(compType: ConcreteType<T>): ComponentFactory<T> {
return this._delegate._compileComponent(compType, true, this._directives, this._pipes)
.syncResult;
compileComponentSync<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
ComponentFactory<T> {
return this._delegate.compileComponentSync(compType, ngModule ? ngModule : this._ngModule);
}
compileAppModuleSync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
AppModuleFactory<T> {
return this._delegate.compileAppModuleSync(moduleType, metadata);
compileModuleSync<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
return this._delegate.compileModuleSync(moduleType);
}
compileAppModuleAsync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
Promise<AppModuleFactory<T>> {
return this._delegate.compileAppModuleAsync(moduleType, metadata);
compileModuleAsync<T>(moduleType: ConcreteType<T>): Promise<NgModuleFactory<T>> {
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); }
}
}

View File

@ -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 = <CompileDirectiveMetadata[]>removeDuplicates(directives);
const uniqPipes = <CompilePipeMetadata[]>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;
}

View File

@ -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<o.Expression>();
private _resolvedProviders: CompileTokenMap<ProviderAst>;
private _instances = new CompileIdentifierMap<CompileTokenMetadata, o.Expression>();
private _resolvedProviders: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>;
private _queryCount = 0;
private _queries = new CompileTokenMap<CompileQuery[]>();
private _queries = new CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>();
private _componentConstructorViewQueryLists: o.Expression[] = [];
public contentNodesByNgContentIndex: Array<o.Expression>[] = null;
@ -144,7 +144,7 @@ export class CompileElement extends CompileNode {
identifierToken(Identifiers.ViewContainerRef), this.appElement.prop('vcRef'));
}
this._resolvedProviders = new CompileTokenMap<ProviderAst>();
this._resolvedProviders = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
this._resolvedProvidersArray.forEach(
provider => this._resolvedProviders.add(provider.token, provider));

View File

@ -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<CompileQuery[]>, query: CompileQuery) {
export function addQueryToTokenMap(
map: CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>, query: CompileQuery) {
query.meta.selectors.forEach((selector) => {
var entry = map.get(selector);
if (isBlank(entry)) {

View File

@ -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<CompileQuery[]>;
public viewQueries: CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>;
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<CompileQuery[]>();
var viewQueries = new CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>();
if (this.viewType === ViewType.COMPONENT) {
var directiveInstance = o.THIS_EXPR.prop('context');
ListWrapper.forEachWithIndex(this.component.viewQueries, (queryMeta, queryIndex) => {

View File

@ -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;
}
}
}

View File

@ -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: '<a></a>',
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(<any>{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);
});
});
});
}

View File

@ -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));
}));
});
});
});
}

View File

@ -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 {
}

View File

@ -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)}'.`);
});
});
}

View File

@ -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<any>;
compiler
.compileAppModuleAsync(
SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]}))
.then((f) => appModuleFactory = f);
let ngModuleFactory: NgModuleFactory<any>;
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();
}));
});
});

View File

@ -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(

View File

@ -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
}]);

View File

@ -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);

View File

@ -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<Type, NgModuleMetadata>();
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;
}
}

View File

@ -87,14 +87,16 @@ export class OverridingTestComponentBuilder extends TestComponentBuilder {
return clone;
}
createAsync<T>(rootComponentType: ConcreteType<T>): Promise<ComponentFixture<T>> {
createAsync<T>(rootComponentType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
Promise<ComponentFixture<T>> {
this._applyMetadataOverrides();
return super.createAsync(rootComponentType);
return super.createAsync(rootComponentType, ngModule);
}
createSync<T>(rootComponentType: ConcreteType<T>): ComponentFixture<T> {
createSync<T>(rootComponentType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
ComponentFixture<T> {
this._applyMetadataOverrides();
return super.createSync(rootComponentType);
return super.createSync(rootComponentType, ngModule);
}
private _applyMetadataOverrides() {

View File

@ -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 */ = [];

View File

@ -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';

View File

@ -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<T> = view.DebugAppView<T>;
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,

View File

@ -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<Type|{[k: string]: any}|any[]> =
/*@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_},
];

View File

@ -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<Type|{[k: string]: any}|any[]> = [];
/**
* This module includes the providers of @angular/core that are needed
* to bootstrap components via `ApplicationRef`.
*
* @experimental
*/
@NgModule({
providers: [
{
provide: NgZone,
useFactory: createNgZone,
deps: <any>[[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 {
}

View File

@ -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<M>(
moduleFactory: AppModuleFactory<M>, platform: PlatformRef): AppModuleRef<M> {
moduleFactory: NgModuleFactory<M>, platform: PlatformRef): NgModuleRef<M> {
// Note: We need to create the NgZone _before_ we instantiate the module,
// as instantiating the module creates some providers eagerly.
// So we create a mini parent injector that just contains the new NgZone and
// pass that as parent to the AppModuleFactory.
// pass that as parent to the NgModuleFactory.
const ngZone = new NgZone({enableLongStackTrace: isDevMode()});
const ngZoneInjector =
ReflectiveInjector.resolveAndCreate([{provide: NgZone, useValue: ngZone}], platform.injector);
@ -204,13 +198,13 @@ export function bootstrapModuleFactory<M>(
}
/**
* Creates an instance of an `@AppModule` for a given platform using the given runtime compiler.
* Creates an instance of an `@NgModule` for a given platform using the given runtime compiler.
*
* ## Simple Example
*
* ```typescript
* @AppModule({
* modules: [BrowserModule]
* @NgModule({
* imports: [BrowserModule]
* })
* class MyModule {}
*
@ -220,10 +214,11 @@ export function bootstrapModuleFactory<M>(
*/
export function bootstrapModule<M>(
moduleType: ConcreteType<M>, platform: PlatformRef,
compilerOptions: CompilerOptions = {}): Promise<AppModuleRef<M>> {
compilerOptions: CompilerOptions | CompilerOptions[] = []): Promise<NgModuleRef<M>> {
const compilerFactory: CompilerFactory = platform.injector.get(CompilerFactory);
const compiler = compilerFactory.createCompiler(compilerOptions);
return compiler.compileAppModuleAsync(moduleType)
const compiler = compilerFactory.createCompiler(
compilerOptions instanceof Array ? compilerOptions : [compilerOptions]);
return compiler.compileModuleAsync(moduleType)
.then((moduleFactory) => bootstrapModuleFactory(moduleFactory, platform))
.then((moduleRef) => {
const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
@ -239,10 +234,7 @@ export function bootstrapModule<M>(
*/
export function coreBootstrap<C>(
componentFactory: ComponentFactory<C>, injector: Injector): ComponentRef<C> {
let console = injector.get(Console);
console.warn('coreBootstrap is deprecated. Use bootstrapModuleFactory instead.');
var appRef: ApplicationRef = injector.get(ApplicationRef);
return appRef.bootstrap(componentFactory);
throw new BaseException('coreBootstrap is deprecated. Use bootstrapModuleFactory instead.');
}
/**
@ -254,15 +246,7 @@ export function coreBootstrap<C>(
*/
export function coreLoadAndBootstrap(
componentType: Type, injector: Injector): Promise<ComponentRef<any>> {
let console = injector.get(Console);
console.warn('coreLoadAndBootstrap is deprecated. Use bootstrapModule instead.');
var appRef: ApplicationRef = injector.get(ApplicationRef);
return appRef.run(() => {
var componentResolver: ComponentResolver = injector.get(ComponentResolver);
return PromiseWrapper
.all([componentResolver.resolveComponent(componentType), appRef.waitForAsyncInitializers()])
.then((arr) => appRef.bootstrap(arr[0]));
});
throw new BaseException('coreLoadAndBootstrap is deprecated. Use bootstrapModule instead.');
}
/**
@ -592,20 +576,3 @@ export class ApplicationRef_ extends ApplicationRef {
get componentTypes(): Type[] { return this._rootComponentTypes; }
}
export const PLATFORM_CORE_PROVIDERS =
/*@ts2dart_const*/[
PlatformRef_,
/*@ts2dart_const*/ (
/* @ts2dart_Provider */ {provide: PlatformRef, useExisting: PlatformRef_})
];
export const APPLICATION_CORE_PROVIDERS = /*@ts2dart_const*/[
/* @ts2dart_Provider */ {
provide: NgZone,
useFactory: createNgZone,
deps: <any>[[new SkipSelfMetadata(), new OptionalMetadata(), NgZone]]
},
ApplicationRef_,
/* @ts2dart_Provider */ {provide: ApplicationRef, useExisting: ApplicationRef_},
];

View File

@ -7,8 +7,6 @@
*/
// Public API for compiler
export {AppModuleFactory, AppModuleRef} from './linker/app_module_factory';
export {AppModuleFactoryLoader} from './linker/app_module_factory_loader';
export {Compiler, CompilerFactory, CompilerOptions, ComponentStillLoadingError} from './linker/compiler';
export {ComponentFactory, ComponentRef} from './linker/component_factory';
export {ComponentFactoryResolver, NoComponentFactoryError} from './linker/component_factory_resolver';
@ -16,8 +14,10 @@ export {ComponentResolver} from './linker/component_resolver';
export {DynamicComponentLoader} from './linker/dynamic_component_loader';
export {ElementRef} from './linker/element_ref';
export {ExpressionChangedAfterItHasBeenCheckedException} from './linker/exceptions';
export {NgModuleFactory, NgModuleRef} from './linker/ng_module_factory';
export {NgModuleFactoryLoader} from './linker/ng_module_factory_loader';
export {QueryList} from './linker/query_list';
export {SystemJsAppModuleLoader} from './linker/system_js_app_module_factory_loader';
export {SystemJsNgModuleLoader} from './linker/system_js_ng_module_factory_loader';
export {SystemJsCmpFactoryResolver, SystemJsComponentResolver} from './linker/systemjs_component_resolver';
export {TemplateRef} from './linker/template_ref';
export {ViewContainerRef} from './linker/view_container_ref';

View File

@ -6,14 +6,15 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector} from '../di';
import {Injector, OpaqueToken} from '../di';
import {BaseException} from '../facade/exceptions';
import {ConcreteType, Type, stringify} from '../facade/lang';
import {ViewEncapsulation} from '../metadata';
import {AppModuleMetadata} from '../metadata/app_module';
import {NgModuleMetadata} from '../metadata/ng_module';
import {AppModuleFactory} from './app_module_factory';
import {ComponentFactory} from './component_factory';
import {ComponentResolver} from './component_resolver';
import {NgModuleFactory} from './ng_module_factory';
/**
@ -32,14 +33,16 @@ export class ComponentStillLoadingError extends BaseException {
* to create {@link ComponentFactory}s, which
* can later be used to create and render a Component instance.
*
* Each `@AppModule` provides an own `Compiler` to its injector,
* that will use the directives/pipes of the app module for compilation
* Each `@NgModule` provides an own `Compiler` to its injector,
* that will use the directives/pipes of the ng module for compilation
* of components.
* @stable
*/
export class Compiler {
/**
* Returns the injector with which the compiler has been created.
*
* @internal
*/
get injector(): Injector {
throw new BaseException(`Runtime compiler is not loaded. Tried to read the injector.`);
@ -48,7 +51,8 @@ export class Compiler {
/**
* Loads the template and styles of a component and returns the associated `ComponentFactory`.
*/
compileComponentAsync<T>(component: ConcreteType<T>): Promise<ComponentFactory<T>> {
compileComponentAsync<T>(component: ConcreteType<T>, ngModule: Type = null):
Promise<ComponentFactory<T>> {
throw new BaseException(
`Runtime compiler is not loaded. Tried to compile ${stringify(component)}`);
}
@ -56,23 +60,21 @@ export class Compiler {
* Compiles the given component. All templates have to be either inline or compiled via
* `compileComponentAsync` before. Otherwise throws a {@link ComponentStillLoadingError}.
*/
compileComponentSync<T>(component: ConcreteType<T>): ComponentFactory<T> {
compileComponentSync<T>(component: ConcreteType<T>, ngModule: Type = null): ComponentFactory<T> {
throw new BaseException(
`Runtime compiler is not loaded. Tried to compile ${stringify(component)}`);
}
/**
* Compiles the given App Module. All templates of the components listed in `precompile`
* Compiles the given NgModule. All templates of the components listed in `precompile`
* have to be either inline or compiled before via `compileComponentAsync` /
* `compileAppModuleAsync`. Otherwise throws a {@link ComponentStillLoadingError}.
* `compileModuleAsync`. Otherwise throws a {@link ComponentStillLoadingError}.
*/
compileAppModuleSync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
AppModuleFactory<T> {
compileModuleSync<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
throw new BaseException(
`Runtime compiler is not loaded. Tried to compile ${stringify(moduleType)}`);
}
compileAppModuleAsync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
Promise<AppModuleFactory<T>> {
compileModuleAsync<T>(moduleType: ConcreteType<T>): Promise<NgModuleFactory<T>> {
throw new BaseException(
`Runtime compiler is not loaded. Tried to compile ${stringify(moduleType)}`);
}
@ -83,7 +85,7 @@ export class Compiler {
clearCache(): void {}
/**
* Clears the cache for the given component/appModule.
* Clears the cache for the given component/ngModule.
*/
clearCacheFor(type: Type) {}
}
@ -98,8 +100,14 @@ export type CompilerOptions = {
useJit?: boolean,
defaultEncapsulation?: ViewEncapsulation,
providers?: any[],
deprecatedAppProviders?: any[]
}
};
/**
* Token to provide CompilerOptions in the platform injector.
*
* @experimental
*/
export const CompilerOptions = new OpaqueToken('compilerOptions');
/**
* A factory for creating a Compiler
@ -107,44 +115,5 @@ export type CompilerOptions = {
* @experimental
*/
export abstract class CompilerFactory {
static mergeOptions(defaultOptions: CompilerOptions = {}, newOptions: CompilerOptions = {}):
CompilerOptions {
return {
useDebug: _firstDefined(newOptions.useDebug, defaultOptions.useDebug),
useJit: _firstDefined(newOptions.useJit, defaultOptions.useJit),
defaultEncapsulation:
_firstDefined(newOptions.defaultEncapsulation, defaultOptions.defaultEncapsulation),
providers: _mergeArrays(defaultOptions.providers, newOptions.providers),
deprecatedAppProviders:
_mergeArrays(defaultOptions.deprecatedAppProviders, newOptions.deprecatedAppProviders)
};
}
withDefaults(options: CompilerOptions = {}): CompilerFactory {
return new _DefaultApplyingCompilerFactory(this, options);
}
abstract createCompiler(options?: CompilerOptions): Compiler;
}
class _DefaultApplyingCompilerFactory extends CompilerFactory {
constructor(private _delegate: CompilerFactory, private _options: CompilerOptions) { super(); }
createCompiler(options: CompilerOptions = {}): Compiler {
return this._delegate.createCompiler(CompilerFactory.mergeOptions(this._options, options));
}
}
function _firstDefined<T>(...args: T[]): T {
for (var i = 0; i < args.length; i++) {
if (args[i] !== undefined) {
return args[i];
}
}
return undefined;
}
function _mergeArrays(...parts: any[][]): any[] {
let result: any[] = [];
parts.forEach((part) => result.push.apply(result, part));
return result;
abstract createCompiler(options?: CompilerOptions[]): Compiler;
}

View File

@ -6,12 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Console} from '../console';
import {Injectable} from '../di/decorators';
import {PromiseWrapper} from '../facade/async';
import {BaseException} from '../facade/exceptions';
import {Type, isBlank, isString, stringify} from '../facade/lang';
import {reflector} from '../reflection/reflection';
import {Type} from '../facade/lang';
import {ComponentFactory} from './component_factory';
/**
@ -19,43 +14,17 @@ import {ComponentFactory} from './component_factory';
* can later be used to create and render a Component instance.
*
* @deprecated Use {@link ComponentFactoryResolver} together with {@link
* AppModule}.precompile}/{@link Component}.precompile or
* NgModule}.precompile}/{@link Component}.precompile or
* {@link ANALYZE_FOR_PRECOMPILE} provider for dynamic component creation.
* Use {@link AppModuleFactoryLoader} for lazy loading.
* Use {@link NgModuleFactoryLoader} for lazy loading.
*/
export abstract class ComponentResolver {
static DynamicCompilationDeprecationMsg =
'ComponentResolver is deprecated for dynamic compilation. Use ComponentFactoryResolver together with @AppModule/@Component.precompile or ANALYZE_FOR_PRECOMPILE provider instead.';
'ComponentResolver is deprecated for dynamic compilation. Use ComponentFactoryResolver together with @NgModule/@Component.precompile or ANALYZE_FOR_PRECOMPILE provider instead. For runtime compile only, you can also use Compiler.compileComponentSync/Async.';
static LazyLoadingDeprecationMsg =
'ComponentResolver is deprecated for lazy loading. Use AppModuleFactoryLoader instead.';
'ComponentResolver is deprecated for lazy loading. Use NgModuleFactoryLoader instead.';
abstract resolveComponent(component: Type|string): Promise<ComponentFactory<any>>;
abstract clearCache(): void;
}
function _isComponentFactory(type: any): boolean {
return type instanceof ComponentFactory;
}
@Injectable()
export class ReflectorComponentResolver extends ComponentResolver {
constructor(private _console: Console) { super(); }
resolveComponent(component: Type|string): Promise<ComponentFactory<any>> {
if (isString(component)) {
return PromiseWrapper.reject(
new BaseException(`Cannot resolve component using '${component}'.`), null);
}
this._console.warn(ComponentResolver.DynamicCompilationDeprecationMsg);
var metadatas = reflector.annotations(<Type>component);
var componentFactory = metadatas.find(_isComponentFactory);
if (isBlank(componentFactory)) {
throw new BaseException(`No precompiled component ${stringify(component)} found`);
}
return PromiseWrapper.resolve(componentFactory);
}
clearCache() {}
}

View File

@ -8,13 +8,15 @@
import {Injectable, Injector, ReflectiveInjector, ResolvedReflectiveProvider} from '../di';
import {Type, isPresent} from '../facade/lang';
import {Compiler} from './compiler';
import {ComponentRef} from './component_factory';
import {ComponentResolver} from './component_resolver';
import {ViewContainerRef} from './view_container_ref';
/**
* Use ComponentResolver and ViewContainerRef directly.
* Use ComponentFactoryResolver and ViewContainerRef directly.
*
* @deprecated
*/
@ -119,12 +121,12 @@ export abstract class DynamicComponentLoader {
@Injectable()
export class DynamicComponentLoader_ extends DynamicComponentLoader {
constructor(private _compiler: ComponentResolver) { super(); }
constructor(private _compiler: Compiler) { super(); }
loadAsRoot(
type: Type, overrideSelectorOrNode: string|any, injector: Injector, onDispose?: () => void,
projectableNodes?: any[][]): Promise<ComponentRef<any>> {
return this._compiler.resolveComponent(type).then(componentFactory => {
return this._compiler.compileComponentAsync(<any>type).then(componentFactory => {
var componentRef = componentFactory.create(
injector, projectableNodes,
isPresent(overrideSelectorOrNode) ? overrideSelectorOrNode : componentFactory.selector);
@ -138,7 +140,7 @@ export class DynamicComponentLoader_ extends DynamicComponentLoader {
loadNextToLocation(
type: Type, location: ViewContainerRef, providers: ResolvedReflectiveProvider[] = null,
projectableNodes: any[][] = null): Promise<ComponentRef<any>> {
return this._compiler.resolveComponent(type).then(componentFactory => {
return this._compiler.compileComponentAsync(<any>type).then(componentFactory => {
var contextInjector = location.parentInjector;
var childInjector = isPresent(providers) && providers.length > 0 ?
ReflectiveInjector.fromResolvedProviders(providers, contextInjector) :

View File

@ -14,15 +14,16 @@ import {CodegenComponentFactoryResolver, ComponentFactoryResolver} from './compo
/**
* Represents an instance of an AppModule created via a {@link AppModuleFactory}.
* Represents an instance of an NgModule created via a {@link NgModuleFactory}.
*
* `AppModuleRef` provides access to the AppModule Instance as well other objects related to this
* AppModule Instance.
* @stable
* `NgModuleRef` provides access to the NgModule Instance as well other objects related to this
* NgModule Instance.
*
* @experimental
*/
export abstract class AppModuleRef<T> {
export abstract class NgModuleRef<T> {
/**
* The injector that contains all of the providers of the AppModule.
* The injector that contains all of the providers of the NgModule.
*/
get injector(): Injector { return unimplemented(); }
@ -33,22 +34,22 @@ export abstract class AppModuleRef<T> {
get componentFactoryResolver(): ComponentFactoryResolver { return unimplemented(); }
/**
* The AppModule instance.
* The NgModule instance.
*/
get instance(): T { return unimplemented(); }
}
/**
* @stable
* @experimental
*/
export class AppModuleFactory<T> {
export class NgModuleFactory<T> {
constructor(
private _injectorClass: {new (parentInjector: Injector): AppModuleInjector<T>},
private _injectorClass: {new (parentInjector: Injector): NgModuleInjector<T>},
private _moduleype: ConcreteType<T>) {}
get moduleType(): ConcreteType<T> { return this._moduleype; }
create(parentInjector: Injector = null): AppModuleRef<T> {
create(parentInjector: Injector): NgModuleRef<T> {
if (!parentInjector) {
parentInjector = Injector.NULL;
}
@ -60,9 +61,9 @@ export class AppModuleFactory<T> {
const _UNDEFINED = new Object();
export abstract class AppModuleInjector<T> extends CodegenComponentFactoryResolver implements
export abstract class NgModuleInjector<T> extends CodegenComponentFactoryResolver implements
Injector,
AppModuleRef<T> {
NgModuleRef<T> {
public instance: T;
constructor(public parent: Injector, factories: ComponentFactory<any>[]) {

View File

@ -6,12 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AppModuleFactory} from './app_module_factory';
import {NgModuleFactory} from './ng_module_factory';
/**
* Used to load app moduled factories.
* Used to load ng moduled factories.
* @experimental
*/
export abstract class AppModuleFactoryLoader {
abstract load(path: string): Promise<AppModuleFactory<any>>;
}
export abstract class NgModuleFactoryLoader {
abstract load(path: string): Promise<NgModuleFactory<any>>;
}

View File

@ -10,9 +10,9 @@
import {Injectable, Optional} from '../di';
import {global} from '../facade/lang';
import {AppModuleFactory} from './app_module_factory';
import {AppModuleFactoryLoader} from './app_module_factory_loader';
import {Compiler} from './compiler';
import {NgModuleFactory} from './ng_module_factory';
import {NgModuleFactoryLoader} from './ng_module_factory_loader';
const _SEPARATOR = '#';
@ -20,18 +20,18 @@ const FACTORY_MODULE_SUFFIX = '.ngfactory';
const FACTORY_CLASS_SUFFIX = 'NgFactory';
/**
* AppModuleFactoryLoader that uses SystemJS to load AppModuleFactory
* NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
* @experimental
*/
@Injectable()
export class SystemJsAppModuleLoader implements AppModuleFactoryLoader {
export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
constructor(@Optional() private _compiler: Compiler) {}
load(path: string): Promise<AppModuleFactory<any>> {
load(path: string): Promise<NgModuleFactory<any>> {
return this._compiler ? this.loadAndCompile(path) : this.loadFactory(path);
}
private loadAndCompile(path: string): Promise<AppModuleFactory<any>> {
private loadAndCompile(path: string): Promise<NgModuleFactory<any>> {
let [module, exportName] = path.split(_SEPARATOR);
if (exportName === undefined) exportName = 'default';
@ -39,10 +39,10 @@ export class SystemJsAppModuleLoader implements AppModuleFactoryLoader {
.System.import(module)
.then((module: any) => module[exportName])
.then((type: any) => checkNotEmpty(type, module, exportName))
.then((type: any) => this._compiler.compileAppModuleAsync(type));
.then((type: any) => this._compiler.compileModuleAsync(type));
}
private loadFactory(path: string): Promise<AppModuleFactory<any>> {
private loadFactory(path: string): Promise<NgModuleFactory<any>> {
let [module, exportName] = path.split(_SEPARATOR);
if (exportName === undefined) exportName = 'default';
@ -58,4 +58,4 @@ function checkNotEmpty(value: any, modulePath: string, exportName: string): any
throw new Error(`Cannot find '${exportName}' in '${modulePath}'`);
}
return value;
}
}

View File

@ -18,9 +18,9 @@ const _SEPARATOR = '#';
/**
* Component resolver that can load components lazily
*
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsAppModuleLoader} to lazy
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsNgModuleLoader} to lazy
* load
* {@link AppModuleFactory}s instead.
* {@link NgModuleFactory}s instead.
*/
@Injectable()
export class SystemJsComponentResolver implements ComponentResolver {
@ -53,9 +53,9 @@ const FACTORY_CLASS_SUFFIX = 'NgFactory';
/**
* Component resolver that can load component factories lazily
*
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsAppModuleLoader}
* @deprecated Lazy loading of components is deprecated. Use {@link SystemJsNgModuleLoader}
* to lazy
* load {@link AppModuleFactory}s instead.
* load {@link NgModuleFactory}s instead.
*/
@Injectable()
export class SystemJsCmpFactoryResolver implements ComponentResolver {

View File

@ -14,15 +14,15 @@
import {ChangeDetectionStrategy} from '../src/change_detection/change_detection';
import {AnimationEntryMetadata} from './animation/metadata';
import {AppModuleMetadata} from './metadata/app_module';
import {AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
import {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
import {NgModuleMetadata} from './metadata/ng_module';
import {ViewEncapsulation, ViewMetadata} from './metadata/view';
export {AppModuleMetadata} from './metadata/app_module';
export {ANALYZE_FOR_PRECOMPILE, AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
export {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
export {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, DoCheck, OnChanges, OnDestroy, OnInit} from './metadata/lifecycle_hooks';
export {NgModuleMetadata} from './metadata/ng_module';
export {ViewEncapsulation, ViewMetadata} from './metadata/view';
import {makeDecorator, makeParamDecorator, makePropDecorator, TypeDecorator,} from './util/decorators';
@ -86,13 +86,13 @@ export interface ViewDecorator extends TypeDecorator {
}
/**
* Interface for the {@link AppModuleMetadata} decorator function.
* Interface for the {@link NgModuleMetadata} decorator function.
*
* See {@link AppModuleMetadataFactory}.
* See {@link NgModuleMetadataFactory}.
*
* @stable
*/
export interface AppModuleDecorator extends TypeDecorator {}
export interface NgModuleDecorator extends TypeDecorator {}
/**
@ -490,25 +490,25 @@ export interface HostListenerMetadataFactory {
}
/**
* {@link AppModuleMetadata} factory for creating annotations, decorators or DSL.
* {@link NgModuleMetadata} factory for creating annotations, decorators or DSL.
*
* @stable
* @experimental
*/
export interface AppModuleMetadataFactory {
(obj: {
export interface NgModuleMetadataFactory {
(obj?: {
providers?: any[],
directives?: Array<Type|any[]>,
pipes?: Array<Type|any[]>,
precompile?: Array<Type|any[]>,
modules?: Array<Type|any[]>,
}): AppModuleDecorator;
new (obj: {
declarations?: Array<Type|any[]>,
imports?: Array<Type|any[]>,
exports?: Array<Type|any[]>,
precompile?: Array<Type|any[]>
}): NgModuleDecorator;
new (obj?: {
providers?: any[],
directives?: Array<Type|any[]>,
pipes?: Array<Type|any[]>,
precompile?: Array<Type|any[]>,
modules?: Array<Type|any[]>,
}): AppModuleMetadata;
declarations?: Array<Type|any[]>,
imports?: Array<Type|any[]>,
exports?: Array<Type|any[]>,
precompile?: Array<Type|any[]>
}): NgModuleMetadata;
}
// TODO(alexeagle): remove the duplication of this doc. It is copied from ComponentMetadata.
@ -1537,9 +1537,9 @@ export var HostBinding: HostBindingMetadataFactory = makePropDecorator(HostBindi
export var HostListener: HostListenerMetadataFactory = makePropDecorator(HostListenerMetadata);
/**
* Declares an app module.
* @stable
* Declares an ng module.
* @experimental
* @Annotation
*/
export var AppModule: AppModuleMetadataFactory =
<AppModuleMetadataFactory>makeDecorator(AppModuleMetadata);
export var NgModule: NgModuleMetadataFactory =
<NgModuleMetadataFactory>makeDecorator(NgModuleMetadata);

View File

@ -13,13 +13,13 @@ import {StringWrapper, Type, isString, stringify} from '../facade/lang';
/**
* This token can be used to create a virtual provider that will populate the
* `precompile` fields of components and app modules based on its `useValue`.
* `precompile` fields of components and ng modules based on its `useValue`.
* All components that are referenced in the `useValue` value (either directly
* or in a nested array or map) will be added to the `precompile` property.
*
* ### Example
* The following example shows how the router can populate the `precompile`
* field of an AppModule based on the router configuration which refers
* field of an NgModule based on the router configuration which refers
* to components.
*
* ```typescript
@ -37,7 +37,7 @@ import {StringWrapper, Type, isString, stringify} from '../facade/lang';
* {path: /teams', component: TeamsComp}
* ];
*
* @AppModule({
* @NgModule({
* providers: [provideRoutes(routes)]
* })
* class ModuleWithRoutes {}

View File

@ -10,10 +10,10 @@ import {InjectableMetadata} from '../di/metadata';
import {Type} from '../facade/lang';
/**
* Declares an Application Module.
* @stable
* Declares an Angular Module.
* @experimental
*/
export class AppModuleMetadata extends InjectableMetadata {
export class NgModuleMetadata extends InjectableMetadata {
/**
* Defines the set of injectable objects that are available in the injector
* of this module.
@ -29,7 +29,7 @@ export class AppModuleMetadata extends InjectableMetadata {
* }
* }
*
* @AppModule({
* @NgModule({
* providers: [
* Greeter
* ]
@ -48,36 +48,52 @@ export class AppModuleMetadata extends InjectableMetadata {
/**
* Specifies a list of directives that can be used within the template
* of any component that is part of this application module.
* Specifies a list of directives/pipes that belong to this module.
*
* ### Example
*
* ```javascript
* @AppModule({
* directives: [NgFor]
* @NgModule({
* declarations: [NgFor]
* })
* class MyAppModule {
* class CommonModule {
* }
* ```
*/
directives: Array<Type|any[]>;
declarations: Array<Type|any[]>;
/**
* Specifies a list of pipes that can be used within the template
* of any component that is part of this application module.
* Specifies a list of modules whose exported directives/pipes
* should be available to templates in this module.
*
* ### Example
*
* ```javascript
* @AppModule({
* pipes: [SomePipe]
* @NgModule({
* imports: [CommonModule]
* })
* class MyAppModule {
* class MainModule {
* }
* ```
*/
pipes: Array<Type|any[]>;
imports: Array<Type|any[]>;
/**
* Specifies a list of directives/pipes/module that can be used within the template
* of any component that is part of an angular module
* that imports this angular module.
*
* ### Example
*
* ```javascript
* @NgModule({
* exports: [NgFor]
* })
* class CommonModule {
* }
* ```
*/
exports: Array<Type|any[]>;
/**
* Defines the components that should be precompiled as well when
@ -87,27 +103,18 @@ export class AppModuleMetadata extends InjectableMetadata {
*/
precompile: Array<Type|any[]>;
/**
* Defines modules that should be included into this module.
* The providers / directives / pipes / precompile entries will be added
* to this module.
* Just like the main module, the modules listed here are also eagerly
* created and accessible via DI.
*/
modules: Array<Type|any[]>;
constructor({providers, directives, pipes, precompile, modules}: {
constructor({providers, declarations, imports, exports, precompile}: {
providers?: any[],
directives?: Array<Type|any[]>,
pipes?: Array<Type|any[]>,
precompile?: Array<Type|any[]>,
modules?: Array<Type|any[]>
declarations?: Array<Type|any[]>,
imports?: Array<Type|any[]>,
exports?: Array<Type|any[]>,
precompile?: Array<Type|any[]>
} = {}) {
super();
this._providers = providers;
this.directives = directives;
this.pipes = pipes;
this.declarations = declarations;
this.imports = imports;
this.exports = exports;
this.precompile = precompile;
this.modules = modules;
}
}

View File

@ -8,7 +8,7 @@
import {Type} from '../src/facade/lang';
import {PLATFORM_CORE_PROVIDERS} from './application_ref';
import {PlatformRef, PlatformRef_, createPlatformFactory} from './application_ref';
import {Console} from './console';
import {Provider} from './di';
import {Reflector, reflector} from './reflection/reflection';
@ -21,13 +21,22 @@ function _reflector(): Reflector {
var __unused: Type; // prevent missing use Dart warning.
const _CORE_PLATFORM_PROVIDERS: Array<any|Type|Provider|any[]> = [
PlatformRef_, {provide: PlatformRef, useExisting: PlatformRef_},
{provide: Reflector, useFactory: _reflector, deps: []},
{provide: ReflectorReader, useExisting: Reflector}, TestabilityRegistry, Console
];
/**
* A default set of providers which should be included in any Angular platform.
* This platform has to be included in any other platform
*
* @experimental
*/
export const PLATFORM_COMMON_PROVIDERS: Array<any|Type|Provider|any[]> = /*@ts2dart_const*/[
PLATFORM_CORE_PROVIDERS,
/*@ts2dart_Provider*/ {provide: Reflector, useFactory: _reflector, deps: []},
/*@ts2dart_Provider*/ {provide: ReflectorReader, useExisting: Reflector}, TestabilityRegistry,
Console
];
export const corePlatform = createPlatformFactory(null, 'core', _CORE_PLATFORM_PROVIDERS);
/**
* A default set of providers which should be included in any Angular platform.
*
* @deprecated Create platforms via `createPlatformFactory(corePlatform, ...) instead!
*/
export const PLATFORM_COMMON_PROVIDERS = _CORE_PLATFORM_PROVIDERS;

View File

@ -34,7 +34,7 @@ import {OpaqueToken} from './di';
* ```
*
* @deprecated Providing platform directives via a provider is deprecated. Provide platform
* directives via an {@link AppModule} instead.
* directives via an {@link NgModule} instead.
*/
export const PLATFORM_DIRECTIVES: OpaqueToken =
/*@ts2dart_const*/ new OpaqueToken('Platform Directives');
@ -63,6 +63,6 @@ export const PLATFORM_DIRECTIVES: OpaqueToken =
* ```
*
* @deprecated Providing platform pipes via a provider is deprecated. Provide platform pipes via an
* {@link AppModule} instead.
* {@link NgModule} instead.
*/
export const PLATFORM_PIPES: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken('Platform Pipes');
export const PLATFORM_PIPES: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken('Platform Pipes');

View File

@ -8,8 +8,10 @@
import {AsyncTestCompleter, ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, inject,} from '@angular/core/testing/testing_internal';
import {SpyChangeDetectorRef} from './spies';
import {ApplicationRef_, ApplicationRef, PLATFORM_CORE_PROVIDERS, APPLICATION_CORE_PROVIDERS} from '@angular/core/src/application_ref';
import {Type, Injector, APP_INITIALIZER, Component, ReflectiveInjector, coreLoadAndBootstrap, PlatformRef, createPlatform, disposePlatform, ComponentResolver, ComponentFactoryResolver, ChangeDetectorRef} from '@angular/core';
import {ConcreteType} from '../src/facade/lang';
import {ApplicationRef_, ApplicationRef} from '@angular/core/src/application_ref';
import {Type, NgModule, CompilerFactory, Injector, APP_INITIALIZER, Component, ReflectiveInjector, bootstrapModule, bootstrapModuleFactory, PlatformRef, disposePlatform, createPlatformFactory, ComponentResolver, ComponentFactoryResolver, ChangeDetectorRef, ApplicationModule} from '@angular/core';
import {coreDynamicPlatform} from '@angular/compiler';
import {Console} from '@angular/core/src/console';
import {BaseException} from '../src/facade/exceptions';
import {PromiseWrapper, PromiseCompleter, TimerWrapper} from '../src/facade/async';
@ -18,36 +20,48 @@ import {ExceptionHandler} from '../src/facade/exception_handler';
export function main() {
describe('bootstrap', () => {
var platform: PlatformRef;
var defaultPlatform: PlatformRef;
var errorLogger: _ArrayLogger;
var someCompFactory: ComponentFactory<any>;
var appProviders: any[];
beforeEach(() => {
errorLogger = new _ArrayLogger();
disposePlatform();
platform = createPlatform(ReflectiveInjector.resolveAndCreate(PLATFORM_CORE_PROVIDERS));
defaultPlatform = createPlatformFactory(coreDynamicPlatform, 'test')();
someCompFactory =
new _MockComponentFactory(new _MockComponentRef(ReflectiveInjector.resolveAndCreate([])));
appProviders = [
{provide: Console, useValue: new _MockConsole()},
{provide: ExceptionHandler, useValue: new ExceptionHandler(errorLogger, false)},
{provide: ComponentResolver, useValue: new _MockComponentResolver(someCompFactory)}
];
});
afterEach(() => { disposePlatform(); });
function createApplication(providers: any[]): ApplicationRef_ {
var appInjector = ReflectiveInjector.resolveAndCreate(
[
APPLICATION_CORE_PROVIDERS, {provide: Console, useValue: new _MockConsole()},
{provide: ExceptionHandler, useValue: new ExceptionHandler(errorLogger, false)},
{provide: ComponentResolver, useValue: new _MockComponentResolver(someCompFactory)},
{provide: ComponentFactoryResolver, useValue: ComponentFactoryResolver.NULL}, providers
],
platform.injector);
function createModule(providers: any[] = []): ConcreteType<any> {
@NgModule({providers: [appProviders, providers], imports: [ApplicationModule]})
class MyModule {
}
return MyModule;
}
function createApplication(
providers: any[] = [], platform: PlatformRef = defaultPlatform): ApplicationRef_ {
const compilerFactory: CompilerFactory = platform.injector.get(CompilerFactory);
const compiler = compilerFactory.createCompiler();
const appInjector =
bootstrapModuleFactory(compiler.compileModuleSync(createModule(providers)), platform)
.injector;
return appInjector.get(ApplicationRef);
}
describe('ApplicationRef', () => {
it('should throw when reentering tick', () => {
var cdRef = <any>new SpyChangeDetectorRef();
var ref = createApplication([]);
var ref = createApplication();
try {
ref.registerChangeDetector(cdRef);
cdRef.spy('detectChanges').andCallFake(() => ref.tick());
@ -59,14 +73,14 @@ export function main() {
describe('run', () => {
it('should rethrow errors even if the exceptionHandler is not rethrowing', () => {
var ref = createApplication([]);
var ref = createApplication();
expect(() => ref.run(() => { throw new BaseException('Test'); })).toThrowError('Test');
});
it('should return a promise with rejected errors even if the exceptionHandler is not rethrowing',
inject(
[AsyncTestCompleter, Injector], (async: AsyncTestCompleter, injector: Injector) => {
var ref = createApplication([]);
var ref = createApplication();
var promise = ref.run(() => PromiseWrapper.reject('Test', null));
PromiseWrapper.catchError(promise, (e) => {
expect(e).toEqual('Test');
@ -76,7 +90,7 @@ export function main() {
});
});
describe('coreLoadAndBootstrap', () => {
describe('bootstrapModule', () => {
it('should wait for asynchronous app initializers',
inject([AsyncTestCompleter, Injector], (async: AsyncTestCompleter, injector: Injector) => {
let completer: PromiseCompleter<any> = PromiseWrapper.completer();
@ -85,16 +99,19 @@ export function main() {
completer.resolve(true);
initializerDone = true;
}, 1);
var app = createApplication(
[{provide: APP_INITIALIZER, useValue: () => completer.promise, multi: true}]);
coreLoadAndBootstrap(MyComp6, app.injector).then(_ => {
expect(initializerDone).toBe(true);
async.done();
});
bootstrapModule(
createModule(
[{provide: APP_INITIALIZER, useValue: () => completer.promise, multi: true}]),
defaultPlatform)
.then(_ => {
expect(initializerDone).toBe(true);
async.done();
});
}));
});
describe('coreBootstrap', () => {
describe('ApplicationRef.bootstrap', () => {
it('should throw if an APP_INITIIALIZER is not yet resolved',
inject([Injector], (injector: Injector) => {
var app = createApplication([{

View File

@ -87,14 +87,13 @@ export function main() {
expect(log.result()).toEqual('1; 2');
}));
// TODO(vicb): check why this doesn't work in JS - linked to open issues on GH ?
xit('should complain if the test throws an exception during async calls', () => {
it('should complain if the test throws an exception during async calls', () => {
expect(() => {
fakeAsync(() => {
PromiseWrapper.resolve(null).then((_) => { throw new BaseException('async'); });
flushMicrotasks();
})();
}).toThrowError('async');
}).toThrowError('Uncaught (in promise): async');
});
it('should complain if a test throws an exception', () => {

View File

@ -1,557 +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 {ANALYZE_FOR_PRECOMPILE, AppModule, AppModuleMetadata, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Directive, Host, Inject, Injectable, Injector, Input, OpaqueToken, Optional, Pipe, Provider, ReflectiveInjector, SelfMetadata, SkipSelf, SkipSelfMetadata, forwardRef, getDebugNode, provide} from '@angular/core';
import {ComponentFixture, configureCompiler} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers';
import {BaseException} from '../../src/facade/exceptions';
import {ConcreteType, IS_DART, Type, stringify} from '../../src/facade/lang';
class Engine {}
class BrokenEngine {
constructor() { throw new BaseException('Broken Engine'); }
}
class DashboardSoftware {}
@Injectable()
class Dashboard {
constructor(software: DashboardSoftware) {}
}
class TurboEngine extends Engine {}
@Injectable()
class Car {
engine: Engine;
constructor(engine: Engine) { this.engine = engine; }
}
@Injectable()
class CarWithOptionalEngine {
engine: Engine;
constructor(@Optional() engine: Engine) { this.engine = engine; }
}
@Injectable()
class CarWithDashboard {
engine: Engine;
dashboard: Dashboard;
constructor(engine: Engine, dashboard: Dashboard) {
this.engine = engine;
this.dashboard = dashboard;
}
}
@Injectable()
class SportsCar extends Car {
engine: Engine;
constructor(engine: Engine) { super(engine); }
}
@Injectable()
class CarWithInject {
engine: Engine;
constructor(@Inject(TurboEngine) engine: Engine) { this.engine = engine; }
}
@Injectable()
class CyclicEngine {
constructor(car: Car) {}
}
class NoAnnotations {
constructor(secretDependency: any) {}
}
function factoryFn(a: any) {}
@Injectable()
class SomeService {
}
@AppModule({})
class SomeModule {
}
@AppModule({providers: [{provide: 'someToken', useValue: 'someValue'}]})
class ModuleWithProvider {
}
@Component({selector: 'comp', template: ''})
class SomeComp {
}
@AppModule({precompile: [SomeComp]})
class ModuleWithPrecompile {
}
@AppModule({
providers:
[{provide: ANALYZE_FOR_PRECOMPILE, multi: true, useValue: [{a: 'b', component: SomeComp}]}]
})
class ModuleWithAnalyzePrecompileProvider {
}
@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
class SomeDirective {
@Input()
someDir: string;
}
@Pipe({name: 'somePipe'})
class SomePipe {
transform(value: string): any { return `transformed ${value}`; }
}
@Component({selector: 'comp', template: `<div [someDir]="'someValue' | somePipe"></div>`})
class CompUsingModuleDirectiveAndPipe {
}
@Component(
{selector: 'parent', template: `<comp></comp>`, directives: [CompUsingModuleDirectiveAndPipe]})
class ParentCompUsingModuleDirectiveAndPipe {
}
@AppModule(
{directives: [SomeDirective], pipes: [SomePipe], precompile: [CompUsingModuleDirectiveAndPipe]})
class ModuleWithDirectivesAndPipes {
}
export function main() {
if (IS_DART) {
declareTests({useJit: false});
} else {
describe('jit', () => { declareTests({useJit: true}); });
describe('no jit', () => { declareTests({useJit: false}); });
}
}
function declareTests({useJit}: {useJit: boolean}) {
describe('AppModule', () => {
var compiler: Compiler;
var injector: Injector;
beforeEach(() => { configureCompiler({useJit: useJit}); });
beforeEach(inject([Compiler, Injector], (_compiler: Compiler, _injector: Injector) => {
compiler = _compiler;
injector = _injector;
}));
describe('precompile', function() {
it('should resolve ComponentFactories', () => {
let appModule = compiler.compileAppModuleSync(ModuleWithPrecompile).create();
expect(appModule.componentFactoryResolver.resolveComponentFactory(SomeComp).componentType)
.toBe(SomeComp);
expect(appModule.injector.get(ComponentFactoryResolver)
.resolveComponentFactory(SomeComp)
.componentType)
.toBe(SomeComp);
});
it('should resolve ComponentFactories via ANALYZE_FOR_PRECOMPILE', () => {
let appModule = compiler.compileAppModuleSync(ModuleWithAnalyzePrecompileProvider).create();
expect(appModule.componentFactoryResolver.resolveComponentFactory(SomeComp).componentType)
.toBe(SomeComp);
expect(appModule.injector.get(ComponentFactoryResolver)
.resolveComponentFactory(SomeComp)
.componentType)
.toBe(SomeComp);
});
it('should resolve ComponentFactories for nested modules', () => {
let appModule =
compiler
.compileAppModuleSync(
SomeModule, new AppModuleMetadata({modules: [ModuleWithPrecompile]}))
.create();
expect(appModule.componentFactoryResolver.resolveComponentFactory(SomeComp).componentType)
.toBe(SomeComp);
expect(appModule.injector.get(ComponentFactoryResolver)
.resolveComponentFactory(SomeComp)
.componentType)
.toBe(SomeComp);
});
});
describe('directives and pipes', () => {
function createComp<T>(
compType: ConcreteType<T>, moduleType: ConcreteType<any>,
moduleMeta: AppModuleMetadata = null): ComponentFixture<T> {
let appModule = compiler.compileAppModuleSync(moduleType, moduleMeta).create();
var cf = appModule.componentFactoryResolver.resolveComponentFactory(compType);
return new ComponentFixture(cf.create(injector), null, false);
}
it('should support module directives and pipes', () => {
let compFixture = createComp(CompUsingModuleDirectiveAndPipe, ModuleWithDirectivesAndPipes);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
it('should support module directives and pipes for nested modules', () => {
let compFixture = createComp(
CompUsingModuleDirectiveAndPipe, SomeModule,
new AppModuleMetadata({modules: [ModuleWithDirectivesAndPipes]}));
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
it('should support module directives and pipes in nested components', () => {
let compFixture =
createComp(ParentCompUsingModuleDirectiveAndPipe, SomeModule, new AppModuleMetadata({
directives: [SomeDirective],
pipes: [SomePipe],
precompile: [ParentCompUsingModuleDirectiveAndPipe]
}));
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].children[0].properties['title'])
.toBe('transformed someValue');
});
it('should provide a Compiler instance that uses the directives/pipes of the module', () => {
let appModule = compiler.compileAppModuleSync(ModuleWithDirectivesAndPipes).create();
let boundCompiler: Compiler = appModule.injector.get(Compiler);
var cf = boundCompiler.compileComponentSync(CompUsingModuleDirectiveAndPipe);
let compFixture = new ComponentFixture(cf.create(injector), null, false);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
it('should provide a ComponentResolver instance that uses the directives/pipes of the module',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
let appModule = compiler.compileAppModuleSync(ModuleWithDirectivesAndPipes).create();
let boundCompiler: ComponentResolver = appModule.injector.get(ComponentResolver);
boundCompiler.resolveComponent(CompUsingModuleDirectiveAndPipe).then((cf) => {
let compFixture = new ComponentFixture(cf.create(injector), null, false);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
async.done();
});
}));
it('should provide a ComponentResolver instance that delegates to the parent ComponentResolver for strings',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
let parentResolver: any =
jasmine.createSpyObj('resolver', ['resolveComponent', 'clearCache']);
let appModule = compiler.compileAppModuleSync(ModuleWithDirectivesAndPipes)
.create(ReflectiveInjector.resolveAndCreate(
[{provide: ComponentResolver, useValue: parentResolver}]));
parentResolver.resolveComponent.and.returnValue(
Promise.resolve('someFactoryFromParent'));
let boundCompiler: ComponentResolver = appModule.injector.get(ComponentResolver);
boundCompiler.resolveComponent('someString').then((result) => {
expect(parentResolver.resolveComponent).toHaveBeenCalledWith('someString');
expect(result).toBe('someFactoryFromParent');
async.done();
});
}));
});
describe('providers', function() {
function createInjector(providers: any[], parent: Injector = null): Injector {
return compiler
.compileAppModuleSync(SomeModule, new AppModuleMetadata({providers: providers}))
.create(parent)
.injector;
}
it('should provide the module',
() => { expect(createInjector([]).get(SomeModule)).toBeAnInstanceOf(SomeModule); });
it('should instantiate a class without dependencies', () => {
var injector = createInjector([Engine]);
var engine = injector.get(Engine);
expect(engine).toBeAnInstanceOf(Engine);
});
it('should resolve dependencies based on type information', () => {
var injector = createInjector([Engine, Car]);
var car = injector.get(Car);
expect(car).toBeAnInstanceOf(Car);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should resolve dependencies based on @Inject annotation', () => {
var injector = createInjector([TurboEngine, Engine, CarWithInject]);
var car = injector.get(CarWithInject);
expect(car).toBeAnInstanceOf(CarWithInject);
expect(car.engine).toBeAnInstanceOf(TurboEngine);
});
it('should throw when no type and not @Inject (class case)', () => {
expect(() => createInjector([NoAnnotations]))
.toThrowError('Can\'t resolve all parameters for NoAnnotations: (?).');
});
it('should throw when no type and not @Inject (factory case)', () => {
expect(() => createInjector([provide('someToken', {useFactory: factoryFn})]))
.toThrowError('Can\'t resolve all parameters for factoryFn: (?).');
});
it('should cache instances', () => {
var injector = createInjector([Engine]);
var e1 = injector.get(Engine);
var e2 = injector.get(Engine);
expect(e1).toBe(e2);
});
it('should provide to a value', () => {
var injector = createInjector([provide(Engine, {useValue: 'fake engine'})]);
var engine = injector.get(Engine);
expect(engine).toEqual('fake engine');
});
it('should provide to a factory', () => {
function sportsCarFactory(e: Engine) { return new SportsCar(e); }
var injector =
createInjector([Engine, provide(Car, {useFactory: sportsCarFactory, deps: [Engine]})]);
var car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should supporting provider to null', () => {
var injector = createInjector([provide(Engine, {useValue: null})]);
var engine = injector.get(Engine);
expect(engine).toBeNull();
});
it('should provide to an alias', () => {
var injector = createInjector([
Engine, provide(SportsCar, {useClass: SportsCar}),
provide(Car, {useExisting: SportsCar})
]);
var car = injector.get(Car);
var sportsCar = injector.get(SportsCar);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car).toBe(sportsCar);
});
it('should support multiProviders', () => {
var injector = createInjector([
Engine, provide(Car, {useClass: SportsCar, multi: true}),
provide(Car, {useClass: CarWithOptionalEngine, multi: true})
]);
var cars = injector.get(Car);
expect(cars.length).toEqual(2);
expect(cars[0]).toBeAnInstanceOf(SportsCar);
expect(cars[1]).toBeAnInstanceOf(CarWithOptionalEngine);
});
it('should support multiProviders that are created using useExisting', () => {
var injector = createInjector(
[Engine, SportsCar, provide(Car, {useExisting: SportsCar, multi: true})]);
var cars = injector.get(Car);
expect(cars.length).toEqual(1);
expect(cars[0]).toBe(injector.get(SportsCar));
});
it('should throw when the aliased provider does not exist', () => {
var injector = createInjector([provide('car', {useExisting: SportsCar})]);
var e = `No provider for ${stringify(SportsCar)}!`;
expect(() => injector.get('car')).toThrowError(e);
});
it('should handle forwardRef in useExisting', () => {
var injector = createInjector([
provide('originalEngine', {useClass: forwardRef(() => Engine)}),
provide('aliasedEngine', {useExisting: <any>forwardRef(() => 'originalEngine')})
]);
expect(injector.get('aliasedEngine')).toBeAnInstanceOf(Engine);
});
it('should support overriding factory dependencies', () => {
var injector = createInjector(
[Engine, provide(Car, {useFactory: (e: Engine) => new SportsCar(e), deps: [Engine]})]);
var car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should support optional dependencies', () => {
var injector = createInjector([CarWithOptionalEngine]);
var car = injector.get(CarWithOptionalEngine);
expect(car.engine).toEqual(null);
});
it('should flatten passed-in providers', () => {
var injector = createInjector([[[Engine, Car]]]);
var car = injector.get(Car);
expect(car).toBeAnInstanceOf(Car);
});
it('should use the last provider when there are multiple providers for same token', () => {
var injector = createInjector(
[provide(Engine, {useClass: Engine}), provide(Engine, {useClass: TurboEngine})]);
expect(injector.get(Engine)).toBeAnInstanceOf(TurboEngine);
});
it('should use non-type tokens', () => {
var injector = createInjector([provide('token', {useValue: 'value'})]);
expect(injector.get('token')).toEqual('value');
});
it('should throw when given invalid providers', () => {
expect(() => createInjector(<any>['blah']))
.toThrowError(
'Invalid provider - only instances of Provider and Type are allowed, got: blah');
});
it('should provide itself', () => {
var parent = createInjector([]);
var child = createInjector([], parent);
expect(child.get(Injector)).toBe(child);
});
it('should throw when no provider defined', () => {
var injector = createInjector([]);
expect(() => injector.get('NonExisting')).toThrowError('No provider for NonExisting!');
});
it('should throw when trying to instantiate a cyclic dependency', () => {
expect(() => createInjector([Car, provide(Engine, {useClass: CyclicEngine})]))
.toThrowError(/Cannot instantiate cyclic dependency! Car/g);
});
it('should support null values', () => {
var injector = createInjector([provide('null', {useValue: null})]);
expect(injector.get('null')).toBe(null);
});
describe('child', () => {
it('should load instances from parent injector', () => {
var parent = createInjector([Engine]);
var child = createInjector([], parent);
var engineFromParent = parent.get(Engine);
var engineFromChild = child.get(Engine);
expect(engineFromChild).toBe(engineFromParent);
});
it('should not use the child providers when resolving the dependencies of a parent provider',
() => {
var parent = createInjector([Car, Engine]);
var child = createInjector([provide(Engine, {useClass: TurboEngine})], parent);
var carFromChild = child.get(Car);
expect(carFromChild.engine).toBeAnInstanceOf(Engine);
});
it('should create new instance in a child injector', () => {
var parent = createInjector([Engine]);
var child = createInjector([provide(Engine, {useClass: TurboEngine})], parent);
var engineFromParent = parent.get(Engine);
var engineFromChild = child.get(Engine);
expect(engineFromParent).not.toBe(engineFromChild);
expect(engineFromChild).toBeAnInstanceOf(TurboEngine);
});
});
describe('depedency resolution', () => {
describe('@Self()', () => {
it('should return a dependency from self', () => {
var inj = createInjector([
Engine,
provide(
Car,
{useFactory: (e: Engine) => new Car(e), deps: [[Engine, new SelfMetadata()]]})
]);
expect(inj.get(Car)).toBeAnInstanceOf(Car);
});
it('should throw when not requested provider on self', () => {
expect(() => createInjector([provide(Car, {
useFactory: (e: Engine) => new Car(e),
deps: [[Engine, new SelfMetadata()]]
})]))
.toThrowError(/No provider for Engine/g);
});
});
describe('default', () => {
it('should not skip self', () => {
var parent = createInjector([Engine]);
var child = createInjector(
[
provide(Engine, {useClass: TurboEngine}),
provide(Car, {useFactory: (e: Engine) => new Car(e), deps: [Engine]})
],
parent);
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
});
});
});
describe('nested modules', () => {
it('should merge the providers of nested modules', () => {
var injector =
compiler
.compileAppModuleSync(SomeModule, new AppModuleMetadata({
providers: [{provide: 'a', useValue: 'aValue'}],
modules: [ModuleWithProvider]
}))
.create()
.injector;
expect(injector.get(SomeModule)).toBeAnInstanceOf(SomeModule);
expect(injector.get(ModuleWithProvider)).toBeAnInstanceOf(ModuleWithProvider);
expect(injector.get('a')).toBe('aValue');
expect(injector.get('someToken')).toBe('someValue');
});
it('should override the providers of nested modules', () => {
var injector = compiler
.compileAppModuleSync(
SomeModule, new AppModuleMetadata({
providers: [{provide: 'someToken', useValue: 'someNewValue'}],
modules: [ModuleWithProvider]
}))
.create()
.injector;
expect(injector.get('someToken')).toBe('someNewValue');
});
});
});
});
}

View File

@ -1775,17 +1775,6 @@ function declareTests({useJit}: {useJit: boolean}) {
});
describe('logging property updates', () => {
beforeEach(() => {
configureCompiler({
providers: [{
provide: CompilerConfig,
// Note: we are testing the `genDebugInfo` flag here, so we
// need to set it explicitely!
useValue: new CompilerConfig({genDebugInfo: true, useJit: useJit})
}]
});
});
it('should reflect property values as attributes',
inject(
[TestComponentBuilder, AsyncTestCompleter],

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,9 @@
*/
import {AsyncTestCompleter, beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder} from '@angular/core/testing';
import {Component, ComponentFactoryResolver, NoComponentFactoryError, forwardRef, ANALYZE_FOR_PRECOMPILE} from '@angular/core';
import {TestComponentBuilder, configureModule} from '@angular/core/testing';
import {Component, ComponentFactoryResolver, NoComponentFactoryError, forwardRef, ANALYZE_FOR_PRECOMPILE, ViewMetadata} from '@angular/core';
import {stringify} from '../../src/facade/lang';
export function main() {
describe('jit', () => { declareTests({useJit: true}); });
@ -17,19 +18,33 @@ export function main() {
function declareTests({useJit}: {useJit: boolean}) {
describe('@Component.precompile', function() {
beforeEach(() => { configureModule({declarations: [MainComp, ChildComp, NestedChildComp]}); });
it('should error if the component was not declared nor imported by the module',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
@Component({selector: 'child', template: ''})
class ChildComp {
}
@Component({template: 'comp', precompile: [ChildComp]})
class SomeComp {
}
expect(() => tcb.createSync(SomeComp))
.toThrowError(
`Component ${stringify(SomeComp)} in NgModule DynamicTestModule uses ${stringify(ChildComp)} via "precompile" but it was neither declared nor imported into the module!`);
}));
it('should resolve ComponentFactories from the same component',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.createAsync(MainComp).then((compFixture) => {
let mainComp: MainComp = compFixture.componentInstance;
expect(compFixture.debugElement.injector.get(ComponentFactoryResolver))
.toBe(mainComp.cfr);
var cf = mainComp.cfr.resolveComponentFactory(ChildComp);
expect(cf.componentType).toBe(ChildComp);
async.done();
});
}));
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
const compFixture = tcb.createSync(MainComp);
let mainComp: MainComp = compFixture.componentInstance;
expect(compFixture.componentRef.injector.get(ComponentFactoryResolver)).toBe(mainComp.cfr);
var cf = mainComp.cfr.resolveComponentFactory(ChildComp);
expect(cf.componentType).toBe(ChildComp);
}));
it('should resolve ComponentFactories via ANALYZE_FOR_PRECOMPILE',
@ -37,63 +52,52 @@ function declareTests({useJit}: {useJit: boolean}) {
let compFixture = tcb.createSync(CompWithAnalyzePrecompileProvider);
let mainComp: CompWithAnalyzePrecompileProvider = compFixture.componentInstance;
let cfr: ComponentFactoryResolver =
compFixture.debugElement.injector.get(ComponentFactoryResolver);
compFixture.componentRef.injector.get(ComponentFactoryResolver);
expect(cfr.resolveComponentFactory(ChildComp).componentType).toBe(ChildComp);
expect(cfr.resolveComponentFactory(NestedChildComp).componentType).toBe(NestedChildComp);
}));
it('should be able to get a component form a parent component (view hiearchy)',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(MainComp, '<child></child>')
.createAsync(MainComp)
.then((compFixture) => {
let childCompEl = compFixture.debugElement.children[0];
let childComp: ChildComp = childCompEl.componentInstance;
// declared on ChildComp directly
expect(childComp.cfr.resolveComponentFactory(NestedChildComp).componentType)
.toBe(NestedChildComp);
// inherited from MainComp
expect(childComp.cfr.resolveComponentFactory(ChildComp).componentType)
.toBe(ChildComp);
async.done();
});
}));
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
const compFixture =
tcb.overrideView(
MainComp,
new ViewMetadata({template: '<child></child>', directives: [ChildComp]}))
.createSync(MainComp);
let childCompEl = compFixture.debugElement.children[0];
let childComp: ChildComp = childCompEl.componentInstance;
// declared on ChildComp directly
expect(childComp.cfr.resolveComponentFactory(NestedChildComp).componentType)
.toBe(NestedChildComp);
// inherited from MainComp
expect(childComp.cfr.resolveComponentFactory(ChildComp).componentType).toBe(ChildComp);
}));
it('should not be able to get components from a parent component (content hierarchy)',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(MainComp, '<child><nested></nested></child>')
.overrideTemplate(ChildComp, '<ng-content></ng-content>')
.createAsync(MainComp)
.then((compFixture) => {
let nestedChildCompEl = compFixture.debugElement.children[0].children[0];
let nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp).componentType)
.toBe(ChildComp);
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
.toThrow(new NoComponentFactoryError(NestedChildComp));
async.done();
});
}));
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
const compFixture = tcb.overrideView(MainComp, new ViewMetadata({
template: '<child><nested></nested></child>',
directives: [ChildComp, NestedChildComp]
}))
.overrideTemplate(ChildComp, '<ng-content></ng-content>')
.createSync(MainComp);
let nestedChildCompEl = compFixture.debugElement.children[0].children[0];
let nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp).componentType)
.toBe(ChildComp);
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
.toThrow(new NoComponentFactoryError(NestedChildComp));
}));
});
}
var DIRECTIVES: any[] = [
forwardRef(() => NestedChildComp),
forwardRef(() => ChildComp),
forwardRef(() => MainComp),
];
@Component({selector: 'nested', directives: DIRECTIVES, template: ''})
@Component({selector: 'nested', template: ''})
class NestedChildComp {
constructor(public cfr: ComponentFactoryResolver) {}
}
@Component({selector: 'child', precompile: [NestedChildComp], directives: DIRECTIVES, template: ''})
@Component({selector: 'child', precompile: [NestedChildComp], template: ''})
class ChildComp {
constructor(public cfr: ComponentFactoryResolver) {}
}
@ -101,7 +105,6 @@ class ChildComp {
@Component({
selector: 'main',
precompile: [ChildComp],
directives: DIRECTIVES,
template: '',
})
class MainComp {

View File

@ -1,50 +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 {ComponentFactory} from '@angular/core/src/linker/component_factory';
import {ComponentResolver, ReflectorComponentResolver} from '@angular/core/src/linker/component_resolver';
import {ReflectionInfo, reflector} from '@angular/core/src/reflection/reflection';
import {AsyncTestCompleter, afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {Console} from '../../src/console';
class DummyConsole implements Console {
log(message: string) {}
warn(message: string) {}
}
export function main() {
describe('Compiler', () => {
var someCompFactory: any /** TODO #9100 */;
var compiler: ComponentResolver;
beforeEach(() => {
someCompFactory = new ComponentFactory(null, null, null);
reflector.registerType(SomeComponent, new ReflectionInfo([someCompFactory]));
compiler = new ReflectorComponentResolver(new DummyConsole());
});
it('should read the template from an annotation',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
compiler.resolveComponent(SomeComponent).then((compFactory: ComponentFactory<any>) => {
expect(compFactory).toBe(someCompFactory);
async.done();
return null;
});
}));
it('should throw when given a string',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
compiler.resolveComponent('someString').catch((e) => {
expect(e.message).toContain('Cannot resolve component using \'someString\'.');
async.done();
});
}));
});
}
class SomeComponent {}

View File

@ -26,7 +26,7 @@ function declareTests({useJit}: {useJit: boolean}) {
describe('platform pipes', () => {
beforeEach(() => {
configureCompiler({useJit: useJit});
configureModule({pipes: [PlatformPipe]});
configureModule({declarations: [PlatformPipe]});
});
it('should overwrite them by custom pipes',

View File

@ -6,10 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AppModule, AppModuleFactory, AppModuleMetadata, AppModuleRef, Compiler, CompilerFactory, ComponentStillLoadingError, Injector, PlatformRef, Provider, ReflectiveInjector, Type, assertPlatform, createPlatform, getPlatform} from '../index';
import {Compiler, CompilerFactory, CompilerOptions, ComponentStillLoadingError, Injector, NgModule, NgModuleFactory, NgModuleMetadata, NgModuleRef, PlatformRef, Provider, ReflectiveInjector, Type, assertPlatform, createPlatform, getPlatform} from '../index';
import {ListWrapper} from '../src/facade/collection';
import {BaseException} from '../src/facade/exceptions';
import {FunctionWrapper, isPresent, stringify} from '../src/facade/lang';
import {ConcreteType, FunctionWrapper, isPresent, stringify} from '../src/facade/lang';
import {AsyncTestCompleter} from './async_test_completer';
@ -22,105 +22,87 @@ export class TestBed implements Injector {
private _instantiated: boolean = false;
private _compiler: Compiler = null;
private _moduleRef: AppModuleRef<any> = null;
private _appModuleFactory: AppModuleFactory<any> = null;
private _moduleRef: NgModuleRef<any> = null;
private _ngModuleFactory: NgModuleFactory<any> = null;
private _compilerProviders: Array<Type|Provider|any[]|any> = [];
private _compilerUseJit: boolean = true;
private _compilerOptions: CompilerOptions[] = [];
private _providers: Array<Type|Provider|any[]|any> = [];
private _directives: Array<Type|any[]|any> = [];
private _pipes: Array<Type|any[]|any> = [];
private _modules: Array<Type|any[]|any> = [];
private _declarations: Array<Type|any[]|any> = [];
private _imports: Array<Type|any[]|any> = [];
private _precompile: Array<Type|any[]|any> = [];
reset() {
this._compiler = null;
this._moduleRef = null;
this._appModuleFactory = null;
this._compilerProviders = [];
this._compilerUseJit = true;
this._ngModuleFactory = null;
this._compilerOptions = [];
this._providers = [];
this._directives = [];
this._pipes = [];
this._modules = [];
this._declarations = [];
this._imports = [];
this._precompile = [];
this._instantiated = false;
}
platform: PlatformRef = null;
appModule: Type = null;
ngModule: Type = null;
configureCompiler(config: {providers?: any[], useJit?: boolean}) {
if (this._instantiated) {
throw new BaseException('Cannot add configuration after test injector is instantiated');
}
if (config.providers) {
this._compilerProviders = ListWrapper.concat(this._compilerProviders, config.providers);
}
if (config.useJit !== undefined) {
this._compilerUseJit = config.useJit;
}
this._compilerOptions.push(config);
}
configureModule(moduleDef: {
providers?: any[],
directives?: any[],
pipes?: any[],
precompile?: any[],
modules?: any[]
}) {
configureModule(
moduleDef: {providers?: any[], declarations?: any[], imports?: any[], precompile?: any[]}) {
if (this._instantiated) {
throw new BaseException('Cannot add configuration after test injector is instantiated');
}
if (moduleDef.providers) {
this._providers = ListWrapper.concat(this._providers, moduleDef.providers);
}
if (moduleDef.directives) {
this._directives = ListWrapper.concat(this._directives, moduleDef.directives);
if (moduleDef.declarations) {
this._declarations = ListWrapper.concat(this._declarations, moduleDef.declarations);
}
if (moduleDef.pipes) {
this._pipes = ListWrapper.concat(this._pipes, moduleDef.pipes);
if (moduleDef.imports) {
this._imports = ListWrapper.concat(this._imports, moduleDef.imports);
}
if (moduleDef.precompile) {
this._precompile = ListWrapper.concat(this._precompile, moduleDef.precompile);
}
if (moduleDef.modules) {
this._modules = ListWrapper.concat(this._modules, moduleDef.modules);
}
}
createAppModuleFactory(): Promise<AppModuleFactory<any>> {
createModuleFactory(): Promise<NgModuleFactory<any>> {
if (this._instantiated) {
throw new BaseException(
'Cannot run precompilation when the test AppModule has already been instantiated. ' +
'Cannot run precompilation when the test NgModule has already been instantiated. ' +
'Make sure you are not using `inject` before `doAsyncPrecompilation`.');
}
if (this._appModuleFactory) {
return Promise.resolve(this._appModuleFactory);
if (this._ngModuleFactory) {
return Promise.resolve(this._ngModuleFactory);
}
let moduleMeta = this._createCompilerAndModuleMeta();
const moduleType = this._createCompilerAndModule();
return this._compiler.compileAppModuleAsync(_NoopModule, moduleMeta)
.then((appModuleFactory) => {
this._appModuleFactory = appModuleFactory;
return appModuleFactory;
});
return this._compiler.compileModuleAsync(moduleType).then((ngModuleFactory) => {
this._ngModuleFactory = ngModuleFactory;
return ngModuleFactory;
});
}
initTestAppModule() {
initTestModule() {
if (this._instantiated) {
return;
}
if (this._appModuleFactory) {
this._createFromModuleFactory(this._appModuleFactory);
if (this._ngModuleFactory) {
this._createFromModuleFactory(this._ngModuleFactory);
} else {
let moduleMeta = this._createCompilerAndModuleMeta();
this._createFromModuleFactory(this._compiler.compileAppModuleSync(_NoopModule, moduleMeta));
let moduleType = this._createCompilerAndModule();
this._createFromModuleFactory(this._compiler.compileModuleSync(moduleType));
}
}
@ -131,31 +113,34 @@ export class TestBed implements Injector {
if (this._instantiated) {
return Promise.resolve(this);
}
let moduleMeta = this._createCompilerAndModuleMeta();
return this._compiler.compileAppModuleAsync(_NoopModule, moduleMeta)
.then((appModuleFactory) => this._createFromModuleFactory(appModuleFactory));
let ngModule = this._createCompilerAndModule();
return this._compiler.compileModuleAsync(ngModule).then(
(ngModuleFactory) => this._createFromModuleFactory(ngModuleFactory));
}
private _createCompilerAndModuleMeta(): AppModuleMetadata {
private _createCompilerAndModule(): ConcreteType<any> {
const providers = this._providers.concat([{provide: TestBed, useValue: this}]);
const declarations = this._declarations;
const imports = [this.ngModule, this._imports];
const precompile = this._precompile;
@NgModule({
providers: providers,
declarations: declarations,
imports: imports,
precompile: precompile
})
class DynamicTestModule {
}
const compilerFactory: CompilerFactory = this.platform.injector.get(CompilerFactory);
this._compiler = compilerFactory.createCompiler({
providers: this._compilerProviders,
useJit: this._compilerUseJit,
deprecatedAppProviders: this._providers
});
const moduleMeta = new AppModuleMetadata({
providers: this._providers.concat([{provide: TestBed, useValue: this}]),
modules: this._modules.concat([this.appModule]),
directives: this._directives,
pipes: this._pipes,
precompile: this._precompile
});
return moduleMeta;
this._compiler =
compilerFactory.createCompiler(this._compilerOptions.concat([{useDebug: true}]));
return DynamicTestModule;
}
private _createFromModuleFactory(appModuleFactory: AppModuleFactory<any>): Injector {
this._moduleRef = appModuleFactory.create(this.platform.injector);
private _createFromModuleFactory(ngModuleFactory: NgModuleFactory<any>): Injector {
this._moduleRef = ngModuleFactory.create(this.platform.injector);
this._instantiated = true;
return this;
}
@ -163,13 +148,13 @@ export class TestBed implements Injector {
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND) {
if (!this._instantiated) {
throw new BaseException(
'Illegal state: The test bed\'s injector has not yet been created. Call initTestAppModule first!');
'Illegal state: The test bed\'s injector has not yet been created. Call initTestNgModule first!');
}
if (token === TestBed) {
return this;
}
// Tests can inject things from the app module and from the compiler,
// but the app module can't inject things from the compiler and vice versa.
// Tests can inject things from the ng module and from the compiler,
// but the ng module can't inject things from the compiler and vice versa.
let result = this._moduleRef.injector.get(token, UNDEFINED);
return result === UNDEFINED ? this._compiler.injector.get(token, notFoundValue) : result;
}
@ -177,7 +162,7 @@ export class TestBed implements Injector {
execute(tokens: any[], fn: Function): any {
if (!this._instantiated) {
throw new BaseException(
'Illegal state: The test bed\'s injector has not yet been created. Call initTestAppModule first!');
'Illegal state: The test bed\'s injector has not yet been created. Call initTestNgModule first!');
}
var params = tokens.map(t => this.get(t));
return FunctionWrapper.apply(fn, params);
@ -219,20 +204,17 @@ export function getTestInjector() {
export function setBaseTestProviders(
platformProviders: Array<Type|Provider|any[]>,
applicationProviders: Array<Type|Provider|any[]>) {
// Create a platform based on the Platform Providers.
var platformRef = createPlatform(ReflectiveInjector.resolveAndCreate(platformProviders));
// Create an AppModule based on the application providers.
@AppModule({providers: applicationProviders})
class TestAppModule {
if (platformProviders.length === 1 && typeof platformProviders[0] === 'function') {
(<any>platformProviders[0])(applicationProviders);
} else {
throw new Error(
`setBaseTestProviders is deprecated and only supports platformProviders that are predefined by Angular. Use 'initTestEnvironment' instead.`);
}
initTestEnvironment(TestAppModule, platformRef);
}
/**
* Initialize the environment for testing with a compiler factory, a PlatformRef, and an
* application module. These are common to every test in the suite.
* angular module. These are common to every test in the suite.
*
* This may only be called once, to set up the common providers for the current test
* suite on the current platform. If you absolutely need to change the providers,
@ -243,13 +225,15 @@ export function setBaseTestProviders(
*
* @experimental
*/
export function initTestEnvironment(appModule: Type, platform: PlatformRef) {
export function initTestEnvironment(ngModule: Type, platform: PlatformRef): Injector {
var testBed = getTestBed();
if (testBed.platform || testBed.appModule) {
if (testBed.platform || testBed.ngModule) {
throw new BaseException('Cannot set base providers because it has already been called');
}
testBed.platform = platform;
testBed.appModule = appModule;
testBed.ngModule = ngModule;
return testBed;
}
/**
@ -269,20 +253,20 @@ export function resetBaseTestProviders() {
export function resetTestEnvironment() {
var testBed = getTestBed();
testBed.platform = null;
testBed.appModule = null;
testBed.ngModule = null;
testBed.reset();
}
/**
* Run asynchronous precompilation for the test's AppModule. It is necessary to call this function
* if your test is using an AppModule which has precompiled components that require an asynchronous
* Run asynchronous precompilation for the test's NgModule. It is necessary to call this function
* if your test is using an NgModule which has precompiled components that require an asynchronous
* call, such as an XHR. Should be called once before the test case.
*
* @experimental
*/
export function doAsyncPrecompilation(): Promise<any> {
let testBed = getTestBed();
return testBed.createAppModuleFactory();
return testBed.createModuleFactory();
}
/**
@ -324,7 +308,7 @@ export function inject(tokens: any[], fn: Function): () => any {
} else {
return () => {
try {
testBed.initTestAppModule();
testBed.initTestModule();
} catch (e) {
if (e instanceof ComponentStillLoadingError) {
throw new Error(
@ -343,13 +327,9 @@ export function inject(tokens: any[], fn: Function): () => any {
* @experimental
*/
export class InjectSetupWrapper {
constructor(private _moduleDef: () => {
providers?: any[],
directives?: any[],
pipes?: any[],
precompile?: any[],
modules?: any[]
}) {}
constructor(
private _moduleDef:
() => {providers?: any[], declarations?: any[], imports?: any[], precompile?: any[]}) {}
private _addModule() {
var moduleDef = this._moduleDef();
@ -378,12 +358,9 @@ export function withProviders(providers: () => any) {
*/
export function withModule(moduleDef: () => {
providers?: any[],
directives?: any[],
pipes?: any[],
precompile?: any[],
modules?: any[]
declarations?: any[],
imports?: any[],
precompile?: any[]
}) {
return new InjectSetupWrapper(moduleDef);
}
class _NoopModule {}

View File

@ -119,25 +119,27 @@ export class TestComponentBuilder {
/**
* Builds and returns a ComponentFixture.
*/
createAsync<T>(rootComponentType: ConcreteType<T>): Promise<ComponentFixture<T>> {
createAsync<T>(rootComponentType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
Promise<ComponentFixture<T>> {
let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false);
let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null);
let compiler: Compiler = this._injector.get(Compiler);
let initComponent = () => {
let promise: Promise<ComponentFactory<any>> =
compiler.compileComponentAsync(rootComponentType);
compiler.compileComponentAsync(rootComponentType, ngModule);
return promise.then(componentFactory => this.createFromFactory(ngZone, componentFactory));
};
return ngZone == null ? initComponent() : ngZone.run(initComponent);
}
createFakeAsync<T>(rootComponentType: ConcreteType<T>): ComponentFixture<T> {
createFakeAsync<T>(rootComponentType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
ComponentFixture<T> {
let result: any /** TODO #9100 */;
let error: any /** TODO #9100 */;
PromiseWrapper.then(
this.createAsync(rootComponentType), (_result) => { result = _result; },
this.createAsync(rootComponentType, ngModule), (_result) => { result = _result; },
(_error) => { error = _error; });
tick();
if (isPresent(error)) {
@ -146,14 +148,15 @@ export class TestComponentBuilder {
return result;
}
createSync<T>(rootComponentType: ConcreteType<T>): ComponentFixture<T> {
createSync<T>(rootComponentType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
ComponentFixture<T> {
let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false);
let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null);
let compiler: Compiler = this._injector.get(Compiler);
let initComponent = () => {
return this.createFromFactory(
ngZone, this._injector.get(Compiler).compileComponentSync(rootComponentType));
ngZone, compiler.compileComponentSync(rootComponentType, ngModule));
};
return ngZone == null ? initComponent() : ngZone.run(initComponent);

View File

@ -49,13 +49,9 @@ export function addProviders(providers: Array<any>): void {
*
* @stable
*/
export function configureModule(moduleDef: {
providers?: any[],
directives?: any[],
pipes?: any[],
precompile?: any[],
modules?: any[]
}): void {
export function configureModule(
moduleDef: {providers?: any[], declarations?: any[], imports?: any[], precompile?: any[]}):
void {
if (!moduleDef) return;
try {
testBed.configureModule(moduleDef);

View File

@ -6,8 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Component, ReflectiveInjector, coreLoadAndBootstrap, createPlatform} from '@angular/core';
import {BROWSER_APP_PROVIDERS, BROWSER_PLATFORM_PROVIDERS} from '@angular/platform-browser';
import {Component, ReflectiveInjector, bootstrapModule, createPlatformFactory} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {browserDynamicPlatform} from '@angular/platform-browser-dynamic';
var appProviders: any[] = [];
@ -16,8 +17,6 @@ var appProviders: any[] = [];
class MyApp {
}
var platform = createPlatform(ReflectiveInjector.resolveAndCreate(BROWSER_PLATFORM_PROVIDERS));
var appInjector =
ReflectiveInjector.resolveAndCreate([BROWSER_APP_PROVIDERS, appProviders], platform.injector);
coreLoadAndBootstrap(MyApp, appInjector);
var myPlatformFactory = createPlatformFactory(browserDynamicPlatform, 'myPlatform');
bootstrapModule(MyApp, myPlatformFactory());
// #enddocregion

View File

@ -155,12 +155,12 @@ export function stringify(token: any): string {
return '' + token;
}
if (token.name) {
return token.name;
}
if (token.overriddenName) {
return token.overriddenName;
}
if (token.name) {
return token.name;
}
var res = token.toString();
var newLineIndex = res.indexOf('\n');

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Type} from '@angular/core';
import {NgModule, Type} from '@angular/core';
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
import {DefaultValueAccessor} from './directives/default_value_accessor';
@ -83,3 +83,10 @@ export const FORM_DIRECTIVES: Type[][] =
export const REACTIVE_FORM_DIRECTIVES: Type[][] =
/*@ts2dart_const*/[REACTIVE_DRIVEN_DIRECTIVES, SHARED_FORM_DIRECTIVES];
/**
* Internal module used for sharing directives between FormsModule and ReactiveFormsModule
*/
@NgModule({declarations: SHARED_FORM_DIRECTIVES, exports: SHARED_FORM_DIRECTIVES})
export class InternalFormsSharedModule {
}

View File

@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AppModule, PLATFORM_DIRECTIVES, Type} from '@angular/core';
import {NgModule, PLATFORM_DIRECTIVES, Type} from '@angular/core';
import {FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES} from './directives';
import {FORM_DIRECTIVES, InternalFormsSharedModule, REACTIVE_DRIVEN_DIRECTIVES, REACTIVE_FORM_DIRECTIVES, SHARED_FORM_DIRECTIVES, TEMPLATE_DRIVEN_DIRECTIVES} from './directives';
import {RadioControlRegistry} from './directives/radio_control_value_accessor';
import {FormBuilder} from './form_builder';
@ -28,18 +28,26 @@ export const REACTIVE_FORM_PROVIDERS: Type[] =
/*@ts2dart_const*/[FormBuilder, RadioControlRegistry];
/**
* The app module for forms.
* The ng module for forms.
* @experimental
*/
@AppModule({providers: [FORM_PROVIDERS], directives: FORM_DIRECTIVES, pipes: []})
@NgModule({
declarations: TEMPLATE_DRIVEN_DIRECTIVES,
providers: [FORM_PROVIDERS],
exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
export class FormsModule {
}
/**
* The app module for reactive forms.
* The ng module for reactive forms.
* @experimental
*/
@AppModule({providers: [REACTIVE_FORM_PROVIDERS], directives: REACTIVE_FORM_DIRECTIVES, pipes: []})
@NgModule({
declarations: [REACTIVE_DRIVEN_DIRECTIVES],
providers: [REACTIVE_FORM_PROVIDERS],
exports: [InternalFormsSharedModule, REACTIVE_DRIVEN_DIRECTIVES]
})
export class ReactiveFormsModule {
}
@ -57,4 +65,4 @@ export function provideForms(): any[] {
return [
{provide: PLATFORM_DIRECTIVES, useValue: FORM_DIRECTIVES, multi: true}, REACTIVE_FORM_PROVIDERS
];
}
}

View File

@ -22,7 +22,7 @@ import {PromiseWrapper} from '../src/facade/promise';
export function main() {
describe('reactive forms integration tests', () => {
beforeEach(() => { configureModule({modules: [FormsModule, ReactiveFormsModule]}); });
beforeEach(() => { configureModule({imports: [FormsModule, ReactiveFormsModule]}); });
it('should initialize DOM elements with the given form object',
inject(

View File

@ -20,7 +20,7 @@ import {ListWrapper} from '../src/facade/collection';
export function main() {
describe('template-driven forms integration tests', () => {
beforeEach(() => { configureModule({modules: [FormsModule]}); });
beforeEach(() => { configureModule({imports: [FormsModule]}); });
it('should support ngModel for single fields',
fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {

View File

@ -6,37 +6,24 @@
* found in the LICENSE file at https://angular.io/license
*/
import {COMMON_DIRECTIVES, COMMON_PIPES} from '@angular/common';
import {COMPILER_PROVIDERS, CompilerConfig, XHR, RUNTIME_COMPILER_FACTORY,} from '@angular/compiler';
import {AppModule, AppModuleRef, ApplicationRef, Compiler, ComponentRef, ComponentResolver, ExceptionHandler, PLATFORM_DIRECTIVES, PLATFORM_PIPES, ReflectiveInjector, Type, coreLoadAndBootstrap, bootstrapModule, bootstrapModuleFactory, isDevMode, OpaqueToken, PlatformRef, getPlatform, assertPlatform, createPlatform, PLATFORM_INITIALIZER, CompilerOptions, CompilerFactory, createPlatformFactory} from '@angular/core';
import {BROWSER_APP_PROVIDERS, BrowserModule, WORKER_APP_APPLICATION_PROVIDERS, WORKER_SCRIPT, WORKER_UI_APPLICATION_PROVIDERS, browserPlatform, workerAppPlatform, workerUiPlatform, BROWSER_PLATFORM_PROVIDERS} from '@angular/platform-browser';
import {XHR, analyzeAppProvidersForDeprecatedConfiguration, coreDynamicPlatform} from '@angular/compiler';
import {ApplicationRef, Compiler, CompilerFactory, CompilerOptions, ComponentRef, ComponentResolver, ExceptionHandler, NgModule, NgModuleRef, OpaqueToken, PLATFORM_DIRECTIVES, PLATFORM_INITIALIZER, PLATFORM_PIPES, PlatformRef, ReflectiveInjector, Type, assertPlatform, bootstrapModule, bootstrapModuleFactory, createPlatform, createPlatformFactory, getPlatform, isDevMode} from '@angular/core';
import {BROWSER_PLATFORM_PROVIDERS, BrowserModule, WORKER_APP_PLATFORM_PROVIDERS, WORKER_SCRIPT, WorkerAppModule, browserPlatform, workerAppPlatform, workerUiPlatform} from '@angular/platform-browser';
import {Console, ReflectionCapabilities, reflector} from './core_private';
import {getDOM, initDomAdapter} from './platform_browser_private';
import {Console} from './core_private';
import {PromiseWrapper} from './src/facade/async';
import {ConcreteType, isPresent, stringify} from './src/facade/lang';
import {INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS} from './src/platform_providers';
import {CachedXHR} from './src/xhr/xhr_cache';
import {XHRImpl} from './src/xhr/xhr_impl';
/**
* @deprecated The compiler providers are already included in the {@link CompilerFactory} that is
* contained the {@link browserDynamicPlatform}()`.
*/
export const BROWSER_APP_COMPILER_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
COMPILER_PROVIDERS, {
provide: CompilerConfig,
useFactory: (platformDirectives: any[], platformPipes: any[]) => {
return new CompilerConfig({
deprecatedPlatformDirectives: platformDirectives,
deprecatedPlatformPipes: platformPipes
});
},
deps: [PLATFORM_DIRECTIVES, PLATFORM_PIPES]
},
{provide: XHR, useClass: XHRImpl},
{provide: PLATFORM_DIRECTIVES, useValue: COMMON_DIRECTIVES, multi: true},
{provide: PLATFORM_PIPES, useValue: COMMON_PIPES, multi: true}
];
export const BROWSER_APP_COMPILER_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [];
/**
* @experimental
@ -44,34 +31,11 @@ export const BROWSER_APP_COMPILER_PROVIDERS: Array<any /*Type | Provider | any[]
export const CACHED_TEMPLATE_PROVIDER: Array<any /*Type | Provider | any[]*/> =
[{provide: XHR, useClass: CachedXHR}];
function initReflector() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
}
/**
* CompilerFactory for the browser dynamic platform
*
* @experimental
*/
export const BROWSER_DYNAMIC_COMPILER_FACTORY =
RUNTIME_COMPILER_FACTORY.withDefaults({providers: [{provide: XHR, useClass: XHRImpl}]});
/**
* Providers for the browser dynamic platform
*
* @experimental
*/
export const BROWSER_DYNAMIC_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
BROWSER_PLATFORM_PROVIDERS,
{provide: CompilerFactory, useValue: BROWSER_DYNAMIC_COMPILER_FACTORY},
{provide: PLATFORM_INITIALIZER, useValue: initReflector, multi: true},
];
/**
* @experimental API related to bootstrapping are still under review.
*/
export const browserDynamicPlatform =
createPlatformFactory('browserDynamic', BROWSER_DYNAMIC_PLATFORM_PROVIDERS);
export const browserDynamicPlatform = createPlatformFactory(
coreDynamicPlatform, 'browserDynamic', INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS);
/**
* Bootstrapping for Angular applications.
@ -142,8 +106,9 @@ export const browserDynamicPlatform =
* ## API (version 2)
* - `appComponentType`: The root component which should act as the application. This is
* a reference to a `Type` which is annotated with `@Component(...)`.
* - `providers`, `directives`, `pipes`, `modules`, `precompile`: Defines the properties
* - `providers`, `declarations`, `imports`, `precompile`: Defines the properties
* of the dynamically created module that is used to bootstrap the module.
* - to configure the compiler, use the `compilerOptions` parameter.
*
* Returns a `Promise` of {@link ComponentRef}.
*
@ -156,11 +121,10 @@ export function bootstrap<C>(
customProviders?: Array<any /*Type | Provider | any[]*/>): Promise<ComponentRef<C>>;
export function bootstrap<C>(
appComponentType: ConcreteType<C>,
{providers, directives, pipes, modules, precompile, compilerOptions}?: {
{providers, imports, declarations, precompile, compilerOptions}?: {
providers?: Array<any /*Type | Provider | any[]*/>,
directives?: any[],
pipes?: any[],
modules?: any[],
declarations?: any[],
imports?: any[],
precompile?: any[],
compilerOptions?: CompilerOptions
}): Promise<ComponentRef<C>>;
@ -168,112 +132,107 @@ export function bootstrap<C>(
appComponentType: ConcreteType<C>,
customProvidersOrDynamicModule?: Array<any /*Type | Provider | any[]*/>| {
providers: Array<any /*Type | Provider | any[]*/>,
directives: any[],
pipes: any[],
modules: any[],
declarations?: any[],
imports: any[],
precompile: any[],
compilerOptions: CompilerOptions
}): Promise<ComponentRef<C>> {
let compilerOptions: CompilerOptions;
let compilerProviders: any = [];
let providers: any[] = [];
let directives: any[] = [];
let pipes: any[] = [];
let modules: any[] = [];
let declarations: any[] = [];
let imports: any[] = [];
let precompile: any[] = [];
let deprecationMessages: string[] = [];
if (customProvidersOrDynamicModule instanceof Array) {
providers = customProvidersOrDynamicModule;
const deprecatedConfiguration = analyzeAppProvidersForDeprecatedConfiguration(providers);
declarations = deprecatedConfiguration.moduleDeclarations.concat(declarations);
compilerOptions = deprecatedConfiguration.compilerOptions;
deprecationMessages = deprecatedConfiguration.deprecationMessages;
} else if (customProvidersOrDynamicModule) {
providers = normalizeArray(customProvidersOrDynamicModule.providers);
directives = normalizeArray(customProvidersOrDynamicModule.directives);
pipes = normalizeArray(customProvidersOrDynamicModule.pipes);
modules = normalizeArray(customProvidersOrDynamicModule.modules);
declarations = normalizeArray(customProvidersOrDynamicModule.declarations);
imports = normalizeArray(customProvidersOrDynamicModule.imports);
precompile = normalizeArray(customProvidersOrDynamicModule.precompile);
compilerOptions = customProvidersOrDynamicModule.compilerOptions;
}
@AppModule({
@NgModule({
providers: providers,
modules: modules.concat([BrowserModule]),
directives: directives,
pipes: pipes,
declarations: declarations.concat([appComponentType]),
imports: [BrowserModule, imports],
precompile: precompile.concat([appComponentType])
})
class DynamicModule {
}
return bootstrapModule(
DynamicModule, browserDynamicPlatform(),
CompilerFactory.mergeOptions(compilerOptions, {deprecatedAppProviders: providers}))
return bootstrapModule(DynamicModule, browserDynamicPlatform(), compilerOptions)
.then((moduleRef) => {
const console = moduleRef.injector.get(Console);
deprecationMessages.forEach((msg) => console.warn(msg));
const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
return appRef.bootstrap(appComponentType);
});
}
/**
* @deprecated Create an {@link AppModule} that includes the {@link WorkerUiModule} and use {@link
* bootstrapModule}
* with the {@link workerUiPlatform}() instead.
* Bootstraps the worker ui.
*
* @experimental
*/
export function bootstrapWorkerUi(
workerScriptUri: string,
customProviders?: Array<any /*Type | Provider | any[]*/>): Promise<ApplicationRef> {
console.warn(
'bootstrapWorkerUi is deprecated. Create an @AppModule that includes the `WorkerUiModule` and use `bootstrapModule` with the `workerUiPlatform()` instead.');
var app = ReflectiveInjector.resolveAndCreate(
[
WORKER_UI_APPLICATION_PROVIDERS, BROWSER_APP_COMPILER_PROVIDERS,
{provide: WORKER_SCRIPT, useValue: workerScriptUri},
isPresent(customProviders) ? customProviders : []
],
workerUiPlatform().injector);
// Return a promise so that we keep the same semantics as Dart,
// and we might want to wait for the app side to come up
// in the future...
return PromiseWrapper.resolve(app.get(ApplicationRef));
customProviders: Array<any /*Type | Provider | any[]*/> = []): Promise<PlatformRef> {
// For now, just creates the worker ui platform...
return Promise.resolve(workerUiPlatform([{
provide: WORKER_SCRIPT,
useValue: workerScriptUri,
}].concat(customProviders)));
}
/**
* @deprecated The compiler providers are already included in the {@link CompilerFactory} that is
* contained the {@link workerAppPlatform}().
* @experimental API related to bootstrapping are still under review.
*/
const WORKER_APP_COMPILER_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
COMPILER_PROVIDERS, {
provide: CompilerConfig,
useFactory: (platformDirectives: any[], platformPipes: any[]) => {
return new CompilerConfig({
deprecatedPlatformDirectives: platformDirectives,
deprecatedPlatformPipes: platformPipes
});
},
deps: [PLATFORM_DIRECTIVES, PLATFORM_PIPES]
},
{provide: XHR, useClass: XHRImpl},
{provide: PLATFORM_DIRECTIVES, useValue: COMMON_DIRECTIVES, multi: true},
{provide: PLATFORM_PIPES, useValue: COMMON_PIPES, multi: true}
];
export const workerAppDynamicPlatform =
createPlatformFactory(coreDynamicPlatform, 'workerAppDynamic', [{
provide: CompilerOptions,
useValue: {providers: [{provide: XHR, useClass: XHRImpl}]},
multi: true
}]);
/**
* @deprecated Create an {@link AppModule} that includes the {@link WorkerAppModule} and use {@link
* @deprecated Create an {@link NgModule} that includes the {@link WorkerAppModule} and use {@link
* bootstrapModule}
* with the {@link workerAppPlatform}() instead.
* with the {@link workerAppDynamicPlatform}() instead.
*/
export function bootstrapWorkerApp(
appComponentType: Type,
customProviders?: Array<any /*Type | Provider | any[]*/>): Promise<ComponentRef<any>> {
export function bootstrapWorkerApp<T>(
appComponentType: ConcreteType<T>,
customProviders?: Array<any /*Type | Provider | any[]*/>): Promise<ComponentRef<T>> {
console.warn(
'bootstrapWorkerApp is deprecated. Create an @AppModule that includes the `WorkerAppModule` and use `bootstrapModule` with the `workerAppPlatform()` instead.');
var appInjector = ReflectiveInjector.resolveAndCreate(
[
WORKER_APP_APPLICATION_PROVIDERS, WORKER_APP_COMPILER_PROVIDERS,
isPresent(customProviders) ? customProviders : []
],
workerAppPlatform().injector);
return coreLoadAndBootstrap(appComponentType, appInjector);
'bootstrapWorkerApp is deprecated. Create an @NgModule that includes the `WorkerAppModule` and use `bootstrapModule` with the `workerAppDynamicPlatform()` instead.');
const deprecatedConfiguration = analyzeAppProvidersForDeprecatedConfiguration(customProviders);
const declarations = [deprecatedConfiguration.moduleDeclarations.concat([appComponentType])];
@NgModule({
providers: customProviders,
declarations: declarations,
imports: [WorkerAppModule],
precompile: [appComponentType]
})
class DynamicModule {
}
return bootstrapModule(
DynamicModule, workerAppDynamicPlatform(), deprecatedConfiguration.compilerOptions)
.then((moduleRef) => {
const console = moduleRef.injector.get(Console);
deprecatedConfiguration.deprecationMessages.forEach((msg) => console.warn(msg));
const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
return appRef.bootstrap(appComponentType);
});
}
function normalizeArray(arr: any[]): any[] {
return arr ? arr : [];
}
}

View File

@ -8,5 +8,6 @@
import {__platform_browser_private__ as r, __platform_browser_private__ as t} from '@angular/platform-browser';
export var INTERNAL_BROWSER_PLATFORM_PROVIDERS: typeof t.INTERNAL_BROWSER_PLATFORM_PROVIDERS =
r.INTERNAL_BROWSER_PLATFORM_PROVIDERS;
export var getDOM: typeof t.getDOM = r.getDOM;
export var initDomAdapter: typeof t.initDomAdapter = r.initDomAdapter;

View File

@ -0,0 +1,23 @@
/**
* @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 {XHR} from '@angular/compiler';
import {CompilerOptions} from '@angular/core';
import {INTERNAL_BROWSER_PLATFORM_PROVIDERS} from '../platform_browser_private';
import {XHRImpl} from './xhr/xhr_impl';
export const INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS: any[] = [
INTERNAL_BROWSER_PLATFORM_PROVIDERS,
{
provide: CompilerOptions,
useValue: {providers: [{provide: XHR, useClass: XHRImpl}]},
multi: true
},
];

View File

@ -6,90 +6,70 @@
* found in the LICENSE file at https://angular.io/license
*/
import {COMMON_DIRECTIVES, COMMON_PIPES} from '@angular/common';
import {CompilerConfig, DirectiveResolver, ViewResolver} from '@angular/compiler';
import {MockDirectiveResolver, MockViewResolver, OverridingTestComponentBuilder} from '@angular/compiler/testing';
import {AppModule, Compiler, CompilerFactory, PLATFORM_DIRECTIVES, PLATFORM_PIPES, PlatformRef, Provider, ReflectiveInjector, Type, createPlatformFactory} from '@angular/core';
import {TestComponentBuilder, TestComponentRenderer} from '@angular/core/testing';
import {BrowserTestModule, TEST_BROWSER_APPLICATION_PROVIDERS, TEST_BROWSER_PLATFORM_PROVIDERS} from '@angular/platform-browser/testing';
import {CompilerConfig, DirectiveResolver, NgModuleResolver, ViewResolver, analyzeAppProvidersForDeprecatedConfiguration} from '@angular/compiler';
import {OverridingTestComponentBuilder, coreDynamicTestingPlatform} from '@angular/compiler/testing';
import {Compiler, CompilerFactory, CompilerOptions, NgModule, PlatformRef, Provider, ReflectiveInjector, Type, createPlatform, createPlatformFactory} from '@angular/core';
import {TestComponentBuilder, TestComponentRenderer, initTestEnvironment} from '@angular/core/testing';
import {BrowserTestingModule, browserTestingPlatform} from '@angular/platform-browser/testing';
import {BROWSER_APP_COMPILER_PROVIDERS, BROWSER_DYNAMIC_COMPILER_FACTORY, BROWSER_DYNAMIC_PLATFORM_PROVIDERS} from './index';
import {Console} from './core_private';
import {browserDynamicPlatform} from './index';
import {INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS} from './src/platform_providers';
import {DOMTestComponentRenderer} from './testing/dom_test_component_renderer';
export * from './private_export_testing'
/**
* CompilerFactory for browser dynamic test platform
*
* @experimental
*/
export const BROWSER_DYNAMIC_TEST_COMPILER_FACTORY = BROWSER_DYNAMIC_COMPILER_FACTORY.withDefaults({
providers: [
{provide: DirectiveResolver, useClass: MockDirectiveResolver},
{provide: ViewResolver, useClass: MockViewResolver}
]
});
/**
* Providers for the browser dynamic platform
*
* @experimental
*/
const BROWSER_DYNAMIC_TEST_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
TEST_BROWSER_PLATFORM_PROVIDERS,
BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
{provide: CompilerFactory, useValue: BROWSER_DYNAMIC_TEST_COMPILER_FACTORY},
];
/**
* @experimental API related to bootstrapping are still under review.
*/
export const browserDynamicTestPlatform =
createPlatformFactory('browserDynamicTest', BROWSER_DYNAMIC_TEST_PLATFORM_PROVIDERS);
export const browserDynamicTestingPlatform = createPlatformFactory(
coreDynamicTestingPlatform, 'browserDynamicTesting',
INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS);
/**
* AppModule for testing.
* NgModule for testing.
*
* @stable
*/
@AppModule({
modules: [BrowserTestModule],
@NgModule({
exports: [BrowserTestingModule],
providers: [
{provide: TestComponentBuilder, useClass: OverridingTestComponentBuilder},
{provide: TestComponentRenderer, useClass: DOMTestComponentRenderer},
]
})
export class BrowserDynamicTestModule {
export class BrowserDynamicTestingModule {
}
// Used only as a shim until TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS is deprecated.
const BROWSER_DYNAMIC_TEST_COMPILER_FACTORY_OLD = BROWSER_DYNAMIC_COMPILER_FACTORY.withDefaults({
providers: [
{provide: DirectiveResolver, useClass: MockDirectiveResolver},
{provide: ViewResolver, useClass: MockViewResolver}
],
deprecatedAppProviders: [
{provide: PLATFORM_DIRECTIVES, useValue: COMMON_DIRECTIVES, multi: true},
{provide: PLATFORM_PIPES, useValue: COMMON_PIPES, multi: true}
]
});
/**
* @deprecated Use initTestEnvironment with browserDynamicTestingPlatform instead.
*/
export const TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
// Note: This is not a real provider but a hack to still support the deprecated
// `setBaseTestProviders` method!
[(appProviders: any[]) => {
const deprecatedConfiguration = analyzeAppProvidersForDeprecatedConfiguration(appProviders);
const platformRef =
createPlatformFactory(browserDynamicTestingPlatform, 'browserDynamicTestingDeprecated', [{
provide: CompilerOptions,
useValue: deprecatedConfiguration.compilerOptions,
multi: true
}])();
@NgModule({
exports: [BrowserDynamicTestingModule],
declarations: [deprecatedConfiguration.moduleDeclarations]
})
class DynamicTestModule {
}
const testInjector = initTestEnvironment(DynamicTestModule, platformRef);
const console: Console = testInjector.get(Console);
deprecatedConfiguration.deprecationMessages.forEach((msg) => console.warn(msg));
}];
/**
* @deprecated Use initTestEnvironment with browserDynamicTestPlatform instead.
* @deprecated Use initTestEnvironment with BrowserDynamicTestingModule instead.
*/
export const TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
TEST_BROWSER_PLATFORM_PROVIDERS,
BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
{provide: CompilerFactory, useValue: BROWSER_DYNAMIC_TEST_COMPILER_FACTORY_OLD},
];
/**
* @deprecated Use initTestEnvironment with BrowserDynamicTestModule instead.
*/
export const TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
TEST_BROWSER_APPLICATION_PROVIDERS,
{provide: TestComponentBuilder, useClass: OverridingTestComponentBuilder},
{provide: TestComponentRenderer, useClass: DOMTestComponentRenderer},
];
export const TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
[];

View File

@ -42,5 +42,6 @@ export var __platform_browser_private__ = {
SharedStylesHost: shared_styles_host.SharedStylesHost,
ELEMENT_PROBE_PROVIDERS: ng_proble.ELEMENT_PROBE_PROVIDERS,
DomEventsPlugin: dom_events.DomEventsPlugin,
initDomAdapter: browser.initDomAdapter
initDomAdapter: browser.initDomAdapter,
INTERNAL_BROWSER_PLATFORM_PROVIDERS: browser.INTERNAL_BROWSER_PLATFORM_PROVIDERS
};

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {COMMON_DIRECTIVES, COMMON_PIPES, PlatformLocation} from '@angular/common';
import {APPLICATION_COMMON_PROVIDERS, AppModule, AppModuleFactory, AppModuleRef, ExceptionHandler, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, RootRenderer, SanitizationService, Testability, assertPlatform, createPlatform, createPlatformFactory, getPlatform, isDevMode} from '@angular/core';
import {CommonModule, PlatformLocation} from '@angular/common';
import {ApplicationModule, ExceptionHandler, NgModule, NgModuleFactory, NgModuleRef, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, RootRenderer, SanitizationService, Testability, assertPlatform, corePlatform, createPlatform, createPlatformFactory, getPlatform, isDevMode} from '@angular/core';
import {wtfInit} from '../core_private';
import {AnimationDriver} from '../src/dom/animation_driver';
@ -28,18 +28,21 @@ import {DomSharedStylesHost, SharedStylesHost} from './dom/shared_styles_host';
import {isBlank} from './facade/lang';
import {DomSanitizationService, DomSanitizationServiceImpl} from './security/dom_sanitization_service';
export const INTERNAL_BROWSER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
{provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true},
{provide: PlatformLocation, useClass: BrowserPlatformLocation}
];
/**
* A set of providers to initialize the Angular platform in a web browser.
*
* Used automatically by `bootstrap`, or can be passed to `platform`.
*
* @experimental API related to bootstrapping are still under review.
* @deprecated Use `browserPlatform()` or create a custom platform factory via
* `createPlatformFactory(browserPlatform, ...)`
*/
export const BROWSER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
PLATFORM_COMMON_PROVIDERS, {provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true},
{provide: PlatformLocation, useClass: BrowserPlatformLocation}
];
export const BROWSER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
[PLATFORM_COMMON_PROVIDERS, INTERNAL_BROWSER_PLATFORM_PROVIDERS];
/**
* @security Replacing built-in sanitization providers exposes the application to XSS risks.
@ -58,27 +61,18 @@ export const BROWSER_SANITIZATION_PROVIDERS: Array<any> = [
* Used automatically by `bootstrap`, or can be passed to {@link PlatformRef
* PlatformRef.application}.
*
* @experimental API related to bootstrapping are still under review.
* @deprecated Create a module that includes `BrowserModule` instead. This is empty for backwards
* compatibility,
* as all of our bootstrap methods add a module implicitly, i.e. keeping this filled would add the
* providers 2x.
*/
export const BROWSER_APP_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
APPLICATION_COMMON_PROVIDERS, BROWSER_SANITIZATION_PROVIDERS,
{provide: ExceptionHandler, useFactory: _exceptionHandler, deps: []},
{provide: DOCUMENT, useFactory: _document, deps: []},
{provide: EVENT_MANAGER_PLUGINS, useClass: DomEventsPlugin, multi: true},
{provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true},
{provide: EVENT_MANAGER_PLUGINS, useClass: HammerGesturesPlugin, multi: true},
{provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig},
{provide: DomRootRenderer, useClass: DomRootRenderer_},
{provide: RootRenderer, useExisting: DomRootRenderer},
{provide: SharedStylesHost, useExisting: DomSharedStylesHost},
{provide: AnimationDriver, useFactory: _resolveDefaultAnimationDriver}, DomSharedStylesHost,
Testability, EventManager, ELEMENT_PROBE_PROVIDERS
];
export const BROWSER_APP_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [];
/**
* @experimental API related to bootstrapping are still under review.
*/
export const browserPlatform = createPlatformFactory('browser', BROWSER_PLATFORM_PROVIDERS);
export const browserPlatform =
createPlatformFactory(corePlatform, 'browser', INTERNAL_BROWSER_PLATFORM_PROVIDERS);
export function initDomAdapter() {
BrowserDomAdapter.makeCurrent();
@ -102,16 +96,26 @@ export function _resolveDefaultAnimationDriver(): AnimationDriver {
}
/**
* The app module for the browser.
* The ng module for the browser.
*
* @experimental
*/
@AppModule({
@NgModule({
providers: [
BROWSER_APP_PROVIDERS,
BROWSER_SANITIZATION_PROVIDERS,
{provide: ExceptionHandler, useFactory: _exceptionHandler, deps: []},
{provide: DOCUMENT, useFactory: _document, deps: []},
{provide: EVENT_MANAGER_PLUGINS, useClass: DomEventsPlugin, multi: true},
{provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true},
{provide: EVENT_MANAGER_PLUGINS, useClass: HammerGesturesPlugin, multi: true},
{provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig},
{provide: DomRootRenderer, useClass: DomRootRenderer_},
{provide: RootRenderer, useExisting: DomRootRenderer},
{provide: SharedStylesHost, useExisting: DomSharedStylesHost},
{provide: AnimationDriver, useFactory: _resolveDefaultAnimationDriver}, DomSharedStylesHost,
Testability, EventManager, ELEMENT_PROBE_PROVIDERS
],
directives: COMMON_DIRECTIVES,
pipes: COMMON_PIPES
exports: [CommonModule, ApplicationModule]
})
export class BrowserModule {
}

View File

@ -6,13 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {APP_INITIALIZER, Injector, NgZone} from '@angular/core';
import {Injector, NgZone, PLATFORM_INITIALIZER} from '@angular/core';
import {BrowserPlatformLocation} from '../../browser/location/browser_platform_location';
import {MessageBasedPlatformLocation} from './platform_location';
/**
* A list of {@link Provider}s. To use the router in a Worker enabled application you must
* include these providers when setting up the render thread.
@ -20,7 +21,7 @@ import {MessageBasedPlatformLocation} from './platform_location';
*/
export const WORKER_UI_LOCATION_PROVIDERS = [
MessageBasedPlatformLocation, BrowserPlatformLocation,
{provide: APP_INITIALIZER, useFactory: initUiLocation, multi: true, deps: [Injector]}
{provide: PLATFORM_INITIALIZER, useFactory: initUiLocation, multi: true, deps: [Injector]}
];
function initUiLocation(injector: Injector): () => void {

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {COMMON_DIRECTIVES, COMMON_PIPES, FORM_PROVIDERS} from '@angular/common';
import {APPLICATION_COMMON_PROVIDERS, APP_INITIALIZER, AppModule, ExceptionHandler, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PlatformRef, ReflectiveInjector, RootRenderer, assertPlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {CommonModule, FORM_PROVIDERS} from '@angular/common';
import {APP_INITIALIZER, ApplicationModule, ExceptionHandler, NgModule, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PlatformRef, ReflectiveInjector, RootRenderer, assertPlatform, corePlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {BROWSER_SANITIZATION_PROVIDERS} from './browser';
import {isBlank, print} from './facade/lang';
@ -29,29 +29,24 @@ class PrintLogger {
}
/**
* @experimental
* @deprecated Use `workerAppPlatform()` or create a custom platform factory via
* `createPlatformFactory(workerAppPlatform, ...)`
*/
export const WORKER_APP_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
PLATFORM_COMMON_PROVIDERS;
/**
* @experimental
* @deprecated Create a module that includes `WorkerAppModule` instead. This is empty for backwards
* compatibility,
* as all of our bootstrap methods add a module implicitly, i.e. keeping this filled would add the
* providers 2x.
*/
export const WORKER_APP_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
APPLICATION_COMMON_PROVIDERS, FORM_PROVIDERS, BROWSER_SANITIZATION_PROVIDERS, Serializer,
{provide: ClientMessageBrokerFactory, useClass: ClientMessageBrokerFactory_},
{provide: ServiceMessageBrokerFactory, useClass: ServiceMessageBrokerFactory_},
WebWorkerRootRenderer, {provide: RootRenderer, useExisting: WebWorkerRootRenderer},
{provide: ON_WEB_WORKER, useValue: true}, RenderStore,
{provide: ExceptionHandler, useFactory: _exceptionHandler, deps: []},
{provide: MessageBus, useFactory: createMessageBus, deps: [NgZone]},
{provide: APP_INITIALIZER, useValue: setupWebWorker, multi: true}
];
export const WORKER_APP_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [];
/**
* @experimental
*/
export const workerAppPlatform = createPlatformFactory('workerApp', WORKER_APP_PLATFORM_PROVIDERS);
export const workerAppPlatform = createPlatformFactory(corePlatform, 'workerApp');
function _exceptionHandler(): ExceptionHandler {
return new ExceptionHandler(new PrintLogger());
@ -77,14 +72,22 @@ function setupWebWorker(): void {
}
/**
* The app module for the worker app side.
* The ng module for the worker app side.
*
* @experimental
*/
@AppModule({
providers: WORKER_APP_APPLICATION_PROVIDERS,
directives: COMMON_DIRECTIVES,
pipes: COMMON_PIPES
@NgModule({
providers: [
FORM_PROVIDERS, BROWSER_SANITIZATION_PROVIDERS, Serializer,
{provide: ClientMessageBrokerFactory, useClass: ClientMessageBrokerFactory_},
{provide: ServiceMessageBrokerFactory, useClass: ServiceMessageBrokerFactory_},
WebWorkerRootRenderer, {provide: RootRenderer, useExisting: WebWorkerRootRenderer},
{provide: ON_WEB_WORKER, useValue: true}, RenderStore,
{provide: ExceptionHandler, useFactory: _exceptionHandler, deps: []},
{provide: MessageBus, useFactory: createMessageBus, deps: [NgZone]},
{provide: APP_INITIALIZER, useValue: setupWebWorker, multi: true}
],
exports: [CommonModule, ApplicationModule]
})
export class WorkerAppModule {
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {APPLICATION_COMMON_PROVIDERS, APP_INITIALIZER, AppModule, ExceptionHandler, Injectable, Injector, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, RootRenderer, Testability, assertPlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {ExceptionHandler, Injectable, Injector, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, RootRenderer, Testability, assertPlatform, corePlatform, createPlatform, createPlatformFactory, getPlatform, isDevMode} from '@angular/core';
import {wtfInit} from '../core_private';
@ -34,6 +34,7 @@ import {ServiceMessageBrokerFactory, ServiceMessageBrokerFactory_} from './web_w
import {MessageBasedRenderer} from './web_workers/ui/renderer';
/**
* Wrapper class that exposes the Worker
* and underlying {@link MessageBus} for lower level message passing.
@ -70,16 +71,8 @@ export const WORKER_UI_STARTABLE_MESSAGING_SERVICE =
/**
* @experimental WebWorker support is currently experimental.
*/
export const WORKER_UI_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
PLATFORM_COMMON_PROVIDERS,
{provide: PLATFORM_INITIALIZER, useValue: initWebWorkerRenderPlatform, multi: true}
];
/**
* @experimental WebWorker support is currently experimental.
*/
export const WORKER_UI_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
APPLICATION_COMMON_PROVIDERS,
export const _WORKER_UI_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
{provide: NgZone, useFactory: createNgZone, deps: []},
MessageBasedRenderer,
{provide: WORKER_UI_STARTABLE_MESSAGING_SERVICE, useExisting: MessageBasedRenderer, multi: true},
BROWSER_SANITIZATION_PROVIDERS,
@ -104,10 +97,27 @@ export const WORKER_UI_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[
Testability,
EventManager,
WebWorkerInstance,
{provide: APP_INITIALIZER, useFactory: initWebWorkerAppFn, multi: true, deps: [Injector]},
{
provide: PLATFORM_INITIALIZER,
useFactory: initWebWorkerRenderPlatform,
multi: true,
deps: [Injector]
},
{provide: MessageBus, useFactory: messageBusFactory, deps: [WebWorkerInstance]}
];
/**
* * @deprecated Use `workerUiPlatform()` or create a custom platform factory via
* `createPlatformFactory(workerUiPlatform, ...)`
*/
export const WORKER_UI_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
[PLATFORM_COMMON_PROVIDERS, _WORKER_UI_PLATFORM_PROVIDERS];
/**
* @deprecated Worker UI only has a platform but no application
*/
export const WORKER_UI_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [];
function initializeGenericWorkerRenderer(injector: Injector) {
var bus = injector.get(MessageBus);
let zone = injector.get(NgZone);
@ -122,27 +132,11 @@ function messageBusFactory(instance: WebWorkerInstance): MessageBus {
return instance.bus;
}
function initWebWorkerRenderPlatform(): void {
BrowserDomAdapter.makeCurrent();
wtfInit();
BrowserGetTestability.init();
}
/**
* @experimental WebWorker support is currently experimental.
*/
export const workerUiPlatform = createPlatformFactory('workerUi', WORKER_UI_PLATFORM_PROVIDERS);
function _exceptionHandler(): ExceptionHandler {
return new ExceptionHandler(getDOM());
}
function _document(): any {
return getDOM().defaultDoc();
}
function initWebWorkerAppFn(injector: Injector): () => void {
function initWebWorkerRenderPlatform(injector: Injector): () => void {
return () => {
BrowserDomAdapter.makeCurrent();
wtfInit();
BrowserGetTestability.init();
var scriptUri: string;
try {
scriptUri = injector.get(WORKER_SCRIPT);
@ -158,6 +152,24 @@ function initWebWorkerAppFn(injector: Injector): () => void {
};
}
/**
* @experimental WebWorker support is currently experimental.
*/
export const workerUiPlatform =
createPlatformFactory(corePlatform, 'workerUi', _WORKER_UI_PLATFORM_PROVIDERS);
function _exceptionHandler(): ExceptionHandler {
return new ExceptionHandler(getDOM());
}
function _document(): any {
return getDOM().defaultDoc();
}
function createNgZone(): NgZone {
return new NgZone({enableLongStackTrace: isDevMode()});
}
/**
* Spawns a new class and initializes the WebWorkerInstance
*/
@ -175,14 +187,3 @@ function _resolveDefaultAnimationDriver(): AnimationDriver {
// work with animations just yet...
return AnimationDriver.NOOP;
}
/**
* The app module for the worker ui side.
* To use this, you need to create an own module that includes this module
* and provides the `WORKER_SCRIPT` token.
*
* @experimental
*/
@AppModule({providers: WORKER_UI_APPLICATION_PROVIDERS})
export class WorkerUiModule {
}

View File

@ -8,15 +8,15 @@
import {LowerCasePipe, NgIf} from '@angular/common';
import {XHR} from '@angular/compiler';
import {APP_INITIALIZER, Component, Directive, ExceptionHandler, Inject, Input, OnDestroy, PLATFORM_DIRECTIVES, PLATFORM_INITIALIZER, PLATFORM_PIPES, Pipe, ReflectiveInjector, coreLoadAndBootstrap, createPlatform, provide} from '@angular/core';
import {APP_INITIALIZER, Component, Directive, ExceptionHandler, Inject, Input, NgModule, OnDestroy, PLATFORM_DIRECTIVES, PLATFORM_INITIALIZER, PLATFORM_PIPES, Pipe, ReflectiveInjector, bootstrapModule, createPlatformFactory, provide} from '@angular/core';
import {ApplicationRef, disposePlatform} from '@angular/core/src/application_ref';
import {Console} from '@angular/core/src/console';
import {ComponentRef} from '@angular/core/src/linker/component_factory';
import {Testability, TestabilityRegistry} from '@angular/core/src/testability/testability';
import {ComponentFixture} from '@angular/core/testing';
import {AsyncTestCompleter, Log, afterEach, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it} from '@angular/core/testing/testing_internal';
import {BROWSER_APP_PROVIDERS, BROWSER_PLATFORM_PROVIDERS} from '@angular/platform-browser';
import {BROWSER_APP_COMPILER_PROVIDERS, bootstrap} from '@angular/platform-browser-dynamic';
import {BrowserModule} from '@angular/platform-browser';
import {bootstrap, browserDynamicPlatform} from '@angular/platform-browser-dynamic';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {DOCUMENT} from '@angular/platform-browser/src/dom/dom_tokens';
import {expect} from '@angular/platform-browser/testing/matchers';
@ -223,16 +223,10 @@ export function main() {
it('should unregister change detectors when components are disposed',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var platform =
createPlatform(ReflectiveInjector.resolveAndCreate(BROWSER_PLATFORM_PROVIDERS));
var app = ReflectiveInjector
.resolveAndCreate(
[BROWSER_APP_PROVIDERS, BROWSER_APP_COMPILER_PROVIDERS, testProviders],
platform.injector)
.get(ApplicationRef);
coreLoadAndBootstrap(HelloRootCmp, app.injector).then((ref) => {
bootstrap(HelloRootCmp, testProviders).then((ref) => {
const appRef = ref.injector.get(ApplicationRef);
ref.destroy();
expect(() => app.tick()).not.toThrow();
expect(() => appRef.tick()).not.toThrow();
async.done();
});
}));
@ -258,24 +252,29 @@ export function main() {
});
}));
it('should run platform initializers', inject([Log], (log: Log) => {
let p = createPlatform(ReflectiveInjector.resolveAndCreate([
BROWSER_PLATFORM_PROVIDERS,
it('should run platform initializers',
inject([Log, AsyncTestCompleter], (log: Log, async: AsyncTestCompleter) => {
let p = createPlatformFactory(browserDynamicPlatform, 'someName', [
{provide: PLATFORM_INITIALIZER, useValue: log.fn('platform_init1'), multi: true},
{provide: PLATFORM_INITIALIZER, useValue: log.fn('platform_init2'), multi: true}
]));
])();
@NgModule({
imports: [BrowserModule],
providers: [
{provide: APP_INITIALIZER, useValue: log.fn('app_init1'), multi: true},
{provide: APP_INITIALIZER, useValue: log.fn('app_init2'), multi: true}
]
})
class SomeModule {
}
expect(log.result()).toEqual('platform_init1; platform_init2');
log.clear();
var a = ReflectiveInjector.resolveAndCreate(
[
BROWSER_APP_PROVIDERS,
{provide: APP_INITIALIZER, useValue: log.fn('app_init1'), multi: true},
{provide: APP_INITIALIZER, useValue: log.fn('app_init2'), multi: true}
],
p.injector);
a.get(ApplicationRef);
expect(log.result()).toEqual('app_init1; app_init2');
bootstrapModule(SomeModule, p).then(() => {
expect(log.result()).toEqual('app_init1; app_init2');
async.done();
});
}));
it('should register each application with the testability registry',
@ -305,7 +304,7 @@ export function main() {
])).then((compRef) => {
expect(el).toHaveText('hello world!');
expect(compilerConsole.warnings).toEqual([
'Passing an instance of XHR to "bootstrap()" as provider is deprecated. Pass the provider via the new parameter "compilerOptions" of "bootstrap()" instead.'
'Passing XHR as regular provider is deprecated. Pass the provider via "compilerOptions" instead.'
]);
async.done();
});
@ -325,10 +324,8 @@ export function main() {
.toBe('transformed someValue');
expect(compilerConsole.warnings).toEqual([
'Passing PLATFORM_DIRECTIVES to "bootstrap()" as provider is deprecated. Use the new parameter "directives" of "bootstrap()" instead.',
'Passing PLATFORM_PIPES to "bootstrap()" as provider is deprecated. Use the new parameter "pipes" of "bootstrap()" instead.',
`Providing platform directives via the PLATFORM_DIRECTIVES provider or the "CompilerConfig" is deprecated. Provide platform directives via an @AppModule instead. Directives: ${stringify(SomeDirective)}`,
`Providing platform pipes via the PLATFORM_PIPES provider or the "CompilerConfig" is deprecated. Provide platform pipes via an @AppModule instead. Pipes: ${stringify(SomePipe)}`
`The PLATFORM_DIRECTIVES provider and CompilerConfig.platformDirectives is deprecated. Add the directives to an NgModule instead! (Directives: ${stringify(SomeDirective)})`,
`The PLATFORM_PIPES provider and CompilerConfig.platformPipes is deprecated. Add the pipes to an NgModule instead! (Pipes: ${stringify(SomePipe)})`
]);
async.done();
});

View File

@ -8,7 +8,7 @@
import {NgIf} from '@angular/common';
import {CompilerConfig, XHR} from '@angular/compiler';
import {AppModule, Component, ComponentFactoryResolver, Directive, Injectable, Input, Pipe, ViewMetadata, provide} from '@angular/core';
import {Component, ComponentFactoryResolver, Directive, Injectable, Input, NgModule, Pipe, ViewMetadata, provide} from '@angular/core';
import {TestComponentBuilder, addProviders, async, configureCompiler, configureModule, doAsyncPrecompilation, fakeAsync, inject, tick, withModule, withProviders} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
@ -112,8 +112,8 @@ class SomePipe {
class CompUsingModuleDirectiveAndPipe {
}
@AppModule({})
class SomeNestedModule {
@NgModule()
class SomeLibModule {
}
@Component({
@ -233,10 +233,9 @@ export function main() {
beforeEach(() => {
moduleConfig = {
providers: [FancyService],
directives: [SomeDirective],
pipes: [SomePipe],
precompile: [CompUsingModuleDirectiveAndPipe],
modules: [SomeNestedModule]
imports: [SomeLibModule],
declarations: [SomeDirective, SomePipe, CompUsingModuleDirectiveAndPipe],
precompile: [CompUsingModuleDirectiveAndPipe]
};
});
@ -256,9 +255,9 @@ export function main() {
expect(el.children[0].properties['title']).toBe('transformed someValue');
}));
it('should use set up nested modules',
inject([SomeNestedModule], (nestedModule: SomeNestedModule) => {
expect(nestedModule).toBeAnInstanceOf(SomeNestedModule);
it('should use set up library modules',
inject([SomeLibModule], (libModule: SomeLibModule) => {
expect(libModule).toBeAnInstanceOf(SomeLibModule);
}));
it('should use set up precompile components',
@ -284,11 +283,10 @@ export function main() {
expect(el.children[0].properties['title']).toBe('transformed someValue');
}));
it('should use set up nested modules',
withModule(() => moduleConfig)
.inject([SomeNestedModule], (nestedModule: SomeNestedModule) => {
expect(nestedModule).toBeAnInstanceOf(SomeNestedModule);
}));
it('should use set up library modules',
withModule(() => moduleConfig).inject([SomeLibModule], (libModule: SomeLibModule) => {
expect(libModule).toBeAnInstanceOf(SomeLibModule);
}));
it('should use set up precompile components',
withModule(() => moduleConfig)
@ -301,7 +299,7 @@ export function main() {
describe('precompile components with template url', () => {
beforeEach(async(() => {
configureModule({precompile: [CompWithUrlTemplate]});
configureModule({declarations: [CompWithUrlTemplate], precompile: [CompWithUrlTemplate]});
doAsyncPrecompilation();
}));
@ -450,7 +448,12 @@ export function main() {
expect(
() =>
it('should fail',
withModule(() => { return {precompile: [CompWithUrlTemplate]}; })
withModule(() => {
return {
declarations: [CompWithUrlTemplate],
precompile: [CompWithUrlTemplate]
};
})
.inject(
[ComponentFactoryResolver],
(resolver: ComponentFactoryResolver) => {

View File

@ -23,8 +23,8 @@ import {MessageBasedRenderer} from '@angular/platform-browser/src/web_workers/ui
import {createPairedMessageBuses, PairedMessageBuses} from '../shared/web_worker_test_util';
import {ServiceMessageBrokerFactory_} from '@angular/platform-browser/src/web_workers/shared/service_message_broker';
import {dispatchEvent} from '../../../../platform-browser/testing/browser_util';
import {BrowserTestModule} from '@angular/platform-browser/testing';
import {browserDynamicTestPlatform} from '@angular/platform-browser-dynamic/testing';
import {BrowserTestingModule} from '@angular/platform-browser/testing';
import {browserDynamicTestingPlatform} from '@angular/platform-browser-dynamic/testing';
export function main() {
function createWebWorkerBrokerFactory(
@ -65,8 +65,8 @@ export function main() {
beforeEach(() => {
uiRenderStore = new RenderStore();
var testUiInjector = new TestBed();
testUiInjector.platform = browserDynamicTestPlatform();
testUiInjector.appModule = BrowserTestModule;
testUiInjector.platform = browserDynamicTestingPlatform();
testUiInjector.ngModule = BrowserTestingModule;
testUiInjector.configureModule({
providers: [
Serializer, {provide: RenderStore, useValue: uiRenderStore},
@ -74,7 +74,7 @@ export function main() {
{provide: RootRenderer, useExisting: DomRootRenderer}
]
});
testUiInjector.initTestAppModule();
testUiInjector.initTestModule();
var uiSerializer = testUiInjector.get(Serializer);
var domRootRenderer = testUiInjector.get(DomRootRenderer);
workerRenderStore = new RenderStore();

View File

@ -7,9 +7,9 @@
*/
import {LocationStrategy} from '@angular/common';
import {APP_ID, AppModule, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, assertPlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {APP_ID, NgModule, NgZone, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, assertPlatform, corePlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {BROWSER_APP_PROVIDERS, BrowserModule} from '../src/browser';
import {BrowserModule} from '../src/browser';
import {BrowserDomAdapter} from '../src/browser/browser_adapter';
import {AnimationDriver} from '../src/dom/animation_driver';
import {ELEMENT_PROBE_PROVIDERS} from '../src/dom/debug/ng_probe';
@ -25,45 +25,46 @@ function createNgZone(): NgZone {
return new NgZone({enableLongStackTrace: true});
}
const _TEST_BROWSER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
[{provide: PLATFORM_INITIALIZER, useValue: initBrowserTests, multi: true}];
/**
* Providers for the browser test platform
*
* @experimental
* @deprecated Use `browserTestingPlatform()` or create a custom platform factory via
* `createPlatformFactory(browserTestingPlatform, ...)`
*/
export const TEST_BROWSER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
PLATFORM_COMMON_PROVIDERS,
{provide: PLATFORM_INITIALIZER, useValue: initBrowserTests, multi: true}
];
export const TEST_BROWSER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
[PLATFORM_COMMON_PROVIDERS, _TEST_BROWSER_PLATFORM_PROVIDERS];
/**
* @deprecated Use initTestEnvironment with BrowserTestModule instead.
* @deprecated Use initTestEnvironment with BrowserTestModule instead. This is empty for backwards
* compatibility,
* as all of our bootstrap methods add a module implicitly, i.e. keeping this filled would add the
* providers 2x.
*/
export const TEST_BROWSER_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
BROWSER_APP_PROVIDERS, {provide: APP_ID, useValue: 'a'}, ELEMENT_PROBE_PROVIDERS,
{provide: NgZone, useFactory: createNgZone},
{provide: AnimationDriver, useValue: AnimationDriver.NOOP}
];
export const TEST_BROWSER_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [];
/**
* Platform for testing
*
* @experimental API related to bootstrapping are still under review.
*/
export const browserTestPlatform =
createPlatformFactory('browserTest', TEST_BROWSER_PLATFORM_PROVIDERS);
export const browserTestingPlatform =
createPlatformFactory(corePlatform, 'browserTesting', _TEST_BROWSER_PLATFORM_PROVIDERS);
/**
* AppModule for testing.
* NgModule for testing.
*
* @stable
* @experimental
*/
@AppModule({
modules: [BrowserModule],
@NgModule({
exports: [BrowserModule],
providers: [
{provide: APP_ID, useValue: 'a'}, ELEMENT_PROBE_PROVIDERS,
{provide: NgZone, useFactory: createNgZone},
{provide: AnimationDriver, useValue: AnimationDriver.NOOP}
]
})
export class BrowserTestModule {
export class BrowserTestingModule {
}

View File

@ -11,3 +11,4 @@ import {__core_private__ as r, __core_private_types__ as t} from '@angular/core'
export var reflector: typeof t.reflector = r.reflector;
export var ReflectionCapabilities: typeof t.ReflectionCapabilities = r.ReflectionCapabilities;
export var wtfInit: typeof t.wtfInit = r.wtfInit;
export var Console: typeof t.Console = r.Console;

View File

@ -7,11 +7,13 @@
*/
import {PlatformLocation} from '@angular/common';
import {CompilerFactory, ComponentRef, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, Type, assertPlatform, coreLoadAndBootstrap, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {BROWSER_DYNAMIC_TEST_COMPILER_FACTORY} from '@angular/platform-browser-dynamic/testing';
import {analyzeAppProvidersForDeprecatedConfiguration, coreDynamicPlatform} from '@angular/compiler';
import {ApplicationRef, CompilerFactory, ComponentRef, NgModule, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, Type, assertPlatform, bootstrapModule, corePlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {ReflectionCapabilities, reflector, wtfInit} from '../core_private';
import {Console, ReflectionCapabilities, reflector, wtfInit} from '../core_private';
import {ConcreteType} from './facade/lang';
import {Parse5DomAdapter} from './parse5_adapter';
function notSupported(feature: string): Error {
@ -31,23 +33,21 @@ class ServerPlatformLocation extends PlatformLocation {
back(): void { notSupported('back'); };
}
/**
* A set of providers to initialize the Angular platform in a server.
*
* Used automatically by `serverBootstrap`, or can be passed to `platform`.
* @experimental
*/
export const SERVER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
PLATFORM_COMMON_PROVIDERS,
export const INTERNAL_SERVER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
{provide: PLATFORM_INITIALIZER, useValue: initParse5Adapter, multi: true},
{provide: PlatformLocation, useClass: ServerPlatformLocation},
];
const SERVER_DYNAMIC_PROVIDERS: any[] = [
SERVER_PLATFORM_PROVIDERS,
{provide: CompilerFactory, useValue: BROWSER_DYNAMIC_TEST_COMPILER_FACTORY},
];
/**
* A set of providers to initialize the Angular platform in a server.
*
* Used automatically by `serverBootstrap`, or can be passed to `platform`.
* @deprecated Use `serverPlatform()` or create a custom platform factory via
* `createPlatformFactory(serverPlatform, ...)`
*/
export const SERVER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
[PLATFORM_COMMON_PROVIDERS, INTERNAL_SERVER_PLATFORM_PROVIDERS];
function initParse5Adapter() {
Parse5DomAdapter.makeCurrent();
@ -57,7 +57,8 @@ function initParse5Adapter() {
/**
* @experimental
*/
export const serverPlatform = createPlatformFactory('server', SERVER_PLATFORM_PROVIDERS);
export const serverPlatform =
createPlatformFactory(corePlatform, 'server', INTERNAL_SERVER_PLATFORM_PROVIDERS);
/**
* The server platform that supports the runtime compiler.
@ -65,7 +66,7 @@ export const serverPlatform = createPlatformFactory('server', SERVER_PLATFORM_PR
* @experimental
*/
export const serverDynamicPlatform =
createPlatformFactory('serverDynamic', SERVER_DYNAMIC_PROVIDERS);
createPlatformFactory(coreDynamicPlatform, 'serverDynamic', INTERNAL_SERVER_PLATFORM_PROVIDERS);
/**
* Used to bootstrap Angular in server environment (such as node).
@ -81,16 +82,35 @@ export const serverDynamicPlatform =
* serverBootstrap(..., [BROWSER_APP_PROVIDERS, BROWSER_APP_COMPILER_PROVIDERS])
* ```
*
* @deprecated create an {@link AppModule} and use {@link bootstrapModule} with the {@link
* @deprecated create an {@link NgModule} and use {@link bootstrapModule} with the {@link
* serverDynamicPlatform}()
* instead.
*/
export function serverBootstrap(
appComponentType: Type,
providers: Array<any /*Type | Provider | any[]*/>): Promise<ComponentRef<any>> {
export function serverBootstrap<T>(
appComponentType: ConcreteType<T>,
customProviders: Array<any /*Type | Provider | any[]*/>): Promise<ComponentRef<T>> {
console.warn(
'serverBootstrap is deprecated. Create an @AppModule and use `bootstrapModule` with the `serverDynamicPlatform()` instead.');
'serverBootstrap is deprecated. Create an @NgModule and use `bootstrapModule` with the `serverDynamicPlatform()` instead.');
reflector.reflectionCapabilities = new ReflectionCapabilities();
var appInjector = ReflectiveInjector.resolveAndCreate(providers, serverPlatform().injector);
return coreLoadAndBootstrap(appComponentType, appInjector);
const deprecatedConfiguration = analyzeAppProvidersForDeprecatedConfiguration(customProviders);
const declarations = [deprecatedConfiguration.moduleDeclarations.concat([appComponentType])];
@NgModule({
providers: customProviders,
declarations: declarations,
imports: [BrowserModule],
precompile: [appComponentType]
})
class DynamicModule {
}
return bootstrapModule(
DynamicModule, serverDynamicPlatform(), deprecatedConfiguration.compilerOptions)
.then((moduleRef) => {
const console = moduleRef.injector.get(Console);
deprecatedConfiguration.deprecationMessages.forEach((msg) => console.warn(msg));
const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
return appRef.bootstrap(appComponentType);
});
}

View File

@ -6,44 +6,67 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AppModule, CompilerFactory, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, assertPlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {BROWSER_DYNAMIC_TEST_COMPILER_FACTORY, BrowserDynamicTestModule, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from '@angular/platform-browser-dynamic/testing';
import {analyzeAppProvidersForDeprecatedConfiguration} from '@angular/compiler';
import {coreDynamicTestingPlatform} from '@angular/compiler/testing';
import {CompilerFactory, CompilerOptions, NgModule, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, assertPlatform, createPlatform, createPlatformFactory, getPlatform} from '@angular/core';
import {initTestEnvironment} from '@angular/core/testing';
import {BrowserDynamicTestingModule, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS, browserDynamicTestingPlatform} from '@angular/platform-browser-dynamic/testing';
import {Console} from '../core_private';
import {serverPlatform} from '../index';
import {Parse5DomAdapter} from '../src/parse5_adapter';
function initServerTests() {
Parse5DomAdapter.makeCurrent();
}
/**
* @deprecated Use initTestEnvironment with serverTestPlatform instead.
*/
export const TEST_SERVER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
/*@ts2dart_const*/[
PLATFORM_COMMON_PROVIDERS,
/*@ts2dart_Provider*/ {provide: PLATFORM_INITIALIZER, useValue: initServerTests, multi: true},
{provide: CompilerFactory, useValue: BROWSER_DYNAMIC_TEST_COMPILER_FACTORY},
];
import {INTERNAL_SERVER_PLATFORM_PROVIDERS} from '../src/server';
/**
* Platform for testing
*
* @experimental API related to bootstrapping are still under review.
*/
export const serverTestPlatform =
createPlatformFactory('serverTest', TEST_SERVER_PLATFORM_PROVIDERS);
export const serverTestingPlatform = createPlatformFactory(
coreDynamicTestingPlatform, 'serverTesting', INTERNAL_SERVER_PLATFORM_PROVIDERS);
/**
* AppModule for testing.
* NgModule for testing.
*
* @stable
* @experimental API related to bootstrapping are still under review.
*/
@AppModule({modules: [BrowserDynamicTestModule]})
export class ServerTestModule {
@NgModule({exports: [BrowserDynamicTestingModule]})
export class ServerTestingModule {
}
/**
* @deprecated Use initTestEnvironment with ServerTestModule instead.
* Providers of the `serverTestingPlatform` to be used for creating own platform based on this.
*
* @deprecated Use `serverTestingPlatform()` or create a custom platform factory via
* `createPlatformFactory(serverTestingPlatform, ...)`
*/
export const TEST_SERVER_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS;
export const TEST_SERVER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
// Note: This is not a real provider but a hack to still support the deprecated
// `setBaseTestProviders` method!
[(appProviders: any[]) => {
const deprecatedConfiguration = analyzeAppProvidersForDeprecatedConfiguration(appProviders);
const platformRef = createPlatformFactory(serverTestingPlatform, 'serverTestingDeprecated', [{
provide: CompilerOptions,
useValue: deprecatedConfiguration.compilerOptions,
multi: true
}])();
@NgModule({
exports: [ServerTestingModule],
declarations: [deprecatedConfiguration.moduleDeclarations]
})
class DynamicTestModule {
}
const testInjector = initTestEnvironment(DynamicTestModule, platformRef);
const console: Console = testInjector.get(Console);
deprecatedConfiguration.deprecationMessages.forEach((msg) => console.warn(msg));
}];
/**
* @deprecated Use initTestEnvironment with ServerTestModule instead. This is empty for backwards
* compatibility,
* as all of our bootstrap methods add a module implicitly, i.e. keeping this filled would add the
* providers 2x.
*/
export const TEST_SERVER_APPLICATION_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [];

View File

@ -9,4 +9,17 @@ The Angular router is designed to solve these problems. Using the router, you ca
Read the overview of the Router [here](http://victorsavkin.com/post/145672529346/angular-router).
## Guide
Read the dev guide [here](https://angular.io/docs/ts/latest/guide/router.html).
Read the dev guide [here](https://angular.io/docs/ts/latest/guide/router.html).
## Local development
```
# keep @angular/router fresh
$ ./scripts/karma.sh
# keep @angular/core fresh
$ ../../../node_modules/.bin/tsc -p modules --emitDecoratorMetadata -w
# start karma
$ ./scripts/karma.sh
```

Some files were not shown because too many files have changed in this diff Show More