Skip to content

Reduce memory use of typescriptArrowFuncDef patterns - #307

Open
kokosabu wants to merge 3 commits into
HerringtonDarkholme:masterfrom
kokosabu:fix-arrowfunc-memory
Open

kokosabu wants to merge 3 commits into
HerringtonDarkholme:masterfrom
kokosabu:fix-arrowfunc-memory

Conversation

@kokosabu

Copy link
Copy Markdown
Contributor

This backports vim/vim PR 21423 by @dkearns (vim commit cff1d9e4e).

#306 removed the exponential backtracking in the paren-based typescriptArrowFuncDef patterns. Its single-character loop \%(\_[^()]\|(\_[^()]*)\)*, however, makes the backtracking engine (regexpengine=1) push state for every character. Memory grows with the length of the parameter list and can exceed 'maxmempattern' (E363), as reported in vim/vim#17247.

This PR unrolls the loop as \_[^()]*\%((\_[^()]*)\_[^()]*\)*, so each iteration consumes a whole parenthesized group. Both the match and the region start patterns are changed. The matched text is unchanged (still one level of nesting).

Thanks to @dkearns for the fix and for agreeing to the backport (vim/vim#21423 (comment)).

Verification

  • Highlighting: compared synstack() names at every position between master and this branch, with regexpengine=1 and 2, on test/test.ts (2245 positions), test/test.tsx (799) and the vim PR's test input (329). 0 differences.
  • With regexpengine=1 maxmempattern=1, master raises E363 at 129 of 329 positions in the vim PR's test input. This branch raises none.
  • Added a vader test that runs with regexpengine=1 maxmempattern=1. With the CI command (Vader! syntax.vader tsx.vader, Vim 9.1 on macOS), this branch passes 151/151 and master exits with status 1. Not run locally with Neovim.
  • merged/ was regenerated with node merge.js. Only the two lines changed in each file.

🤖 Generated with Claude Code

kokosabu and others added 3 commits October 13, 2026 22:43
The paren-based typescriptArrowFuncDef patterns repeat a single-character
alternative, \%(\_[^()]\|(\_[^()]*)\)*. The backtracking engine pushes
state for every iteration, so its memory grows with the length of the
parameter list and can exceed 'maxmempattern' (E363). Unroll the loop as
\_[^()]*\%((\_[^()]*)\_[^()]*\)* so each iteration consumes a whole
parenthesized group. The matched text is unchanged.

Backport of vim/vim PR 21423 by Doug Kearns (vim commit cff1d9e4e).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restore the previous 'regexpengine' and 'maxmempattern' values instead of
the defaults, so later cases keep the engine the suite was started with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant