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:
parent
cd9ae66b35
commit
9f5b490800
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as ng from '@angular/compiler-cli';
|
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 fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as tsickle from 'tsickle';
|
import * as tsickle from 'tsickle';
|
||||||
|
@ -35,6 +35,9 @@ export function main(args) {
|
||||||
return 0;
|
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 {
|
export function runOneBuild(args: string[], inputs?: {[path: string]: string}): boolean {
|
||||||
if (args[0] === '-p') args.shift();
|
if (args[0] === '-p') args.shift();
|
||||||
// Strip leading at-signs, used to indicate a params file
|
// Strip leading at-signs, used to indicate a params file
|
||||||
|
@ -141,10 +144,8 @@ export function relativeToRootDirs(filePath: string, rootDirs: string[]): string
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compile({
|
export function compile({allDepsCompiledWithBazel = true, compilerOpts, tsHost, bazelOpts, files,
|
||||||
allDepsCompiledWithBazel = true, compilerOpts, tsHost, bazelOpts, files, inputs, expectedOuts,
|
inputs, expectedOuts, gatherDiagnostics, bazelHost}: {
|
||||||
gatherDiagnostics, bazelHost,
|
|
||||||
}: {
|
|
||||||
allDepsCompiledWithBazel?: boolean,
|
allDepsCompiledWithBazel?: boolean,
|
||||||
compilerOpts: ng.CompilerOptions,
|
compilerOpts: ng.CompilerOptions,
|
||||||
tsHost: ts.CompilerHost, inputs?: {[path: string]: string},
|
tsHost: ts.CompilerHost, inputs?: {[path: string]: string},
|
||||||
|
@ -152,15 +153,41 @@ export function compile({
|
||||||
files: string[],
|
files: string[],
|
||||||
expectedOuts: string[],
|
expectedOuts: string[],
|
||||||
gatherDiagnostics?: (program: ng.Program) => ng.Diagnostics,
|
gatherDiagnostics?: (program: ng.Program) => ng.Diagnostics,
|
||||||
bazelHost?: BazelHost,
|
bazelHost?: CompilerHost,
|
||||||
}): {diagnostics: ng.Diagnostics, program: ng.Program} {
|
}): {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) {
|
if (!bazelOpts.es5Mode) {
|
||||||
compilerOpts.annotateForClosureCompiler = true;
|
compilerOpts.annotateForClosureCompiler = true;
|
||||||
compilerOpts.annotationsAs = 'static fields';
|
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.
|
// Disable downleveling and Closure annotation if in Ivy mode.
|
||||||
if (compilerOpts.enableIvy) {
|
if (isInIvyMode) {
|
||||||
compilerOpts.annotationsAs = 'decorators';
|
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) {
|
if (!bazelHost) {
|
||||||
const fileLoader = createFileLoader(inputs, bazelOpts);
|
bazelHost = new CompilerHost(
|
||||||
bazelHost = new BazelHost(
|
|
||||||
files, compilerOpts, bazelOpts, tsHost, fileLoader, generatedFileModuleResolver);
|
files, compilerOpts, bazelOpts, tsHost, fileLoader, generatedFileModuleResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also need to disable decorator downleveling in the BazelHost in Ivy mode.
|
// Also need to disable decorator downleveling in the BazelHost in Ivy mode.
|
||||||
if (compilerOpts.enableIvy) {
|
if (isInIvyMode) {
|
||||||
bazelHost.transformDecorators = false;
|
bazelHost.transformDecorators = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,68 +433,6 @@ export function compile({
|
||||||
return {program, diagnostics};
|
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
|
* Generate metadata.json for the specified `files`. By default, metadata.json
|
||||||
* is only generated by the compiler if --flatModuleOutFile is specified. But
|
* is only generated by the compiler if --flatModuleOutFile is specified. But
|
||||||
|
|
Loading…
Reference in New Issue