mirror of
https://github.com/neovim/neovim.git
synced 2025-10-08 10:56:31 +00:00
floatwin: show error if window is closed immediately #11476
Autocmds may close window while it is being entered, then win_set_minimal_style(wp) operates on an invalid pointer. We could silently ignore this instead, but it is unlikely to be intentional, so it is more useful to show an error. fix #11383
This commit is contained in:
@@ -1096,6 +1096,10 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config,
|
|||||||
if (enter) {
|
if (enter) {
|
||||||
win_enter(wp, false);
|
win_enter(wp, false);
|
||||||
}
|
}
|
||||||
|
if (!win_valid(wp)) {
|
||||||
|
api_set_error(err, kErrorTypeException, "Window was closed immediately");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (buffer > 0) {
|
if (buffer > 0) {
|
||||||
nvim_win_set_buf(wp->handle, buffer, err);
|
nvim_win_set_buf(wp->handle, buffer, err);
|
||||||
}
|
}
|
||||||
|
@@ -4372,9 +4372,10 @@ static void win_goto_hor(bool left, long count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Make window `wp` the current window.
|
||||||
* Make window "wp" the current window.
|
///
|
||||||
*/
|
/// @warning Autocmds may close the window immediately, so caller must check
|
||||||
|
/// win_valid(wp).
|
||||||
void win_enter(win_T *wp, bool undo_sync)
|
void win_enter(win_T *wp, bool undo_sync)
|
||||||
{
|
{
|
||||||
win_enter_ext(wp, undo_sync, false, false, true, true);
|
win_enter_ext(wp, undo_sync, false, false, true, true);
|
||||||
|
@@ -2,9 +2,11 @@ local helpers = require('test.functional.helpers')(after_each)
|
|||||||
local Screen = require('test.functional.ui.screen')
|
local Screen = require('test.functional.ui.screen')
|
||||||
local os = require('os')
|
local os = require('os')
|
||||||
local clear, feed = helpers.clear, helpers.feed
|
local clear, feed = helpers.clear, helpers.feed
|
||||||
|
local assert_alive = helpers.assert_alive
|
||||||
local command, feed_command = helpers.command, helpers.feed_command
|
local command, feed_command = helpers.command, helpers.feed_command
|
||||||
local eval = helpers.eval
|
local eval = helpers.eval
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
|
local exec_lua = helpers.exec_lua
|
||||||
local insert = helpers.insert
|
local insert = helpers.insert
|
||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
local curbufmeths = helpers.curbufmeths
|
local curbufmeths = helpers.curbufmeths
|
||||||
@@ -12,7 +14,7 @@ local funcs = helpers.funcs
|
|||||||
local run = helpers.run
|
local run = helpers.run
|
||||||
local pcall_err = helpers.pcall_err
|
local pcall_err = helpers.pcall_err
|
||||||
|
|
||||||
describe('floating windows', function()
|
describe('floatwin', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
clear()
|
clear()
|
||||||
end)
|
end)
|
||||||
@@ -56,6 +58,31 @@ describe('floating windows', function()
|
|||||||
eq(1000, funcs.win_getid())
|
eq(1000, funcs.win_getid())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('closed immediately by autocmd #11383', function()
|
||||||
|
eq('Error executing lua: [string "<nvim>"]:4: Window was closed immediately',
|
||||||
|
pcall_err(exec_lua, [[
|
||||||
|
local a = vim.api
|
||||||
|
local function crashes(contents)
|
||||||
|
local buf = a.nvim_create_buf(false, true)
|
||||||
|
local floatwin = a.nvim_open_win(buf, true, {
|
||||||
|
relative = 'cursor';
|
||||||
|
style = 'minimal';
|
||||||
|
row = 0; col = 0;
|
||||||
|
height = #contents;
|
||||||
|
width = 10;
|
||||||
|
})
|
||||||
|
a.nvim_buf_set_lines(buf, 0, -1, true, contents)
|
||||||
|
local winnr = vim.fn.win_id2win(floatwin)
|
||||||
|
a.nvim_command('wincmd p')
|
||||||
|
a.nvim_command('autocmd CursorMoved * ++once '..winnr..'wincmd c')
|
||||||
|
return buf, floatwin
|
||||||
|
end
|
||||||
|
crashes{'foo'}
|
||||||
|
crashes{'bar'}
|
||||||
|
]]))
|
||||||
|
assert_alive()
|
||||||
|
end)
|
||||||
|
|
||||||
local function with_ext_multigrid(multigrid)
|
local function with_ext_multigrid(multigrid)
|
||||||
local screen
|
local screen
|
||||||
before_each(function()
|
before_each(function()
|
||||||
|
@@ -52,10 +52,10 @@ describe('UI receives option updates', function()
|
|||||||
local evs = {}
|
local evs = {}
|
||||||
screen = Screen.new(20,5)
|
screen = Screen.new(20,5)
|
||||||
-- Override mouse_on/mouse_off handlers.
|
-- Override mouse_on/mouse_off handlers.
|
||||||
function screen._handle_mouse_on()
|
function screen:_handle_mouse_on()
|
||||||
table.insert(evs, 'mouse_on')
|
table.insert(evs, 'mouse_on')
|
||||||
end
|
end
|
||||||
function screen._handle_mouse_off()
|
function screen:_handle_mouse_off()
|
||||||
table.insert(evs, 'mouse_off')
|
table.insert(evs, 'mouse_off')
|
||||||
end
|
end
|
||||||
screen:attach()
|
screen:attach()
|
||||||
|
Reference in New Issue
Block a user