-
Notifications
You must be signed in to change notification settings - Fork 128
Description
Description
There's a timer API mismatch in lua/claudecode/selection.lua that mixes incompatible timer APIs. The code uses vim.defer_fn() to create a debounce timer but then calls vim.loop.timer_stop() to stop it. These are different timer systems:
vim.defer_fn()returns a timer handle that should be stopped usingtimer:stop()andtimer:close()vim.loop.timer_stop()expects a libuv timer created withvim.loop.new_timer()orvim.uv.new_timer()
Affected Code
File: lua/claudecode/selection.lua
Location 1: debounce_update() function (lines ~109-118)
function M.debounce_update()
if M.state.debounce_timer then
vim.loop.timer_stop(M.state.debounce_timer) -- ❌ Wrong API
end
M.state.debounce_timer = vim.defer_fn(function() -- Returns different timer type
M.update_selection()
M.state.debounce_timer = nil
end, M.state.debounce_ms)
endLocation 2: disable() function (lines ~48-51)
if M.state.debounce_timer then
vim.loop.timer_stop(M.state.debounce_timer) -- ❌ Wrong API
M.state.debounce_timer = nil
endPotential Impact
This could cause undefined behavior or crashes, especially in newer Neovim versions where the timer handle types may have changed. In Neovim 0.11.x, vim.defer_fn returns a userdata object that may not be compatible with vim.loop.timer_stop().
Suggested Fix
Use consistent timer APIs. Either:
Option A: Use vim.uv.new_timer() consistently:
function M.debounce_update()
if M.state.debounce_timer then
M.state.debounce_timer:stop()
M.state.debounce_timer:close()
M.state.debounce_timer = nil
end
local timer = vim.uv.new_timer()
M.state.debounce_timer = timer
timer:start(M.state.debounce_ms, 0, vim.schedule_wrap(function()
if M.state.debounce_timer == timer then
M.state.debounce_timer = nil
end
timer:stop()
timer:close()
M.update_selection()
end))
endOption B: Use vim.fn.timer_stop() with vim.defer_fn:
function M.debounce_update()
if M.state.debounce_timer then
vim.fn.timer_stop(M.state.debounce_timer)
end
M.state.debounce_timer = vim.defer_fn(function()
M.update_selection()
M.state.debounce_timer = nil
end, M.state.debounce_ms)
endEnvironment
- Neovim: 0.11.5
- OS: macOS
Full Diff (Option A approach)
diff --git a/lua/claudecode/selection.lua b/lua/claudecode/selection.lua
index 9bbfed9..ac21196 100644
--- a/lua/claudecode/selection.lua
+++ b/lua/claudecode/selection.lua
@@ -46,7 +46,8 @@ function M.disable()
M.server = nil
if M.state.debounce_timer then
- vim.loop.timer_stop(M.state.debounce_timer)
+ M.state.debounce_timer:stop()
+ M.state.debounce_timer:close()
M.state.debounce_timer = nil
end
end
@@ -108,13 +109,21 @@ end
---its execution.
function M.debounce_update()
if M.state.debounce_timer then
- vim.loop.timer_stop(M.state.debounce_timer)
+ M.state.debounce_timer:stop()
+ M.state.debounce_timer:close()
+ M.state.debounce_timer = nil
end
- M.state.debounce_timer = vim.defer_fn(function()
+ local timer = vim.uv.new_timer()
+ M.state.debounce_timer = timer
+ timer:start(M.state.debounce_ms, 0, vim.schedule_wrap(function()
+ if M.state.debounce_timer == timer then
+ M.state.debounce_timer = nil
+ end
+ timer:stop()
+ timer:close()
M.update_selection()
- M.state.debounce_timer = nil
- end, M.state.debounce_ms)
+ end))
endFound while debugging an unrelated Neovim crash issue.
** This issue was detected and opened by 🤖 Claude Opus