refactor(compiler): split compiler and core (#18683)

After this, neither @angular/compiler nor @angular/comnpiler-cli depend
on @angular/core.

This add a duplication of some interfaces and enums which is stored
in @angular/compiler/src/core.ts

BREAKING CHANGE:
- `@angular/platform-server` now additionally depends on
  `@angular/platform-browser-dynamic` as a peer dependency.


PR Close #18683
This commit is contained in:
Tobias Bosch
2017-08-16 09:00:03 -07:00
committed by Miško Hevery
parent a0ca01d580
commit 0cc77b4a69
107 changed files with 1504 additions and 1564 deletions

View File

@ -6,27 +6,26 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Attribute, ChangeDetectionStrategy, Component, ComponentFactory, Directive, Host, Inject, Injectable, InjectionToken, ModuleWithProviders, Optional, Provider, Query, RendererType2, SchemaMetadata, Self, SkipSelf, Type, resolveForwardRef, ɵConsole as Console, ɵERROR_COMPONENT_TYPE, ɵccf as createComponentFactory, ɵisPromise as isPromise, ɵstringify as stringify} from '@angular/core';
import {StaticSymbol, StaticSymbolCache} from './aot/static_symbol';
import {ngfactoryFilePath} from './aot/util';
import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions';
import * as cpl from './compile_metadata';
import {CompileReflector} from './compile_reflector';
import {CompilerConfig} from './config';
import {ChangeDetectionStrategy, Component, Directive, ModuleWithProviders, Provider, Query, SchemaMetadata, Type, createAttribute, createComponent, createHost, createInject, createInjectable, createInjectionToken, createOptional, createSelf, createSkipSelf} from './core';
import {DirectiveNormalizer} from './directive_normalizer';
import {DirectiveResolver} from './directive_resolver';
import {Identifiers} from './identifiers';
import {CompilerInjectable} from './injectable';
import {getAllLifecycleHooks} from './lifecycle_reflector';
import {NgModuleResolver} from './ng_module_resolver';
import {PipeResolver} from './pipe_resolver';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {SummaryResolver} from './summary_resolver';
import {SyncAsync, ValueTransformer, noUndefined, syntaxError, visitValue} from './util';
import {Console, SyncAsync, ValueTransformer, isPromise, noUndefined, resolveForwardRef, stringify, syntaxError, visitValue} from './util';
export type ErrorCollector = (error: any, type?: any) => void;
export const ERROR_COLLECTOR_TOKEN = new InjectionToken('ErrorCollector');
export const ERROR_COMPONENT_TYPE = 'ngComponentType';
// Design notes:
// - don't lazily create metadata:
@ -35,15 +34,14 @@ export const ERROR_COLLECTOR_TOKEN = new InjectionToken('ErrorCollector');
// But we want to report errors even when the async work is
// not required to check that the user would have been able
// to wait correctly.
@CompilerInjectable()
export class CompileMetadataResolver {
private _nonNormalizedDirectiveCache =
new Map<Type<any>, {annotation: Directive, metadata: cpl.CompileDirectiveMetadata}>();
private _directiveCache = new Map<Type<any>, cpl.CompileDirectiveMetadata>();
private _summaryCache = new Map<Type<any>, cpl.CompileTypeSummary|null>();
private _pipeCache = new Map<Type<any>, cpl.CompilePipeMetadata>();
private _ngModuleCache = new Map<Type<any>, cpl.CompileNgModuleMetadata>();
private _ngModuleOfTypes = new Map<Type<any>, Type<any>>();
new Map<Type, {annotation: Directive, metadata: cpl.CompileDirectiveMetadata}>();
private _directiveCache = new Map<Type, cpl.CompileDirectiveMetadata>();
private _summaryCache = new Map<Type, cpl.CompileTypeSummary|null>();
private _pipeCache = new Map<Type, cpl.CompilePipeMetadata>();
private _ngModuleCache = new Map<Type, cpl.CompileNgModuleMetadata>();
private _ngModuleOfTypes = new Map<Type, Type>();
constructor(
private _config: CompilerConfig, private _ngModuleResolver: NgModuleResolver,
@ -51,13 +49,12 @@ export class CompileMetadataResolver {
private _summaryResolver: SummaryResolver<any>,
private _schemaRegistry: ElementSchemaRegistry,
private _directiveNormalizer: DirectiveNormalizer, private _console: Console,
@Optional() private _staticSymbolCache: StaticSymbolCache,
private _reflector: CompileReflector,
@Optional() @Inject(ERROR_COLLECTOR_TOKEN) private _errorCollector?: ErrorCollector) {}
private _staticSymbolCache: StaticSymbolCache, private _reflector: CompileReflector,
private _errorCollector?: ErrorCollector) {}
getReflector(): CompileReflector { return this._reflector; }
clearCacheFor(type: Type<any>) {
clearCacheFor(type: Type) {
const dirMeta = this._directiveCache.get(type);
this._directiveCache.delete(type);
this._nonNormalizedDirectiveCache.delete(type);
@ -115,7 +112,7 @@ export class CompileMetadataResolver {
return this.getGeneratedClass(dirType, cpl.hostViewClassName(dirType));
}
getHostComponentType(dirType: any): StaticSymbol|Type<any> {
getHostComponentType(dirType: any): StaticSymbol|Type {
const name = `${cpl.identifierName({reference: dirType})}_Host`;
if (dirType instanceof StaticSymbol) {
return this._staticSymbolCache.get(dirType.filePath, name);
@ -127,7 +124,7 @@ export class CompileMetadataResolver {
}
}
private getRendererType(dirType: any): StaticSymbol|RendererType2 {
private getRendererType(dirType: any): StaticSymbol|object {
if (dirType instanceof StaticSymbol) {
return this._staticSymbolCache.get(
ngfactoryFilePath(dirType.filePath), cpl.rendererTypeName(dirType));
@ -140,7 +137,7 @@ export class CompileMetadataResolver {
private getComponentFactory(
selector: string, dirType: any, inputs: {[key: string]: string}|null,
outputs: {[key: string]: string}): StaticSymbol|ComponentFactory<any> {
outputs: {[key: string]: string}): StaticSymbol|object {
if (dirType instanceof StaticSymbol) {
return this._staticSymbolCache.get(
ngfactoryFilePath(dirType.filePath), cpl.componentFactoryName(dirType));
@ -148,14 +145,15 @@ export class CompileMetadataResolver {
const hostView = this.getHostComponentViewClass(dirType);
// Note: ngContentSelectors will be filled later once the template is
// loaded.
const createComponentFactory =
this._reflector.resolveExternalReference(Identifiers.createComponentFactory);
return createComponentFactory(selector, dirType, <any>hostView, inputs, outputs, []);
}
}
private initComponentFactory(
factory: StaticSymbol|ComponentFactory<any>, ngContentSelectors: string[]) {
private initComponentFactory(factory: StaticSymbol|object, ngContentSelectors: string[]) {
if (!(factory instanceof StaticSymbol)) {
factory.ngContentSelectors.push(...ngContentSelectors);
(factory as any).ngContentSelectors.push(...ngContentSelectors);
}
}
@ -250,23 +248,24 @@ export class CompileMetadataResolver {
}
let nonNormalizedTemplateMetadata: cpl.CompileTemplateMetadata = undefined !;
if (dirMeta instanceof Component) {
if (createComponent.isTypeOf(dirMeta)) {
// component
assertArrayOfStrings('styles', dirMeta.styles);
assertArrayOfStrings('styleUrls', dirMeta.styleUrls);
assertInterpolationSymbols('interpolation', dirMeta.interpolation);
const compMeta = dirMeta as Component;
assertArrayOfStrings('styles', compMeta.styles);
assertArrayOfStrings('styleUrls', compMeta.styleUrls);
assertInterpolationSymbols('interpolation', compMeta.interpolation);
const animations = dirMeta.animations;
const animations = compMeta.animations;
nonNormalizedTemplateMetadata = new cpl.CompileTemplateMetadata({
encapsulation: noUndefined(dirMeta.encapsulation),
template: noUndefined(dirMeta.template),
templateUrl: noUndefined(dirMeta.templateUrl),
styles: dirMeta.styles || [],
styleUrls: dirMeta.styleUrls || [],
encapsulation: noUndefined(compMeta.encapsulation),
template: noUndefined(compMeta.template),
templateUrl: noUndefined(compMeta.templateUrl),
styles: compMeta.styles || [],
styleUrls: compMeta.styleUrls || [],
animations: animations || [],
interpolation: noUndefined(dirMeta.interpolation),
isInline: !!dirMeta.template,
interpolation: noUndefined(compMeta.interpolation),
isInline: !!compMeta.template,
externalStylesheets: [],
ngContentSelectors: [],
preserveWhitespaces: noUndefined(dirMeta.preserveWhitespaces),
@ -278,16 +277,17 @@ export class CompileMetadataResolver {
let entryComponentMetadata: cpl.CompileEntryComponentMetadata[] = [];
let selector = dirMeta.selector;
if (dirMeta instanceof Component) {
if (createComponent.isTypeOf(dirMeta)) {
// Component
changeDetectionStrategy = dirMeta.changeDetection !;
if (dirMeta.viewProviders) {
const compMeta = dirMeta as Component;
changeDetectionStrategy = compMeta.changeDetection !;
if (compMeta.viewProviders) {
viewProviders = this._getProvidersMetadata(
dirMeta.viewProviders, entryComponentMetadata,
compMeta.viewProviders, entryComponentMetadata,
`viewProviders for "${stringifyType(directiveType)}"`, [], directiveType);
}
if (dirMeta.entryComponents) {
entryComponentMetadata = flattenAndDedupeArray(dirMeta.entryComponents)
if (compMeta.entryComponents) {
entryComponentMetadata = flattenAndDedupeArray(compMeta.entryComponents)
.map((type) => this._getEntryComponentMetadata(type) !)
.concat(entryComponentMetadata);
}
@ -444,7 +444,7 @@ export class CompileMetadataResolver {
if (meta.imports) {
flattenAndDedupeArray(meta.imports).forEach((importedType) => {
let importedModuleType: Type<any> = undefined !;
let importedModuleType: Type = undefined !;
if (isValidType(importedType)) {
importedModuleType = importedType;
} else if (importedType && importedType.ngModule) {
@ -603,7 +603,7 @@ export class CompileMetadataResolver {
return compileMeta;
}
private _checkSelfImport(moduleType: Type<any>, importedModuleType: Type<any>): boolean {
private _checkSelfImport(moduleType: Type, importedModuleType: Type): boolean {
if (moduleType === importedModuleType) {
this._reportError(
syntaxError(`'${stringifyType(moduleType)}' module can't import itself`), moduleType);
@ -612,7 +612,7 @@ export class CompileMetadataResolver {
return false;
}
private _getTypeDescriptor(type: Type<any>): string {
private _getTypeDescriptor(type: Type): string {
if (this.isDirective(type)) {
return 'directive';
}
@ -633,7 +633,7 @@ export class CompileMetadataResolver {
}
private _addTypeToModule(type: Type<any>, moduleType: Type<any>) {
private _addTypeToModule(type: Type, moduleType: Type) {
const oldModule = this._ngModuleOfTypes.get(type);
if (oldModule && oldModule !== moduleType) {
this._reportError(
@ -685,16 +685,14 @@ export class CompileMetadataResolver {
return result;
}
private _getIdentifierMetadata(type: Type<any>): cpl.CompileIdentifierMetadata {
private _getIdentifierMetadata(type: Type): cpl.CompileIdentifierMetadata {
type = resolveForwardRef(type);
return {reference: type};
}
isInjectable(type: any): boolean {
const annotations = this._reflector.annotations(type);
// Note: We need an exact check here as @Component / @Directive / ... inherit
// from @CompilerInjectable!
return annotations.some(ann => ann.constructor === Injectable);
return annotations.some(ann => createInjectable.isTypeOf(ann));
}
getInjectableSummary(type: any): cpl.CompileTypeSummary {
@ -704,7 +702,7 @@ export class CompileMetadataResolver {
};
}
private _getInjectableMetadata(type: Type<any>, dependencies: any[]|null = null):
private _getInjectableMetadata(type: Type, dependencies: any[]|null = null):
cpl.CompileTypeMetadata {
const typeSummary = this._loadSummary(type, cpl.CompileSummaryKind.Injectable);
if (typeSummary) {
@ -713,9 +711,8 @@ export class CompileMetadataResolver {
return this._getTypeMetadata(type, dependencies);
}
private _getTypeMetadata(
type: Type<any>, dependencies: any[]|null = null,
throwOnUnknownDeps = true): cpl.CompileTypeMetadata {
private _getTypeMetadata(type: Type, dependencies: any[]|null = null, throwOnUnknownDeps = true):
cpl.CompileTypeMetadata {
const identifier = this._getIdentifierMetadata(type);
return {
reference: identifier.reference,
@ -780,7 +777,7 @@ export class CompileMetadataResolver {
}
private _getDependenciesMetadata(
typeOrFunc: Type<any>|Function, dependencies: any[]|null,
typeOrFunc: Type|Function, dependencies: any[]|null,
throwOnUnknownDeps = true): cpl.CompileDiDependencyMetadata[] {
let hasUnknownDeps = false;
const params = dependencies || this._reflector.parameters(typeOrFunc) || [];
@ -794,20 +791,21 @@ export class CompileMetadataResolver {
let token: any = null;
if (Array.isArray(param)) {
param.forEach((paramEntry) => {
if (paramEntry instanceof Host) {
if (createHost.isTypeOf(paramEntry)) {
isHost = true;
} else if (paramEntry instanceof Self) {
} else if (createSelf.isTypeOf(paramEntry)) {
isSelf = true;
} else if (paramEntry instanceof SkipSelf) {
} else if (createSkipSelf.isTypeOf(paramEntry)) {
isSkipSelf = true;
} else if (paramEntry instanceof Optional) {
} else if (createOptional.isTypeOf(paramEntry)) {
isOptional = true;
} else if (paramEntry instanceof Attribute) {
} else if (createAttribute.isTypeOf(paramEntry)) {
isAttribute = true;
token = paramEntry.attributeName;
} else if (paramEntry instanceof Inject) {
} else if (createInject.isTypeOf(paramEntry)) {
token = paramEntry.token;
} else if (paramEntry instanceof InjectionToken) {
} else if (
createInjectionToken.isTypeOf(paramEntry) || paramEntry instanceof StaticSymbol) {
token = paramEntry;
} else if (isValidType(paramEntry) && token == null) {
token = paramEntry;
@ -995,7 +993,7 @@ export class CompileMetadataResolver {
private _getQueriesMetadata(
queries: {[key: string]: Query}, isViewQuery: boolean,
directiveType: Type<any>): cpl.CompileQueryMetadata[] {
directiveType: Type): cpl.CompileQueryMetadata[] {
const res: cpl.CompileQueryMetadata[] = [];
Object.keys(queries).forEach((propertyName: string) => {
@ -1010,7 +1008,7 @@ export class CompileMetadataResolver {
private _queryVarBindings(selector: any): string[] { return selector.split(/\s*,\s*/); }
private _getQueryMetadata(q: Query, propertyName: string, typeOrFunc: Type<any>|Function):
private _getQueryMetadata(q: Query, propertyName: string, typeOrFunc: Type|Function):
cpl.CompileQueryMetadata {
let selectors: cpl.CompileTokenMetadata[];
if (typeof q.selector === 'string') {
@ -1098,9 +1096,9 @@ function stringifyType(type: any): string {
/**
* Indicates that a component is still being loaded in a synchronous compile.
*/
function componentStillLoadingError(compType: Type<any>) {
function componentStillLoadingError(compType: Type) {
const error =
Error(`Can't compile synchronously as ${stringify(compType)} is still being loaded!`);
(error as any)[ɵERROR_COMPONENT_TYPE] = compType;
(error as any)[ERROR_COMPONENT_TYPE] = compType;
return error;
}