UNPKG

@angular/compiler

Version:

Angular - the compiler library

802 lines • 151 kB
/** * @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 * as tslib_1 from "tslib"; import { componentFactoryName, flatten, identifierName, templateSourceUrl } from '../compile_metadata'; import { ConstantPool } from '../constant_pool'; import { ViewEncapsulation } from '../core'; import { MessageBundle } from '../i18n/message_bundle'; import { Identifiers, createTokenForExternalReference } from '../identifiers'; import { HtmlParser } from '../ml_parser/html_parser'; import { removeWhitespaces } from '../ml_parser/html_whitespaces'; import { DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig } from '../ml_parser/interpolation_config'; import * as o from '../output/output_ast'; import { compileNgModuleFromRender2 as compileR3Module } from '../render3/r3_module_compiler'; import { compilePipeFromRender2 as compileR3Pipe } from '../render3/r3_pipe_compiler'; import { htmlAstToRender3Ast } from '../render3/r3_template_transform'; import { compileComponentFromRender2 as compileR3Component, compileDirectiveFromRender2 as compileR3Directive } from '../render3/view/compiler'; import { DomElementSchemaRegistry } from '../schema/dom_element_schema_registry'; import { BindingParser } from '../template_parser/binding_parser'; import { error, syntaxError, visitValue } from '../util'; import { GeneratedFile } from './generated_file'; import { listLazyRoutes, parseLazyRoute } from './lazy_routes'; import { StaticSymbol } from './static_symbol'; import { createForJitStub, serializeSummaries } from './summary_serializer'; import { ngfactoryFilePath, normalizeGenFileSuffix, splitTypescriptSuffix, summaryFileName, summaryForJitFileName } from './util'; var AotCompiler = /** @class */ (function () { function AotCompiler(_config, _options, _host, reflector, _metadataResolver, _templateParser, _styleCompiler, _viewCompiler, _typeCheckCompiler, _ngModuleCompiler, _injectableCompiler, _outputEmitter, _summaryResolver, _symbolResolver) { this._config = _config; this._options = _options; this._host = _host; this.reflector = reflector; this._metadataResolver = _metadataResolver; this._templateParser = _templateParser; this._styleCompiler = _styleCompiler; this._viewCompiler = _viewCompiler; this._typeCheckCompiler = _typeCheckCompiler; this._ngModuleCompiler = _ngModuleCompiler; this._injectableCompiler = _injectableCompiler; this._outputEmitter = _outputEmitter; this._summaryResolver = _summaryResolver; this._symbolResolver = _symbolResolver; this._templateAstCache = new Map(); this._analyzedFiles = new Map(); this._analyzedFilesForInjectables = new Map(); } AotCompiler.prototype.clearCache = function () { this._metadataResolver.clearCache(); }; AotCompiler.prototype.analyzeModulesSync = function (rootFiles) { var _this = this; var analyzeResult = analyzeAndValidateNgModules(rootFiles, this._host, this._symbolResolver, this._metadataResolver); analyzeResult.ngModules.forEach(function (ngModule) { return _this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, true); }); return analyzeResult; }; AotCompiler.prototype.analyzeModulesAsync = function (rootFiles) { var _this = this; var analyzeResult = analyzeAndValidateNgModules(rootFiles, this._host, this._symbolResolver, this._metadataResolver); return Promise .all(analyzeResult.ngModules.map(function (ngModule) { return _this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, false); })) .then(function () { return analyzeResult; }); }; AotCompiler.prototype._analyzeFile = function (fileName) { var analyzedFile = this._analyzedFiles.get(fileName); if (!analyzedFile) { analyzedFile = analyzeFile(this._host, this._symbolResolver, this._metadataResolver, fileName); this._analyzedFiles.set(fileName, analyzedFile); } return analyzedFile; }; AotCompiler.prototype._analyzeFileForInjectables = function (fileName) { var analyzedFile = this._analyzedFilesForInjectables.get(fileName); if (!analyzedFile) { analyzedFile = analyzeFileForInjectables(this._host, this._symbolResolver, this._metadataResolver, fileName); this._analyzedFilesForInjectables.set(fileName, analyzedFile); } return analyzedFile; }; AotCompiler.prototype.findGeneratedFileNames = function (fileName) { var _this = this; var genFileNames = []; var file = this._analyzeFile(fileName); // Make sure we create a .ngfactory if we have a injectable/directive/pipe/NgModule // or a reference to a non source file. // Note: This is overestimating the required .ngfactory files as the real calculation is harder. // Only do this for StubEmitFlags.Basic, as adding a type check block // does not change this file (as we generate type check blocks based on NgModules). if (this._options.allowEmptyCodegenFiles || file.directives.length || file.pipes.length || file.injectables.length || file.ngModules.length || file.exportsNonSourceFiles) { genFileNames.push(ngfactoryFilePath(file.fileName, true)); if (this._options.enableSummariesForJit) { genFileNames.push(summaryForJitFileName(file.fileName, true)); } } var fileSuffix = normalizeGenFileSuffix(splitTypescriptSuffix(file.fileName, true)[1]); file.directives.forEach(function (dirSymbol) { var compMeta = _this._metadataResolver.getNonNormalizedDirectiveMetadata(dirSymbol).metadata; if (!compMeta.isComponent) { return; } // Note: compMeta is a component and therefore template is non null. compMeta.template.styleUrls.forEach(function (styleUrl) { var normalizedUrl = _this._host.resourceNameToFileName(styleUrl, file.fileName); if (!normalizedUrl) { throw syntaxError("Couldn't resolve resource " + styleUrl + " relative to " + file.fileName); } var needsShim = (compMeta.template.encapsulation || _this._config.defaultEncapsulation) === ViewEncapsulation.Emulated; genFileNames.push(_stylesModuleUrl(normalizedUrl, needsShim, fileSuffix)); if (_this._options.allowEmptyCodegenFiles) { genFileNames.push(_stylesModuleUrl(normalizedUrl, !needsShim, fileSuffix)); } }); }); return genFileNames; }; AotCompiler.prototype.emitBasicStub = function (genFileName, originalFileName) { var outputCtx = this._createOutputContext(genFileName); if (genFileName.endsWith('.ngfactory.ts')) { if (!originalFileName) { throw new Error("Assertion error: require the original file for .ngfactory.ts stubs. File: " + genFileName); } var originalFile = this._analyzeFile(originalFileName); this._createNgFactoryStub(outputCtx, originalFile, 1 /* Basic */); } else if (genFileName.endsWith('.ngsummary.ts')) { if (this._options.enableSummariesForJit) { if (!originalFileName) { throw new Error("Assertion error: require the original file for .ngsummary.ts stubs. File: " + genFileName); } var originalFile = this._analyzeFile(originalFileName); _createEmptyStub(outputCtx); originalFile.ngModules.forEach(function (ngModule) { // create exports that user code can reference createForJitStub(outputCtx, ngModule.type.reference); }); } } else if (genFileName.endsWith('.ngstyle.ts')) { _createEmptyStub(outputCtx); } // Note: for the stubs, we don't need a property srcFileUrl, // as later on in emitAllImpls we will create the proper GeneratedFiles with the // correct srcFileUrl. // This is good as e.g. for .ngstyle.ts files we can't derive // the url of components based on the genFileUrl. return this._codegenSourceModule('unknown', outputCtx); }; AotCompiler.prototype.emitTypeCheckStub = function (genFileName, originalFileName) { var originalFile = this._analyzeFile(originalFileName); var outputCtx = this._createOutputContext(genFileName); if (genFileName.endsWith('.ngfactory.ts')) { this._createNgFactoryStub(outputCtx, originalFile, 2 /* TypeCheck */); } return outputCtx.statements.length > 0 ? this._codegenSourceModule(originalFile.fileName, outputCtx) : null; }; AotCompiler.prototype.loadFilesAsync = function (fileNames, tsFiles) { var _this = this; var files = fileNames.map(function (fileName) { return _this._analyzeFile(fileName); }); var loadingPromises = []; files.forEach(function (file) { return file.ngModules.forEach(function (ngModule) { return loadingPromises.push(_this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, false)); }); }); var analyzedInjectables = tsFiles.map(function (tsFile) { return _this._analyzeFileForInjectables(tsFile); }); return Promise.all(loadingPromises).then(function (_) { return ({ analyzedModules: mergeAndValidateNgFiles(files), analyzedInjectables: analyzedInjectables, }); }); }; AotCompiler.prototype.loadFilesSync = function (fileNames, tsFiles) { var _this = this; var files = fileNames.map(function (fileName) { return _this._analyzeFile(fileName); }); files.forEach(function (file) { return file.ngModules.forEach(function (ngModule) { return _this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, true); }); }); var analyzedInjectables = tsFiles.map(function (tsFile) { return _this._analyzeFileForInjectables(tsFile); }); return { analyzedModules: mergeAndValidateNgFiles(files), analyzedInjectables: analyzedInjectables, }; }; AotCompiler.prototype._createNgFactoryStub = function (outputCtx, file, emitFlags) { var _this = this; var componentId = 0; file.ngModules.forEach(function (ngModuleMeta, ngModuleIndex) { // Note: the code below needs to executed for StubEmitFlags.Basic and StubEmitFlags.TypeCheck, // so we don't change the .ngfactory file too much when adding the type-check block. // create exports that user code can reference _this._ngModuleCompiler.createStub(outputCtx, ngModuleMeta.type.reference); // add references to the symbols from the metadata. // These can be used by the type check block for components, // and they also cause TypeScript to include these files into the program too, // which will make them part of the analyzedFiles. var externalReferences = tslib_1.__spread(ngModuleMeta.transitiveModule.directives.map(function (d) { return d.reference; }), ngModuleMeta.transitiveModule.pipes.map(function (d) { return d.reference; }), ngModuleMeta.importedModules.map(function (m) { return m.type.reference; }), ngModuleMeta.exportedModules.map(function (m) { return m.type.reference; }), _this._externalIdentifierReferences([Identifiers.TemplateRef, Identifiers.ElementRef])); var externalReferenceVars = new Map(); externalReferences.forEach(function (ref, typeIndex) { externalReferenceVars.set(ref, "_decl" + ngModuleIndex + "_" + typeIndex); }); externalReferenceVars.forEach(function (varName, reference) { outputCtx.statements.push(o.variable(varName) .set(o.NULL_EXPR.cast(o.DYNAMIC_TYPE)) .toDeclStmt(o.expressionType(outputCtx.importExpr(reference, /* typeParams */ null, /* useSummaries */ false)))); }); if (emitFlags & 2 /* TypeCheck */) { // add the type-check block for all components of the NgModule ngModuleMeta.declaredDirectives.forEach(function (dirId) { var compMeta = _this._metadataResolver.getDirectiveMetadata(dirId.reference); if (!compMeta.isComponent) { return; } componentId++; _this._createTypeCheckBlock(outputCtx, compMeta.type.reference.name + "_Host_" + componentId, ngModuleMeta, _this._metadataResolver.getHostComponentMetadata(compMeta), [compMeta.type], externalReferenceVars); _this._createTypeCheckBlock(outputCtx, compMeta.type.reference.name + "_" + componentId, ngModuleMeta, compMeta, ngModuleMeta.transitiveModule.directives, externalReferenceVars); }); } }); if (outputCtx.statements.length === 0) { _createEmptyStub(outputCtx); } }; AotCompiler.prototype._externalIdentifierReferences = function (references) { var e_1, _a; var result = []; try { for (var references_1 = tslib_1.__values(references), references_1_1 = references_1.next(); !references_1_1.done; references_1_1 = references_1.next()) { var reference = references_1_1.value; var token = createTokenForExternalReference(this.reflector, reference); if (token.identifier) { result.push(token.identifier.reference); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (references_1_1 && !references_1_1.done && (_a = references_1.return)) _a.call(references_1); } finally { if (e_1) throw e_1.error; } } return result; }; AotCompiler.prototype._createTypeCheckBlock = function (ctx, componentId, moduleMeta, compMeta, directives, externalReferenceVars) { var _a; var _b = this._parseTemplate(compMeta, moduleMeta, directives), parsedTemplate = _b.template, usedPipes = _b.pipes; (_a = ctx.statements).push.apply(_a, tslib_1.__spread(this._typeCheckCompiler.compileComponent(componentId, compMeta, parsedTemplate, usedPipes, externalReferenceVars, ctx))); }; AotCompiler.prototype.emitMessageBundle = function (analyzeResult, locale) { var _this = this; var errors = []; var htmlParser = new HtmlParser(); // TODO(vicb): implicit tags & attributes var messageBundle = new MessageBundle(htmlParser, [], {}, locale); analyzeResult.files.forEach(function (file) { var compMetas = []; file.directives.forEach(function (directiveType) { var dirMeta = _this._metadataResolver.getDirectiveMetadata(directiveType); if (dirMeta && dirMeta.isComponent) { compMetas.push(dirMeta); } }); compMetas.forEach(function (compMeta) { var html = compMeta.template.template; // Template URL points to either an HTML or TS file depending on whether // the file is used with `templateUrl:` or `template:`, respectively. var templateUrl = compMeta.template.templateUrl; var interpolationConfig = InterpolationConfig.fromArray(compMeta.template.interpolation); errors.push.apply(errors, tslib_1.__spread(messageBundle.updateFromTemplate(html, templateUrl, interpolationConfig))); }); }); if (errors.length) { throw new Error(errors.map(function (e) { return e.toString(); }).join('\n')); } return messageBundle; }; AotCompiler.prototype.emitAllPartialModules = function (_a, r3Files) { var _this = this; var ngModuleByPipeOrDirective = _a.ngModuleByPipeOrDirective, files = _a.files; var contextMap = new Map(); var getContext = function (fileName) { if (!contextMap.has(fileName)) { contextMap.set(fileName, _this._createOutputContext(fileName)); } return contextMap.get(fileName); }; files.forEach(function (file) { return _this._compilePartialModule(file.fileName, ngModuleByPipeOrDirective, file.directives, file.pipes, file.ngModules, file.injectables, getContext(file.fileName)); }); r3Files.forEach(function (file) { return _this._compileShallowModules(file.fileName, file.shallowModules, getContext(file.fileName)); }); return Array.from(contextMap.values()) .map(function (context) { return ({ fileName: context.genFilePath, statements: tslib_1.__spread(context.constantPool.statements, context.statements), }); }); }; AotCompiler.prototype._compileShallowModules = function (fileName, shallowModules, context) { var _this = this; shallowModules.forEach(function (module) { return compileR3Module(context, module, _this._injectableCompiler); }); }; AotCompiler.prototype._compilePartialModule = function (fileName, ngModuleByPipeOrDirective, directives, pipes, ngModules, injectables, context) { var _this = this; var errors = []; var schemaRegistry = new DomElementSchemaRegistry(); var hostBindingParser = new BindingParser(this._templateParser.expressionParser, DEFAULT_INTERPOLATION_CONFIG, schemaRegistry, [], errors); // Process all components and directives directives.forEach(function (directiveType) { var directiveMetadata = _this._metadataResolver.getDirectiveMetadata(directiveType); if (directiveMetadata.isComponent) { var module = ngModuleByPipeOrDirective.get(directiveType); module || error("Cannot determine the module for component '" + identifierName(directiveMetadata.type) + "'"); var htmlAst = directiveMetadata.template.htmlAst; var preserveWhitespaces = directiveMetadata.template.preserveWhitespaces; if (!preserveWhitespaces) { htmlAst = removeWhitespaces(htmlAst); } var render3Ast = htmlAstToRender3Ast(htmlAst.rootNodes, hostBindingParser); // Map of StaticType by directive selectors var directiveTypeBySel_1 = new Map(); var directives_1 = module.transitiveModule.directives.map(function (dir) { return _this._metadataResolver.getDirectiveSummary(dir.reference); }); directives_1.forEach(function (directive) { if (directive.selector) { directiveTypeBySel_1.set(directive.selector, directive.type.reference); } }); // Map of StaticType by pipe names var pipeTypeByName_1 = new Map(); var pipes_1 = module.transitiveModule.pipes.map(function (pipe) { return _this._metadataResolver.getPipeSummary(pipe.reference); }); pipes_1.forEach(function (pipe) { pipeTypeByName_1.set(pipe.name, pipe.type.reference); }); compileR3Component(context, directiveMetadata, render3Ast, _this.reflector, hostBindingParser, directiveTypeBySel_1, pipeTypeByName_1); } else { compileR3Directive(context, directiveMetadata, _this.reflector, hostBindingParser); } }); pipes.forEach(function (pipeType) { var pipeMetadata = _this._metadataResolver.getPipeMetadata(pipeType); if (pipeMetadata) { compileR3Pipe(context, pipeMetadata, _this.reflector); } }); injectables.forEach(function (injectable) { return _this._injectableCompiler.compile(injectable, context); }); }; AotCompiler.prototype.emitAllPartialModules2 = function (files) { var _this = this; // Using reduce like this is a select many pattern (where map is a select pattern) return files.reduce(function (r, file) { r.push.apply(r, tslib_1.__spread(_this._emitPartialModule2(file.fileName, file.injectables))); return r; }, []); }; AotCompiler.prototype._emitPartialModule2 = function (fileName, injectables) { var _this = this; var context = this._createOutputContext(fileName); injectables.forEach(function (injectable) { return _this._injectableCompiler.compile(injectable, context); }); if (context.statements && context.statements.length > 0) { return [{ fileName: fileName, statements: tslib_1.__spread(context.constantPool.statements, context.statements) }]; } return []; }; AotCompiler.prototype.emitAllImpls = function (analyzeResult) { var _this = this; var ngModuleByPipeOrDirective = analyzeResult.ngModuleByPipeOrDirective, files = analyzeResult.files; var sourceModules = files.map(function (file) { return _this._compileImplFile(file.fileName, ngModuleByPipeOrDirective, file.directives, file.pipes, file.ngModules, file.injectables); }); return flatten(sourceModules); }; AotCompiler.prototype._compileImplFile = function (srcFileUrl, ngModuleByPipeOrDirective, directives, pipes, ngModules, injectables) { var _this = this; var fileSuffix = normalizeGenFileSuffix(splitTypescriptSuffix(srcFileUrl, true)[1]); var generatedFiles = []; var outputCtx = this._createOutputContext(ngfactoryFilePath(srcFileUrl, true)); generatedFiles.push.apply(generatedFiles, tslib_1.__spread(this._createSummary(srcFileUrl, directives, pipes, ngModules, injectables, outputCtx))); // compile all ng modules ngModules.forEach(function (ngModuleMeta) { return _this._compileModule(outputCtx, ngModuleMeta); }); // compile components directives.forEach(function (dirType) { var compMeta = _this._metadataResolver.getDirectiveMetadata(dirType); if (!compMeta.isComponent) { return; } var ngModule = ngModuleByPipeOrDirective.get(dirType); if (!ngModule) { throw new Error("Internal Error: cannot determine the module for component " + identifierName(compMeta.type) + "!"); } // compile styles var componentStylesheet = _this._styleCompiler.compileComponent(outputCtx, compMeta); // Note: compMeta is a component and therefore template is non null. compMeta.template.externalStylesheets.forEach(function (stylesheetMeta) { // Note: fill non shim and shim style files as they might // be shared by component with and without ViewEncapsulation. var shim = _this._styleCompiler.needsStyleShim(compMeta); generatedFiles.push(_this._codegenStyles(srcFileUrl, compMeta, stylesheetMeta, shim, fileSuffix)); if (_this._options.allowEmptyCodegenFiles) { generatedFiles.push(_this._codegenStyles(srcFileUrl, compMeta, stylesheetMeta, !shim, fileSuffix)); } }); // compile components var compViewVars = _this._compileComponent(outputCtx, compMeta, ngModule, ngModule.transitiveModule.directives, componentStylesheet, fileSuffix); _this._compileComponentFactory(outputCtx, compMeta, ngModule, fileSuffix); }); if (outputCtx.statements.length > 0 || this._options.allowEmptyCodegenFiles) { var srcModule = this._codegenSourceModule(srcFileUrl, outputCtx); generatedFiles.unshift(srcModule); } return generatedFiles; }; AotCompiler.prototype._createSummary = function (srcFileName, directives, pipes, ngModules, injectables, ngFactoryCtx) { var _this = this; var symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileName) .map(function (symbol) { return _this._symbolResolver.resolveSymbol(symbol); }); var typeData = tslib_1.__spread(ngModules.map(function (meta) { return ({ summary: _this._metadataResolver.getNgModuleSummary(meta.type.reference), metadata: _this._metadataResolver.getNgModuleMetadata(meta.type.reference) }); }), directives.map(function (ref) { return ({ summary: _this._metadataResolver.getDirectiveSummary(ref), metadata: _this._metadataResolver.getDirectiveMetadata(ref) }); }), pipes.map(function (ref) { return ({ summary: _this._metadataResolver.getPipeSummary(ref), metadata: _this._metadataResolver.getPipeMetadata(ref) }); }), injectables.map(function (ref) { return ({ summary: _this._metadataResolver.getInjectableSummary(ref.symbol), metadata: _this._metadataResolver.getInjectableSummary(ref.symbol).type }); })); var forJitOutputCtx = this._options.enableSummariesForJit ? this._createOutputContext(summaryForJitFileName(srcFileName, true)) : null; var _a = serializeSummaries(srcFileName, forJitOutputCtx, this._summaryResolver, this._symbolResolver, symbolSummaries, typeData), json = _a.json, exportAs = _a.exportAs; exportAs.forEach(function (entry) { ngFactoryCtx.statements.push(o.variable(entry.exportAs).set(ngFactoryCtx.importExpr(entry.symbol)).toDeclStmt(null, [ o.StmtModifier.Exported ])); }); var summaryJson = new GeneratedFile(srcFileName, summaryFileName(srcFileName), json); var result = [summaryJson]; if (forJitOutputCtx) { result.push(this._codegenSourceModule(srcFileName, forJitOutputCtx)); } return result; }; AotCompiler.prototype._compileModule = function (outputCtx, ngModule) { var providers = []; if (this._options.locale) { var normalizedLocale = this._options.locale.replace(/_/g, '-'); providers.push({ token: createTokenForExternalReference(this.reflector, Identifiers.LOCALE_ID), useValue: normalizedLocale, }); } if (this._options.i18nFormat) { providers.push({ token: createTokenForExternalReference(this.reflector, Identifiers.TRANSLATIONS_FORMAT), useValue: this._options.i18nFormat }); } this._ngModuleCompiler.compile(outputCtx, ngModule, providers); }; AotCompiler.prototype._compileComponentFactory = function (outputCtx, compMeta, ngModule, fileSuffix) { var hostMeta = this._metadataResolver.getHostComponentMetadata(compMeta); var hostViewFactoryVar = this._compileComponent(outputCtx, hostMeta, ngModule, [compMeta.type], null, fileSuffix) .viewClassVar; var compFactoryVar = componentFactoryName(compMeta.type.reference); var inputsExprs = []; for (var propName in compMeta.inputs) { var templateName = compMeta.inputs[propName]; // Don't quote so that the key gets minified... inputsExprs.push(new o.LiteralMapEntry(propName, o.literal(templateName), false)); } var outputsExprs = []; for (var propName in compMeta.outputs) { var templateName = compMeta.outputs[propName]; // Don't quote so that the key gets minified... outputsExprs.push(new o.LiteralMapEntry(propName, o.literal(templateName), false)); } outputCtx.statements.push(o.variable(compFactoryVar) .set(o.importExpr(Identifiers.createComponentFactory).callFn([ o.literal(compMeta.selector), outputCtx.importExpr(compMeta.type.reference), o.variable(hostViewFactoryVar), new o.LiteralMapExpr(inputsExprs), new o.LiteralMapExpr(outputsExprs), o.literalArr(compMeta.template.ngContentSelectors.map(function (selector) { return o.literal(selector); })) ])) .toDeclStmt(o.importType(Identifiers.ComponentFactory, [o.expressionType(outputCtx.importExpr(compMeta.type.reference))], [o.TypeModifier.Const]), [o.StmtModifier.Final, o.StmtModifier.Exported])); }; AotCompiler.prototype._compileComponent = function (outputCtx, compMeta, ngModule, directiveIdentifiers, componentStyles, fileSuffix) { var _a = this._parseTemplate(compMeta, ngModule, directiveIdentifiers), parsedTemplate = _a.template, usedPipes = _a.pipes; var stylesExpr = componentStyles ? o.variable(componentStyles.stylesVar) : o.literalArr([]); var viewResult = this._viewCompiler.compileComponent(outputCtx, compMeta, parsedTemplate, stylesExpr, usedPipes); if (componentStyles) { _resolveStyleStatements(this._symbolResolver, componentStyles, this._styleCompiler.needsStyleShim(compMeta), fileSuffix); } return viewResult; }; AotCompiler.prototype._parseTemplate = function (compMeta, ngModule, directiveIdentifiers) { var _this = this; if (this._templateAstCache.has(compMeta.type.reference)) { return this._templateAstCache.get(compMeta.type.reference); } var preserveWhitespaces = compMeta.template.preserveWhitespaces; var directives = directiveIdentifiers.map(function (dir) { return _this._metadataResolver.getDirectiveSummary(dir.reference); }); var pipes = ngModule.transitiveModule.pipes.map(function (pipe) { return _this._metadataResolver.getPipeSummary(pipe.reference); }); var result = this._templateParser.parse(compMeta, compMeta.template.htmlAst, directives, pipes, ngModule.schemas, templateSourceUrl(ngModule.type, compMeta, compMeta.template), preserveWhitespaces); this._templateAstCache.set(compMeta.type.reference, result); return result; }; AotCompiler.prototype._createOutputContext = function (genFilePath) { var _this = this; var importExpr = function (symbol, typeParams, useSummaries) { if (typeParams === void 0) { typeParams = null; } if (useSummaries === void 0) { useSummaries = true; } if (!(symbol instanceof StaticSymbol)) { throw new Error("Internal error: unknown identifier " + JSON.stringify(symbol)); } var arity = _this._symbolResolver.getTypeArity(symbol) || 0; var _a = _this._symbolResolver.getImportAs(symbol, useSummaries) || symbol, filePath = _a.filePath, name = _a.name, members = _a.members; var importModule = _this._fileNameToModuleName(filePath, genFilePath); // It should be good enough to compare filePath to genFilePath and if they are equal // there is a self reference. However, ngfactory files generate to .ts but their // symbols have .d.ts so a simple compare is insufficient. They should be canonical // and is tracked by #17705. var selfReference = _this._fileNameToModuleName(genFilePath, genFilePath); var moduleName = importModule === selfReference ? null : importModule; // 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. var suppliedTypeParams = typeParams || []; var missingTypeParamsCount = arity - suppliedTypeParams.length; var allTypeParams = suppliedTypeParams.concat(new Array(missingTypeParamsCount).fill(o.DYNAMIC_TYPE)); return members.reduce(function (expr, memberName) { return expr.prop(memberName); }, o.importExpr(new o.ExternalReference(moduleName, name, null), allTypeParams)); }; return { statements: [], genFilePath: genFilePath, importExpr: importExpr, constantPool: new ConstantPool() }; }; AotCompiler.prototype._fileNameToModuleName = function (importedFilePath, containingFilePath) { return this._summaryResolver.getKnownModuleName(importedFilePath) || this._symbolResolver.getKnownModuleName(importedFilePath) || this._host.fileNameToModuleName(importedFilePath, containingFilePath); }; AotCompiler.prototype._codegenStyles = function (srcFileUrl, compMeta, stylesheetMetadata, isShimmed, fileSuffix) { var outputCtx = this._createOutputContext(_stylesModuleUrl(stylesheetMetadata.moduleUrl, isShimmed, fileSuffix)); var compiledStylesheet = this._styleCompiler.compileStyles(outputCtx, compMeta, stylesheetMetadata, isShimmed); _resolveStyleStatements(this._symbolResolver, compiledStylesheet, isShimmed, fileSuffix); return this._codegenSourceModule(srcFileUrl, outputCtx); }; AotCompiler.prototype._codegenSourceModule = function (srcFileUrl, ctx) { return new GeneratedFile(srcFileUrl, ctx.genFilePath, ctx.statements); }; AotCompiler.prototype.listLazyRoutes = function (entryRoute, analyzedModules) { var e_2, _a, e_3, _b; var self = this; if (entryRoute) { var symbol = parseLazyRoute(entryRoute, this.reflector).referencedModule; return visitLazyRoute(symbol); } else if (analyzedModules) { var allLazyRoutes = []; try { for (var _c = tslib_1.__values(analyzedModules.ngModules), _d = _c.next(); !_d.done; _d = _c.next()) { var ngModule = _d.value; var lazyRoutes = listLazyRoutes(ngModule, this.reflector); try { for (var lazyRoutes_1 = tslib_1.__values(lazyRoutes), lazyRoutes_1_1 = lazyRoutes_1.next(); !lazyRoutes_1_1.done; lazyRoutes_1_1 = lazyRoutes_1.next()) { var lazyRoute = lazyRoutes_1_1.value; allLazyRoutes.push(lazyRoute); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (lazyRoutes_1_1 && !lazyRoutes_1_1.done && (_b = lazyRoutes_1.return)) _b.call(lazyRoutes_1); } finally { if (e_3) throw e_3.error; } } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_2) throw e_2.error; } } return allLazyRoutes; } else { throw new Error("Either route or analyzedModules has to be specified!"); } function visitLazyRoute(symbol, seenRoutes, allLazyRoutes) { if (seenRoutes === void 0) { seenRoutes = new Set(); } if (allLazyRoutes === void 0) { allLazyRoutes = []; } var e_4, _a; // Support pointing to default exports, but stop recursing there, // as the StaticReflector does not yet support default exports. if (seenRoutes.has(symbol) || !symbol.name) { return allLazyRoutes; } seenRoutes.add(symbol); var lazyRoutes = listLazyRoutes(self._metadataResolver.getNgModuleMetadata(symbol, true), self.reflector); try { for (var lazyRoutes_2 = tslib_1.__values(lazyRoutes), lazyRoutes_2_1 = lazyRoutes_2.next(); !lazyRoutes_2_1.done; lazyRoutes_2_1 = lazyRoutes_2.next()) { var lazyRoute = lazyRoutes_2_1.value; allLazyRoutes.push(lazyRoute); visitLazyRoute(lazyRoute.referencedModule, seenRoutes, allLazyRoutes); } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (lazyRoutes_2_1 && !lazyRoutes_2_1.done && (_a = lazyRoutes_2.return)) _a.call(lazyRoutes_2); } finally { if (e_4) throw e_4.error; } } return allLazyRoutes; } }; return AotCompiler; }()); export { AotCompiler }; function _createEmptyStub(outputCtx) { // Note: We need to produce at least one import statement so that // TypeScript knows that the file is an es6 module. Otherwise our generated // exports / imports won't be emitted properly by TypeScript. outputCtx.statements.push(o.importExpr(Identifiers.ComponentFactory).toStmt()); } function _resolveStyleStatements(symbolResolver, compileResult, needsShim, fileSuffix) { compileResult.dependencies.forEach(function (dep) { dep.setValue(symbolResolver.getStaticSymbol(_stylesModuleUrl(dep.moduleUrl, needsShim, fileSuffix), dep.name)); }); } function _stylesModuleUrl(stylesheetUrl, shim, suffix) { return "" + stylesheetUrl + (shim ? '.shim' : '') + ".ngstyle" + suffix; } export function analyzeNgModules(fileNames, host, staticSymbolResolver, metadataResolver) { var files = _analyzeFilesIncludingNonProgramFiles(fileNames, host, staticSymbolResolver, metadataResolver); return mergeAnalyzedFiles(files); } export function analyzeAndValidateNgModules(fileNames, host, staticSymbolResolver, metadataResolver) { return validateAnalyzedModules(analyzeNgModules(fileNames, host, staticSymbolResolver, metadataResolver)); } function validateAnalyzedModules(analyzedModules) { if (analyzedModules.symbolsMissingModule && analyzedModules.symbolsMissingModule.length) { var messages = analyzedModules.symbolsMissingModule.map(function (s) { return "Cannot determine the module for class " + s.name + " in " + s.filePath + "! Add " + s.name + " to the NgModule to fix it."; }); throw syntaxError(messages.join('\n')); } return analyzedModules; } // Analyzes all of the program files, // including files that are not part of the program // but are referenced by an NgModule. function _analyzeFilesIncludingNonProgramFiles(fileNames, host, staticSymbolResolver, metadataResolver) { var seenFiles = new Set(); var files = []; var visitFile = function (fileName) { if (seenFiles.has(fileName) || !host.isSourceFile(fileName)) { return false; } seenFiles.add(fileName); var analyzedFile = analyzeFile(host, staticSymbolResolver, metadataResolver, fileName); files.push(analyzedFile); analyzedFile.ngModules.forEach(function (ngModule) { ngModule.transitiveModule.modules.forEach(function (modMeta) { return visitFile(modMeta.reference.filePath); }); }); }; fileNames.forEach(function (fileName) { return visitFile(fileName); }); return files; } export function analyzeFile(host, staticSymbolResolver, metadataResolver, fileName) { var directives = []; var pipes = []; var injectables = []; var ngModules = []; var hasDecorators = staticSymbolResolver.hasDecorators(fileName); var exportsNonSourceFiles = false; // Don't analyze .d.ts files that have no decorators as a shortcut // to speed up the analysis. This prevents us from // resolving the references in these files. // Note: exportsNonSourceFiles is only needed when compiling with summaries, // which is not the case when .d.ts files are treated as input files. if (!fileName.endsWith('.d.ts') || hasDecorators) { staticSymbolResolver.getSymbolsOf(fileName).forEach(function (symbol) { var resolvedSymbol = staticSymbolResolver.resolveSymbol(symbol); var symbolMeta = resolvedSymbol.metadata; if (!symbolMeta || symbolMeta.__symbolic === 'error') { return; } var isNgSymbol = false; if (symbolMeta.__symbolic === 'class') { if (metadataResolver.isDirective(symbol)) { isNgSymbol = true; directives.push(symbol); } else if (metadataResolver.isPipe(symbol)) { isNgSymbol = true; pipes.push(symbol); } else if (metadataResolver.isNgModule(symbol)) { var ngModule = metadataResolver.getNgModuleMetadata(symbol, false); if (ngModule) { isNgSymbol = true; ngModules.push(ngModule); } } else if (metadataResolver.isInjectable(symbol)) { isNgSymbol = true; var injectable = metadataResolver.getInjectableMetadata(symbol, null, false); if (injectable) { injectables.push(injectable); } } } if (!isNgSymbol) { exportsNonSourceFiles = exportsNonSourceFiles || isValueExportingNonSourceFile(host, symbolMeta); } }); } return { fileName: fileName, directives: directives, pipes: pipes, ngModules: ngModules, injectables: injectables, exportsNonSourceFiles: exportsNonSourceFiles, }; } export function analyzeFileForInjectables(host, staticSymbolResolver, metadataResolver, fileName) { var injectables = []; var shallowModules = []; if (staticSymbolResolver.hasDecorators(fileName)) { staticSymbolResolver.getSymbolsOf(fileName).forEach(function (symbol) { var resolvedSymbol = staticSymbolResolver.resolveSymbol(symbol); var symbolMeta = resolvedSymbol.metadata; if (!symbolMeta || symbolMeta.__symbolic === 'error') { return; } if (symbolMeta.__symbolic === 'class') { if (metadataResolver.isInjectable(symbol)) { var injectable = metadataResolver.getInjectableMetadata(symbol, null, false); if (injectable) { injectables.push(injectable); } } else if (metadataResolver.isNgModule(symbol)) { var module = metadataResolver.getShallowModuleMetadata(symbol); if (module) { shallowModules.push(module); } } } }); } return { fileName: fileName, injectables: injectables, shallowModules: shallowModules }; } function isValueExportingNonSourceFile(host, metadata) { var exportsNonSourceFiles = false; var Visitor = /** @class */ (function () { function Visitor() { } Visitor.prototype.visitArray = function (arr, context) { var _this = this; arr.forEach(function (v) { return visitValue(v, _this, context); }); }; Visitor.prototype.visitStringMap = function (map, context) { var _this = this; Object.keys(map).forEach(function (key) { return visitValue(map[key], _this, context); }); }; Visitor.prototype.visitPrimitive = function (value, context) { }; Visitor.prototype.visitOther = function (value, context) { if (value instanceof StaticSymbol && !host.isSourceFile(value.filePath)) { exportsNonSourceFiles = true; } }; return Visitor; }()); visitValue(metadata, new Visitor(), null); return exportsNonSourceFiles; } export function mergeAnalyzedFiles(analyzedFiles) { var allNgModules = []; var ngModuleByPipeOrDirective = new Map(); var allPipesAndDirectives = new Set(); analyzedFiles.forEach(function (af) { af.ngModules.forEach(function (ngModule) { allNgModules.push(ngModule); ngModule.declaredDirectives.forEach(function (d) { return ngModuleByPipeOrDirective.set(d.reference, ngModule); }); ngModule.declaredPipes.forEach(function (p) { return ngModuleByPipeOrDirective.set(p.reference, ngModule); }); }); af.directives.forEach(function (d) { return allPipesAndDirectives.add(d); }); af.pipes.forEach(function (p) { return allPipesAndDirectives.add(p); }); }); var symbolsMissingModule = []; allPipesAndDirectives.forEach(function (ref) { if (!ngModuleByPipeOrDirective.has(ref)) { symbolsMissingModule.push(ref); } }); return { ngModules: allNgModules, ngModuleByPipeOrDirective: ngModuleByPipeOrDirective, symbolsMissingModule: symbolsMissingModule, files: analyzedFiles }; } function mergeAndValidateNgFiles(files) { return validateAnalyzedModules(mergeAnalyzedFiles(files)); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGlsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvYW90L2NvbXBpbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRzs7QUFFSCxPQUFPLEVBQThRLG9CQUFvQixFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUVsWCxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDOUMsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sU0FBUyxDQUFDO0FBQzFDLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUMsV0FBVyxFQUFFLCtCQUErQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFJNUUsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLCtCQUErQixDQUFDO0FBQ2hFLE9BQU8sRUFBQyw0QkFBNEIsRUFBRSxtQkFBbUIsRUFBQyxNQUFNLG1DQUFtQyxDQUFDO0FBR3BHLE9BQU8sS0FBSyxDQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFFMUMsT0FBTyxFQUFDLDBCQUEwQixJQUFJLGVBQWUsRUFBQyxNQUFNLCtCQUErQixDQUFDO0FBQzVGLE9BQU8sRUFBQyxzQkFBc0IsSUFBSSxhQUFhLEVBQUMsTUFBTSw2QkFBNkIsQ0FBQztBQUNwRixPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSxrQ0FBa0MsQ0FBQztBQUNyRSxPQUFPLEVBQUMsMkJBQTJCLElBQUksa0JBQWtCLEVBQUUsMkJBQTJCLElBQUksa0JBQWtCLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUM5SSxPQUFPLEVBQUMsd0JBQXdCLEVBQUMsTUFBTSx1Q0FBdUMsQ0FBQztBQUcv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