Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14145,8 +14145,8 @@ namespace ts {
return resultType;

function getTypeAtFlowNode(flow: FlowNode): FlowType {
if (flowDepth === 2500) {
// We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error
if (flowDepth === 2000) {
// We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
// and disable further control flow analysis in the containing function or module body.
flowAnalysisDisabled = true;
reportFlowControlError(reference);
Expand Down Expand Up @@ -14283,7 +14283,8 @@ namespace ts {
}
}
else {
const indexType = getTypeOfExpression((<ElementAccessExpression>node.left).argumentExpression);
// We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time)
const indexType = getContextFreeTypeOfExpression((<ElementAccessExpression>node.left).argumentExpression);
if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) {
evolvedType = addEvolvingArrayElementType(evolvedType, node.right);
}
Expand Down Expand Up @@ -21619,9 +21620,13 @@ namespace ts {
* It sets the contextual type of the node to any before calling getTypeOfExpression.
*/
function getContextFreeTypeOfExpression(node: Expression) {
const links = getNodeLinks(node);
if (links.contextFreeType) {
return links.contextFreeType;
}
const saveContextualType = node.contextualType;
node.contextualType = anyType;
const type = getTypeOfExpression(node);
const type = links.contextFreeType = checkExpression(node, CheckMode.SkipContextSensitive);
node.contextualType = saveContextualType;
return type;
}
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3642,6 +3642,7 @@ namespace ts {
superCall?: SuperCall; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
switchTypes?: Type[]; // Cached array of switch case expression types
jsxNamespace?: Symbol | false; // Resolved jsx namespace symbol for this node
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
}

export const enum TypeFlags {
Expand Down
158 changes: 158 additions & 0 deletions tests/baselines/reference/deeplyDependentLargeArrayMutation.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
=== tests/cases/compiler/foo.js ===
// repro from #26031
function build() {
>build : Symbol(build, Decl(foo.js, 0, 0))

var arr = [];
>arr : Symbol(arr, Decl(foo.js, 2, 7))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

arr[arr.length] = 'value';
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>arr.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(foo.js, 2, 7))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
}
Loading