0
0
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:
Bram Moolenaar 2020-09-08 22:06:44 +02:00
parent 57ad94c5a9
commit 6defa7bf0a
7 changed files with 99 additions and 3 deletions

View File

@ -3126,6 +3126,7 @@ invoke_popup_filter(win_T *wp, int c)
typval_T argv[3]; typval_T argv[3];
char_u buf[NUMBUFLEN]; char_u buf[NUMBUFLEN];
linenr_T old_lnum = wp->w_cursor.lnum; linenr_T old_lnum = wp->w_cursor.lnum;
int prev_called_emsg = called_emsg;
// Emergency exit: CTRL-C closes the popup. // Emergency exit: CTRL-C closes the popup.
if (c == Ctrl_C) if (c == Ctrl_C)
@ -3151,10 +3152,35 @@ invoke_popup_filter(win_T *wp, int c)
argv[2].v_type = VAR_UNKNOWN; argv[2].v_type = VAR_UNKNOWN;
// NOTE: The callback might close the popup and make "wp" invalid. // 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) if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
popup_highlight_curline(wp); popup_highlight_curline(wp);
res = tv_get_bool(&rettv);
// 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); vim_free(argv[1].vval.v_string);
clear_tv(&rettv); clear_tv(&rettv);

View File

@ -3338,6 +3338,7 @@ struct window_S
// with "cursorline" set // with "cursorline" set
callback_T w_close_cb; // popup close callback callback_T w_close_cb; // popup close callback
callback_T w_filter_cb; // popup filter 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 int w_filter_mode; // mode when filter callback is used
win_T *w_popup_curwin; // close popup if curwin differs win_T *w_popup_curwin; // close popup if curwin differs

View 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|

View 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|

View 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|

View File

@ -3516,7 +3516,44 @@ func Test_popupwin_filter_close_ctrl_c()
call VerifyScreenDump(buf, 'Test_popupwin_ctrl_c', {}) call VerifyScreenDump(buf, 'Test_popupwin_ctrl_c', {})
call StopVimInTerminal(buf) 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 endfunc
func Test_popupwin_atcursor_far_right() func Test_popupwin_atcursor_far_right()

View File

@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1636,
/**/ /**/
1635, 1635,
/**/ /**/