Revert "refactor(compiler): refactor and export Bazel host creation. (#34686)" (#35063)

This reverts commit cb142b6df9.

The intention of this commit was for a consumer of the `compile` function to
pass the `bazelHost` it returns into future invocations, reusing the
`FileCache` between them. However, first-party ngc_wrapped does not do this,
which caused a performance regression as the `FileCache` was no longer
shared between compilations.

PR Close #35063
This commit is contained in:
Alex Rickabaugh 2020-01-30 11:04:27 -08:00 committed by Andrew Kushnir
parent cd9ae66b35
commit 9f5b490800
1 changed files with 64 additions and 72 deletions

View File

@ -7,7 +7,7 @@
*/
import * as ng from '@angular/compiler-cli';
import {BazelOptions, CachedFileLoader, CompilerHost as BazelHost, FileCache, FileLoader, UncachedFileLoader, constructManifest, debug, parseTsconfig, resolveNormalizedPath, runAsWorker, runWorkerLoop} from '@bazel/typescript';
import {BazelOptions, CachedFileLoader, CompilerHost, FileCache, FileLoader, UncachedFileLoader, constructManifest, debug, parseTsconfig, resolveNormalizedPath, runAsWorker, runWorkerLoop} from '@bazel/typescript';
import * as fs from 'fs';
import * as path from 'path';
import * as tsickle from 'tsickle';
@ -35,6 +35,9 @@ export function main(args) {
return 0;
}
/** The one FileCache instance used in this process. */
const fileCache = new FileCache<ts.SourceFile>(debug);
export function runOneBuild(args: string[], inputs?: {[path: string]: string}): boolean {
if (args[0] === '-p') args.shift();
// Strip leading at-signs, used to indicate a params file
@ -141,10 +144,8 @@ export function relativeToRootDirs(filePath: string, rootDirs: string[]): string
return filePath;
}
export function compile({
allDepsCompiledWithBazel = true, compilerOpts, tsHost, bazelOpts, files, inputs, expectedOuts,
gatherDiagnostics, bazelHost,
}: {
export function compile({allDepsCompiledWithBazel = true, compilerOpts, tsHost, bazelOpts, files,
inputs, expectedOuts, gatherDiagnostics, bazelHost}: {
allDepsCompiledWithBazel?: boolean,
compilerOpts: ng.CompilerOptions,
tsHost: ts.CompilerHost, inputs?: {[path: string]: string},
@ -152,15 +153,41 @@ export function compile({
files: string[],
expectedOuts: string[],
gatherDiagnostics?: (program: ng.Program) => ng.Diagnostics,
bazelHost?: BazelHost,
bazelHost?: CompilerHost,
}): {diagnostics: ng.Diagnostics, program: ng.Program} {
let fileLoader: FileLoader;
if (bazelOpts.maxCacheSizeMb !== undefined) {
const maxCacheSizeBytes = bazelOpts.maxCacheSizeMb * (1 << 20);
fileCache.setMaxCacheSize(maxCacheSizeBytes);
} else {
fileCache.resetMaxCacheSize();
}
if (inputs) {
fileLoader = new CachedFileLoader(fileCache);
// Resolve the inputs to absolute paths to match TypeScript internals
const resolvedInputs = new Map<string, string>();
const inputKeys = Object.keys(inputs);
for (let i = 0; i < inputKeys.length; i++) {
const key = inputKeys[i];
resolvedInputs.set(resolveNormalizedPath(key), inputs[key]);
}
fileCache.updateCache(resolvedInputs);
} else {
fileLoader = new UncachedFileLoader();
}
if (!bazelOpts.es5Mode) {
compilerOpts.annotateForClosureCompiler = true;
compilerOpts.annotationsAs = 'static fields';
}
// Detect from compilerOpts whether the entrypoint is being invoked in Ivy mode.
const isInIvyMode = compilerOpts.enableIvy === 'ngtsc';
// Disable downleveling and Closure annotation if in Ivy mode.
if (compilerOpts.enableIvy) {
if (isInIvyMode) {
compilerOpts.annotationsAs = 'decorators';
}
@ -185,14 +212,41 @@ export function compile({
}
};
// Patch fileExists when resolving modules, so that CompilerHost can ask TypeScript to
// resolve non-existing generated files that don't exist on disk, but are
// synthetic and added to the `programWithStubs` based on real inputs.
const generatedFileModuleResolverHost = Object.create(tsHost);
generatedFileModuleResolverHost.fileExists = (fileName: string) => {
const match = NGC_GEN_FILES.exec(fileName);
if (match) {
const [, file, suffix, ext] = match;
// Performance: skip looking for files other than .d.ts or .ts
if (ext !== '.ts' && ext !== '.d.ts') return false;
if (suffix.indexOf('ngstyle') >= 0) {
// Look for foo.css on disk
fileName = file;
} else {
// Look for foo.d.ts or foo.ts on disk
fileName = file + (ext || '');
}
}
return tsHost.fileExists(fileName);
};
function generatedFileModuleResolver(
moduleName: string, containingFile: string,
compilerOptions: ts.CompilerOptions): ts.ResolvedModuleWithFailedLookupLocations {
return ts.resolveModuleName(
moduleName, containingFile, compilerOptions, generatedFileModuleResolverHost);
}
if (!bazelHost) {
const fileLoader = createFileLoader(inputs, bazelOpts);
bazelHost = new BazelHost(
bazelHost = new CompilerHost(
files, compilerOpts, bazelOpts, tsHost, fileLoader, generatedFileModuleResolver);
}
// Also need to disable decorator downleveling in the BazelHost in Ivy mode.
if (compilerOpts.enableIvy) {
if (isInIvyMode) {
bazelHost.transformDecorators = false;
}
@ -379,68 +433,6 @@ export function compile({
return {program, diagnostics};
}
/** A module resolver for handling generated files in Bazel. */
export function generatedFileModuleResolver(
moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions,
host: ts.ModuleResolutionHost, ): ts.ResolvedModuleWithFailedLookupLocations {
// Patch fileExists when resolving modules, so that CompilerHost can ask
// TypeScript to resolve non-existing generated files that don't exist on
// disk, but are synthetic and added to the `programWithStubs` based on real
// inputs.
const generatedFileModuleResolverHost = Object.assign({}, host, {
fileExists: (...[fileName, ...rest]: Parameters<typeof host.fileExists>):
ReturnType<typeof host.fileExists> => {
const match = NGC_GEN_FILES.exec(fileName);
if (match) {
const [, file, suffix, ext] = match;
// Performance: skip looking for files other than .d.ts or .ts
if (ext !== '.ts' && ext !== '.d.ts') return false;
if (suffix.indexOf('ngstyle') >= 0) {
// Look for foo.css on disk
fileName = file;
} else {
// Look for foo.d.ts or foo.ts on disk
fileName = file + (ext || '');
}
}
return host.fileExists(fileName, ...rest);
},
});
return ts.resolveModuleName(
moduleName, containingFile, compilerOptions, generatedFileModuleResolverHost);
}
/** Creates a {@link FileLoader} to cache Bazel inputs.*/
export function createFileLoader(
inputs: {[key: string]: string} | undefined, bazelOpts: BazelOptions): FileLoader {
/** The one FileCache instance used in this process. */
const fileCache = new FileCache<ts.SourceFile>(debug);
if (bazelOpts.maxCacheSizeMb !== undefined) {
const maxCacheSizeBytes = bazelOpts.maxCacheSizeMb * (1 << 20);
fileCache.setMaxCacheSize(maxCacheSizeBytes);
} else {
fileCache.resetMaxCacheSize();
}
if (inputs) {
const fileLoader = new CachedFileLoader(fileCache);
// Resolve the inputs to absolute paths to match TypeScript internals
const resolvedInputs = new Map<string, string>();
const inputKeys = Object.keys(inputs);
for (let i = 0; i < inputKeys.length; i++) {
const key = inputKeys[i];
resolvedInputs.set(resolveNormalizedPath(key), inputs[key]);
}
fileCache.updateCache(resolvedInputs);
return fileLoader;
} else {
return new UncachedFileLoader();
}
}
/**
* Generate metadata.json for the specified `files`. By default, metadata.json
* is only generated by the compiler if --flatModuleOutFile is specified. But