diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-12-05 21:22:08 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-12-05 21:22:08 +0100 |
commit | 56602ba153af7130b76daf83933922aaea3e2646 (patch) | |
tree | 13cf686a65d3673353517f66f2d9ad88f336cb8b | |
parent | f665e97ffa06817975810cb511b13dbaa83ec630 (diff) | |
download | vim-git-56602ba153af7130b76daf83933922aaea3e2646.tar.gz |
patch 8.2.2097: Vim9: using :silent! when calling a function prevents abortv8.2.2097
Problem: Vim9: using :silent! when calling a function prevents abortng that
function.
Solution: Add emsg_silent_def and did_emsg_def.
-rw-r--r-- | src/globals.h | 6 | ||||
-rw-r--r-- | src/message.c | 6 | ||||
-rw-r--r-- | src/testdir/test_vim9_func.vim | 16 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9execute.c | 15 |
5 files changed, 43 insertions, 2 deletions
diff --git a/src/globals.h b/src/globals.h index af1a85c82..4f54d0fae 100644 --- a/src/globals.h +++ b/src/globals.h @@ -230,6 +230,8 @@ EXTERN int did_endif INIT(= FALSE); // just had ":endif" EXTERN int did_emsg; // set by emsg() when the message // is displayed or thrown #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 // when did_emsg is reset. 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 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 cmd_silent INIT(= FALSE); // don't echo the command line diff --git a/src/message.c b/src/message.c index 43e7e5e52..e4f96d0de 100644 --- a/src/message.c +++ b/src/message.c @@ -697,6 +697,12 @@ emsg_core(char_u *s) } 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 ch_log(NULL, "ERROR silent: %s", (char *)s); #endif diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 4e8ee888d..f831c7199 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1784,6 +1784,22 @@ def Test_reset_did_emsg() delfunc! g:Func 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() var lines =<< trim END vim9script diff --git a/src/version.c b/src/version.c index 66ec86a20..95f3f62e7 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2097, +/**/ 2096, /**/ 2095, diff --git a/src/vim9execute.c b/src/vim9execute.c index 980ebb51a..7e8b336d0 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -851,6 +851,8 @@ call_def_function( msglist_T *private_msg_list = NULL; cmdmod_T save_cmdmod; 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 orig_funcdepth; @@ -1021,6 +1023,11 @@ call_def_function( // Do turn errors into exceptions. 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. init_instr_idx(ufunc, argc, &ectx); @@ -3008,8 +3015,10 @@ func_return: on_error: // Jump here for an error that does not require aborting execution. - // If "emsg_silent" is set then ignore the error. - if (did_emsg_cumul + did_emsg == did_emsg_before && emsg_silent) + // If "emsg_silent" is set then ignore the error, unless it was set + // when calling the function. + if (did_emsg_cumul + did_emsg == did_emsg_before + && emsg_silent && did_emsg_def == 0) continue; on_fatal_error: // Jump here for an error that messes up the stack. @@ -3056,6 +3065,8 @@ failed: undo_cmdmod(&cmdmod); cmdmod = save_cmdmod; } + emsg_silent_def = save_emsg_silent_def; + did_emsg_def += save_did_emsg_def; failed_early: // Free all local variables, but not arguments. |