Skip to content

Commit ffb4dd5

Browse files
author
Andy Hanson
committed
Don't check an expression if it was checked cached
1 parent 7715b51 commit ffb4dd5

File tree

4 files changed

+21
-12
lines changed

4 files changed

+21
-12
lines changed

src/compiler/checker.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@ namespace ts {
421421
let deferredGlobalTemplateStringsArrayType: ObjectType;
422422

423423
let deferredNodes: Node[];
424+
const seenDeferredNodes = createMap<true>(); // For assertion that we don't defer the same node twice
424425
let deferredUnusedIdentifierNodes: Node[];
425-
const seenDeferredUnusedIdentifiers = createMap<true>(); // For assertion that we don't defer the same identifier twice
426426

427427
let flowLoopStart = 0;
428428
let flowLoopCount = 0;
@@ -19573,14 +19573,14 @@ namespace ts {
1957319573
const links = getNodeLinks(node);
1957419574
if (!links.resolvedType) {
1957519575
if (checkMode) {
19576-
return checkExpression(node, checkMode);
19576+
return checkExpressionNoCache(node, checkMode);
1957719577
}
1957819578
// When computing a type that we're going to cache, we need to ignore any ongoing control flow
1957919579
// analysis because variables may have transient types in indeterminable states. Moving flowLoopStart
1958019580
// to the top of the stack ensures all transient types are computed from a known point.
1958119581
const saveFlowLoopStart = flowLoopStart;
1958219582
flowLoopStart = flowLoopCount;
19583-
links.resolvedType = checkExpression(node, checkMode);
19583+
links.resolvedType = checkExpressionNoCache(node, checkMode);
1958419584
flowLoopStart = saveFlowLoopStart;
1958519585
}
1958619586
return links.resolvedType;
@@ -19715,14 +19715,19 @@ namespace ts {
1971519715
return type;
1971619716
}
1971719717

19718+
function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode): Type {
19719+
// Do nothing if this was already checked by a `checkExpressionCached` call
19720+
return getNodeLinks(node).resolvedType || checkExpressionNoCache(node, checkMode);
19721+
}
19722+
1971819723
// Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
1971919724
// contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
1972019725
// expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in
1972119726
// conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function
1972219727
// object, it serves as an indicator that all contained function and arrow expressions should be considered to
1972319728
// have the wildcard function type; this form of type check is used during overload resolution to exclude
1972419729
// contextually typed function and arrow expressions in the initial phase.
19725-
function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode): Type {
19730+
function checkExpressionNoCache(node: Expression | QualifiedName, checkMode: CheckMode | undefined): Type {
1972619731
let type: Type;
1972719732
if (node.kind === SyntaxKind.QualifiedName) {
1972819733
type = checkQualifiedName(<QualifiedName>node);
@@ -19802,7 +19807,7 @@ namespace ts {
1980219807
case SyntaxKind.ParenthesizedExpression:
1980319808
return checkParenthesizedExpression(<ParenthesizedExpression>node, checkMode);
1980419809
case SyntaxKind.ClassExpression:
19805-
return checkClassExpression(<ClassExpression>node);
19810+
return checkClassExpression(<ClassExpression>node, checkMode);
1980619811
case SyntaxKind.FunctionExpression:
1980719812
case SyntaxKind.ArrowFunction:
1980819813
return checkFunctionExpressionOrObjectLiteralMethod(<FunctionExpression>node, checkMode);
@@ -21573,7 +21578,6 @@ namespace ts {
2157321578

2157421579
function registerForUnusedIdentifiersCheck(node: Node) {
2157521580
if (deferredUnusedIdentifierNodes) {
21576-
Debug.assert(addToSeen(seenDeferredUnusedIdentifiers, getNodeId(node)), "Deferring unused identifier check twice");
2157721581
deferredUnusedIdentifierNodes.push(node);
2157821582
}
2157921583
}
@@ -23175,9 +23179,11 @@ namespace ts {
2317523179
return true;
2317623180
}
2317723181

23178-
function checkClassExpression(node: ClassExpression): Type {
23179-
checkClassLikeDeclaration(node);
23180-
checkNodeDeferred(node);
23182+
function checkClassExpression(node: ClassExpression, checkMode: CheckMode | undefined): Type {
23183+
if (!checkMode) {
23184+
checkClassLikeDeclaration(node);
23185+
checkNodeDeferred(node);
23186+
}
2318123187
return getTypeOfSymbol(getSymbolOfNode(node));
2318223188
}
2318323189

@@ -24519,6 +24525,7 @@ namespace ts {
2451924525
// Delaying the type check of the body ensures foo has been assigned a type.
2452024526
function checkNodeDeferred(node: Node) {
2452124527
if (deferredNodes) {
24528+
Debug.assert(addToSeen(seenDeferredNodes, getNodeId(node)));
2452224529
deferredNodes.push(node);
2452324530
}
2452424531
}
@@ -24584,7 +24591,7 @@ namespace ts {
2458424591
}
2458524592

2458624593
deferredNodes = undefined;
24587-
seenDeferredUnusedIdentifiers.clear();
24594+
seenDeferredNodes.clear();
2458824595
deferredUnusedIdentifierNodes = undefined;
2458924596

2459024597
if (isExternalOrCommonJsModule(node)) {

src/harness/harness.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ interface XMLHttpRequest {
7373
}
7474
/* tslint:enable:no-var-keyword */
7575

76+
ts.Debug.currentAssertionLevel = ts.AssertionLevel.Normal;
77+
7678
namespace Utils {
7779
// Setup some globals based on the current environment
7880
export const enum ExecutionEnvironment {

tests/baselines/reference/arrayLiteralComments.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
=== tests/cases/compiler/arrayLiteralComments.ts ===
22
var testArrayWithFunc = [
33
>testArrayWithFunc : (string | number | (() => void) | number[] | { a: number; })[]
4-
>[ // Function comment function() { let x = 1; }, // String comment '1', // Numeric comment 2, // Object comment { a: 1 }, // Array comment [1, 2, 3]] : (string | number | (() => void) | number[] | { a: number; })[]
4+
>[ // Function comment function() { let x = 1; }, // String comment '1', // Numeric comment 2, // Object comment { a: 1 }, // Array comment [1, 2, 3]] : (string | number | (() => void) | { a: number; } | number[])[]
55

66
// Function comment
77
function() {

tests/baselines/reference/heterogeneousArrayLiterals.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var d = [{}, 1]; // {}[]
2828

2929
var e = [{}, Object]; // {}[]
3030
>e : {}[]
31-
>[{}, Object] : (ObjectConstructor | {})[]
31+
>[{}, Object] : ({} | ObjectConstructor)[]
3232
>{} : {}
3333
>Object : ObjectConstructor
3434

0 commit comments

Comments
 (0)