neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit c3d22d32ee4b4c1911ec15f2a77683d09b09f845
parent b52d15853e89149472c1ecd9cce3a84e4af0785a
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date:   Sat,  9 Mar 2024 20:24:08 +0000

vim-patch:8.2.3862: crash on exit with EXITFREE and using win_execute()

Problem:    Crash on exit with EXITFREE and using win_execute().
Solution:   Also save and restore tp_topframe. (issue vim/vim#9374)

https://github.com/vim/vim/commit/dab17a0689a2f31f69f428975f84b0c3c7ba3030

Couldn't repro the crash in the test, but I only care about this patch so
switch_win sets topframe properly for win_split_ins in nvim_open_win and
nvim_win_set_config.
Add a test using nvim_win_call and :wincmd, as I couldn't repro the issue via
nvim_open_win or nvim_win_set_config (though it's clear they're affected by this
patch).

That said, at that point, could just use {un}use_tabpage inside switch_win
instead, which also updates tp_curwin (though maybe continue to not set it in
restore_win). That would also fix possible inconsistent behaviour such as:

:call win_execute(w, "let curwin_nr1 = tabpagewinnr(1)")
:let curwin_nr2 = tabpagewinnr(1)

Where it's possible for curwin_nr1 != curwin_nr2 if these commands are run from
the 1st tabpage, but window "w" is in the 2nd (as the 1st tabpage's tp_curwin
may still be invalid). I'll probably PR a fix for that later in Vim.

Co-authored-by: Bram Moolenaar <Bram@vim.org>

Diffstat:
Msrc/nvim/eval/window.c | 4++++
Mtest/functional/lua/vim_spec.lua | 14++++++++++++++
Mtest/old/testdir/test_execute_func.vim | 22++++++++++++++++++++++
3 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c @@ -958,9 +958,11 @@ int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool n if (no_display) { curtab->tp_firstwin = firstwin; curtab->tp_lastwin = lastwin; + curtab->tp_topframe = topframe; curtab = tp; firstwin = curtab->tp_firstwin; lastwin = curtab->tp_lastwin; + topframe = curtab->tp_topframe; } else { goto_tabpage_tp(tp, false, false); } @@ -989,9 +991,11 @@ void restore_win_noblock(switchwin_T *switchwin, bool no_display) if (no_display) { curtab->tp_firstwin = firstwin; curtab->tp_lastwin = lastwin; + curtab->tp_topframe = topframe; curtab = switchwin->sw_curtab; firstwin = curtab->tp_firstwin; lastwin = curtab->tp_lastwin; + topframe = curtab->tp_topframe; } else { goto_tabpage_tp(switchwin->sw_curtab, false, false); } diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua @@ -3664,6 +3664,20 @@ describe('lua stdlib', function() ]] ) end) + + it('layout in current tabpage does not affect windows in others', function() + command('tab split') + local t2_move_win = api.nvim_get_current_win() + command('vsplit') + local t2_other_win = api.nvim_get_current_win() + command('tabprevious') + matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) + command('vsplit') + + -- Without vim-patch:8.2.3862, this gives E36, despite just the 1st tabpage being full. + exec_lua('vim.api.nvim_win_call(..., function() vim.cmd.wincmd "J" end)', t2_move_win) + eq({ 'col', { { 'leaf', t2_other_win }, { 'leaf', t2_move_win } } }, fn.winlayout(2)) + end) end) describe('vim.iconv', function() diff --git a/test/old/testdir/test_execute_func.vim b/test/old/testdir/test_execute_func.vim @@ -3,6 +3,7 @@ source view_util.vim source check.vim source vim9.vim +source term_util.vim func NestedEval() let nested = execute('echo "nested\nlines"') @@ -177,6 +178,27 @@ func Test_win_execute_visual_redraw() bwipe! endfunc +func Test_win_execute_on_startup() + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + [repeat('x', &columns)]->writefile('Xfile1') + silent tabedit Xfile2 + var id = win_getid() + silent tabedit Xfile3 + autocmd VimEnter * win_execute(id, 'close') + END + call writefile(lines, 'XwinExecute') + let buf = RunVimInTerminal('-p Xfile1 -Nu XwinExecute', {}) + + " this was crashing on exit with EXITFREE defined + call StopVimInTerminal(buf) + + call delete('XwinExecute') + call delete('Xfile1') +endfunc + func Test_execute_cmd_with_null() call assert_equal("", execute(v:_null_string)) call assert_equal("", execute(v:_null_list))