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
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
}
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
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
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;
// 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);
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.
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.