0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 8.2.2097: Vim9: using :silent! when calling a function prevents abort

Problem:    Vim9: using :silent! when calling a function prevents abortng that
            function.
Solution:   Add emsg_silent_def and did_emsg_def.
This commit is contained in:
Bram Moolenaar
2020-12-05 21:22:08 +01:00
parent f665e97ffa
commit 56602ba153
5 changed files with 43 additions and 2 deletions

View File

@@ -230,6 +230,8 @@ EXTERN int did_endif INIT(= FALSE); // just had ":endif"
EXTERN int did_emsg; // set by emsg() when the message EXTERN int did_emsg; // set by emsg() when the message
// is displayed or thrown // is displayed or thrown
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
EXTERN int did_emsg_def; // set by emsg() when emsg_silent
// is set before calling a function
EXTERN int did_emsg_cumul; // cumulative did_emsg, increased EXTERN int did_emsg_cumul; // cumulative did_emsg, increased
// when did_emsg is reset. // when did_emsg is reset.
EXTERN int called_vim_beep; // set if vim_beep() is called EXTERN int called_vim_beep; // set if vim_beep() is called
@@ -1134,6 +1136,10 @@ EXTERN int is_export INIT(= FALSE); // :export {cmd}
EXTERN int msg_silent INIT(= 0); // don't print messages EXTERN int msg_silent INIT(= 0); // don't print messages
EXTERN int emsg_silent INIT(= 0); // don't print error messages EXTERN int emsg_silent INIT(= 0); // don't print error messages
#ifdef FEAT_EVAL
EXTERN int emsg_silent_def INIT(= 0); // value of emsg_silent when a :def
// function is called
#endif
EXTERN int emsg_noredir INIT(= 0); // don't redirect error messages EXTERN int emsg_noredir INIT(= 0); // don't redirect error messages
EXTERN int cmd_silent INIT(= FALSE); // don't echo the command line EXTERN int cmd_silent INIT(= FALSE); // don't echo the command line

View File

@@ -697,6 +697,12 @@ emsg_core(char_u *s)
} }
redir_write(s, -1); redir_write(s, -1);
} }
#ifdef FEAT_EVAL
// Only increment did_emsg_def when :silent! wasn't used inside the
// :def function.
if (emsg_silent == emsg_silent_def)
++did_emsg_def;
#endif
#ifdef FEAT_JOB_CHANNEL #ifdef FEAT_JOB_CHANNEL
ch_log(NULL, "ERROR silent: %s", (char *)s); ch_log(NULL, "ERROR silent: %s", (char *)s);
#endif #endif

View File

@@ -1784,6 +1784,22 @@ def Test_reset_did_emsg()
delfunc! g:Func delfunc! g:Func
enddef enddef
def Test_abort_with_silent_call()
var lines =<< trim END
vim9script
g:result = 'none'
def Func()
g:result += 3
g:result = 'yes'
enddef
# error is silenced, but function aborts on error
silent! Func()
assert_equal('none', g:result)
unlet g:result
END
CheckScriptSuccess(lines)
enddef
def Test_continues_with_silent_error() def Test_continues_with_silent_error()
var lines =<< trim END var lines =<< trim END
vim9script vim9script

View File

@@ -750,6 +750,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 */
/**/
2097,
/**/ /**/
2096, 2096,
/**/ /**/

View File

@@ -851,6 +851,8 @@ call_def_function(
msglist_T *private_msg_list = NULL; msglist_T *private_msg_list = NULL;
cmdmod_T save_cmdmod; cmdmod_T save_cmdmod;
int restore_cmdmod = FALSE; int restore_cmdmod = FALSE;
int save_emsg_silent_def = emsg_silent_def;
int save_did_emsg_def = did_emsg_def;
int trylevel_at_start = trylevel; int trylevel_at_start = trylevel;
int orig_funcdepth; int orig_funcdepth;
@@ -1021,6 +1023,11 @@ call_def_function(
// Do turn errors into exceptions. // Do turn errors into exceptions.
suppress_errthrow = FALSE; suppress_errthrow = FALSE;
// When ":silent!" was used before calling then we still abort the
// function. If ":silent!" is used in the function then we don't.
emsg_silent_def = emsg_silent;
did_emsg_def = 0;
// Decide where to start execution, handles optional arguments. // Decide where to start execution, handles optional arguments.
init_instr_idx(ufunc, argc, &ectx); init_instr_idx(ufunc, argc, &ectx);
@@ -3008,8 +3015,10 @@ func_return:
on_error: on_error:
// Jump here for an error that does not require aborting execution. // Jump here for an error that does not require aborting execution.
// If "emsg_silent" is set then ignore the error. // If "emsg_silent" is set then ignore the error, unless it was set
if (did_emsg_cumul + did_emsg == did_emsg_before && emsg_silent) // when calling the function.
if (did_emsg_cumul + did_emsg == did_emsg_before
&& emsg_silent && did_emsg_def == 0)
continue; continue;
on_fatal_error: on_fatal_error:
// Jump here for an error that messes up the stack. // Jump here for an error that messes up the stack.
@@ -3056,6 +3065,8 @@ failed:
undo_cmdmod(&cmdmod); undo_cmdmod(&cmdmod);
cmdmod = save_cmdmod; cmdmod = save_cmdmod;
} }
emsg_silent_def = save_emsg_silent_def;
did_emsg_def += save_did_emsg_def;
failed_early: failed_early:
// Free all local variables, but not arguments. // Free all local variables, but not arguments.