Skip to content

Fix stack overflow when slicing a zipped Seq of unknown size from the end - #2311

Merged
bdurrer merged 1 commit into
immutable-js:mainfrom
b84330808:fix-zip-cache-result
Oct 31, 2026
Merged

bdurrer merged 1 commit into
immutable-js:mainfrom
b84330808:fix-zip-cache-result

Conversation

@b84330808

Copy link
Copy Markdown
Contributor

Slicing a zipped Seq of unknown size from the end overflows the stack:

Seq([1, 2, 3]).filter(() => true).zip(Seq([4, 5, 6])).slice(-1);
// RangeError: Maximum call stack size exceeded

takeLast(n), zipWith and zipAll do the same.

sliceFactory calls cacheResult() on a Seq of unknown size before resolving a negative index, then calls itself again. zipWithFactory sets __iterate on the zipped Seq instead of __iterateUncached. cacheResult() only does anything when __iterateUncached exists, so the size stays unknown and sliceFactory recurses forever. With the rename, Seq#__iterate uses the cache and cacheResult() works.

This doesn't overlap with #2308, which changes the reverse branch of __iteratorUncached in the same factory; the two merge cleanly and the tests pass together.

The test in __tests__/zip.ts fails on main and passes with this change. The same code is on 6.x.

I used Claude Code to write this change.

`zipWithFactory` set `__iterate` on the zipped Seq instead of
`__iterateUncached`. That skipped the cache in `Seq#__iterate`, and
`cacheResult()` did nothing because it checks for `__iterateUncached`.
`slice` caches a Seq of unknown size before resolving a negative index,
so `slice(-1)` or `takeLast(n)` on a zip of a Seq of unknown size
recursed until "Maximum call stack size exceeded".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@bdurrer

bdurrer commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Thanks for your PRs around reverse

@bdurrer
bdurrer merged commit 3a78df2 into immutable-js:main Oct 31, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants