[Flight] Fix visitAsyncNode infinite recursion with circular async nodes #35246
+26
−12
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The
visitAsyncNodefunction usednullas both an "in progress" marker and a valid cached result. When a node was revisited during its own traversal (circular reference), the function returnednullas if it were a cached result, which could lead to infinite recursion.This bug was introduced in #35005 when
visitedwas changed from aSetto aMapfor caching return values.This change:
IN_PROGRESSsentinel Symbol to distinguish nodes currently being evaluated from cached resultsnullon cycle detection to indicate "no I/O found on this cyclic path" (notundefined, which would signal abort semantics and skip emitting I/O info for other non-cyclic branches)visitAsyncNodeImplreturns, includingnull/undefinedvalues, so revisits get the real computed value instead of the sentinelThis fixes
RangeError: Maximum call stack size exceededthat occurs in Next.js 15.5.0+ when using database clients like Gel/EdgeDB that create circular promise chains in their async sequences.How did you test this change?
Validated manually in Next.js apps (15.5, 16.0.5, 16.1.0-canary) using the Gel/EdgeDB repro that previously hit the stack overflow. No React unit test added; the internal module system made mocking
getAsyncSequenceFromPromiseimpractical from the test suite. Fix verified via integration runs only.Reproduction Repository
https://github.com/jere-co/next-debug
This repository contains:
/docs