fix(treesitter): ignore stale fold refresh callbacks

Problem:

The fold refresh path for foldminlines/foldnestmax creates a new
FoldInfo and starts an async parse. If FileType or BufUnload re-enters
before that callback returns, foldinfos[bufnr] can be cleared or
replaced. The callback then indexes a stale slot and raises an "attempt
to index a nil value" error.

Solution:

Capture the FoldInfo created for the refresh and carry that object
through the async callback. Before calling foldupdate(), verify that the
buffer still points at the same FoldInfo generation; otherwise ignore
the stale callback.

AI-assisted: Codex

Fixes #38461
This commit is contained in:
Lewis Russell
2026-03-24 15:46:56 +00:00
committed by Lewis Russell
parent b233f71b1b
commit ea878f456a

View File

@@ -450,10 +450,16 @@ api.nvim_create_autocmd('OptionSet', {
or foldinfos[buf] and { buf }
or {}
for _, bufnr in ipairs(bufs) do
foldinfos[bufnr] = FoldInfo.new(bufnr)
local foldinfo = FoldInfo.new(bufnr)
foldinfos[bufnr] = foldinfo
api.nvim_buf_call(bufnr, function()
compute_folds_levels(bufnr, foldinfos[bufnr], nil, nil, function()
foldinfos[bufnr]:foldupdate(bufnr, 0, api.nvim_buf_line_count(bufnr))
compute_folds_levels(bufnr, foldinfo, nil, nil, function()
-- FileType/BufUnload can clear or replace the fold state while this
-- async parse is in flight. Ignore callbacks for stale generations.
if foldinfos[bufnr] ~= foldinfo then
return
end
foldinfo:foldupdate(bufnr, 0, api.nvim_buf_line_count(bufnr))
end)
end)
end