refactor(compiler): make `OutputAst` contain the moduleName, not the filePath (#16832).
The goal of this change is to simplify the emitters, as we will soon create a new one to emit TypeScript nodes directly.
This commit is contained in:
parent
3b28c75d1f
commit
6123b9c0c6
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileStylesheetMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers';
|
||||
import {CompileMetadataResolver} from '../metadata_resolver';
|
||||
|
@ -16,8 +16,8 @@ import * as o from '../output/output_ast';
|
|||
import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
|
||||
import {SummaryResolver} from '../summary_resolver';
|
||||
import {TemplateParser} from '../template_parser/template_parser';
|
||||
import {syntaxError} from '../util';
|
||||
import {ViewCompiler} from '../view_compiler/view_compiler';
|
||||
import {OutputContext, syntaxError} from '../util';
|
||||
import {ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler';
|
||||
|
||||
import {AotCompilerHost} from './compiler_host';
|
||||
import {GeneratedFile} from './generated_file';
|
||||
|
@ -60,16 +60,15 @@ export class AotCompiler {
|
|||
directives: StaticSymbol[], pipes: StaticSymbol[], ngModules: StaticSymbol[],
|
||||
injectables: StaticSymbol[]): GeneratedFile[] {
|
||||
const fileSuffix = splitTypescriptSuffix(srcFileUrl, true)[1];
|
||||
const statements: o.Statement[] = [];
|
||||
const exportedVars: string[] = [];
|
||||
const generatedFiles: GeneratedFile[] = [];
|
||||
|
||||
generatedFiles.push(...this._createSummary(
|
||||
srcFileUrl, directives, pipes, ngModules, injectables, statements, exportedVars));
|
||||
const outputCtx = this._createOutputContext(ngfactoryFilePath(srcFileUrl, true));
|
||||
|
||||
generatedFiles.push(
|
||||
...this._createSummary(srcFileUrl, directives, pipes, ngModules, injectables, outputCtx));
|
||||
|
||||
// compile all ng modules
|
||||
exportedVars.push(
|
||||
...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements)));
|
||||
ngModules.forEach((ngModuleType) => this._compileModule(outputCtx, ngModuleType));
|
||||
|
||||
// compile components
|
||||
directives.forEach((dirType) => {
|
||||
|
@ -86,22 +85,20 @@ export class AotCompiler {
|
|||
_assertComponent(compMeta);
|
||||
|
||||
// compile styles
|
||||
const stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
|
||||
stylesCompileResults.externalStylesheets.forEach((compiledStyleSheet) => {
|
||||
generatedFiles.push(this._codgenStyles(srcFileUrl, compiledStyleSheet, fileSuffix));
|
||||
const componentStylesheet = this._styleCompiler.compileComponent(outputCtx, compMeta);
|
||||
// Note: compMeta is a component and therefore template is non null.
|
||||
compMeta.template !.externalStylesheets.forEach((stylesheetMeta) => {
|
||||
generatedFiles.push(this._codegenStyles(srcFileUrl, compMeta, stylesheetMeta, fileSuffix));
|
||||
});
|
||||
|
||||
// compile components
|
||||
const compViewVars = this._compileComponent(
|
||||
compMeta, ngModule, ngModule.transitiveModule.directives,
|
||||
stylesCompileResults.componentStylesheet, fileSuffix, statements);
|
||||
exportedVars.push(
|
||||
this._compileComponentFactory(compMeta, ngModule, fileSuffix, statements),
|
||||
compViewVars.viewClassVar, compViewVars.compRenderTypeVar);
|
||||
outputCtx, compMeta, ngModule, ngModule.transitiveModule.directives, componentStylesheet,
|
||||
fileSuffix);
|
||||
this._compileComponentFactory(outputCtx, compMeta, ngModule, fileSuffix);
|
||||
});
|
||||
if (statements.length > 0) {
|
||||
const srcModule = this._codegenSourceModule(
|
||||
srcFileUrl, ngfactoryFilePath(srcFileUrl, true), statements, exportedVars);
|
||||
if (outputCtx.statements.length > 0) {
|
||||
const srcModule = this._codegenSourceModule(srcFileUrl, outputCtx);
|
||||
generatedFiles.unshift(srcModule);
|
||||
}
|
||||
return generatedFiles;
|
||||
|
@ -109,8 +106,8 @@ export class AotCompiler {
|
|||
|
||||
private _createSummary(
|
||||
srcFileUrl: string, directives: StaticSymbol[], pipes: StaticSymbol[],
|
||||
ngModules: StaticSymbol[], injectables: StaticSymbol[], targetStatements: o.Statement[],
|
||||
targetExportedVars: string[]): GeneratedFile[] {
|
||||
ngModules: StaticSymbol[], injectables: StaticSymbol[],
|
||||
ngFactoryCtx: OutputContext): GeneratedFile[] {
|
||||
const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileUrl)
|
||||
.map(symbol => this._symbolResolver.resolveSymbol(symbol));
|
||||
const typeData: {
|
||||
|
@ -136,22 +133,23 @@ export class AotCompiler {
|
|||
metadata: this._metadataResolver.getInjectableSummary(ref) !.type
|
||||
}))
|
||||
];
|
||||
const {json, exportAs, forJit} =
|
||||
serializeSummaries(this._summaryResolver, this._symbolResolver, symbolSummaries, typeData);
|
||||
const forJitOutputCtx = this._createOutputContext(summaryForJitFileName(srcFileUrl, true));
|
||||
const forJitTargetFilePath = summaryForJitFileName(srcFileUrl, true);
|
||||
const {json, exportAs} = serializeSummaries(
|
||||
forJitOutputCtx, this._summaryResolver, this._symbolResolver, symbolSummaries, typeData);
|
||||
exportAs.forEach((entry) => {
|
||||
targetStatements.push(
|
||||
o.variable(entry.exportAs).set(o.importExpr({reference: entry.symbol})).toDeclStmt());
|
||||
targetExportedVars.push(entry.exportAs);
|
||||
ngFactoryCtx.statements.push(
|
||||
o.variable(entry.exportAs).set(ngFactoryCtx.importExpr(entry.symbol)).toDeclStmt(null, [
|
||||
o.StmtModifier.Exported
|
||||
]));
|
||||
});
|
||||
return [
|
||||
new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json),
|
||||
this._codegenSourceModule(
|
||||
srcFileUrl, summaryForJitFileName(srcFileUrl, true), forJit.statements,
|
||||
forJit.exportedVars)
|
||||
this._codegenSourceModule(srcFileUrl, forJitOutputCtx)
|
||||
];
|
||||
}
|
||||
|
||||
private _compileModule(ngModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
|
||||
private _compileModule(outputCtx: OutputContext, ngModuleType: StaticSymbol): void {
|
||||
const ngModule = this._metadataResolver.getNgModuleMetadata(ngModuleType) !;
|
||||
const providers: CompileProviderMetadata[] = [];
|
||||
|
||||
|
@ -169,20 +167,17 @@ export class AotCompiler {
|
|||
});
|
||||
}
|
||||
|
||||
const appCompileResult = this._ngModuleCompiler.compile(ngModule, providers);
|
||||
targetStatements.push(...appCompileResult.statements);
|
||||
return appCompileResult.ngModuleFactoryVar;
|
||||
this._ngModuleCompiler.compile(outputCtx, ngModule, providers);
|
||||
}
|
||||
|
||||
private _compileComponentFactory(
|
||||
compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata, fileSuffix: string,
|
||||
targetStatements: o.Statement[]): string {
|
||||
outputCtx: OutputContext, compMeta: CompileDirectiveMetadata,
|
||||
ngModule: CompileNgModuleMetadata, fileSuffix: string): void {
|
||||
const hostType = this._metadataResolver.getHostComponentType(compMeta.type.reference);
|
||||
const hostMeta = createHostComponentMeta(
|
||||
hostType, compMeta, this._metadataResolver.getHostComponentViewClass(hostType));
|
||||
const hostViewFactoryVar =
|
||||
this._compileComponent(
|
||||
hostMeta, ngModule, [compMeta.type], null, fileSuffix, targetStatements)
|
||||
this._compileComponent(outputCtx, hostMeta, ngModule, [compMeta.type], null, fileSuffix)
|
||||
.viewClassVar;
|
||||
const compFactoryVar = componentFactoryName(compMeta.type.reference);
|
||||
const inputsExprs: o.LiteralMapEntry[] = [];
|
||||
|
@ -198,10 +193,10 @@ export class AotCompiler {
|
|||
outputsExprs.push(new o.LiteralMapEntry(propName, o.literal(templateName), false));
|
||||
}
|
||||
|
||||
targetStatements.push(
|
||||
outputCtx.statements.push(
|
||||
o.variable(compFactoryVar)
|
||||
.set(o.importExpr(createIdentifier(Identifiers.createComponentFactory)).callFn([
|
||||
o.literal(compMeta.selector), o.importExpr(compMeta.type),
|
||||
.set(o.importExpr(Identifiers.createComponentFactory).callFn([
|
||||
o.literal(compMeta.selector), outputCtx.importExpr(compMeta.type.reference),
|
||||
o.variable(hostViewFactoryVar), new o.LiteralMapExpr(inputsExprs),
|
||||
new o.LiteralMapExpr(outputsExprs),
|
||||
o.literalArr(
|
||||
|
@ -209,17 +204,16 @@ export class AotCompiler {
|
|||
]))
|
||||
.toDeclStmt(
|
||||
o.importType(
|
||||
createIdentifier(Identifiers.ComponentFactory), [o.importType(compMeta.type) !],
|
||||
Identifiers.ComponentFactory,
|
||||
[o.expressionType(outputCtx.importExpr(compMeta.type.reference)) !],
|
||||
[o.TypeModifier.Const]),
|
||||
[o.StmtModifier.Final]));
|
||||
return compFactoryVar;
|
||||
[o.StmtModifier.Final, o.StmtModifier.Exported]));
|
||||
}
|
||||
|
||||
private _compileComponent(
|
||||
compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata,
|
||||
directiveIdentifiers: CompileIdentifierMetadata[], componentStyles: CompiledStylesheet|null,
|
||||
fileSuffix: string,
|
||||
targetStatements: o.Statement[]): {viewClassVar: string, compRenderTypeVar: string} {
|
||||
outputCtx: OutputContext, compMeta: CompileDirectiveMetadata,
|
||||
ngModule: CompileNgModuleMetadata, directiveIdentifiers: CompileIdentifierMetadata[],
|
||||
componentStyles: CompiledStylesheet|null, fileSuffix: string): ViewCompileResult {
|
||||
const directives =
|
||||
directiveIdentifiers.map(dir => this._metadataResolver.getDirectiveSummary(dir.reference));
|
||||
const pipes = ngModule.transitiveModule.pipes.map(
|
||||
|
@ -229,44 +223,70 @@ export class AotCompiler {
|
|||
compMeta, compMeta.template !.template !, directives, pipes, ngModule.schemas,
|
||||
templateSourceUrl(ngModule.type, compMeta, compMeta.template !));
|
||||
const stylesExpr = componentStyles ? o.variable(componentStyles.stylesVar) : o.literalArr([]);
|
||||
const viewResult =
|
||||
this._viewCompiler.compileComponent(compMeta, parsedTemplate, stylesExpr, usedPipes);
|
||||
const viewResult = this._viewCompiler.compileComponent(
|
||||
outputCtx, compMeta, parsedTemplate, stylesExpr, usedPipes);
|
||||
if (componentStyles) {
|
||||
targetStatements.push(
|
||||
..._resolveStyleStatements(this._symbolResolver, componentStyles, fileSuffix));
|
||||
_resolveStyleStatements(
|
||||
this._symbolResolver, componentStyles, this._styleCompiler.needsStyleShim(compMeta),
|
||||
fileSuffix);
|
||||
}
|
||||
targetStatements.push(...viewResult.statements);
|
||||
return {viewClassVar: viewResult.viewClassVar, compRenderTypeVar: viewResult.rendererTypeVar};
|
||||
return viewResult;
|
||||
}
|
||||
|
||||
private _codgenStyles(
|
||||
fileUrl: string, stylesCompileResult: CompiledStylesheet, fileSuffix: string): GeneratedFile {
|
||||
_resolveStyleStatements(this._symbolResolver, stylesCompileResult, fileSuffix);
|
||||
return this._codegenSourceModule(
|
||||
fileUrl,
|
||||
_stylesModuleUrl(
|
||||
stylesCompileResult.meta.moduleUrl !, stylesCompileResult.isShimmed, fileSuffix),
|
||||
stylesCompileResult.statements, [stylesCompileResult.stylesVar]);
|
||||
private _createOutputContext(genFilePath: string): OutputContext {
|
||||
const importExpr = (symbol: StaticSymbol, typeParams: o.Type[] | null = null) => {
|
||||
if (!(symbol instanceof StaticSymbol)) {
|
||||
throw new Error(`Internal error: unknown identifier ${JSON.stringify(symbol)}`);
|
||||
}
|
||||
const arity = this._symbolResolver.getTypeArity(symbol) || 0;
|
||||
const {filePath, name, members} = this._symbolResolver.getImportAs(symbol) || symbol;
|
||||
const moduleName = this._symbolResolver.fileNameToModuleName(filePath, genFilePath);
|
||||
// If we are in a type expression that refers to a generic type then supply
|
||||
// the required type parameters. If there were not enough type parameters
|
||||
// supplied, supply any as the type. Outside a type expression the reference
|
||||
// should not supply type parameters and be treated as a simple value reference
|
||||
// to the constructor function itself.
|
||||
const suppliedTypeParams = typeParams || [];
|
||||
const missingTypeParamsCount = arity - suppliedTypeParams.length;
|
||||
const allTypeParams =
|
||||
suppliedTypeParams.concat(new Array(missingTypeParamsCount).fill(o.DYNAMIC_TYPE));
|
||||
return members.reduce(
|
||||
(expr, memberName) => expr.prop(memberName),
|
||||
<o.Expression>o.importExpr(
|
||||
new o.ExternalReference(moduleName, name, null), allTypeParams));
|
||||
};
|
||||
|
||||
return {statements: [], genFilePath, importExpr};
|
||||
}
|
||||
|
||||
private _codegenSourceModule(
|
||||
srcFileUrl: string, genFileUrl: string, statements: o.Statement[],
|
||||
exportedVars: string[]): GeneratedFile {
|
||||
private _codegenStyles(
|
||||
srcFileUrl: string, compMeta: CompileDirectiveMetadata,
|
||||
stylesheetMetadata: CompileStylesheetMetadata, fileSuffix: string): GeneratedFile {
|
||||
const outputCtx = this._createOutputContext(_stylesModuleUrl(
|
||||
stylesheetMetadata.moduleUrl !, this._styleCompiler.needsStyleShim(compMeta), fileSuffix));
|
||||
const compiledStylesheet =
|
||||
this._styleCompiler.compileStyles(outputCtx, compMeta, stylesheetMetadata);
|
||||
_resolveStyleStatements(
|
||||
this._symbolResolver, compiledStylesheet, this._styleCompiler.needsStyleShim(compMeta),
|
||||
fileSuffix);
|
||||
return this._codegenSourceModule(srcFileUrl, outputCtx);
|
||||
}
|
||||
|
||||
private _codegenSourceModule(srcFileUrl: string, ctx: OutputContext): GeneratedFile {
|
||||
return new GeneratedFile(
|
||||
srcFileUrl, genFileUrl,
|
||||
srcFileUrl, ctx.genFilePath,
|
||||
this._outputEmitter.emitStatements(
|
||||
sourceUrl(srcFileUrl), genFileUrl, statements, exportedVars, this._genFilePreamble));
|
||||
sourceUrl(srcFileUrl), ctx.genFilePath, ctx.statements, this._genFilePreamble));
|
||||
}
|
||||
}
|
||||
|
||||
function _resolveStyleStatements(
|
||||
reflector: StaticSymbolResolver, compileResult: CompiledStylesheet,
|
||||
fileSuffix: string): o.Statement[] {
|
||||
symbolResolver: StaticSymbolResolver, compileResult: CompiledStylesheet, needsShim: boolean,
|
||||
fileSuffix: string): void {
|
||||
compileResult.dependencies.forEach((dep) => {
|
||||
dep.valuePlaceholder.reference = reflector.getStaticSymbol(
|
||||
_stylesModuleUrl(dep.moduleUrl, dep.isShimmed, fileSuffix), dep.name);
|
||||
dep.setValue(symbolResolver.getStaticSymbol(
|
||||
_stylesModuleUrl(dep.moduleUrl, needsShim, fileSuffix), dep.name));
|
||||
});
|
||||
return compileResult.statements;
|
||||
}
|
||||
|
||||
function _stylesModuleUrl(stylesheetUrl: string, shim: boolean, suffix: string): string {
|
||||
|
|
|
@ -71,8 +71,7 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
|
|||
const viewCompiler = new ViewCompiler(config, elementSchemaRegistry);
|
||||
const compiler = new AotCompiler(
|
||||
config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler,
|
||||
new NgModuleCompiler(), new TypeScriptEmitter(symbolResolver), summaryResolver,
|
||||
options.locale || null, options.i18nFormat || null, options.genFilePreamble || null,
|
||||
symbolResolver);
|
||||
new NgModuleCompiler(), new TypeScriptEmitter(), summaryResolver, options.locale || null,
|
||||
options.i18nFormat || null, options.genFilePreamble || null, symbolResolver);
|
||||
return {compiler, reflector: staticReflector};
|
||||
}
|
||||
|
|
|
@ -8,25 +8,21 @@
|
|||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary} from '../compile_metadata';
|
||||
import * as o from '../output/output_ast';
|
||||
import {Summary, SummaryResolver} from '../summary_resolver';
|
||||
import {ValueTransformer, ValueVisitor, visitValue} from '../util';
|
||||
import {OutputContext, ValueTransformer, ValueVisitor, visitValue} from '../util';
|
||||
|
||||
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
||||
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
|
||||
import {summaryForJitFileName, summaryForJitName} from './util';
|
||||
|
||||
export function serializeSummaries(
|
||||
summaryResolver: SummaryResolver<StaticSymbol>, symbolResolver: StaticSymbolResolver,
|
||||
symbols: ResolvedStaticSymbol[], types: {
|
||||
forJitCtx: OutputContext, summaryResolver: SummaryResolver<StaticSymbol>,
|
||||
symbolResolver: StaticSymbolResolver, symbols: ResolvedStaticSymbol[], types: {
|
||||
summary: CompileTypeSummary,
|
||||
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
|
||||
CompileTypeMetadata
|
||||
}[]): {
|
||||
json: string,
|
||||
exportAs: {symbol: StaticSymbol, exportAs: string}[],
|
||||
forJit: {statements: o.Statement[], exportedVars: string[]}
|
||||
} {
|
||||
}[]): {json: string, exportAs: {symbol: StaticSymbol, exportAs: string}[]} {
|
||||
const toJsonSerializer = new ToJsonSerializer(symbolResolver, summaryResolver);
|
||||
const forJitSerializer = new ForJitSerializer(symbolResolver);
|
||||
const forJitSerializer = new ForJitSerializer(forJitCtx, symbolResolver);
|
||||
|
||||
// for symbols, we use everything except for the class metadata itself
|
||||
// (we keep the statics though), as the class metadata is contained in the
|
||||
|
@ -81,8 +77,8 @@ export function serializeSummaries(
|
|||
}
|
||||
});
|
||||
const {json, exportAs} = toJsonSerializer.serialize();
|
||||
const {statements, exportedVars} = forJitSerializer.serialize(exportAs);
|
||||
return {json, forJit: {statements, exportedVars}, exportAs};
|
||||
forJitSerializer.serialize(exportAs);
|
||||
return {json, exportAs};
|
||||
}
|
||||
|
||||
export function deserializeSummaries(symbolCache: StaticSymbolCache, json: string):
|
||||
|
@ -192,7 +188,7 @@ class ForJitSerializer {
|
|||
isLibrary: boolean
|
||||
}>();
|
||||
|
||||
constructor(private symbolResolver: StaticSymbolResolver) {}
|
||||
constructor(private outputCtx: OutputContext, private symbolResolver: StaticSymbolResolver) {}
|
||||
|
||||
addSourceType(
|
||||
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|
|
||||
|
@ -204,10 +200,7 @@ class ForJitSerializer {
|
|||
this.data.set(summary.type.reference, {summary, metadata: null, isLibrary: true});
|
||||
}
|
||||
|
||||
serialize(exportAs: {symbol: StaticSymbol, exportAs: string}[]):
|
||||
{statements: o.Statement[], exportedVars: string[]} {
|
||||
const statements: o.Statement[] = [];
|
||||
const exportedVars: string[] = [];
|
||||
serialize(exportAs: {symbol: StaticSymbol, exportAs: string}[]): void {
|
||||
const ngModuleSymbols = new Set<StaticSymbol>();
|
||||
|
||||
Array.from(this.data.values()).forEach(({summary, metadata, isLibrary}) => {
|
||||
|
@ -222,11 +215,10 @@ class ForJitSerializer {
|
|||
}
|
||||
if (!isLibrary) {
|
||||
const fnName = summaryForJitName(summary.type.reference.name);
|
||||
statements.push(
|
||||
this.outputCtx.statements.push(
|
||||
o.fn([], [new o.ReturnStatement(this.serializeSummaryWithDeps(summary, metadata !))],
|
||||
new o.ArrayType(o.DYNAMIC_TYPE))
|
||||
.toDeclStmt(fnName, [o.StmtModifier.Final]));
|
||||
exportedVars.push(fnName);
|
||||
.toDeclStmt(fnName, [o.StmtModifier.Final, o.StmtModifier.Exported]));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -234,13 +226,12 @@ class ForJitSerializer {
|
|||
const symbol = entry.symbol;
|
||||
if (ngModuleSymbols.has(symbol)) {
|
||||
const jitExportAsName = summaryForJitName(entry.exportAs);
|
||||
statements.push(
|
||||
o.variable(jitExportAsName).set(this.serializeSummaryRef(symbol)).toDeclStmt());
|
||||
exportedVars.push(jitExportAsName);
|
||||
this.outputCtx.statements.push(
|
||||
o.variable(jitExportAsName).set(this.serializeSummaryRef(symbol)).toDeclStmt(null, [
|
||||
o.StmtModifier.Exported
|
||||
]));
|
||||
}
|
||||
});
|
||||
|
||||
return {statements, exportedVars};
|
||||
}
|
||||
|
||||
private serializeSummaryWithDeps(
|
||||
|
@ -283,10 +274,12 @@ class ForJitSerializer {
|
|||
private serializeSummaryRef(typeSymbol: StaticSymbol): o.Expression {
|
||||
const jitImportedSymbol = this.symbolResolver.getStaticSymbol(
|
||||
summaryForJitFileName(typeSymbol.filePath), summaryForJitName(typeSymbol.name));
|
||||
return o.importExpr({reference: jitImportedSymbol});
|
||||
return this.outputCtx.importExpr(jitImportedSymbol);
|
||||
}
|
||||
|
||||
private serializeSummary(data: {[key: string]: any}): o.Expression {
|
||||
const outputCtx = this.outputCtx;
|
||||
|
||||
class Transformer implements ValueVisitor {
|
||||
visitArray(arr: any[], context: any): any {
|
||||
return o.literalArr(arr.map(entry => visitValue(entry, this, context)));
|
||||
|
@ -298,7 +291,7 @@ class ForJitSerializer {
|
|||
visitPrimitive(value: any, context: any): any { return o.literal(value); }
|
||||
visitOther(value: any, context: any): any {
|
||||
if (value instanceof StaticSymbol) {
|
||||
return o.importExpr({reference: value});
|
||||
return outputCtx.importExpr(value);
|
||||
} else {
|
||||
throw new Error(`Illegal State: Encountered value ${value}`);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ export * from './ml_parser/html_tags';
|
|||
export * from './ml_parser/interpolation_config';
|
||||
export * from './ml_parser/tags';
|
||||
export {NgModuleCompiler} from './ng_module_compiler';
|
||||
export * from './output/path_util';
|
||||
export * from './output/ts_emitter';
|
||||
export * from './parse_util';
|
||||
export * from './schema/dom_element_schema_registry';
|
||||
|
|
|
@ -286,10 +286,8 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
|
|||
args.push(o.literal(ast.strings[ast.strings.length - 1]));
|
||||
|
||||
return ast.expressions.length <= 9 ?
|
||||
o.importExpr(createIdentifier(Identifiers.inlineInterpolate)).callFn(args) :
|
||||
o.importExpr(createIdentifier(Identifiers.interpolate)).callFn([
|
||||
args[0], o.literalArr(args.slice(1))
|
||||
]);
|
||||
o.importExpr(Identifiers.inlineInterpolate).callFn(args) :
|
||||
o.importExpr(Identifiers.interpolate).callFn([args[0], o.literalArr(args.slice(1))]);
|
||||
}
|
||||
|
||||
visitKeyedRead(ast: cdAst.KeyedRead, mode: _Mode): any {
|
||||
|
|
|
@ -9,117 +9,129 @@
|
|||
import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, NgModuleRef, QueryList, Renderer, SecurityContext, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation, ɵCodegenComponentFactoryResolver, ɵEMPTY_ARRAY, ɵEMPTY_MAP, ɵand, ɵccf, ɵcmf, ɵcrt, ɵdid, ɵeld, ɵinlineInterpolate, ɵinterpolate, ɵmod, ɵmpd, ɵncd, ɵnov, ɵpad, ɵpid, ɵpod, ɵppd, ɵprd, ɵqud, ɵreflector, ɵregisterModuleFactory, ɵted, ɵunv, ɵvid} from '@angular/core';
|
||||
|
||||
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||
import * as o from './output/output_ast';
|
||||
|
||||
const CORE = assetUrl('core');
|
||||
|
||||
export interface IdentifierSpec {
|
||||
name: string;
|
||||
moduleUrl: string;
|
||||
runtime: any;
|
||||
}
|
||||
|
||||
export class Identifiers {
|
||||
static ANALYZE_FOR_ENTRY_COMPONENTS: IdentifierSpec = {
|
||||
static ANALYZE_FOR_ENTRY_COMPONENTS: o.ExternalReference = {
|
||||
name: 'ANALYZE_FOR_ENTRY_COMPONENTS',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ANALYZE_FOR_ENTRY_COMPONENTS
|
||||
};
|
||||
static ElementRef: IdentifierSpec = {name: 'ElementRef', moduleUrl: CORE, runtime: ElementRef};
|
||||
static NgModuleRef: IdentifierSpec = {name: 'NgModuleRef', moduleUrl: CORE, runtime: NgModuleRef};
|
||||
static ElementRef:
|
||||
o.ExternalReference = {name: 'ElementRef', moduleName: CORE, runtime: ElementRef};
|
||||
static NgModuleRef:
|
||||
o.ExternalReference = {name: 'NgModuleRef', moduleName: CORE, runtime: NgModuleRef};
|
||||
static ViewContainerRef:
|
||||
IdentifierSpec = {name: 'ViewContainerRef', moduleUrl: CORE, runtime: ViewContainerRef};
|
||||
static ChangeDetectorRef:
|
||||
IdentifierSpec = {name: 'ChangeDetectorRef', moduleUrl: CORE, runtime: ChangeDetectorRef};
|
||||
static QueryList: IdentifierSpec = {name: 'QueryList', moduleUrl: CORE, runtime: QueryList};
|
||||
static TemplateRef: IdentifierSpec = {name: 'TemplateRef', moduleUrl: CORE, runtime: TemplateRef};
|
||||
static CodegenComponentFactoryResolver: IdentifierSpec = {
|
||||
o.ExternalReference = {name: 'ViewContainerRef', moduleName: CORE, runtime: ViewContainerRef};
|
||||
static ChangeDetectorRef: o.ExternalReference = {
|
||||
name: 'ChangeDetectorRef',
|
||||
moduleName: CORE,
|
||||
runtime: ChangeDetectorRef
|
||||
};
|
||||
static QueryList: o.ExternalReference = {name: 'QueryList', moduleName: CORE, runtime: QueryList};
|
||||
static TemplateRef:
|
||||
o.ExternalReference = {name: 'TemplateRef', moduleName: CORE, runtime: TemplateRef};
|
||||
static CodegenComponentFactoryResolver: o.ExternalReference = {
|
||||
name: 'ɵCodegenComponentFactoryResolver',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ɵCodegenComponentFactoryResolver
|
||||
};
|
||||
static ComponentFactoryResolver: IdentifierSpec = {
|
||||
static ComponentFactoryResolver: o.ExternalReference = {
|
||||
name: 'ComponentFactoryResolver',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ComponentFactoryResolver
|
||||
};
|
||||
static ComponentFactory:
|
||||
IdentifierSpec = {name: 'ComponentFactory', moduleUrl: CORE, runtime: ComponentFactory};
|
||||
o.ExternalReference = {name: 'ComponentFactory', moduleName: CORE, runtime: ComponentFactory};
|
||||
static ComponentRef:
|
||||
IdentifierSpec = {name: 'ComponentRef', moduleUrl: CORE, runtime: ComponentRef};
|
||||
o.ExternalReference = {name: 'ComponentRef', moduleName: CORE, runtime: ComponentRef};
|
||||
static NgModuleFactory:
|
||||
IdentifierSpec = {name: 'NgModuleFactory', moduleUrl: CORE, runtime: NgModuleFactory};
|
||||
static createModuleFactory: IdentifierSpec = {
|
||||
o.ExternalReference = {name: 'NgModuleFactory', moduleName: CORE, runtime: NgModuleFactory};
|
||||
static createModuleFactory: o.ExternalReference = {
|
||||
name: 'ɵcmf',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ɵcmf,
|
||||
};
|
||||
static moduleDef: IdentifierSpec = {
|
||||
static moduleDef: o.ExternalReference = {
|
||||
name: 'ɵmod',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ɵmod,
|
||||
};
|
||||
static moduleProviderDef: IdentifierSpec = {
|
||||
static moduleProviderDef: o.ExternalReference = {
|
||||
name: 'ɵmpd',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ɵmpd,
|
||||
};
|
||||
static RegisterModuleFactoryFn: IdentifierSpec = {
|
||||
static RegisterModuleFactoryFn: o.ExternalReference = {
|
||||
name: 'ɵregisterModuleFactory',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ɵregisterModuleFactory,
|
||||
};
|
||||
static Injector: IdentifierSpec = {name: 'Injector', moduleUrl: CORE, runtime: Injector};
|
||||
static ViewEncapsulation:
|
||||
IdentifierSpec = {name: 'ViewEncapsulation', moduleUrl: CORE, runtime: ViewEncapsulation};
|
||||
static ChangeDetectionStrategy: IdentifierSpec = {
|
||||
static Injector: o.ExternalReference = {name: 'Injector', moduleName: CORE, runtime: Injector};
|
||||
static ViewEncapsulation: o.ExternalReference = {
|
||||
name: 'ViewEncapsulation',
|
||||
moduleName: CORE,
|
||||
runtime: ViewEncapsulation
|
||||
};
|
||||
static ChangeDetectionStrategy: o.ExternalReference = {
|
||||
name: 'ChangeDetectionStrategy',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: ChangeDetectionStrategy
|
||||
};
|
||||
static SecurityContext: IdentifierSpec = {
|
||||
static SecurityContext: o.ExternalReference = {
|
||||
name: 'SecurityContext',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
runtime: SecurityContext,
|
||||
};
|
||||
static LOCALE_ID: IdentifierSpec = {name: 'LOCALE_ID', moduleUrl: CORE, runtime: LOCALE_ID};
|
||||
static TRANSLATIONS_FORMAT:
|
||||
IdentifierSpec = {name: 'TRANSLATIONS_FORMAT', moduleUrl: CORE, runtime: TRANSLATIONS_FORMAT};
|
||||
static inlineInterpolate:
|
||||
IdentifierSpec = {name: 'ɵinlineInterpolate', moduleUrl: CORE, runtime: ɵinlineInterpolate};
|
||||
static LOCALE_ID: o.ExternalReference = {name: 'LOCALE_ID', moduleName: CORE, runtime: LOCALE_ID};
|
||||
static TRANSLATIONS_FORMAT: o.ExternalReference = {
|
||||
name: 'TRANSLATIONS_FORMAT',
|
||||
moduleName: CORE,
|
||||
runtime: TRANSLATIONS_FORMAT
|
||||
};
|
||||
static inlineInterpolate: o.ExternalReference = {
|
||||
name: 'ɵinlineInterpolate',
|
||||
moduleName: CORE,
|
||||
runtime: ɵinlineInterpolate
|
||||
};
|
||||
static interpolate:
|
||||
IdentifierSpec = {name: 'ɵinterpolate', moduleUrl: CORE, runtime: ɵinterpolate};
|
||||
o.ExternalReference = {name: 'ɵinterpolate', moduleName: CORE, runtime: ɵinterpolate};
|
||||
static EMPTY_ARRAY:
|
||||
IdentifierSpec = {name: 'ɵEMPTY_ARRAY', moduleUrl: CORE, runtime: ɵEMPTY_ARRAY};
|
||||
static EMPTY_MAP: IdentifierSpec = {name: 'ɵEMPTY_MAP', moduleUrl: CORE, runtime: ɵEMPTY_MAP};
|
||||
static Renderer: IdentifierSpec = {name: 'Renderer', moduleUrl: CORE, runtime: Renderer};
|
||||
static viewDef: IdentifierSpec = {name: 'ɵvid', moduleUrl: CORE, runtime: ɵvid};
|
||||
static elementDef: IdentifierSpec = {name: 'ɵeld', moduleUrl: CORE, runtime: ɵeld};
|
||||
static anchorDef: IdentifierSpec = {name: 'ɵand', moduleUrl: CORE, runtime: ɵand};
|
||||
static textDef: IdentifierSpec = {name: 'ɵted', moduleUrl: CORE, runtime: ɵted};
|
||||
static directiveDef: IdentifierSpec = {name: 'ɵdid', moduleUrl: CORE, runtime: ɵdid};
|
||||
static providerDef: IdentifierSpec = {name: 'ɵprd', moduleUrl: CORE, runtime: ɵprd};
|
||||
static queryDef: IdentifierSpec = {name: 'ɵqud', moduleUrl: CORE, runtime: ɵqud};
|
||||
static pureArrayDef: IdentifierSpec = {name: 'ɵpad', moduleUrl: CORE, runtime: ɵpad};
|
||||
static pureObjectDef: IdentifierSpec = {name: 'ɵpod', moduleUrl: CORE, runtime: ɵpod};
|
||||
static purePipeDef: IdentifierSpec = {name: 'ɵppd', moduleUrl: CORE, runtime: ɵppd};
|
||||
static pipeDef: IdentifierSpec = {name: 'ɵpid', moduleUrl: CORE, runtime: ɵpid};
|
||||
static nodeValue: IdentifierSpec = {name: 'ɵnov', moduleUrl: CORE, runtime: ɵnov};
|
||||
static ngContentDef: IdentifierSpec = {name: 'ɵncd', moduleUrl: CORE, runtime: ɵncd};
|
||||
static unwrapValue: IdentifierSpec = {name: 'ɵunv', moduleUrl: CORE, runtime: ɵunv};
|
||||
static createRendererType2: IdentifierSpec = {name: 'ɵcrt', moduleUrl: CORE, runtime: ɵcrt};
|
||||
static RendererType2: IdentifierSpec = {
|
||||
o.ExternalReference = {name: 'ɵEMPTY_ARRAY', moduleName: CORE, runtime: ɵEMPTY_ARRAY};
|
||||
static EMPTY_MAP:
|
||||
o.ExternalReference = {name: 'ɵEMPTY_MAP', moduleName: CORE, runtime: ɵEMPTY_MAP};
|
||||
static Renderer: o.ExternalReference = {name: 'Renderer', moduleName: CORE, runtime: Renderer};
|
||||
static viewDef: o.ExternalReference = {name: 'ɵvid', moduleName: CORE, runtime: ɵvid};
|
||||
static elementDef: o.ExternalReference = {name: 'ɵeld', moduleName: CORE, runtime: ɵeld};
|
||||
static anchorDef: o.ExternalReference = {name: 'ɵand', moduleName: CORE, runtime: ɵand};
|
||||
static textDef: o.ExternalReference = {name: 'ɵted', moduleName: CORE, runtime: ɵted};
|
||||
static directiveDef: o.ExternalReference = {name: 'ɵdid', moduleName: CORE, runtime: ɵdid};
|
||||
static providerDef: o.ExternalReference = {name: 'ɵprd', moduleName: CORE, runtime: ɵprd};
|
||||
static queryDef: o.ExternalReference = {name: 'ɵqud', moduleName: CORE, runtime: ɵqud};
|
||||
static pureArrayDef: o.ExternalReference = {name: 'ɵpad', moduleName: CORE, runtime: ɵpad};
|
||||
static pureObjectDef: o.ExternalReference = {name: 'ɵpod', moduleName: CORE, runtime: ɵpod};
|
||||
static purePipeDef: o.ExternalReference = {name: 'ɵppd', moduleName: CORE, runtime: ɵppd};
|
||||
static pipeDef: o.ExternalReference = {name: 'ɵpid', moduleName: CORE, runtime: ɵpid};
|
||||
static nodeValue: o.ExternalReference = {name: 'ɵnov', moduleName: CORE, runtime: ɵnov};
|
||||
static ngContentDef: o.ExternalReference = {name: 'ɵncd', moduleName: CORE, runtime: ɵncd};
|
||||
static unwrapValue: o.ExternalReference = {name: 'ɵunv', moduleName: CORE, runtime: ɵunv};
|
||||
static createRendererType2: o.ExternalReference = {name: 'ɵcrt', moduleName: CORE, runtime: ɵcrt};
|
||||
static RendererType2: o.ExternalReference = {
|
||||
name: 'RendererType2',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
// type only
|
||||
runtime: null
|
||||
};
|
||||
static ViewDefinition: IdentifierSpec = {
|
||||
static ViewDefinition: o.ExternalReference = {
|
||||
name: 'ɵViewDefinition',
|
||||
moduleUrl: CORE,
|
||||
moduleName: CORE,
|
||||
// type only
|
||||
runtime: null
|
||||
};
|
||||
static createComponentFactory: IdentifierSpec = {name: 'ɵccf', moduleUrl: CORE, runtime: ɵccf};
|
||||
static createComponentFactory:
|
||||
o.ExternalReference = {name: 'ɵccf', moduleName: CORE, runtime: ɵccf};
|
||||
}
|
||||
|
||||
export function assetUrl(pkg: string, path: string | null = null, type: string = 'src'): string {
|
||||
|
@ -130,12 +142,12 @@ export function assetUrl(pkg: string, path: string | null = null, type: string =
|
|||
}
|
||||
}
|
||||
|
||||
export function resolveIdentifier(identifier: IdentifierSpec) {
|
||||
export function resolveIdentifier(identifier: o.ExternalReference) {
|
||||
let name = identifier.name;
|
||||
return ɵreflector.resolveIdentifier(name, identifier.moduleUrl, null, identifier.runtime);
|
||||
return ɵreflector.resolveIdentifier(name !, identifier.moduleName !, null, identifier.runtime);
|
||||
}
|
||||
|
||||
export function createIdentifier(identifier: IdentifierSpec): CompileIdentifierMetadata {
|
||||
export function createIdentifier(identifier: o.ExternalReference): CompileIdentifierMetadata {
|
||||
return {reference: resolveIdentifier(identifier)};
|
||||
}
|
||||
|
||||
|
@ -143,12 +155,12 @@ export function identifierToken(identifier: CompileIdentifierMetadata): CompileT
|
|||
return {identifier: identifier};
|
||||
}
|
||||
|
||||
export function createIdentifierToken(identifier: IdentifierSpec): CompileTokenMetadata {
|
||||
export function createIdentifierToken(identifier: o.ExternalReference): CompileTokenMetadata {
|
||||
return identifierToken(createIdentifier(identifier));
|
||||
}
|
||||
|
||||
export function createEnumIdentifier(
|
||||
enumType: IdentifierSpec, name: string): CompileIdentifierMetadata {
|
||||
enumType: o.ExternalReference, name: string): CompileIdentifierMetadata {
|
||||
const resolvedEnum = ɵreflector.resolveEnum(resolveIdentifier(enumType), name);
|
||||
return {reference: resolvedEnum};
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import {jitStatements} from '../output/output_jit';
|
|||
import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
|
||||
import {SummaryResolver} from '../summary_resolver';
|
||||
import {TemplateParser} from '../template_parser/template_parser';
|
||||
import {SyncAsyncResult} from '../util';
|
||||
import {OutputContext, SyncAsyncResult} from '../util';
|
||||
import {ViewCompiler} from '../view_compiler/view_compiler';
|
||||
|
||||
|
||||
|
@ -153,14 +153,14 @@ export class JitCompiler implements Compiler {
|
|||
// Always provide a bound Compiler
|
||||
const extraProviders = [this._metadataResolver.getProviderMetadata(new ProviderMeta(
|
||||
Compiler, {useFactory: () => new ModuleBoundCompiler(this, moduleMeta.type.reference)}))];
|
||||
const compileResult = this._ngModuleCompiler.compile(moduleMeta, extraProviders);
|
||||
const outputCtx = createOutputContext();
|
||||
const compileResult = this._ngModuleCompiler.compile(outputCtx, moduleMeta, extraProviders);
|
||||
if (!this._compilerConfig.useJit) {
|
||||
ngModuleFactory =
|
||||
interpretStatements(compileResult.statements, [compileResult.ngModuleFactoryVar])[0];
|
||||
interpretStatements(outputCtx.statements)[compileResult.ngModuleFactoryVar];
|
||||
} else {
|
||||
ngModuleFactory = jitStatements(
|
||||
ngModuleJitUrl(moduleMeta), compileResult.statements,
|
||||
[compileResult.ngModuleFactoryVar])[0];
|
||||
ngModuleJitUrl(moduleMeta), outputCtx.statements, )[compileResult.ngModuleFactoryVar];
|
||||
}
|
||||
this._compiledNgModuleCache.set(moduleMeta.type.reference, ngModuleFactory);
|
||||
}
|
||||
|
@ -272,11 +272,14 @@ export class JitCompiler implements Compiler {
|
|||
}
|
||||
const compMeta = template.compMeta;
|
||||
const externalStylesheetsByModuleUrl = new Map<string, CompiledStylesheet>();
|
||||
const stylesCompileResult = this._styleCompiler.compileComponent(compMeta);
|
||||
stylesCompileResult.externalStylesheets.forEach(
|
||||
(r) => { externalStylesheetsByModuleUrl.set(r.meta.moduleUrl !, r); });
|
||||
this._resolveStylesCompileResult(
|
||||
stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl);
|
||||
const outputContext = createOutputContext();
|
||||
const componentStylesheet = this._styleCompiler.compileComponent(outputContext, compMeta);
|
||||
compMeta.template !.externalStylesheets.forEach((stylesheetMeta) => {
|
||||
const compiledStylesheet =
|
||||
this._styleCompiler.compileStyles(createOutputContext(), compMeta, stylesheetMeta);
|
||||
externalStylesheetsByModuleUrl.set(stylesheetMeta.moduleUrl !, compiledStylesheet);
|
||||
});
|
||||
this._resolveStylesCompileResult(componentStylesheet, externalStylesheetsByModuleUrl);
|
||||
const directives =
|
||||
template.directives.map(dir => this._metadataResolver.getDirectiveSummary(dir.reference));
|
||||
const pipes = template.ngModule.transitiveModule.pipes.map(
|
||||
|
@ -285,22 +288,17 @@ export class JitCompiler implements Compiler {
|
|||
compMeta, compMeta.template !.template !, directives, pipes, template.ngModule.schemas,
|
||||
templateSourceUrl(template.ngModule.type, template.compMeta, template.compMeta.template !));
|
||||
const compileResult = this._viewCompiler.compileComponent(
|
||||
compMeta, parsedTemplate, ir.variable(stylesCompileResult.componentStylesheet.stylesVar),
|
||||
outputContext, compMeta, parsedTemplate, ir.variable(componentStylesheet.stylesVar),
|
||||
usedPipes);
|
||||
const statements =
|
||||
stylesCompileResult.componentStylesheet.statements.concat(compileResult.statements);
|
||||
let viewClassAndRendererTypeVars = compMeta.isHost ?
|
||||
[compileResult.viewClassVar] :
|
||||
[compileResult.viewClassVar, compileResult.rendererTypeVar];
|
||||
let viewClass: any;
|
||||
let rendererType: any;
|
||||
let evalResult: any;
|
||||
if (!this._compilerConfig.useJit) {
|
||||
[viewClass, rendererType] = interpretStatements(statements, viewClassAndRendererTypeVars);
|
||||
evalResult = interpretStatements(outputContext.statements);
|
||||
} else {
|
||||
[viewClass, rendererType] = jitStatements(
|
||||
templateJitUrl(template.ngModule.type, template.compMeta), statements,
|
||||
viewClassAndRendererTypeVars);
|
||||
evalResult = jitStatements(
|
||||
templateJitUrl(template.ngModule.type, template.compMeta), outputContext.statements);
|
||||
}
|
||||
const viewClass = evalResult[compileResult.viewClassVar];
|
||||
const rendererType = evalResult[compileResult.rendererTypeVar];
|
||||
template.compiled(viewClass, rendererType);
|
||||
}
|
||||
|
||||
|
@ -310,7 +308,7 @@ export class JitCompiler implements Compiler {
|
|||
const nestedCompileResult = externalStylesheetsByModuleUrl.get(dep.moduleUrl) !;
|
||||
const nestedStylesArr = this._resolveAndEvalStylesCompileResult(
|
||||
nestedCompileResult, externalStylesheetsByModuleUrl);
|
||||
dep.valuePlaceholder.reference = nestedStylesArr;
|
||||
dep.setValue(nestedStylesArr);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -319,11 +317,11 @@ export class JitCompiler implements Compiler {
|
|||
externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>): string[] {
|
||||
this._resolveStylesCompileResult(result, externalStylesheetsByModuleUrl);
|
||||
if (!this._compilerConfig.useJit) {
|
||||
return interpretStatements(result.statements, [result.stylesVar])[0];
|
||||
return interpretStatements(result.outputCtx.statements)[result.stylesVar];
|
||||
} else {
|
||||
return jitStatements(
|
||||
sharedStylesheetJitUrl(result.meta, this._sharedStylesheetCount++), result.statements,
|
||||
[result.stylesVar])[0];
|
||||
sharedStylesheetJitUrl(result.meta, this._sharedStylesheetCount++),
|
||||
result.outputCtx.statements)[result.stylesVar];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -404,3 +402,9 @@ function flattenSummaries(fn: () => any[], out: CompileTypeSummary[] = []): Comp
|
|||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function createOutputContext(): OutputContext {
|
||||
const importExpr = (symbol: any) =>
|
||||
ir.importExpr({name: identifierName(symbol), moduleName: null, runtime: symbol});
|
||||
return {statements: [], genFilePath: '', importExpr};
|
||||
}
|
||||
|
|
|
@ -14,58 +14,61 @@ import {CompilerInjectable} from './injectable';
|
|||
import * as o from './output/output_ast';
|
||||
import {typeSourceSpan} from './parse_util';
|
||||
import {NgModuleProviderAnalyzer} from './provider_analyzer';
|
||||
import {OutputContext} from './util';
|
||||
import {componentFactoryResolverProviderDef, depDef, providerDef} from './view_compiler/provider_compiler';
|
||||
|
||||
export class NgModuleCompileResult {
|
||||
constructor(public statements: o.Statement[], public ngModuleFactoryVar: string) {}
|
||||
constructor(public ngModuleFactoryVar: string) {}
|
||||
}
|
||||
|
||||
const LOG_VAR = o.variable('_l');
|
||||
|
||||
@CompilerInjectable()
|
||||
export class NgModuleCompiler {
|
||||
compile(ngModuleMeta: CompileNgModuleMetadata, extraProviders: CompileProviderMetadata[]):
|
||||
NgModuleCompileResult {
|
||||
compile(
|
||||
ctx: OutputContext, ngModuleMeta: CompileNgModuleMetadata,
|
||||
extraProviders: CompileProviderMetadata[]): NgModuleCompileResult {
|
||||
const sourceSpan = typeSourceSpan('NgModule', ngModuleMeta.type);
|
||||
const entryComponentFactories = ngModuleMeta.transitiveModule.entryComponents;
|
||||
const bootstrapComponents = ngModuleMeta.bootstrapComponents;
|
||||
const providerParser = new NgModuleProviderAnalyzer(ngModuleMeta, extraProviders, sourceSpan);
|
||||
const providerDefs =
|
||||
[componentFactoryResolverProviderDef(NodeFlags.None, entryComponentFactories)]
|
||||
.concat(providerParser.parse().map((provider) => providerDef(provider)))
|
||||
[componentFactoryResolverProviderDef(ctx, NodeFlags.None, entryComponentFactories)]
|
||||
.concat(providerParser.parse().map((provider) => providerDef(ctx, provider)))
|
||||
.map(({providerExpr, depsExpr, flags, tokenExpr}) => {
|
||||
return o.importExpr(createIdentifier(Identifiers.moduleProviderDef)).callFn([
|
||||
return o.importExpr(Identifiers.moduleProviderDef).callFn([
|
||||
o.literal(flags), tokenExpr, providerExpr, depsExpr
|
||||
]);
|
||||
});
|
||||
|
||||
const ngModuleDef =
|
||||
o.importExpr(createIdentifier(Identifiers.moduleDef)).callFn([o.literalArr(providerDefs)]);
|
||||
const ngModuleDef = o.importExpr(Identifiers.moduleDef).callFn([o.literalArr(providerDefs)]);
|
||||
const ngModuleDefFactory = o.fn(
|
||||
[new o.FnParam(LOG_VAR.name !)], [new o.ReturnStatement(ngModuleDef)], o.INFERRED_TYPE);
|
||||
|
||||
const ngModuleFactoryVar = `${identifierName(ngModuleMeta.type)}NgFactory`;
|
||||
const ngModuleFactoryStmt =
|
||||
o.variable(ngModuleFactoryVar)
|
||||
.set(o.importExpr(createIdentifier(Identifiers.createModuleFactory)).callFn([
|
||||
o.importExpr(ngModuleMeta.type),
|
||||
o.literalArr(bootstrapComponents.map(id => o.importExpr(id))), ngModuleDefFactory
|
||||
.set(o.importExpr(Identifiers.createModuleFactory).callFn([
|
||||
ctx.importExpr(ngModuleMeta.type.reference),
|
||||
o.literalArr(bootstrapComponents.map(id => ctx.importExpr(id.reference))),
|
||||
ngModuleDefFactory
|
||||
]))
|
||||
.toDeclStmt(
|
||||
o.importType(
|
||||
createIdentifier(Identifiers.NgModuleFactory),
|
||||
[o.importType(ngModuleMeta.type) !], [o.TypeModifier.Const]),
|
||||
[o.StmtModifier.Final]);
|
||||
Identifiers.NgModuleFactory,
|
||||
[o.expressionType(ctx.importExpr(ngModuleMeta.type.reference)) !],
|
||||
[o.TypeModifier.Const]),
|
||||
[o.StmtModifier.Final, o.StmtModifier.Exported]);
|
||||
|
||||
const stmts: o.Statement[] = [ngModuleFactoryStmt];
|
||||
ctx.statements.push(ngModuleFactoryStmt);
|
||||
if (ngModuleMeta.id) {
|
||||
const registerFactoryStmt =
|
||||
o.importExpr(createIdentifier(Identifiers.RegisterModuleFactoryFn))
|
||||
o.importExpr(Identifiers.RegisterModuleFactoryFn)
|
||||
.callFn([o.literal(ngModuleMeta.id), o.variable(ngModuleFactoryVar)])
|
||||
.toStmt();
|
||||
stmts.push(registerFactoryStmt);
|
||||
ctx.statements.push(registerFactoryStmt);
|
||||
}
|
||||
|
||||
return new NgModuleCompileResult(stmts, ngModuleFactoryVar);
|
||||
return new NgModuleCompileResult(ngModuleFactoryVar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ export const CATCH_STACK_VAR = o.variable('stack', null, null);
|
|||
|
||||
export abstract class OutputEmitter {
|
||||
abstract emitStatements(
|
||||
srcFilePath: string, genFilePath: string, stmts: o.Statement[], exportedVars: string[],
|
||||
srcFilePath: string, genFilePath: string, stmts: o.Statement[],
|
||||
preamble?: string|null): string;
|
||||
}
|
||||
|
||||
|
@ -31,21 +31,15 @@ class _EmittedLine {
|
|||
}
|
||||
|
||||
export class EmitterVisitorContext {
|
||||
static createRoot(exportedVars: string[]): EmitterVisitorContext {
|
||||
return new EmitterVisitorContext(exportedVars, 0);
|
||||
}
|
||||
static createRoot(): EmitterVisitorContext { return new EmitterVisitorContext(0); }
|
||||
|
||||
private _lines: _EmittedLine[];
|
||||
private _classes: o.ClassStmt[] = [];
|
||||
|
||||
constructor(private _exportedVars: string[], private _indent: number) {
|
||||
this._lines = [new _EmittedLine(_indent)];
|
||||
}
|
||||
constructor(private _indent: number) { this._lines = [new _EmittedLine(_indent)]; }
|
||||
|
||||
private get _currentLine(): _EmittedLine { return this._lines[this._lines.length - 1]; }
|
||||
|
||||
isExportedVar(varName: string): boolean { return this._exportedVars.indexOf(varName) !== -1; }
|
||||
|
||||
println(from?: {sourceSpan: ParseSourceSpan | null}|null, lastPart: string = ''): void {
|
||||
this.print(from || null, lastPart, true);
|
||||
}
|
||||
|
|
|
@ -1,65 +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 {ParseSourceSpan} from '../parse_util';
|
||||
|
||||
import * as o from './output_ast';
|
||||
|
||||
|
||||
/**
|
||||
* Create a new class stmts based on the given data.
|
||||
*/
|
||||
export function createClassStmt(config: {
|
||||
name: string,
|
||||
parent?: o.Expression,
|
||||
parentArgs?: o.Expression[],
|
||||
ctorParams?: o.FnParam[],
|
||||
builders: ClassBuilderPart | ClassBuilderPart[],
|
||||
modifiers?: o.StmtModifier[],
|
||||
sourceSpan?: ParseSourceSpan
|
||||
}): o.ClassStmt {
|
||||
const parentArgs = config.parentArgs || [];
|
||||
const superCtorStmts = config.parent ? [o.SUPER_EXPR.callFn(parentArgs).toStmt()] : [];
|
||||
const builder =
|
||||
concatClassBuilderParts(Array.isArray(config.builders) ? config.builders : [config.builders]);
|
||||
const ctor =
|
||||
new o.ClassMethod(null, config.ctorParams || [], superCtorStmts.concat(builder.ctorStmts));
|
||||
|
||||
return new o.ClassStmt(
|
||||
config.name, config.parent || null, builder.fields, builder.getters, ctor, builder.methods,
|
||||
config.modifiers || [], config.sourceSpan);
|
||||
}
|
||||
|
||||
function concatClassBuilderParts(builders: ClassBuilderPart[]) {
|
||||
return {
|
||||
fields: [].concat(...(builders.map((builder => builder.fields || [])) as any)),
|
||||
methods: [].concat(...(builders.map(builder => builder.methods || []) as any)),
|
||||
getters: [].concat(...(builders.map(builder => builder.getters || []) as any)),
|
||||
ctorStmts: [].concat(...(builders.map(builder => builder.ctorStmts || []) as any)),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects data for a generated class.
|
||||
*/
|
||||
export interface ClassBuilderPart {
|
||||
fields?: o.ClassField[];
|
||||
methods?: o.ClassMethod[];
|
||||
getters?: o.ClassGetter[];
|
||||
ctorStmts?: o.Statement[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects data for a generated class.
|
||||
*/
|
||||
export interface ClassBuilder {
|
||||
fields: o.ClassField[];
|
||||
methods: o.ClassMethod[];
|
||||
getters: o.ClassGetter[];
|
||||
ctorStmts: o.Statement[];
|
||||
}
|
|
@ -13,24 +13,21 @@ import {CompileIdentifierMetadata} from '../compile_metadata';
|
|||
import {EmitterVisitorContext, OutputEmitter} from './abstract_emitter';
|
||||
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
|
||||
import * as o from './output_ast';
|
||||
import {ImportResolver} from './path_util';
|
||||
|
||||
export class JavaScriptEmitter implements OutputEmitter {
|
||||
constructor(private _importResolver: ImportResolver) {}
|
||||
|
||||
emitStatements(
|
||||
srcFilePath: string, genFilePath: string, stmts: o.Statement[], exportedVars: string[],
|
||||
srcFilePath: string, genFilePath: string, stmts: o.Statement[],
|
||||
preamble: string = ''): string {
|
||||
const converter = new JsEmitterVisitor(genFilePath, this._importResolver);
|
||||
const ctx = EmitterVisitorContext.createRoot(exportedVars);
|
||||
const converter = new JsEmitterVisitor();
|
||||
const ctx = EmitterVisitorContext.createRoot();
|
||||
converter.visitAllStatements(stmts, ctx);
|
||||
|
||||
const preambleLines = preamble ? preamble.split('\n') : [];
|
||||
converter.importsWithPrefixes.forEach((prefix, importedFilePath) => {
|
||||
converter.importsWithPrefixes.forEach((prefix, importedModuleName) => {
|
||||
// Note: can't write the real word for import as it screws up system.js auto detection...
|
||||
preambleLines.push(
|
||||
`var ${prefix} = req` +
|
||||
`uire('${this._importResolver.fileNameToModuleName(importedFilePath, genFilePath)}');`);
|
||||
`uire('${importedModuleName}');`);
|
||||
});
|
||||
|
||||
const sm =
|
||||
|
@ -47,46 +44,36 @@ export class JavaScriptEmitter implements OutputEmitter {
|
|||
class JsEmitterVisitor extends AbstractJsEmitterVisitor {
|
||||
importsWithPrefixes = new Map<string, string>();
|
||||
|
||||
constructor(private _genFilePath: string, private _importResolver: ImportResolver) { super(); }
|
||||
|
||||
private _resolveStaticSymbol(value: CompileIdentifierMetadata): StaticSymbol {
|
||||
const reference = value.reference;
|
||||
if (!(reference instanceof StaticSymbol)) {
|
||||
throw new Error(`Internal error: unknown identifier ${JSON.stringify(value)}`);
|
||||
}
|
||||
return this._importResolver.getImportAs(reference) || reference;
|
||||
}
|
||||
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
|
||||
const {name, filePath} = this._resolveStaticSymbol(ast.value);
|
||||
if (filePath != this._genFilePath) {
|
||||
let prefix = this.importsWithPrefixes.get(filePath);
|
||||
const {name, moduleName} = ast.value;
|
||||
if (moduleName) {
|
||||
let prefix = this.importsWithPrefixes.get(moduleName);
|
||||
if (prefix == null) {
|
||||
prefix = `i${this.importsWithPrefixes.size}`;
|
||||
this.importsWithPrefixes.set(filePath, prefix);
|
||||
this.importsWithPrefixes.set(moduleName, prefix);
|
||||
}
|
||||
ctx.print(ast, `${prefix}.`);
|
||||
}
|
||||
ctx.print(ast, name);
|
||||
ctx.print(ast, name !);
|
||||
return null;
|
||||
}
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
super.visitDeclareVarStmt(stmt, ctx);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.println(stmt, exportVar(stmt.name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {
|
||||
super.visitDeclareFunctionStmt(stmt, ctx);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.println(stmt, exportVar(stmt.name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
|
||||
super.visitDeclareClassStmt(stmt, ctx);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.println(stmt, exportVar(stmt.name));
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
|
||||
import {CompileIdentifierMetadata} from '../compile_metadata';
|
||||
import {ParseSourceSpan} from '../parse_util';
|
||||
|
||||
//// Types
|
||||
|
@ -344,8 +343,8 @@ export class LiteralExpr extends Expression {
|
|||
|
||||
export class ExternalExpr extends Expression {
|
||||
constructor(
|
||||
public value: CompileIdentifierMetadata, type?: Type|null,
|
||||
public typeParams: Type[]|null = null, sourceSpan?: ParseSourceSpan|null) {
|
||||
public value: ExternalReference, type?: Type|null, public typeParams: Type[]|null = null,
|
||||
sourceSpan?: ParseSourceSpan|null) {
|
||||
super(type, sourceSpan);
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
|
@ -353,6 +352,9 @@ export class ExternalExpr extends Expression {
|
|||
}
|
||||
}
|
||||
|
||||
export class ExternalReference {
|
||||
constructor(public moduleName: string|null, public name: string|null, public runtime: any|null) {}
|
||||
}
|
||||
|
||||
export class ConditionalExpr extends Expression {
|
||||
public trueCase: Expression;
|
||||
|
@ -533,7 +535,8 @@ export const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);
|
|||
//// Statements
|
||||
export enum StmtModifier {
|
||||
Final,
|
||||
Private
|
||||
Private,
|
||||
Exported
|
||||
}
|
||||
|
||||
export abstract class Statement {
|
||||
|
@ -1125,13 +1128,13 @@ export function variable(
|
|||
}
|
||||
|
||||
export function importExpr(
|
||||
id: CompileIdentifierMetadata, typeParams: Type[] | null = null,
|
||||
id: ExternalReference, typeParams: Type[] | null = null,
|
||||
sourceSpan?: ParseSourceSpan | null): ExternalExpr {
|
||||
return new ExternalExpr(id, null, typeParams, sourceSpan);
|
||||
}
|
||||
|
||||
export function importType(
|
||||
id: CompileIdentifierMetadata, typeParams: Type[] | null = null,
|
||||
id: ExternalReference, typeParams: Type[] | null = null,
|
||||
typeModifiers: TypeModifier[] | null = null): ExpressionType|null {
|
||||
return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null;
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
import * as o from './output_ast';
|
||||
import {debugOutputAstAsTypeScript} from './ts_emitter';
|
||||
|
||||
export function interpretStatements(statements: o.Statement[], resultVars: string[]): any[] {
|
||||
const stmtsWithReturn = statements.concat(
|
||||
[new o.ReturnStatement(o.literalArr(resultVars.map(resultVar => o.variable(resultVar))))]);
|
||||
export function interpretStatements(statements: o.Statement[]): {[key: string]: any} {
|
||||
const ctx = new _ExecutionContext(null, null, null, new Map<string, any>());
|
||||
const visitor = new StatementInterpreter();
|
||||
const result = visitor.visitAllStatements(stmtsWithReturn, ctx);
|
||||
return result != null ? result.value : null;
|
||||
visitor.visitAllStatements(statements, ctx);
|
||||
const result: {[key: string]: any} = {};
|
||||
ctx.exports.forEach((exportName) => { result[exportName] = ctx.vars.get(exportName); });
|
||||
return result;
|
||||
}
|
||||
|
||||
function _executeFunctionStatements(
|
||||
|
@ -32,6 +32,8 @@ function _executeFunctionStatements(
|
|||
}
|
||||
|
||||
class _ExecutionContext {
|
||||
exports: string[] = [];
|
||||
|
||||
constructor(
|
||||
public parent: _ExecutionContext|null, public instance: any, public className: string|null,
|
||||
public vars: Map<string, any>) {}
|
||||
|
@ -90,6 +92,9 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
|||
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: _ExecutionContext): any {
|
||||
ctx.vars.set(stmt.name, stmt.value.visitExpression(this, ctx));
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.exports.push(stmt.name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitWriteVarExpr(expr: o.WriteVarExpr, ctx: _ExecutionContext): any {
|
||||
|
@ -185,6 +190,9 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
|||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: _ExecutionContext): any {
|
||||
const clazz = createDynamicClass(stmt, ctx, this);
|
||||
ctx.vars.set(stmt.name, clazz);
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.exports.push(stmt.name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitExpressionStmt(stmt: o.ExpressionStatement, ctx: _ExecutionContext): any {
|
||||
|
@ -219,9 +227,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
|||
return new clazz(...args);
|
||||
}
|
||||
visitLiteralExpr(ast: o.LiteralExpr, ctx: _ExecutionContext): any { return ast.value; }
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: _ExecutionContext): any {
|
||||
return ast.value.reference;
|
||||
}
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: _ExecutionContext): any { return ast.value.runtime; }
|
||||
visitConditionalExpr(ast: o.ConditionalExpr, ctx: _ExecutionContext): any {
|
||||
if (ast.condition.visitExpression(this, ctx)) {
|
||||
return ast.trueCase.visitExpression(this, ctx);
|
||||
|
@ -246,6 +252,9 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
|||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: _ExecutionContext): any {
|
||||
const paramNames = stmt.params.map((param) => param.name);
|
||||
ctx.vars.set(stmt.name, _declareFn(paramNames, stmt.statements, ctx, this));
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.exports.push(stmt.name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr, ctx: _ExecutionContext): any {
|
||||
|
|
|
@ -35,19 +35,24 @@ function evalExpression(
|
|||
return new Function(...fnArgNames.concat(fnBody))(...fnArgValues);
|
||||
}
|
||||
|
||||
export function jitStatements(
|
||||
sourceUrl: string, statements: o.Statement[], resultVars: string[]): any[] {
|
||||
export function jitStatements(sourceUrl: string, statements: o.Statement[]): {[key: string]: any} {
|
||||
const converter = new JitEmitterVisitor();
|
||||
const ctx = EmitterVisitorContext.createRoot(resultVars);
|
||||
const returnStmt =
|
||||
new o.ReturnStatement(o.literalArr(resultVars.map(resultVar => o.variable(resultVar))));
|
||||
converter.visitAllStatements(statements.concat([returnStmt]), ctx);
|
||||
const ctx = EmitterVisitorContext.createRoot();
|
||||
converter.visitAllStatements(statements, ctx);
|
||||
converter.createReturnStmt(ctx);
|
||||
return evalExpression(sourceUrl, ctx, converter.getArgs());
|
||||
}
|
||||
|
||||
class JitEmitterVisitor extends AbstractJsEmitterVisitor {
|
||||
private _evalArgNames: string[] = [];
|
||||
private _evalArgValues: any[] = [];
|
||||
private _evalExportedVars: string[] = [];
|
||||
|
||||
createReturnStmt(ctx: EmitterVisitorContext) {
|
||||
const stmt = new o.ReturnStatement(new o.LiteralMapExpr(this._evalExportedVars.map(
|
||||
resultVar => new o.LiteralMapEntry(resultVar, o.variable(resultVar)))));
|
||||
stmt.visitStatement(this, ctx);
|
||||
}
|
||||
|
||||
getArgs(): {[key: string]: any} {
|
||||
const result: {[key: string]: any} = {};
|
||||
|
@ -58,15 +63,36 @@ class JitEmitterVisitor extends AbstractJsEmitterVisitor {
|
|||
}
|
||||
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
|
||||
const value = ast.value.reference;
|
||||
const value = ast.value.runtime;
|
||||
let id = this._evalArgValues.indexOf(value);
|
||||
if (id === -1) {
|
||||
id = this._evalArgValues.length;
|
||||
this._evalArgValues.push(value);
|
||||
const name = identifierName(ast.value) || 'val';
|
||||
const name = identifierName({reference: ast.value.runtime}) || 'val';
|
||||
this._evalArgNames.push(`jit_${name}${id}`);
|
||||
}
|
||||
ctx.print(ast, this._evalArgNames[id]);
|
||||
return null;
|
||||
}
|
||||
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
this._evalExportedVars.push(stmt.name);
|
||||
}
|
||||
return super.visitDeclareVarStmt(stmt, ctx);
|
||||
}
|
||||
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
this._evalExportedVars.push(stmt.name);
|
||||
}
|
||||
return super.visitDeclareFunctionStmt(stmt, ctx);
|
||||
}
|
||||
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
this._evalExportedVars.push(stmt.name);
|
||||
}
|
||||
return super.visitDeclareClassStmt(stmt, ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +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 {StaticSymbol} from '../aot/static_symbol';
|
||||
|
||||
/**
|
||||
* Interface that defines how import statements should be generated.
|
||||
*/
|
||||
export abstract class ImportResolver {
|
||||
/**
|
||||
* Converts a file path to a module name that can be used as an `import.
|
||||
* I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`.
|
||||
*/
|
||||
abstract fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null;
|
||||
|
||||
/**
|
||||
* Converts the given StaticSymbol into another StaticSymbol that should be used
|
||||
* to generate the import from.
|
||||
*/
|
||||
abstract getImportAs(symbol: StaticSymbol): StaticSymbol|null;
|
||||
|
||||
/**
|
||||
* Determine the arity of a type.
|
||||
*/
|
||||
abstract getTypeArity(symbol: StaticSymbol): number|null;
|
||||
}
|
|
@ -12,18 +12,13 @@ import {CompileIdentifierMetadata} from '../compile_metadata';
|
|||
|
||||
import {AbstractEmitterVisitor, CATCH_ERROR_VAR, CATCH_STACK_VAR, EmitterVisitorContext, OutputEmitter} from './abstract_emitter';
|
||||
import * as o from './output_ast';
|
||||
import {ImportResolver} from './path_util';
|
||||
|
||||
const _debugFilePath = '/debug/lib';
|
||||
|
||||
export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.Type | any[]):
|
||||
string {
|
||||
const converter = new _TsEmitterVisitor(_debugFilePath, {
|
||||
fileNameToModuleName(filePath: string, containingFilePath: string) { return filePath; },
|
||||
getImportAs(symbol: StaticSymbol | null) { return null; },
|
||||
getTypeArity: symbol => null
|
||||
});
|
||||
const ctx = EmitterVisitorContext.createRoot([]);
|
||||
const converter = new _TsEmitterVisitor();
|
||||
const ctx = EmitterVisitorContext.createRoot();
|
||||
const asts: any[] = Array.isArray(ast) ? ast : [ast];
|
||||
|
||||
asts.forEach((ast) => {
|
||||
|
@ -42,30 +37,27 @@ export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.T
|
|||
|
||||
|
||||
export class TypeScriptEmitter implements OutputEmitter {
|
||||
constructor(private _importResolver: ImportResolver) {}
|
||||
|
||||
emitStatements(
|
||||
srcFilePath: string, genFilePath: string, stmts: o.Statement[], exportedVars: string[],
|
||||
srcFilePath: string, genFilePath: string, stmts: o.Statement[],
|
||||
preamble: string = ''): string {
|
||||
const converter = new _TsEmitterVisitor(genFilePath, this._importResolver);
|
||||
const converter = new _TsEmitterVisitor();
|
||||
|
||||
const ctx = EmitterVisitorContext.createRoot(exportedVars);
|
||||
const ctx = EmitterVisitorContext.createRoot();
|
||||
|
||||
converter.visitAllStatements(stmts, ctx);
|
||||
|
||||
const preambleLines = preamble ? preamble.split('\n') : [];
|
||||
converter.reexports.forEach((reexports, exportedFilePath) => {
|
||||
converter.reexports.forEach((reexports, exportedModuleName) => {
|
||||
const reexportsCode =
|
||||
reexports.map(reexport => `${reexport.name} as ${reexport.as}`).join(',');
|
||||
preambleLines.push(
|
||||
`export {${reexportsCode}} from '${this._importResolver.fileNameToModuleName(exportedFilePath, genFilePath)}';`);
|
||||
preambleLines.push(`export {${reexportsCode}} from '${exportedModuleName}';`);
|
||||
});
|
||||
|
||||
converter.importsWithPrefixes.forEach((prefix, importedFilePath) => {
|
||||
converter.importsWithPrefixes.forEach((prefix, importedModuleName) => {
|
||||
// Note: can't write the real word for import as it screws up system.js auto detection...
|
||||
preambleLines.push(
|
||||
`imp` +
|
||||
`ort * as ${prefix} from '${this._importResolver.fileNameToModuleName(importedFilePath, genFilePath)}';`);
|
||||
`ort * as ${prefix} from '${importedModuleName}';`);
|
||||
});
|
||||
|
||||
const sm =
|
||||
|
@ -82,9 +74,7 @@ export class TypeScriptEmitter implements OutputEmitter {
|
|||
class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor {
|
||||
private typeExpression = 0;
|
||||
|
||||
constructor(private _genFilePath: string, private _importResolver: ImportResolver) {
|
||||
super(false);
|
||||
}
|
||||
constructor() { super(false); }
|
||||
|
||||
importsWithPrefixes = new Map<string, string>();
|
||||
reexports = new Map<string, {name: string, as: string}[]>();
|
||||
|
@ -136,20 +126,21 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
|||
}
|
||||
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
if (ctx.isExportedVar(stmt.name) && stmt.value instanceof o.ExternalExpr && !stmt.type) {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported) && stmt.value instanceof o.ExternalExpr &&
|
||||
!stmt.type) {
|
||||
// check for a reexport
|
||||
const {name, filePath, members} = this._resolveStaticSymbol(stmt.value.value);
|
||||
if (members !.length === 0 && filePath !== this._genFilePath) {
|
||||
let reexports = this.reexports.get(filePath);
|
||||
const {name, moduleName} = stmt.value.value;
|
||||
if (moduleName) {
|
||||
let reexports = this.reexports.get(moduleName);
|
||||
if (!reexports) {
|
||||
reexports = [];
|
||||
this.reexports.set(filePath, reexports);
|
||||
this.reexports.set(moduleName, reexports);
|
||||
}
|
||||
reexports.push({name, as: stmt.name});
|
||||
reexports.push({name: name !, as: stmt.name});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.print(stmt, `export `);
|
||||
}
|
||||
if (stmt.hasModifier(o.StmtModifier.Final)) {
|
||||
|
@ -187,7 +178,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
|||
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.pushClass(stmt);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.print(stmt, `export `);
|
||||
}
|
||||
ctx.print(stmt, `class ${stmt.name}`);
|
||||
|
@ -273,7 +264,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
|||
}
|
||||
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
if (stmt.hasModifier(o.StmtModifier.Exported)) {
|
||||
ctx.print(stmt, `export `);
|
||||
}
|
||||
ctx.print(stmt, `function ${stmt.name}(`);
|
||||
|
@ -376,40 +367,18 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
|||
}, params, ctx, ',');
|
||||
}
|
||||
|
||||
private _resolveStaticSymbol(value: CompileIdentifierMetadata):
|
||||
{name: string, filePath: string, members?: string[], arity?: number} {
|
||||
const reference = value.reference;
|
||||
if (!(reference instanceof StaticSymbol)) {
|
||||
throw new Error(`Internal error: unknown identifier ${JSON.stringify(value)}`);
|
||||
}
|
||||
const arity = this._importResolver.getTypeArity(reference) || undefined;
|
||||
const importReference = this._importResolver.getImportAs(reference) || reference;
|
||||
return {
|
||||
name: importReference.name,
|
||||
filePath: importReference.filePath,
|
||||
members: importReference.members, arity
|
||||
};
|
||||
}
|
||||
|
||||
private _visitIdentifier(
|
||||
value: CompileIdentifierMetadata, typeParams: o.Type[]|null,
|
||||
ctx: EmitterVisitorContext): void {
|
||||
const {name, filePath, members, arity} = this._resolveStaticSymbol(value);
|
||||
if (filePath != this._genFilePath) {
|
||||
let prefix = this.importsWithPrefixes.get(filePath);
|
||||
value: o.ExternalReference, typeParams: o.Type[]|null, ctx: EmitterVisitorContext): void {
|
||||
const {name, moduleName} = value;
|
||||
if (moduleName) {
|
||||
let prefix = this.importsWithPrefixes.get(moduleName);
|
||||
if (prefix == null) {
|
||||
prefix = `i${this.importsWithPrefixes.size}`;
|
||||
this.importsWithPrefixes.set(filePath, prefix);
|
||||
this.importsWithPrefixes.set(moduleName, prefix);
|
||||
}
|
||||
ctx.print(null, `${prefix}.`);
|
||||
}
|
||||
if (members !.length) {
|
||||
ctx.print(null, name);
|
||||
ctx.print(null, '.');
|
||||
ctx.print(null, members !.join('.'));
|
||||
} else {
|
||||
ctx.print(null, name);
|
||||
}
|
||||
ctx.print(null, name !);
|
||||
|
||||
if (this.typeExpression > 0) {
|
||||
// If we are in a type expression that refers to a generic type then supply
|
||||
|
@ -417,19 +386,10 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
|||
// supplied, supply any as the type. Outside a type expression the reference
|
||||
// should not supply type parameters and be treated as a simple value reference
|
||||
// to the constructor function itself.
|
||||
const suppliedParameters = (typeParams && typeParams.length) || 0;
|
||||
const additionalParameters = (arity || 0) - suppliedParameters;
|
||||
if (suppliedParameters > 0 || additionalParameters > 0) {
|
||||
const suppliedParameters = typeParams || [];
|
||||
if (suppliedParameters.length > 0) {
|
||||
ctx.print(null, `<`);
|
||||
if (suppliedParameters > 0) {
|
||||
this.visitAllObjects(type => type.visitType(this, ctx), typeParams !, ctx, ',');
|
||||
}
|
||||
if (additionalParameters > 0) {
|
||||
for (let i = 0; i < additionalParameters; i++) {
|
||||
if (i > 0 || suppliedParameters > 0) ctx.print(null, ',');
|
||||
ctx.print(null, 'any');
|
||||
}
|
||||
}
|
||||
this.visitAllObjects(type => type.visitType(this, ctx), typeParams !, ctx, ',');
|
||||
ctx.print(null, `>`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,19 @@
|
|||
*/
|
||||
|
||||
|
||||
import {ValueTransformer, visitValue} from '../util';
|
||||
import {OutputContext, ValueTransformer, visitValue} from '../util';
|
||||
|
||||
import * as o from './output_ast';
|
||||
|
||||
export const QUOTED_KEYS = '$quoted$';
|
||||
|
||||
export function convertValueToOutputAst(value: any, type: o.Type | null = null): o.Expression {
|
||||
return visitValue(value, new _ValueOutputAstTransformer(), type);
|
||||
export function convertValueToOutputAst(
|
||||
ctx: OutputContext, value: any, type: o.Type | null = null): o.Expression {
|
||||
return visitValue(value, new _ValueOutputAstTransformer(ctx), type);
|
||||
}
|
||||
|
||||
class _ValueOutputAstTransformer implements ValueTransformer {
|
||||
constructor(private ctx: OutputContext) {}
|
||||
visitArray(arr: any[], type: o.Type): o.Expression {
|
||||
return o.literalArr(arr.map(value => visitValue(value, this, null)), type);
|
||||
}
|
||||
|
@ -38,7 +40,7 @@ class _ValueOutputAstTransformer implements ValueTransformer {
|
|||
if (value instanceof o.Expression) {
|
||||
return value;
|
||||
} else {
|
||||
return o.importExpr({reference: value});
|
||||
return this.ctx.importExpr(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import {CompilerInjectable} from './injectable';
|
|||
import * as o from './output/output_ast';
|
||||
import {ShadowCss} from './shadow_css';
|
||||
import {UrlResolver} from './url_resolver';
|
||||
import {OutputContext} from './util';
|
||||
|
||||
const COMPONENT_VARIABLE = '%COMP%';
|
||||
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
|
||||
|
@ -20,19 +21,12 @@ const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
|
|||
|
||||
export class StylesCompileDependency {
|
||||
constructor(
|
||||
public name: string, public moduleUrl: string, public isShimmed: boolean,
|
||||
public valuePlaceholder: CompileIdentifierMetadata) {}
|
||||
}
|
||||
|
||||
export class StylesCompileResult {
|
||||
constructor(
|
||||
public componentStylesheet: CompiledStylesheet,
|
||||
public externalStylesheets: CompiledStylesheet[]) {}
|
||||
public name: string, public moduleUrl: string, public setValue: (value: any) => void) {}
|
||||
}
|
||||
|
||||
export class CompiledStylesheet {
|
||||
constructor(
|
||||
public statements: o.Statement[], public stylesVar: string,
|
||||
public outputCtx: OutputContext, public stylesVar: string,
|
||||
public dependencies: StylesCompileDependency[], public isShimmed: boolean,
|
||||
public meta: CompileStylesheetMetadata) {}
|
||||
}
|
||||
|
@ -43,44 +37,53 @@ export class StyleCompiler {
|
|||
|
||||
constructor(private _urlResolver: UrlResolver) {}
|
||||
|
||||
compileComponent(comp: CompileDirectiveMetadata): StylesCompileResult {
|
||||
compileComponent(outputCtx: OutputContext, comp: CompileDirectiveMetadata): CompiledStylesheet {
|
||||
const template = comp.template !;
|
||||
const externalStylesheets: CompiledStylesheet[] = [];
|
||||
const componentStylesheet: CompiledStylesheet = this._compileStyles(
|
||||
comp, new CompileStylesheetMetadata({
|
||||
return this._compileStyles(
|
||||
outputCtx, comp, new CompileStylesheetMetadata({
|
||||
styles: template.styles,
|
||||
styleUrls: template.styleUrls,
|
||||
moduleUrl: identifierModuleUrl(comp.type)
|
||||
}),
|
||||
true);
|
||||
template.externalStylesheets.forEach((stylesheetMeta) => {
|
||||
const compiledStylesheet = this._compileStyles(comp, stylesheetMeta, false);
|
||||
externalStylesheets.push(compiledStylesheet);
|
||||
});
|
||||
return new StylesCompileResult(componentStylesheet, externalStylesheets);
|
||||
}
|
||||
|
||||
compileStyles(
|
||||
outputCtx: OutputContext, comp: CompileDirectiveMetadata,
|
||||
stylesheet: CompileStylesheetMetadata): CompiledStylesheet {
|
||||
return this._compileStyles(outputCtx, comp, stylesheet, false);
|
||||
}
|
||||
|
||||
needsStyleShim(comp: CompileDirectiveMetadata): boolean {
|
||||
return comp.template !.encapsulation === ViewEncapsulation.Emulated;
|
||||
}
|
||||
|
||||
private _compileStyles(
|
||||
comp: CompileDirectiveMetadata, stylesheet: CompileStylesheetMetadata,
|
||||
isComponentStylesheet: boolean): CompiledStylesheet {
|
||||
const shim = comp.template !.encapsulation === ViewEncapsulation.Emulated;
|
||||
const styleExpressions =
|
||||
outputCtx: OutputContext, comp: CompileDirectiveMetadata,
|
||||
stylesheet: CompileStylesheetMetadata, isComponentStylesheet: boolean): CompiledStylesheet {
|
||||
const shim = this.needsStyleShim(comp);
|
||||
const styleExpressions: o.Expression[] =
|
||||
stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
|
||||
const dependencies: StylesCompileDependency[] = [];
|
||||
for (let i = 0; i < stylesheet.styleUrls.length; i++) {
|
||||
const identifier: CompileIdentifierMetadata = {reference: null};
|
||||
stylesheet.styleUrls.forEach((styleUrl) => {
|
||||
const exprIndex = styleExpressions.length;
|
||||
// Note: This placeholder will be filled later.
|
||||
styleExpressions.push(null !);
|
||||
dependencies.push(new StylesCompileDependency(
|
||||
getStylesVarName(null), stylesheet.styleUrls[i], shim, identifier));
|
||||
styleExpressions.push(new o.ExternalExpr(identifier));
|
||||
}
|
||||
getStylesVarName(null), styleUrl,
|
||||
(value) => styleExpressions[exprIndex] = outputCtx.importExpr(value)));
|
||||
});
|
||||
// styles variable contains plain strings and arrays of other styles arrays (recursive),
|
||||
// so we set its type to dynamic.
|
||||
const stylesVar = getStylesVarName(isComponentStylesheet ? comp : null);
|
||||
const stmt = o.variable(stylesVar)
|
||||
.set(o.literalArr(
|
||||
styleExpressions, new o.ArrayType(o.DYNAMIC_TYPE, [o.TypeModifier.Const])))
|
||||
.toDeclStmt(null, [o.StmtModifier.Final]);
|
||||
return new CompiledStylesheet([stmt], stylesVar, dependencies, shim, stylesheet);
|
||||
.toDeclStmt(null, isComponentStylesheet ? [o.StmtModifier.Final] : [
|
||||
o.StmtModifier.Final, o.StmtModifier.Exported
|
||||
]);
|
||||
outputCtx.statements.push(stmt);
|
||||
return new CompiledStylesheet(outputCtx, stylesVar, dependencies, shim, stylesheet);
|
||||
}
|
||||
|
||||
private _shimIfNeeded(style: string, shim: boolean): string {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import * as o from './output/output_ast';
|
||||
|
||||
export const MODULE_SUFFIX = '';
|
||||
|
||||
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
||||
|
@ -138,3 +140,9 @@ export function utf8Encode(str: string): string {
|
|||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
export interface OutputContext {
|
||||
genFilePath: string;
|
||||
statements: o.Statement[];
|
||||
importExpr(reference: any, typeParams?: o.Type[]|null): o.Expression;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,9 @@ import {Identifiers, createIdentifier, createIdentifierToken, resolveIdentifier}
|
|||
import * as o from '../output/output_ast';
|
||||
import {convertValueToOutputAst} from '../output/value_util';
|
||||
import {ProviderAst, ProviderAstType} from '../template_parser/template_ast';
|
||||
import {OutputContext} from '../util';
|
||||
|
||||
export function providerDef(providerAst: ProviderAst): {
|
||||
export function providerDef(ctx: OutputContext, providerAst: ProviderAst): {
|
||||
providerExpr: o.Expression,
|
||||
flags: NodeFlags,
|
||||
depsExpr: o.Expression,
|
||||
|
@ -36,16 +37,17 @@ export function providerDef(providerAst: ProviderAst): {
|
|||
}
|
||||
});
|
||||
const {providerExpr, flags: providerFlags, depsExpr} = providerAst.multiProvider ?
|
||||
multiProviderDef(flags, providerAst.providers) :
|
||||
singleProviderDef(flags, providerAst.providerType, providerAst.providers[0]);
|
||||
multiProviderDef(ctx, flags, providerAst.providers) :
|
||||
singleProviderDef(ctx, flags, providerAst.providerType, providerAst.providers[0]);
|
||||
return {
|
||||
providerExpr,
|
||||
flags: providerFlags, depsExpr,
|
||||
tokenExpr: tokenExpr(providerAst.token),
|
||||
tokenExpr: tokenExpr(ctx, providerAst.token),
|
||||
};
|
||||
}
|
||||
|
||||
function multiProviderDef(flags: NodeFlags, providers: CompileProviderMetadata[]):
|
||||
function multiProviderDef(
|
||||
ctx: OutputContext, flags: NodeFlags, providers: CompileProviderMetadata[]):
|
||||
{providerExpr: o.Expression, flags: NodeFlags, depsExpr: o.Expression} {
|
||||
const allDepDefs: o.Expression[] = [];
|
||||
const allParams: o.FnParam[] = [];
|
||||
|
@ -53,15 +55,15 @@ function multiProviderDef(flags: NodeFlags, providers: CompileProviderMetadata[]
|
|||
let expr: o.Expression;
|
||||
if (provider.useClass) {
|
||||
const depExprs = convertDeps(providerIndex, provider.deps || provider.useClass.diDeps);
|
||||
expr = o.importExpr(provider.useClass).instantiate(depExprs);
|
||||
expr = ctx.importExpr(provider.useClass.reference).instantiate(depExprs);
|
||||
} else if (provider.useFactory) {
|
||||
const depExprs = convertDeps(providerIndex, provider.deps || provider.useFactory.diDeps);
|
||||
expr = o.importExpr(provider.useFactory).callFn(depExprs);
|
||||
expr = ctx.importExpr(provider.useFactory.reference).callFn(depExprs);
|
||||
} else if (provider.useExisting) {
|
||||
const depExprs = convertDeps(providerIndex, [{token: provider.useExisting}]);
|
||||
expr = depExprs[0];
|
||||
} else {
|
||||
expr = convertValueToOutputAst(provider.useValue);
|
||||
expr = convertValueToOutputAst(ctx, provider.useValue);
|
||||
}
|
||||
return expr;
|
||||
});
|
||||
|
@ -77,28 +79,29 @@ function multiProviderDef(flags: NodeFlags, providers: CompileProviderMetadata[]
|
|||
return deps.map((dep, depIndex) => {
|
||||
const paramName = `p${providerIndex}_${depIndex}`;
|
||||
allParams.push(new o.FnParam(paramName, o.DYNAMIC_TYPE));
|
||||
allDepDefs.push(depDef(dep));
|
||||
allDepDefs.push(depDef(ctx, dep));
|
||||
return o.variable(paramName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function singleProviderDef(
|
||||
flags: NodeFlags, providerType: ProviderAstType, providerMeta: CompileProviderMetadata):
|
||||
ctx: OutputContext, flags: NodeFlags, providerType: ProviderAstType,
|
||||
providerMeta: CompileProviderMetadata):
|
||||
{providerExpr: o.Expression, flags: NodeFlags, depsExpr: o.Expression} {
|
||||
let providerExpr: o.Expression;
|
||||
let deps: CompileDiDependencyMetadata[];
|
||||
if (providerType === ProviderAstType.Directive || providerType === ProviderAstType.Component) {
|
||||
providerExpr = o.importExpr(providerMeta.useClass !);
|
||||
providerExpr = ctx.importExpr(providerMeta.useClass !.reference);
|
||||
flags |= NodeFlags.TypeDirective;
|
||||
deps = providerMeta.deps || providerMeta.useClass !.diDeps;
|
||||
} else {
|
||||
if (providerMeta.useClass) {
|
||||
providerExpr = o.importExpr(providerMeta.useClass);
|
||||
providerExpr = ctx.importExpr(providerMeta.useClass.reference);
|
||||
flags |= NodeFlags.TypeClassProvider;
|
||||
deps = providerMeta.deps || providerMeta.useClass.diDeps;
|
||||
} else if (providerMeta.useFactory) {
|
||||
providerExpr = o.importExpr(providerMeta.useFactory);
|
||||
providerExpr = ctx.importExpr(providerMeta.useFactory.reference);
|
||||
flags |= NodeFlags.TypeFactoryProvider;
|
||||
deps = providerMeta.deps || providerMeta.useFactory.diDeps;
|
||||
} else if (providerMeta.useExisting) {
|
||||
|
@ -106,23 +109,24 @@ function singleProviderDef(
|
|||
flags |= NodeFlags.TypeUseExistingProvider;
|
||||
deps = [{token: providerMeta.useExisting}];
|
||||
} else {
|
||||
providerExpr = convertValueToOutputAst(providerMeta.useValue);
|
||||
providerExpr = convertValueToOutputAst(ctx, providerMeta.useValue);
|
||||
flags |= NodeFlags.TypeValueProvider;
|
||||
deps = [];
|
||||
}
|
||||
}
|
||||
const depsExpr = o.literalArr(deps.map(dep => depDef(dep)));
|
||||
const depsExpr = o.literalArr(deps.map(dep => depDef(ctx, dep)));
|
||||
return {providerExpr, flags, depsExpr};
|
||||
}
|
||||
|
||||
function tokenExpr(tokenMeta: CompileTokenMetadata): o.Expression {
|
||||
return tokenMeta.identifier ? o.importExpr(tokenMeta.identifier) : o.literal(tokenMeta.value);
|
||||
function tokenExpr(ctx: OutputContext, tokenMeta: CompileTokenMetadata): o.Expression {
|
||||
return tokenMeta.identifier ? ctx.importExpr(tokenMeta.identifier.reference) :
|
||||
o.literal(tokenMeta.value);
|
||||
}
|
||||
|
||||
export function depDef(dep: CompileDiDependencyMetadata): o.Expression {
|
||||
export function depDef(ctx: OutputContext, dep: CompileDiDependencyMetadata): o.Expression {
|
||||
// Note: the following fields have already been normalized out by provider_analyzer:
|
||||
// - isAttribute, isSelf, isHost
|
||||
const expr = dep.isValue ? convertValueToOutputAst(dep.value) : tokenExpr(dep.token !);
|
||||
const expr = dep.isValue ? convertValueToOutputAst(ctx, dep.value) : tokenExpr(ctx, dep.token !);
|
||||
let flags = DepFlags.None;
|
||||
if (dep.isSkipSelf) {
|
||||
flags |= DepFlags.SkipSelf;
|
||||
|
@ -168,14 +172,14 @@ export function lifecycleHookToNodeFlag(lifecycleHook: LifecycleHooks): NodeFlag
|
|||
}
|
||||
|
||||
export function componentFactoryResolverProviderDef(
|
||||
flags: NodeFlags, entryComponents: CompileEntryComponentMetadata[]): {
|
||||
ctx: OutputContext, flags: NodeFlags, entryComponents: CompileEntryComponentMetadata[]): {
|
||||
providerExpr: o.Expression,
|
||||
flags: NodeFlags,
|
||||
depsExpr: o.Expression,
|
||||
tokenExpr: o.Expression
|
||||
} {
|
||||
const entryComponentFactories = entryComponents.map(
|
||||
(entryComponent) => o.importExpr({reference: entryComponent.componentFactory}));
|
||||
const entryComponentFactories =
|
||||
entryComponents.map((entryComponent) => ctx.importExpr(entryComponent.componentFactory));
|
||||
const token = createIdentifierToken(Identifiers.ComponentFactoryResolver);
|
||||
const classMeta = {
|
||||
diDeps: [
|
||||
|
@ -187,10 +191,10 @@ export function componentFactoryResolverProviderDef(
|
|||
reference: resolveIdentifier(Identifiers.CodegenComponentFactoryResolver)
|
||||
};
|
||||
const {providerExpr, flags: providerFlags, depsExpr} =
|
||||
singleProviderDef(flags, ProviderAstType.PrivateService, {
|
||||
singleProviderDef(ctx, flags, ProviderAstType.PrivateService, {
|
||||
token,
|
||||
multi: false,
|
||||
useClass: classMeta,
|
||||
});
|
||||
return {providerExpr, flags: providerFlags, depsExpr, tokenExpr: tokenExpr(token)};
|
||||
return {providerExpr, flags: providerFlags, depsExpr, tokenExpr: tokenExpr(ctx, token)};
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import {convertValueToOutputAst} from '../output/value_util';
|
|||
import {ParseSourceSpan} from '../parse_util';
|
||||
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
||||
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAst, ProviderAstType, QueryMatch, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
|
||||
import {OutputContext} from '../util';
|
||||
|
||||
import {componentFactoryResolverProviderDef, depDef, lifecycleHookToNodeFlag, providerDef} from './provider_compiler';
|
||||
|
||||
|
@ -29,9 +30,7 @@ const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
|||
const NG_CONTAINER_TAG = 'ng-container';
|
||||
|
||||
export class ViewCompileResult {
|
||||
constructor(
|
||||
public statements: o.Statement[], public viewClassVar: string,
|
||||
public rendererTypeVar: string) {}
|
||||
constructor(public viewClassVar: string, public rendererTypeVar: string) {}
|
||||
}
|
||||
|
||||
@CompilerInjectable()
|
||||
|
@ -40,49 +39,47 @@ export class ViewCompiler {
|
|||
private _genConfigNext: CompilerConfig, private _schemaRegistry: ElementSchemaRegistry) {}
|
||||
|
||||
compileComponent(
|
||||
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
|
||||
usedPipes: CompilePipeSummary[]): ViewCompileResult {
|
||||
outputCtx: OutputContext, component: CompileDirectiveMetadata, template: TemplateAst[],
|
||||
styles: o.Expression, usedPipes: CompilePipeSummary[]): ViewCompileResult {
|
||||
let embeddedViewCount = 0;
|
||||
const staticQueryIds = findStaticQueryIds(template);
|
||||
|
||||
const statements: o.Statement[] = [];
|
||||
|
||||
let renderComponentVarName: string = undefined !;
|
||||
if (!component.isHost) {
|
||||
const template = component.template !;
|
||||
const customRenderData: o.LiteralMapEntry[] = [];
|
||||
if (template.animations && template.animations.length) {
|
||||
customRenderData.push(
|
||||
new o.LiteralMapEntry('animation', convertValueToOutputAst(template.animations), true));
|
||||
customRenderData.push(new o.LiteralMapEntry(
|
||||
'animation', convertValueToOutputAst(outputCtx, template.animations), true));
|
||||
}
|
||||
|
||||
const renderComponentVar = o.variable(rendererTypeName(component.type.reference));
|
||||
renderComponentVarName = renderComponentVar.name !;
|
||||
statements.push(
|
||||
outputCtx.statements.push(
|
||||
renderComponentVar
|
||||
.set(o.importExpr(createIdentifier(Identifiers.createRendererType2))
|
||||
.callFn([new o.LiteralMapExpr([
|
||||
new o.LiteralMapEntry('encapsulation', o.literal(template.encapsulation)),
|
||||
new o.LiteralMapEntry('styles', styles),
|
||||
new o.LiteralMapEntry('data', new o.LiteralMapExpr(customRenderData))
|
||||
])]))
|
||||
.set(o.importExpr(Identifiers.createRendererType2).callFn([new o.LiteralMapExpr([
|
||||
new o.LiteralMapEntry('encapsulation', o.literal(template.encapsulation)),
|
||||
new o.LiteralMapEntry('styles', styles),
|
||||
new o.LiteralMapEntry('data', new o.LiteralMapExpr(customRenderData))
|
||||
])]))
|
||||
.toDeclStmt(
|
||||
o.importType(createIdentifier(Identifiers.RendererType2)),
|
||||
[o.StmtModifier.Final]));
|
||||
o.importType(Identifiers.RendererType2),
|
||||
[o.StmtModifier.Final, o.StmtModifier.Exported]));
|
||||
}
|
||||
|
||||
const viewBuilderFactory = (parent: ViewBuilder | null): ViewBuilder => {
|
||||
const embeddedViewIndex = embeddedViewCount++;
|
||||
return new ViewBuilder(
|
||||
parent, component, embeddedViewIndex, usedPipes, staticQueryIds, viewBuilderFactory);
|
||||
outputCtx, parent, component, embeddedViewIndex, usedPipes, staticQueryIds,
|
||||
viewBuilderFactory);
|
||||
};
|
||||
|
||||
const visitor = viewBuilderFactory(null);
|
||||
visitor.visitAll([], template);
|
||||
|
||||
statements.push(...visitor.build());
|
||||
outputCtx.statements.push(...visitor.build());
|
||||
|
||||
return new ViewCompileResult(statements, visitor.viewName, renderComponentVarName);
|
||||
return new ViewCompileResult(visitor.viewName, renderComponentVarName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,15 +116,17 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
private children: ViewBuilder[] = [];
|
||||
|
||||
constructor(
|
||||
private parent: ViewBuilder|null, private component: CompileDirectiveMetadata,
|
||||
private embeddedViewIndex: number, private usedPipes: CompilePipeSummary[],
|
||||
private outputCtx: OutputContext, private parent: ViewBuilder|null,
|
||||
private component: CompileDirectiveMetadata, private embeddedViewIndex: number,
|
||||
private usedPipes: CompilePipeSummary[],
|
||||
private staticQueryIds: Map<TemplateAst, StaticAndDynamicQueryIds>,
|
||||
private viewBuilderFactory: ViewBuilderFactory) {
|
||||
// TODO(tbosch): The old view compiler used to use an `any` type
|
||||
// for the context in any embedded view. We keep this behaivor for now
|
||||
// to be able to introduce the new view compiler without too many errors.
|
||||
this.compType =
|
||||
this.embeddedViewIndex > 0 ? o.DYNAMIC_TYPE : o.importType(this.component.type) !;
|
||||
this.compType = this.embeddedViewIndex > 0 ?
|
||||
o.DYNAMIC_TYPE :
|
||||
o.expressionType(outputCtx.importExpr(this.component.type.reference)) !;
|
||||
}
|
||||
|
||||
get viewName(): string {
|
||||
|
@ -156,7 +155,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes.push(() => ({
|
||||
sourceSpan: null,
|
||||
nodeFlags: flags,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.queryDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.queryDef).callFn([
|
||||
o.literal(flags), o.literal(queryId),
|
||||
new o.LiteralMapExpr(
|
||||
[new o.LiteralMapEntry(query.propertyName, o.literal(bindingType))])
|
||||
|
@ -170,7 +169,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes.push(() => ({
|
||||
sourceSpan: null,
|
||||
nodeFlags: NodeFlags.TypeElement,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.anchorDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.anchorDef).callFn([
|
||||
o.literal(NodeFlags.None), o.NULL_EXPR, o.NULL_EXPR, o.literal(0)
|
||||
])
|
||||
}));
|
||||
|
@ -193,13 +192,14 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
}
|
||||
const viewFactory = new o.DeclareFunctionStmt(
|
||||
this.viewName, [new o.FnParam(LOG_VAR.name !)],
|
||||
[new o.ReturnStatement(o.importExpr(createIdentifier(Identifiers.viewDef)).callFn([
|
||||
[new o.ReturnStatement(o.importExpr(Identifiers.viewDef).callFn([
|
||||
o.literal(viewFlags),
|
||||
o.literalArr(nodeDefExprs),
|
||||
updateDirectivesFn,
|
||||
updateRendererFn,
|
||||
]))],
|
||||
o.importType(createIdentifier(Identifiers.ViewDefinition)));
|
||||
o.importType(Identifiers.ViewDefinition),
|
||||
this.embeddedViewIndex === 0 ? [o.StmtModifier.Exported] : []);
|
||||
|
||||
targetStatements.push(viewFactory);
|
||||
return targetStatements;
|
||||
|
@ -229,7 +229,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes.push(() => ({
|
||||
sourceSpan: ast.sourceSpan,
|
||||
nodeFlags: NodeFlags.TypeNgContent,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.ngContentDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.ngContentDef).callFn([
|
||||
o.literal(ast.ngContentIndex), o.literal(ast.index)
|
||||
])
|
||||
}));
|
||||
|
@ -240,7 +240,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes.push(() => ({
|
||||
sourceSpan: ast.sourceSpan,
|
||||
nodeFlags: NodeFlags.TypeText,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.textDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.textDef).callFn([
|
||||
o.literal(ast.ngContentIndex), o.literalArr([o.literal(ast.value)])
|
||||
])
|
||||
}));
|
||||
|
@ -262,7 +262,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes[nodeIndex] = () => ({
|
||||
sourceSpan: ast.sourceSpan,
|
||||
nodeFlags: NodeFlags.TypeText,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.textDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.textDef).callFn([
|
||||
o.literal(ast.ngContentIndex), o.literalArr(inter.strings.map(s => o.literal(s)))
|
||||
]),
|
||||
updateRenderer: updateRendererExpressions
|
||||
|
@ -289,7 +289,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes[nodeIndex] = () => ({
|
||||
sourceSpan: ast.sourceSpan,
|
||||
nodeFlags: NodeFlags.TypeElement | flags,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.anchorDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.anchorDef).callFn([
|
||||
o.literal(flags),
|
||||
queryMatchesExpr,
|
||||
o.literal(ast.ngContentIndex),
|
||||
|
@ -343,11 +343,11 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
const childCount = this.nodes.length - nodeIndex - 1;
|
||||
|
||||
const compAst = ast.directives.find(dirAst => dirAst.directive.isComponent);
|
||||
let compRendererType = o.NULL_EXPR;
|
||||
let compView = o.NULL_EXPR;
|
||||
let compRendererType = o.NULL_EXPR as o.Expression;
|
||||
let compView = o.NULL_EXPR as o.Expression;
|
||||
if (compAst) {
|
||||
compView = o.importExpr({reference: compAst.directive.componentViewType});
|
||||
compRendererType = o.importExpr({reference: compAst.directive.rendererType});
|
||||
compView = this.outputCtx.importExpr(compAst.directive.componentViewType);
|
||||
compRendererType = this.outputCtx.importExpr(compAst.directive.rendererType);
|
||||
}
|
||||
|
||||
// elementDef(
|
||||
|
@ -361,7 +361,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes[nodeIndex] = () => ({
|
||||
sourceSpan: ast.sourceSpan,
|
||||
nodeFlags: NodeFlags.TypeElement | flags,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.elementDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.elementDef).callFn([
|
||||
o.literal(flags),
|
||||
queryMatchesExpr,
|
||||
o.literal(ast.ngContentIndex),
|
||||
|
@ -492,7 +492,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes.push(() => ({
|
||||
sourceSpan: dirAst.sourceSpan,
|
||||
nodeFlags: flags,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.queryDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.queryDef).callFn([
|
||||
o.literal(flags), o.literal(queryId),
|
||||
new o.LiteralMapExpr(
|
||||
[new o.LiteralMapEntry(query.propertyName, o.literal(bindingType))])
|
||||
|
@ -548,9 +548,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
}));
|
||||
}
|
||||
|
||||
const dirContextExpr = o.importExpr(createIdentifier(Identifiers.nodeValue)).callFn([
|
||||
VIEW_VAR, o.literal(nodeIndex)
|
||||
]);
|
||||
const dirContextExpr =
|
||||
o.importExpr(Identifiers.nodeValue).callFn([VIEW_VAR, o.literal(nodeIndex)]);
|
||||
const hostBindings = dirAst.hostProperties.map((inputAst) => ({
|
||||
context: dirContextExpr,
|
||||
dirAst,
|
||||
|
@ -570,7 +569,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes[nodeIndex] = () => ({
|
||||
sourceSpan: dirAst.sourceSpan,
|
||||
nodeFlags: NodeFlags.TypeDirective | flags,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.directiveDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.directiveDef).callFn([
|
||||
o.literal(flags), queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR,
|
||||
o.literal(childCount), providerExpr, depsExpr,
|
||||
inputDefs.length ? new o.LiteralMapExpr(inputDefs) : o.NULL_EXPR,
|
||||
|
@ -591,7 +590,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
const componentDirMeta = directives.find(dirAst => dirAst.directive.isComponent);
|
||||
if (componentDirMeta && componentDirMeta.directive.entryComponents.length) {
|
||||
const {providerExpr, depsExpr, flags, tokenExpr} = componentFactoryResolverProviderDef(
|
||||
NodeFlags.PrivateProvider, componentDirMeta.directive.entryComponents);
|
||||
this.outputCtx, NodeFlags.PrivateProvider, componentDirMeta.directive.entryComponents);
|
||||
this._addProviderNode({
|
||||
providerExpr,
|
||||
depsExpr,
|
||||
|
@ -619,7 +618,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
() => ({
|
||||
sourceSpan: data.sourceSpan,
|
||||
nodeFlags: data.flags,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.providerDef)).callFn([
|
||||
nodeDef: o.importExpr(Identifiers.providerDef).callFn([
|
||||
o.literal(data.flags),
|
||||
data.queryMatchExprs.length ? o.literalArr(data.queryMatchExprs) : o.NULL_EXPR,
|
||||
data.tokenExpr, data.providerExpr, data.depsExpr
|
||||
|
@ -644,7 +643,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
o.literalArr([o.literal(match.queryId), o.literal(QueryValueType.Provider)]));
|
||||
}
|
||||
});
|
||||
const {providerExpr, depsExpr, flags: providerFlags, tokenExpr} = providerDef(providerAst);
|
||||
const {providerExpr, depsExpr, flags: providerFlags, tokenExpr} =
|
||||
providerDef(this.outputCtx, providerAst);
|
||||
return {
|
||||
flags: flags | providerFlags,
|
||||
queryMatchExprs,
|
||||
|
@ -665,9 +665,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
// check references
|
||||
const refNodeIndex = currBuilder.refNodeIndices[name];
|
||||
if (refNodeIndex != null) {
|
||||
return o.importExpr(createIdentifier(Identifiers.nodeValue)).callFn([
|
||||
currViewExpr, o.literal(refNodeIndex)
|
||||
]);
|
||||
return o.importExpr(Identifiers.nodeValue).callFn([currViewExpr, o.literal(refNodeIndex)]);
|
||||
}
|
||||
|
||||
// check variables
|
||||
|
@ -682,25 +680,23 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
|
||||
createLiteralArrayConverter(sourceSpan: ParseSourceSpan, argCount: number): BuiltinConverter {
|
||||
if (argCount === 0) {
|
||||
const valueExpr = o.importExpr(createIdentifier(Identifiers.EMPTY_ARRAY));
|
||||
const valueExpr = o.importExpr(Identifiers.EMPTY_ARRAY);
|
||||
return () => valueExpr;
|
||||
}
|
||||
|
||||
const nodeIndex = this.nodes.length;
|
||||
// pureArrayDef(argCount: number): NodeDef;
|
||||
this.nodes.push(
|
||||
() => ({
|
||||
sourceSpan,
|
||||
nodeFlags: NodeFlags.TypePureArray,
|
||||
nodeDef:
|
||||
o.importExpr(createIdentifier(Identifiers.pureArrayDef)).callFn([o.literal(argCount)])
|
||||
}));
|
||||
this.nodes.push(() => ({
|
||||
sourceSpan,
|
||||
nodeFlags: NodeFlags.TypePureArray,
|
||||
nodeDef: o.importExpr(Identifiers.pureArrayDef).callFn([o.literal(argCount)])
|
||||
}));
|
||||
|
||||
return (args: o.Expression[]) => callCheckStmt(nodeIndex, args);
|
||||
}
|
||||
createLiteralMapConverter(sourceSpan: ParseSourceSpan, keys: string[]): BuiltinConverter {
|
||||
if (keys.length === 0) {
|
||||
const valueExpr = o.importExpr(createIdentifier(Identifiers.EMPTY_MAP));
|
||||
const valueExpr = o.importExpr(Identifiers.EMPTY_MAP);
|
||||
return () => valueExpr;
|
||||
}
|
||||
|
||||
|
@ -709,8 +705,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes.push(() => ({
|
||||
sourceSpan,
|
||||
nodeFlags: NodeFlags.TypePureObject,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.pureObjectDef))
|
||||
.callFn([o.literalArr(keys.map(key => o.literal(key)))])
|
||||
nodeDef: o.importExpr(Identifiers.pureObjectDef).callFn([o.literalArr(
|
||||
keys.map(key => o.literal(key)))])
|
||||
}));
|
||||
|
||||
return (args: o.Expression[]) => callCheckStmt(nodeIndex, args);
|
||||
|
@ -724,8 +720,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
this.nodes.push(() => ({
|
||||
sourceSpan: expression.sourceSpan,
|
||||
nodeFlags: NodeFlags.TypePurePipe,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.purePipeDef))
|
||||
.callFn([o.literal(argCount)])
|
||||
nodeDef: o.importExpr(Identifiers.purePipeDef).callFn([o.literal(argCount)])
|
||||
}));
|
||||
|
||||
// find underlying pipe in the component view
|
||||
|
@ -737,18 +732,15 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
}
|
||||
const pipeNodeIndex = compBuilder.purePipeNodeIndices[name];
|
||||
const pipeValueExpr: o.Expression =
|
||||
o.importExpr(createIdentifier(Identifiers.nodeValue)).callFn([
|
||||
compViewExpr, o.literal(pipeNodeIndex)
|
||||
]);
|
||||
o.importExpr(Identifiers.nodeValue).callFn([compViewExpr, o.literal(pipeNodeIndex)]);
|
||||
|
||||
return (args: o.Expression[]) => callUnwrapValue(
|
||||
expression.nodeIndex, expression.bindingIndex,
|
||||
callCheckStmt(nodeIndex, [pipeValueExpr].concat(args)));
|
||||
} else {
|
||||
const nodeIndex = this._createPipe(expression.sourceSpan, pipe);
|
||||
const nodeValueExpr = o.importExpr(createIdentifier(Identifiers.nodeValue)).callFn([
|
||||
VIEW_VAR, o.literal(nodeIndex)
|
||||
]);
|
||||
const nodeValueExpr =
|
||||
o.importExpr(Identifiers.nodeValue).callFn([VIEW_VAR, o.literal(nodeIndex)]);
|
||||
|
||||
return (args: o.Expression[]) => callUnwrapValue(
|
||||
expression.nodeIndex, expression.bindingIndex,
|
||||
|
@ -766,16 +758,17 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
|||
}
|
||||
});
|
||||
|
||||
const depExprs = pipe.type.diDeps.map(depDef);
|
||||
const depExprs = pipe.type.diDeps.map((diDep) => depDef(this.outputCtx, diDep));
|
||||
// function pipeDef(
|
||||
// flags: NodeFlags, ctor: any, deps: ([DepFlags, any] | any)[]): NodeDef
|
||||
this.nodes.push(() => ({
|
||||
sourceSpan,
|
||||
nodeFlags: NodeFlags.TypePipe,
|
||||
nodeDef: o.importExpr(createIdentifier(Identifiers.pipeDef)).callFn([
|
||||
o.literal(flags), o.importExpr(pipe.type), o.literalArr(depExprs)
|
||||
])
|
||||
}));
|
||||
this.nodes.push(
|
||||
() => ({
|
||||
sourceSpan,
|
||||
nodeFlags: NodeFlags.TypePipe,
|
||||
nodeDef: o.importExpr(Identifiers.pipeDef).callFn([
|
||||
o.literal(flags), this.outputCtx.importExpr(pipe.type.reference), o.literalArr(depExprs)
|
||||
])
|
||||
}));
|
||||
return nodeIndex;
|
||||
}
|
||||
|
||||
|
@ -984,7 +977,7 @@ function callCheckStmt(nodeIndex: number, exprs: o.Expression[]): o.Expression {
|
|||
}
|
||||
|
||||
function callUnwrapValue(nodeIndex: number, bindingIdx: number, expr: o.Expression): o.Expression {
|
||||
return o.importExpr(createIdentifier(Identifiers.unwrapValue)).callFn([
|
||||
return o.importExpr(Identifiers.unwrapValue).callFn([
|
||||
VIEW_VAR, o.literal(nodeIndex), o.literal(bindingIdx), expr
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
import {AotSummaryResolver, AotSummaryResolverHost, CompileSummaryKind, CompileTypeSummary, ResolvedStaticSymbol, StaticSymbol, StaticSymbolCache, StaticSymbolResolver} from '@angular/compiler';
|
||||
import {deserializeSummaries, serializeSummaries} from '@angular/compiler/src/aot/summary_serializer';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {OutputContext} from '@angular/compiler/src/util';
|
||||
import * as path from 'path';
|
||||
|
||||
import {MockStaticSymbolResolverHost, MockSummaryResolver} from './static_symbol_resolver_spec';
|
||||
|
@ -32,7 +34,9 @@ export function main() {
|
|||
const mockSummaryResolver = new MockSummaryResolver([]);
|
||||
const symbolResolver = new StaticSymbolResolver(
|
||||
new MockStaticSymbolResolverHost({}), symbolCache, mockSummaryResolver);
|
||||
return serializeSummaries(mockSummaryResolver, symbolResolver, symbols, []).json;
|
||||
return serializeSummaries(
|
||||
createMockOutputContext(), mockSummaryResolver, symbolResolver, symbols, [])
|
||||
.json;
|
||||
}
|
||||
|
||||
it('should load serialized summary files', () => {
|
||||
|
@ -108,4 +112,8 @@ export class MockAotSummaryResolverHost implements AotSummaryResolverHost {
|
|||
isSourceFile(filePath: string) { return !filePath.endsWith('.d.ts'); }
|
||||
|
||||
loadSummary(filePath: string): string { return this.summaries[filePath]; }
|
||||
}
|
||||
|
||||
export function createMockOutputContext(): OutputContext {
|
||||
return {statements: [], genFilePath: 'someGenFilePath', importExpr: () => o.NULL_EXPR};
|
||||
}
|
|
@ -11,7 +11,7 @@ import {deserializeSummaries, serializeSummaries} from '@angular/compiler/src/ao
|
|||
import {summaryFileName} from '@angular/compiler/src/aot/util';
|
||||
|
||||
import {MockStaticSymbolResolverHost} from './static_symbol_resolver_spec';
|
||||
import {MockAotSummaryResolverHost} from './summary_resolver_spec';
|
||||
import {MockAotSummaryResolverHost, createMockOutputContext} from './summary_resolver_spec';
|
||||
|
||||
|
||||
export function main() {
|
||||
|
@ -43,7 +43,7 @@ export function main() {
|
|||
it('should serialize various data correctly', () => {
|
||||
init();
|
||||
const serializedData = serializeSummaries(
|
||||
summaryResolver, symbolResolver,
|
||||
createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/some_values.ts', 'Values'),
|
||||
|
@ -105,34 +105,35 @@ export function main() {
|
|||
it('should automatically add exported directives / pipes of NgModules that are not source files',
|
||||
() => {
|
||||
init();
|
||||
const externalSerialized = serializeSummaries(summaryResolver, symbolResolver, [], [
|
||||
{
|
||||
summary: {
|
||||
summaryKind: CompileSummaryKind.Pipe,
|
||||
type: {
|
||||
reference: symbolCache.get('/tmp/external.ts', 'SomeExternalPipe'),
|
||||
}
|
||||
} as any,
|
||||
metadata: null as any
|
||||
},
|
||||
{
|
||||
summary: {
|
||||
summaryKind: CompileSummaryKind.Directive,
|
||||
type: {
|
||||
reference: symbolCache.get('/tmp/external.ts', 'SomeExternalDir'),
|
||||
const externalSerialized =
|
||||
serializeSummaries(createMockOutputContext(), summaryResolver, symbolResolver, [], [
|
||||
{
|
||||
summary: {
|
||||
summaryKind: CompileSummaryKind.Pipe,
|
||||
type: {
|
||||
reference: symbolCache.get('/tmp/external.ts', 'SomeExternalPipe'),
|
||||
}
|
||||
} as any,
|
||||
metadata: null as any
|
||||
},
|
||||
providers: [],
|
||||
viewProviders: [],
|
||||
} as any,
|
||||
metadata: null as any
|
||||
}
|
||||
]);
|
||||
{
|
||||
summary: {
|
||||
summaryKind: CompileSummaryKind.Directive,
|
||||
type: {
|
||||
reference: symbolCache.get('/tmp/external.ts', 'SomeExternalDir'),
|
||||
},
|
||||
providers: [],
|
||||
viewProviders: [],
|
||||
} as any,
|
||||
metadata: null as any
|
||||
}
|
||||
]);
|
||||
init({
|
||||
'/tmp/external.ngsummary.json': externalSerialized.json,
|
||||
});
|
||||
|
||||
const serialized = serializeSummaries(
|
||||
summaryResolver, symbolResolver, [], [{
|
||||
createMockOutputContext(), summaryResolver, symbolResolver, [], [{
|
||||
summary: <any>{
|
||||
summaryKind: CompileSummaryKind.NgModule,
|
||||
type: {reference: symbolCache.get('/tmp/some_module.ts', 'SomeModule')},
|
||||
|
@ -162,7 +163,7 @@ export function main() {
|
|||
() => {
|
||||
init();
|
||||
const externalSerialized = serializeSummaries(
|
||||
summaryResolver, symbolResolver,
|
||||
createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/external.ts', 'PROVIDERS'),
|
||||
|
@ -194,7 +195,7 @@ export function main() {
|
|||
{__symbolic: 'module', version: 3, metadata: {'external': 'b'}}
|
||||
});
|
||||
const serialized = serializeSummaries(
|
||||
summaryResolver, symbolResolver, [{
|
||||
createMockOutputContext(), summaryResolver, symbolResolver, [{
|
||||
symbol: symbolCache.get('/tmp/test.ts', 'main'),
|
||||
metadata: {
|
||||
local: symbolCache.get('/tmp/local.ts', 'local'),
|
||||
|
@ -229,7 +230,7 @@ export function main() {
|
|||
it('should create "importAs" names for non source symbols', () => {
|
||||
init();
|
||||
const serialized = serializeSummaries(
|
||||
summaryResolver, symbolResolver, [{
|
||||
createMockOutputContext(), summaryResolver, symbolResolver, [{
|
||||
symbol: symbolCache.get('/tmp/test.ts', 'main'),
|
||||
metadata: [
|
||||
symbolCache.get('/tmp/external.d.ts', 'lib'),
|
||||
|
|
|
@ -18,7 +18,7 @@ export function main() {
|
|||
const fileB = new ParseSourceFile('b0b1b2b3b4b5b6b7b8b9', 'b.js');
|
||||
let ctx: EmitterVisitorContext;
|
||||
|
||||
beforeEach(() => { ctx = EmitterVisitorContext.createRoot([]); });
|
||||
beforeEach(() => { ctx = EmitterVisitorContext.createRoot(); });
|
||||
|
||||
it('should add source files to the source map', () => {
|
||||
ctx.print(createSourceSpan(fileA, 0), 'o0');
|
||||
|
|
|
@ -10,7 +10,6 @@ import {StaticSymbol} from '@angular/compiler/src/aot/static_symbol';
|
|||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {ImportResolver} from '@angular/compiler/src/output/path_util';
|
||||
import {SourceMap} from '@angular/compiler/src/output/source_map';
|
||||
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '@angular/compiler/src/parse_util';
|
||||
|
||||
|
@ -19,31 +18,16 @@ import {extractSourceMap, originalPositionFor} from './source_map_util';
|
|||
const someGenFilePath = 'somePackage/someGenFile';
|
||||
const someSourceFilePath = 'somePackage/someSourceFile';
|
||||
|
||||
class SimpleJsImportGenerator implements ImportResolver {
|
||||
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
|
||||
return importedUrlStr;
|
||||
}
|
||||
getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
|
||||
getTypeArity(symbol: StaticSymbol): number|null { return null; }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
describe('JavaScriptEmitter', () => {
|
||||
let importResolver: ImportResolver;
|
||||
let emitter: JavaScriptEmitter;
|
||||
let someVar: o.ReadVarExpr;
|
||||
|
||||
beforeEach(() => {
|
||||
importResolver = new SimpleJsImportGenerator();
|
||||
emitter = new JavaScriptEmitter(importResolver);
|
||||
});
|
||||
beforeEach(() => { emitter = new JavaScriptEmitter(); });
|
||||
|
||||
function emitSourceMap(
|
||||
stmt: o.Statement | o.Statement[], exportedVars: string[] | null = null,
|
||||
preamble?: string): SourceMap {
|
||||
function emitSourceMap(stmt: o.Statement | o.Statement[], preamble?: string): SourceMap {
|
||||
const stmts = Array.isArray(stmt) ? stmt : [stmt];
|
||||
const source = emitter.emitStatements(
|
||||
someSourceFilePath, someGenFilePath, stmts, exportedVars || [], preamble);
|
||||
const source = emitter.emitStatements(someSourceFilePath, someGenFilePath, stmts, preamble);
|
||||
return extractSourceMap(source) !;
|
||||
}
|
||||
|
||||
|
@ -54,7 +38,7 @@ export function main() {
|
|||
const endLocation = new ParseLocation(source, 7, 0, 6);
|
||||
const sourceSpan = new ParseSourceSpan(startLocation, endLocation);
|
||||
const someVar = o.variable('someVar', null, sourceSpan);
|
||||
const sm = emitSourceMap(someVar.toStmt(), [], '/* MyPreamble \n */');
|
||||
const sm = emitSourceMap(someVar.toStmt(), '/* MyPreamble \n */');
|
||||
|
||||
expect(sm.sources).toEqual([someSourceFilePath, 'in.js']);
|
||||
expect(sm.sourcesContent).toEqual([' ', ';;;var']);
|
||||
|
|
|
@ -7,10 +7,8 @@
|
|||
*/
|
||||
|
||||
import {StaticSymbol} from '@angular/compiler/src/aot/static_symbol';
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {ImportResolver} from '@angular/compiler/src/output/path_util';
|
||||
|
||||
import {stripSourceMapAndNewLine} from './abstract_emitter_spec';
|
||||
|
||||
|
@ -18,20 +16,9 @@ const someGenFilePath = 'somePackage/someGenFile';
|
|||
const someSourceFilePath = 'somePackage/someSourceFile';
|
||||
const anotherModuleUrl = 'somePackage/someOtherPath';
|
||||
|
||||
const sameModuleIdentifier: CompileIdentifierMetadata = {
|
||||
reference: new StaticSymbol(someGenFilePath, 'someLocalId', [])
|
||||
};
|
||||
const externalModuleIdentifier: CompileIdentifierMetadata = {
|
||||
reference: new StaticSymbol(anotherModuleUrl, 'someExternalId', [])
|
||||
};
|
||||
const sameModuleIdentifier = new o.ExternalReference(null, 'someLocalId', null);
|
||||
|
||||
class SimpleJsImportGenerator implements ImportResolver {
|
||||
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
|
||||
return importedUrlStr;
|
||||
}
|
||||
getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
|
||||
getTypeArity(symbol: StaticSymbol): number|null { return null; }
|
||||
}
|
||||
const externalModuleIdentifier = new o.ExternalReference(anotherModuleUrl, 'someExternalId', null);
|
||||
|
||||
export function main() {
|
||||
// Note supported features of our OutputAstin JavaScript / ES5:
|
||||
|
@ -39,29 +26,26 @@ export function main() {
|
|||
// - declaring fields
|
||||
|
||||
describe('JavaScriptEmitter', () => {
|
||||
let importResolver: ImportResolver;
|
||||
let emitter: JavaScriptEmitter;
|
||||
let someVar: o.ReadVarExpr;
|
||||
|
||||
beforeEach(() => {
|
||||
importResolver = new SimpleJsImportGenerator();
|
||||
emitter = new JavaScriptEmitter(importResolver);
|
||||
emitter = new JavaScriptEmitter();
|
||||
someVar = o.variable('someVar');
|
||||
});
|
||||
|
||||
function emitStmt(
|
||||
stmt: o.Statement, exportedVars: string[] | null = null, preamble?: string): string {
|
||||
const source = emitter.emitStatements(
|
||||
someSourceFilePath, someGenFilePath, [stmt], exportedVars || [], preamble);
|
||||
function emitStmt(stmt: o.Statement, preamble?: string): string {
|
||||
const source = emitter.emitStatements(someSourceFilePath, someGenFilePath, [stmt], preamble);
|
||||
return stripSourceMapAndNewLine(source);
|
||||
}
|
||||
|
||||
it('should declare variables', () => {
|
||||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt())).toEqual(`var someVar = 1;`);
|
||||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(), ['someVar'])).toEqual([
|
||||
'var someVar = 1;',
|
||||
`Object.defineProperty(exports, 'someVar', { get: function() { return someVar; }});`
|
||||
].join('\n'));
|
||||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(null, [o.StmtModifier.Exported])))
|
||||
.toEqual([
|
||||
'var someVar = 1;',
|
||||
`Object.defineProperty(exports, 'someVar', { get: function() { return someVar; }});`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should read and write variables', () => {
|
||||
|
@ -144,16 +128,6 @@ export function main() {
|
|||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support `importAs` for external identifiers', () => {
|
||||
spyOn(importResolver, 'getImportAs')
|
||||
.and.returnValue(new StaticSymbol('somePackage/importAsModule', 'importAsName', []));
|
||||
expect(emitStmt(o.importExpr(externalModuleIdentifier).toStmt())).toEqual([
|
||||
`var i0 = re` +
|
||||
`quire('somePackage/importAsModule');`,
|
||||
`i0.importAsName;`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support operators', () => {
|
||||
const lhs = o.variable('lhs');
|
||||
const rhs = o.variable('rhs');
|
||||
|
@ -193,10 +167,11 @@ export function main() {
|
|||
it('should support function statements', () => {
|
||||
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [], [
|
||||
]))).toEqual(['function someFn() {', '}'].join('\n'));
|
||||
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [], []), ['someFn'])).toEqual([
|
||||
'function someFn() {', '}',
|
||||
`Object.defineProperty(exports, 'someFn', { get: function() { return someFn; }});`
|
||||
].join('\n'));
|
||||
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [], [], null, [o.StmtModifier.Exported])))
|
||||
.toEqual([
|
||||
'function someFn() {', '}',
|
||||
`Object.defineProperty(exports, 'someFn', { get: function() { return someFn; }});`
|
||||
].join('\n'));
|
||||
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [], [
|
||||
new o.ReturnStatement(o.literal(1))
|
||||
]))).toEqual(['function someFn() {', ' return 1;', '}'].join('\n'));
|
||||
|
@ -240,7 +215,8 @@ export function main() {
|
|||
it('should support declaring classes', () => {
|
||||
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
|
||||
]))).toEqual(['function SomeClass() {', '}'].join('\n'));
|
||||
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, []), ['SomeClass']))
|
||||
expect(emitStmt(new o.ClassStmt(
|
||||
'SomeClass', null !, [], [], null !, [], [o.StmtModifier.Exported])))
|
||||
.toEqual([
|
||||
'function SomeClass() {', '}',
|
||||
`Object.defineProperty(exports, 'SomeClass', { get: function() { return SomeClass; }});`
|
||||
|
@ -319,7 +295,7 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should support a preamble', () => {
|
||||
expect(emitStmt(o.variable('a').toStmt(), [], '/* SomePreamble */')).toBe([
|
||||
expect(emitStmt(o.variable('a').toStmt(), '/* SomePreamble */')).toBe([
|
||||
'/* SomePreamble */', 'a;'
|
||||
].join('\n'));
|
||||
});
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import {ParseLocation, ParseSourceFile} from '@angular/compiler';
|
||||
import {StaticSymbol} from '@angular/compiler/src/aot/static_symbol';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {ImportResolver} from '@angular/compiler/src/output/path_util';
|
||||
import {SourceMap} from '@angular/compiler/src/output/source_map';
|
||||
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
import {ParseSourceSpan} from '@angular/compiler/src/parse_util';
|
||||
|
@ -19,36 +18,23 @@ import {extractSourceMap, originalPositionFor} from './source_map_util';
|
|||
const someGenFilePath = 'somePackage/someGenFile';
|
||||
const someSourceFilePath = 'somePackage/someSourceFile';
|
||||
|
||||
class SimpleJsImportGenerator implements ImportResolver {
|
||||
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
|
||||
return importedUrlStr;
|
||||
}
|
||||
getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
|
||||
getTypeArity(symbol: StaticSymbol): number|null { return null; }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
// Not supported features of our OutputAst in TS:
|
||||
// - real `const` like in Dart
|
||||
// - final fields
|
||||
|
||||
describe('TypeScriptEmitter', () => {
|
||||
let importResolver: ImportResolver;
|
||||
let emitter: TypeScriptEmitter;
|
||||
let someVar: o.ReadVarExpr;
|
||||
|
||||
beforeEach(() => {
|
||||
importResolver = new SimpleJsImportGenerator();
|
||||
emitter = new TypeScriptEmitter(importResolver);
|
||||
emitter = new TypeScriptEmitter();
|
||||
someVar = o.variable('someVar');
|
||||
});
|
||||
|
||||
function emitSourceMap(
|
||||
stmt: o.Statement | o.Statement[], exportedVars: string[] | null = null,
|
||||
preamble?: string): SourceMap {
|
||||
function emitSourceMap(stmt: o.Statement | o.Statement[], preamble?: string): SourceMap {
|
||||
const stmts = Array.isArray(stmt) ? stmt : [stmt];
|
||||
const source = emitter.emitStatements(
|
||||
someSourceFilePath, someGenFilePath, stmts, exportedVars || [], preamble);
|
||||
const source = emitter.emitStatements(someSourceFilePath, someGenFilePath, stmts, preamble);
|
||||
return extractSourceMap(source) !;
|
||||
}
|
||||
|
||||
|
@ -59,7 +45,7 @@ export function main() {
|
|||
const endLocation = new ParseLocation(source, 7, 0, 6);
|
||||
const sourceSpan = new ParseSourceSpan(startLocation, endLocation);
|
||||
const someVar = o.variable('someVar', null, sourceSpan);
|
||||
const sm = emitSourceMap(someVar.toStmt(), [], '/* MyPreamble \n */');
|
||||
const sm = emitSourceMap(someVar.toStmt(), '/* MyPreamble \n */');
|
||||
|
||||
expect(sm.sources).toEqual([someSourceFilePath, 'in.js']);
|
||||
expect(sm.sourcesContent).toEqual([' ', ';;;var']);
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
*/
|
||||
|
||||
import {StaticSymbol} from '@angular/compiler/src/aot/static_symbol';
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {ImportResolver} from '@angular/compiler/src/output/path_util';
|
||||
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
|
||||
import {stripSourceMapAndNewLine} from './abstract_emitter_spec';
|
||||
|
@ -18,21 +16,9 @@ const someGenFilePath = 'somePackage/someGenFile';
|
|||
const someSourceFilePath = 'somePackage/someSourceFile';
|
||||
const anotherModuleUrl = 'somePackage/someOtherPath';
|
||||
|
||||
const sameModuleIdentifier: CompileIdentifierMetadata = {
|
||||
reference: new StaticSymbol(someGenFilePath, 'someLocalId', [])
|
||||
};
|
||||
const sameModuleIdentifier = new o.ExternalReference(null, 'someLocalId', null);
|
||||
|
||||
const externalModuleIdentifier: CompileIdentifierMetadata = {
|
||||
reference: new StaticSymbol(anotherModuleUrl, 'someExternalId', [])
|
||||
};
|
||||
|
||||
class SimpleJsImportGenerator implements ImportResolver {
|
||||
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
|
||||
return importedUrlStr;
|
||||
}
|
||||
getImportAs(symbol: StaticSymbol): StaticSymbol|null { return null; }
|
||||
getTypeArity(symbol: StaticSymbol): number|null { return null; }
|
||||
}
|
||||
const externalModuleIdentifier = new o.ExternalReference(anotherModuleUrl, 'someExternalId', null);
|
||||
|
||||
export function main() {
|
||||
// Not supported features of our OutputAst in TS:
|
||||
|
@ -40,22 +26,17 @@ export function main() {
|
|||
// - final fields
|
||||
|
||||
describe('TypeScriptEmitter', () => {
|
||||
let importResolver: ImportResolver;
|
||||
let emitter: TypeScriptEmitter;
|
||||
let someVar: o.ReadVarExpr;
|
||||
|
||||
beforeEach(() => {
|
||||
importResolver = new SimpleJsImportGenerator();
|
||||
emitter = new TypeScriptEmitter(importResolver);
|
||||
emitter = new TypeScriptEmitter();
|
||||
someVar = o.variable('someVar', null, null);
|
||||
});
|
||||
|
||||
function emitStmt(
|
||||
stmt: o.Statement | o.Statement[], exportedVars: string[] | null = null,
|
||||
preamble?: string): string {
|
||||
function emitStmt(stmt: o.Statement | o.Statement[], preamble?: string): string {
|
||||
const stmts = Array.isArray(stmt) ? stmt : [stmt];
|
||||
const source = emitter.emitStatements(
|
||||
someSourceFilePath, someGenFilePath, stmts, exportedVars || [], preamble);
|
||||
const source = emitter.emitStatements(someSourceFilePath, someGenFilePath, stmts, preamble);
|
||||
return stripSourceMapAndNewLine(source);
|
||||
}
|
||||
|
||||
|
@ -63,7 +44,7 @@ export function main() {
|
|||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt())).toEqual(`var someVar:any = 1;`);
|
||||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(null, [o.StmtModifier.Final])))
|
||||
.toEqual(`const someVar:any = 1;`);
|
||||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(), ['someVar']))
|
||||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(null, [o.StmtModifier.Exported])))
|
||||
.toEqual(`export var someVar:any = 1;`);
|
||||
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(o.INT_TYPE)))
|
||||
.toEqual(`var someVar:number = 1;`);
|
||||
|
@ -74,8 +55,9 @@ export function main() {
|
|||
describe('declare variables with ExternExpressions as values', () => {
|
||||
it('should create no reexport if the identifier is in the same module', () => {
|
||||
// identifier is in the same module -> no reexport
|
||||
expect(emitStmt(someVar.set(o.importExpr(sameModuleIdentifier)).toDeclStmt(), ['someVar']))
|
||||
.toEqual('export var someVar:any = someLocalId;');
|
||||
expect(emitStmt(someVar.set(o.importExpr(sameModuleIdentifier)).toDeclStmt(null, [
|
||||
o.StmtModifier.Exported
|
||||
]))).toEqual('export var someVar:any = someLocalId;');
|
||||
});
|
||||
|
||||
it('should create no reexport if the variable is not exported', () => {
|
||||
|
@ -85,31 +67,17 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should create no reexport if the variable is typed', () => {
|
||||
expect(emitStmt(
|
||||
someVar.set(o.importExpr(externalModuleIdentifier)).toDeclStmt(o.DYNAMIC_TYPE),
|
||||
['someVar']))
|
||||
expect(emitStmt(someVar.set(o.importExpr(externalModuleIdentifier))
|
||||
.toDeclStmt(o.DYNAMIC_TYPE, [o.StmtModifier.Exported])))
|
||||
.toEqual([
|
||||
`import * as i0 from 'somePackage/someOtherPath';`,
|
||||
`export var someVar:any = i0.someExternalId;`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should create no reexport if the identifier has members', () => {
|
||||
const externalModuleIdentifierWithMembers: CompileIdentifierMetadata = {
|
||||
reference: new StaticSymbol(anotherModuleUrl, 'someExternalId', ['a'])
|
||||
};
|
||||
expect(emitStmt(
|
||||
someVar.set(o.importExpr(externalModuleIdentifierWithMembers)).toDeclStmt(),
|
||||
['someVar']))
|
||||
.toEqual([
|
||||
`import * as i0 from 'somePackage/someOtherPath';`,
|
||||
`export var someVar:any = i0.someExternalId.a;`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should create a reexport', () => {
|
||||
expect(
|
||||
emitStmt(someVar.set(o.importExpr(externalModuleIdentifier)).toDeclStmt(), ['someVar']))
|
||||
expect(emitStmt(someVar.set(o.importExpr(externalModuleIdentifier))
|
||||
.toDeclStmt(null, [o.StmtModifier.Exported])))
|
||||
.toEqual([
|
||||
`export {someExternalId as someVar} from 'somePackage/someOtherPath';`, ``
|
||||
].join('\n'));
|
||||
|
@ -117,30 +85,19 @@ export function main() {
|
|||
|
||||
it('should create multiple reexports from the same file', () => {
|
||||
const someVar2 = o.variable('someVar2');
|
||||
const externalModuleIdentifier2: CompileIdentifierMetadata = {
|
||||
reference: new StaticSymbol(anotherModuleUrl, 'someExternalId2', [])
|
||||
};
|
||||
expect(emitStmt(
|
||||
[
|
||||
someVar.set(o.importExpr(externalModuleIdentifier)).toDeclStmt(),
|
||||
someVar2.set(o.importExpr(externalModuleIdentifier2)).toDeclStmt()
|
||||
],
|
||||
['someVar', 'someVar2']))
|
||||
const externalModuleIdentifier2 =
|
||||
new o.ExternalReference(anotherModuleUrl, 'someExternalId2', null);
|
||||
expect(emitStmt([
|
||||
someVar.set(o.importExpr(externalModuleIdentifier))
|
||||
.toDeclStmt(null, [o.StmtModifier.Exported]),
|
||||
someVar2.set(o.importExpr(externalModuleIdentifier2))
|
||||
.toDeclStmt(null, [o.StmtModifier.Exported])
|
||||
]))
|
||||
.toEqual([
|
||||
`export {someExternalId as someVar,someExternalId2 as someVar2} from 'somePackage/someOtherPath';`,
|
||||
``
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should use `importAs` for reexports', () => {
|
||||
spyOn(importResolver, 'getImportAs')
|
||||
.and.returnValue(new StaticSymbol('somePackage/importAsModule', 'importAsName', []));
|
||||
expect(
|
||||
emitStmt(someVar.set(o.importExpr(externalModuleIdentifier)).toDeclStmt(), ['someVar']))
|
||||
.toEqual([
|
||||
`export {importAsName as someVar} from 'somePackage/importAsModule';`, ``
|
||||
].join('\n'));
|
||||
});
|
||||
});
|
||||
|
||||
it('should read and write variables', () => {
|
||||
|
@ -230,14 +187,6 @@ export function main() {
|
|||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support `importAs` for external identifiers', () => {
|
||||
spyOn(importResolver, 'getImportAs')
|
||||
.and.returnValue(new StaticSymbol('somePackage/importAsModule', 'importAsName', []));
|
||||
expect(emitStmt(o.importExpr(externalModuleIdentifier).toStmt())).toEqual([
|
||||
`import * as i0 from 'somePackage/importAsModule';`, `i0.importAsName;`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support operators', () => {
|
||||
const lhs = o.variable('lhs');
|
||||
const rhs = o.variable('rhs');
|
||||
|
@ -277,9 +226,8 @@ export function main() {
|
|||
it('should support function statements', () => {
|
||||
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [], [
|
||||
]))).toEqual(['function someFn():void {', '}'].join('\n'));
|
||||
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [], []), ['someFn'])).toEqual([
|
||||
'export function someFn():void {', '}'
|
||||
].join('\n'));
|
||||
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [], [], null, [o.StmtModifier.Exported])))
|
||||
.toEqual(['export function someFn():void {', '}'].join('\n'));
|
||||
expect(emitStmt(new o.DeclareFunctionStmt(
|
||||
'someFn', [], [new o.ReturnStatement(o.literal(1))], o.INT_TYPE)))
|
||||
.toEqual(['function someFn():number {', ' return 1;', '}'].join('\n'));
|
||||
|
@ -324,8 +272,9 @@ export function main() {
|
|||
it('should support declaring classes', () => {
|
||||
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
|
||||
]))).toEqual(['class SomeClass {', '}'].join('\n'));
|
||||
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, []), ['SomeClass']))
|
||||
.toEqual(['export class SomeClass {', '}'].join('\n'));
|
||||
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [], [
|
||||
o.StmtModifier.Exported
|
||||
]))).toEqual(['export class SomeClass {', '}'].join('\n'));
|
||||
expect(emitStmt(new o.ClassStmt('SomeClass', o.variable('SomeSuperClass'), [], [], null !, [
|
||||
]))).toEqual(['class SomeClass extends SomeSuperClass {', '}'].join('\n'));
|
||||
});
|
||||
|
@ -439,16 +388,6 @@ export function main() {
|
|||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support `importAs` for external types', () => {
|
||||
spyOn(importResolver, 'getImportAs')
|
||||
.and.returnValue(new StaticSymbol('somePackage/importAsModule', 'importAsName', []));
|
||||
const writeVarExpr = o.variable('a').set(o.NULL_EXPR);
|
||||
expect(emitStmt(writeVarExpr.toDeclStmt(o.importType(externalModuleIdentifier)))).toEqual([
|
||||
`import * as i0 from 'somePackage/importAsModule';`,
|
||||
`var a:i0.importAsName = (null as any);`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support expression types', () => {
|
||||
expect(
|
||||
emitStmt(o.variable('a').set(o.NULL_EXPR).toDeclStmt(o.expressionType(o.variable('b')))))
|
||||
|
@ -479,7 +418,7 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should support a preamble', () => {
|
||||
expect(emitStmt(o.variable('a').toStmt(), [], '/* SomePreamble */')).toBe([
|
||||
expect(emitStmt(o.variable('a').toStmt(), '/* SomePreamble */')).toBe([
|
||||
'/* SomePreamble */', 'a;'
|
||||
].join('\n'));
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue