mirror of
https://github.com/vim/vim.git
synced 2025-09-01 21:03:39 -04:00
patch 8.2.1636: get stuck if a popup filter causes an error
Problem: Get stuck if a popup filter causes an error. Solution: Check whether the function can be called and does not cause an error. (closes #6902)
This commit is contained in:
parent
57ad94c5a9
commit
6defa7bf0a
@ -3126,6 +3126,7 @@ invoke_popup_filter(win_T *wp, int c)
|
||||
typval_T argv[3];
|
||||
char_u buf[NUMBUFLEN];
|
||||
linenr_T old_lnum = wp->w_cursor.lnum;
|
||||
int prev_called_emsg = called_emsg;
|
||||
|
||||
// Emergency exit: CTRL-C closes the popup.
|
||||
if (c == Ctrl_C)
|
||||
@ -3151,10 +3152,35 @@ invoke_popup_filter(win_T *wp, int c)
|
||||
argv[2].v_type = VAR_UNKNOWN;
|
||||
|
||||
// NOTE: The callback might close the popup and make "wp" invalid.
|
||||
call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv);
|
||||
if (call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv) == FAIL)
|
||||
{
|
||||
// Cannot call the function, close the popup to avoid that the filter
|
||||
// eats keys and the user can't get out.
|
||||
popup_close_with_retval(wp, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
|
||||
popup_highlight_curline(wp);
|
||||
|
||||
// If an error was given always return FALSE, so that keys are not
|
||||
// consumed and the user can type something.
|
||||
// If we get three errors in a row then close the popup. Decrement the
|
||||
// error count by 1/10 if there are no errors, thus allowing up to 1 in
|
||||
// 10 calls to cause an error.
|
||||
if (win_valid_popup(wp) && called_emsg > prev_called_emsg)
|
||||
{
|
||||
wp->w_filter_errors += 10;
|
||||
if (wp->w_filter_errors >= 30)
|
||||
popup_close_with_retval(wp, -1);
|
||||
res = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (win_valid_popup(wp) && wp->w_filter_errors > 0)
|
||||
--wp->w_filter_errors;
|
||||
res = tv_get_bool(&rettv);
|
||||
}
|
||||
|
||||
vim_free(argv[1].vval.v_string);
|
||||
clear_tv(&rettv);
|
||||
|
@ -3338,6 +3338,7 @@ struct window_S
|
||||
// with "cursorline" set
|
||||
callback_T w_close_cb; // popup close callback
|
||||
callback_T w_filter_cb; // popup filter callback
|
||||
int w_filter_errors; // popup filter error count
|
||||
int w_filter_mode; // mode when filter callback is used
|
||||
|
||||
win_T *w_popup_curwin; // close popup if curwin differs
|
||||
|
10
src/testdir/dumps/Test_popupwin_three_errors_1.dump
Normal file
10
src/testdir/dumps/Test_popupwin_three_errors_1.dump
Normal file
@ -0,0 +1,10 @@
|
||||
> +0&#ffffff0@74
|
||||
|~+0#4040ff13&| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @27|o+0#0000001#ffd7ff255|n|e| |t|w|o| |t|h|r|e@1|.@2| +0#4040ff13#ffffff0@29
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|E+0#ffffff16#e000002|8|9|6|:| |A|r|g|u|m|e|n|t| |o|f| |f|i|l|t|e|r|(|)| |m|u|s|t| |b|e| |a| |L|i|s|t|,| |D|i|c|t|i|o|n|a|r|y| |o|r| |B|l|o|b| +0#0000000#ffffff0@13
|
||||
@57|0|,|0|-|1| @8|A|l@1|
|
10
src/testdir/dumps/Test_popupwin_three_errors_2.dump
Normal file
10
src/testdir/dumps/Test_popupwin_three_errors_2.dump
Normal file
@ -0,0 +1,10 @@
|
||||
> +0&#ffffff0@74
|
||||
|~+0#4040ff13&| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|E+0#ffffff16#e000002|8|9|6|:| |A|r|g|u|m|e|n|t| |o|f| |f|i|l|t|e|r|(|)| |m|u|s|t| |b|e| |a| |L|i|s|t|,| |D|i|c|t|i|o|n|a|r|y| |o|r| |B|l|o|b| +0#0000000#ffffff0@13
|
||||
@57|0|,|0|-|1| @8|A|l@1|
|
10
src/testdir/dumps/Test_popupwin_wrong_name.dump
Normal file
10
src/testdir/dumps/Test_popupwin_wrong_name.dump
Normal file
@ -0,0 +1,10 @@
|
||||
> +0&#ffffff0@74
|
||||
|~+0#4040ff13&| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|E+0#ffffff16#e000002|1@1|7|:| |U|n|k|n|o|w|n| |f|u|n|c|t|i|o|n|:| |N|o|S|u|c|h|F|u|n|c| +0#0000000#ffffff0@22|0|,|0|-|1| @8|A|l@1|
|
@ -3516,7 +3516,44 @@ func Test_popupwin_filter_close_ctrl_c()
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_ctrl_c', {})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopupCorners')
|
||||
call delete('XtestPopupCtrlC')
|
||||
endfunc
|
||||
|
||||
func Test_popupwin_filter_close_wrong_name()
|
||||
CheckScreendump
|
||||
|
||||
let lines =<< trim END
|
||||
call popup_create('one two three...', {'filter': 'NoSuchFunc'})
|
||||
END
|
||||
call writefile(lines, 'XtestPopupWrongName')
|
||||
|
||||
let buf = RunVimInTerminal('-S XtestPopupWrongName', #{rows: 10})
|
||||
|
||||
call term_sendkeys(buf, "j")
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_wrong_name', {})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopupWrongName')
|
||||
endfunc
|
||||
|
||||
func Test_popupwin_filter_close_three_errors()
|
||||
CheckScreendump
|
||||
|
||||
let lines =<< trim END
|
||||
set cmdheight=2
|
||||
call popup_create('one two three...', {'filter': 'filter'})
|
||||
END
|
||||
call writefile(lines, 'XtestPopupThreeErrors')
|
||||
|
||||
let buf = RunVimInTerminal('-S XtestPopupThreeErrors', #{rows: 10})
|
||||
|
||||
call term_sendkeys(buf, "jj")
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_three_errors_1', {})
|
||||
call term_sendkeys(buf, "j")
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_three_errors_2', {})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopupThreeErrors')
|
||||
endfunc
|
||||
|
||||
func Test_popupwin_atcursor_far_right()
|
||||
|
@ -754,6 +754,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1636,
|
||||
/**/
|
||||
1635,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user