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