From 3cd07709ba578657682a9a881759d03a2718fd23 Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:56:36 +0000 Subject: [PATCH] fix(terminal): don't always leave if enter autocmds delete buffer #38324 Problem: #38316 is a bit aggressive; we need not always leave Terminal mode if autocmds put us in a different terminal. Solution: don't skip entering; let terminal_check_focus handle whether we should immediately leave. --- src/nvim/terminal.c | 10 +++++----- test/functional/terminal/buffer_spec.lua | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index be77e6d70f..c8772a7ffc 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -951,13 +951,13 @@ bool terminal_enter(void) may_trigger_modechanged(); s->term->refcount--; if (s->term->buf_handle == 0) { - s->close = true; // skip entering and close - } else { - s->state.execute = terminal_execute; - s->state.check = terminal_check; - state_enter(&s->state); + s->close = true; } + s->state.execute = terminal_execute; + s->state.check = terminal_check; + state_enter(&s->state); + if (!s->got_bsl_o) { restart_edit = 0; } diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 9907e1e66b..464625764a 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -1147,13 +1147,23 @@ describe(':terminal buffer', function() end) it('no heap-use-after-free from autocmds when entering terminal mode', function() - local chans = api.nvim_list_chans() local buf = api.nvim_get_current_buf() - api.nvim_open_term(0, {}) + local chan = api.nvim_open_term(0, {}) command('autocmd TermEnter,ModeChanged * ++once bwipeout!') feed('i') eq(false, api.nvim_buf_is_valid(buf)) - eq(chans, api.nvim_list_chans()) + eq({}, api.nvim_get_chan_info(chan)) + eq('n', fn.mode()) + + -- Remain in Terminal mode if autocmds put us in a different terminal. + buf = api.nvim_get_current_buf() + chan = api.nvim_open_term(0, {}) + command('autocmd TermEnter,ModeChanged * ++once bwipeout! | let g:chan = nvim_open_term(0, {})') + feed('i') + eq(false, api.nvim_buf_is_valid(buf)) + eq({}, api.nvim_get_chan_info(chan)) + eq(api.nvim_get_current_buf(), api.nvim_get_chan_info(eval('g:chan')).buffer) + eq('t', fn.mode()) end) local enew_screen = [[