test(compiler-cli): workaround for performance cliff in TypeScript (#39707)

The type checker had to do extensive work in resolving the
`NodePath.get` method call for the `NodePath` that had an intersection
type of `ts.VariableDeclarator&{init:t.Expression}`. The `NodePath.get`
method is typed using a conditional type which became expensive to
compute with this intersection type. As a workaround, the original
`init` property is explicitly omitted which avoids the performance
cliff. This brings down the compile time by 15s.

PR Close #39707
This commit is contained in:
JoostK 2020-11-16 13:02:27 +01:00 committed by Andrew Kushnir
parent bfa20e11a6
commit 8348556b77
1 changed files with 10 additions and 3 deletions

View File

@ -10,7 +10,6 @@ import traverse, {NodePath} from '@babel/traverse';
import * as t from '@babel/types'; import * as t from '@babel/types';
import {BabelDeclarationScope} from '../src/babel_declaration_scope'; import {BabelDeclarationScope} from '../src/babel_declaration_scope';
describe('BabelDeclarationScope', () => { describe('BabelDeclarationScope', () => {
describe('getConstantScopeRef()', () => { describe('getConstantScopeRef()', () => {
it('should return a path to the ES module where the expression was imported', () => { it('should return a path to the ES module where the expression was imported', () => {
@ -83,11 +82,19 @@ describe('BabelDeclarationScope', () => {
}); });
}); });
/**
* The type of a variable declarator that is known to have an initializer.
*
* Note: the `init` property is explicitly omitted to workaround a performance cliff in the
* TypeScript type checker.
*/
type InitializedVariableDeclarator = Omit<t.VariableDeclarator, 'init'>&{init: t.Expression};
function findVarDeclaration( function findVarDeclaration(
file: t.File, varName: string): NodePath<t.VariableDeclarator&{init: t.Expression}> { file: t.File, varName: string): NodePath<InitializedVariableDeclarator> {
let varDecl: NodePath<t.VariableDeclarator>|undefined = undefined; let varDecl: NodePath<t.VariableDeclarator>|undefined = undefined;
traverse(file, { traverse(file, {
VariableDeclarator: (path) => { VariableDeclarator: (path: NodePath<t.VariableDeclarator>) => {
const id = path.get('id'); const id = path.get('id');
if (id.isIdentifier() && id.node.name === varName && path.get('init') !== null) { if (id.isIdentifier() && id.node.name === varName && path.get('init') !== null) {
varDecl = path; varDecl = path;