perf(ngcc): shortcircuit tokenizing in ESM dependency host (#37639)

This dependency host tokenizes files to identify all the imported
paths. This commit calculates the last place in the source code
where there can be an import path; it then exits the tokenization
when we get to this point in the file.

Testing with a reasonably large project showed that the tokenizer
spends about 2/3 as much time scanning files. For example in a
"noop" hot run of ngcc using the program-based entry-point
finder the percentage of time spent in the `scan()` function of
the TS tokenizer goes down from 9.9% to 6.6%.

PR Close #37639
This commit is contained in:
Pete Bacon Darwin 2020-06-18 20:44:48 +01:00 committed by Misko Hevery
parent d0437b3be0
commit bd7f440357
1 changed files with 7 additions and 0 deletions

View File

@ -47,10 +47,14 @@ export class EsmDependencyHost extends DependencyHostBase {
const templateStack: ts.SyntaxKind[] = [];
let lastToken: ts.SyntaxKind = ts.SyntaxKind.Unknown;
let currentToken: ts.SyntaxKind = ts.SyntaxKind.Unknown;
const stopAtIndex = findLastPossibleImportOrReexport(fileContents);
this.scanner.setText(fileContents);
while ((currentToken = this.scanner.scan()) !== ts.SyntaxKind.EndOfFileToken) {
if (this.scanner.getTokenPos() > stopAtIndex) {
break;
}
switch (currentToken) {
case ts.SyntaxKind.TemplateHead:
// TemplateHead indicates the beginning of a backticked string
@ -266,6 +270,9 @@ export function hasImportOrReexportStatements(source: string): boolean {
return /(?:import|export)[\s\S]+?(["'])(?:\\\1|.)+?\1/.test(source);
}
function findLastPossibleImportOrReexport(source: string): number {
return Math.max(source.lastIndexOf('import'), source.lastIndexOf(' from '));
}
/**
* Check whether the given statement is an import with a string literal module specifier.