diff options
author | Felipe Vicentin <42344207+Vinschers@users.noreply.github.com> | 2025-02-02 01:25:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-01 16:25:38 -0800 |
commit | 289c9d21cb91ec6c47496230ca49eef42a04250c (patch) | |
tree | 7110c7195711618021eca8d9da96e97b4426f109 /test/functional | |
parent | 0985e784d8dce58748343207e176bf61303b7d68 (diff) | |
download | rneovim-289c9d21cb91ec6c47496230ca49eef42a04250c.tar.gz rneovim-289c9d21cb91ec6c47496230ca49eef42a04250c.tar.bz2 rneovim-289c9d21cb91ec6c47496230ca49eef42a04250c.zip |
fix(autocmds): once=true Lua event-handler may call itself #29544
Problem:
Event handler declared with `once=true` can re-trigger itself (i.e. more
than once!) by calling `nvim_exec_autocmds` or `:doautocmd`.
Analysis:
This happens because the callback is executed before deletion/cleanup
(`aucmd_del`). And calling `aucmd_del` before `call_autocmd_callback`
breaks the autocmd execution...
Solution:
Set `ac->pat=NULL` to temporarily "delete" the autocmd, then restore it
after executing the callback.
Fix #25526
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Diffstat (limited to 'test/functional')
-rw-r--r-- | test/functional/autocmd/autocmd_spec.lua | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index c62e4752e0..1b7275ebf6 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -160,7 +160,7 @@ describe('autocmd', function() it('++once', function() -- :help autocmd-once -- - -- ":autocmd ... ++once" executes its handler once, then removes the handler. + -- ":autocmd … ++once" executes its handler once, then removes the handler. -- local expected = { 'Many1', @@ -206,7 +206,7 @@ describe('autocmd', function() ) -- - -- ":autocmd ... ++once" handlers can be deleted. + -- ":autocmd … ++once" handlers can be deleted. -- expected = {} command('let g:foo = []') @@ -216,7 +216,7 @@ describe('autocmd', function() eq(expected, eval('g:foo')) -- - -- ":autocmd ... <buffer> ++once ++nested" + -- ":autocmd … <buffer> ++once ++nested" -- expected = { 'OptionSet-Once', @@ -250,6 +250,24 @@ describe('autocmd', function() --- Autocommands ---]]), fn.execute('autocmd Tabnew') ) + + -- + -- :autocmd does not recursively call ++once Lua handlers. + -- + exec_lua [[vim.g.count = 0]] + eq(0, eval('g:count')) + exec_lua [[ + vim.api.nvim_create_autocmd('User', { + once = true, + pattern = nil, + callback = function() + vim.g.count = vim.g.count + 1 + vim.api.nvim_exec_autocmds('User', { pattern = nil }) + end, + }) + vim.api.nvim_exec_autocmds('User', { pattern = nil }) + ]] + eq(1, eval('g:count')) end) it('internal `aucmd_win` window', function() |