diff options
-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 af1a85c82a..4f54d0faec 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 43e7e5e526..e4f96d0de7 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 4e8ee888da..f831c7199c 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 66ec86a209..95f3f62e7e 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 980ebb51a8..7e8b336d09 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. |