aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-11-29 23:48:14 -0800
committerGitHub <noreply@github.com>2019-11-29 23:48:14 -0800
commitf6e7857c54a015cdfac9ce65ec0b65d65d590aeb (patch)
tree88aec7943072ce57536f4a7b26af627601d29817
parent1f684cf80a0026848f5d64794dfca05654a9f66a (diff)
downloadrneovim-f6e7857c54a015cdfac9ce65ec0b65d65d590aeb.tar.gz
rneovim-f6e7857c54a015cdfac9ce65ec0b65d65d590aeb.tar.bz2
rneovim-f6e7857c54a015cdfac9ce65ec0b65d65d590aeb.zip
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
-rw-r--r--src/nvim/api/vim.c4
-rw-r--r--src/nvim/window.c7
-rw-r--r--test/functional/ui/float_spec.lua29
-rw-r--r--test/functional/ui/options_spec.lua4
4 files changed, 38 insertions, 6 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 9adc61b843..e4a9bd64ff 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1096,6 +1096,10 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config,
if (enter) {
win_enter(wp, false);
}
+ if (!win_valid(wp)) {
+ api_set_error(err, kErrorTypeException, "Window was closed immediately");
+ return 0;
+ }
if (buffer > 0) {
nvim_win_set_buf(wp->handle, buffer, err);
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index dee36df433..76fc36607c 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -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)
{
win_enter_ext(wp, undo_sync, false, false, true, true);
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 8ddb2e90a6..7a5569c14b 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -2,9 +2,11 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local os = require('os')
local clear, feed = helpers.clear, helpers.feed
+local assert_alive = helpers.assert_alive
local command, feed_command = helpers.command, helpers.feed_command
local eval = helpers.eval
local eq = helpers.eq
+local exec_lua = helpers.exec_lua
local insert = helpers.insert
local meths = helpers.meths
local curbufmeths = helpers.curbufmeths
@@ -12,7 +14,7 @@ local funcs = helpers.funcs
local run = helpers.run
local pcall_err = helpers.pcall_err
-describe('floating windows', function()
+describe('floatwin', function()
before_each(function()
clear()
end)
@@ -56,6 +58,31 @@ describe('floating windows', function()
eq(1000, funcs.win_getid())
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 screen
before_each(function()
diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua
index 31007b92b1..581e196bbb 100644
--- a/test/functional/ui/options_spec.lua
+++ b/test/functional/ui/options_spec.lua
@@ -52,10 +52,10 @@ describe('UI receives option updates', function()
local evs = {}
screen = Screen.new(20,5)
-- Override mouse_on/mouse_off handlers.
- function screen._handle_mouse_on()
+ function screen:_handle_mouse_on()
table.insert(evs, 'mouse_on')
end
- function screen._handle_mouse_off()
+ function screen:_handle_mouse_off()
table.insert(evs, 'mouse_off')
end
screen:attach()