# HG changeset patch # User Bram Moolenaar # Date 1628943303 -7200 # Node ID f8bcd21e6e24218cfbaa76d5adbb403628d36eaf # Parent 8b76de69fa5519629f602445ec7ffc3ebb8d48ab patch 8.2.3341: Vim9: function call aborted despite try/catch Commit: https://github.com/vim/vim/commit/88c89c77229e725ab2613b022249e2f506d82b82 Author: Bram Moolenaar Date: Sat Aug 14 14:01:05 2021 +0200 patch 8.2.3341: Vim9: function call aborted despite try/catch Problem: Vim9: function call aborted despite try/catch. (Naohiro Ono) Solution: Ignore error caught by try/catch. (closes https://github.com/vim/vim/issues/8755) diff --git a/src/evalvars.c b/src/evalvars.c --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1193,7 +1193,8 @@ list_arg_vars(exarg_T *eap, char_u *arg, if (!VIM_ISWHITE(*arg) && !ends_excmd(*arg)) { emsg_severe = TRUE; - semsg(_(e_trailing_arg), arg); + if (!error) + semsg(_(e_trailing_arg), arg); break; } } diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -238,8 +238,8 @@ EXTERN int did_emsg_def; // set by 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 did_uncaught_emsg; // emsg() was called and did not - // cause an exception +EXTERN int uncaught_emsg; // number of times emsg() was + // called and did show a message #endif EXTERN int did_emsg_syntax; // did_emsg set because of a // syntax error diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -733,7 +733,7 @@ emsg_core(char_u *s) flush_buffers(FLUSH_MINIMAL); // flush internal buffers ++did_emsg; // flag for DoOneCmd() #ifdef FEAT_EVAL - did_uncaught_emsg = TRUE; + ++uncaught_emsg; #endif } diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -160,6 +160,52 @@ def Test_autoload_names() delete(dir, 'rf') enddef +def Test_autoload_error_in_script() + var dir = 'Xdir/autoload' + mkdir(dir, 'p') + + var lines =<< trim END + func scripterror#function() + let g:called_function = 'yes' + endfunc + let 0 = 1 + END + writefile(lines, dir .. '/scripterror.vim') + + var save_rtp = &rtp + exe 'set rtp=' .. getcwd() .. '/Xdir' + + g:called_function = 'no' + # The error in the autoload script cannot be checked with assert_fails(), use + # CheckDefSuccess() instead of CheckDefFailure() + try + CheckDefSuccess(['scripterror#function()']) + catch + assert_match('E121: Undefined variable: 0', v:exception) + endtry + assert_equal('no', g:called_function) + + lines =<< trim END + func scriptcaught#function() + let g:called_function = 'yes' + endfunc + try + let 0 = 1 + catch + let g:caught = v:exception + endtry + END + writefile(lines, dir .. '/scriptcaught.vim') + + g:called_function = 'no' + CheckDefSuccess(['scriptcaught#function()']) + assert_match('E121: Undefined variable: 0', g:caught) + assert_equal('yes', g:called_function) + + &rtp = save_rtp + delete(dir, 'rf') +enddef + def CallRecursive(n: number): number return CallRecursive(n + 1) enddef diff --git a/src/testdir/vim9.vim b/src/testdir/vim9.vim --- a/src/testdir/vim9.vim +++ b/src/testdir/vim9.vim @@ -12,10 +12,10 @@ func CheckDefSuccess(lines) try exe 'so ' .. fname call Func() - delfunc! Func finally call chdir(cwd) call delete(fname) + delfunc! Func endtry endfunc diff --git a/src/time.c b/src/time.c --- a/src/time.c +++ b/src/time.c @@ -520,6 +520,7 @@ check_due_timer(void) int save_timer_busy = timer_busy; int save_vgetc_busy = vgetc_busy; int save_did_emsg = did_emsg; + int prev_uncaught_emsg = uncaught_emsg; int save_called_emsg = called_emsg; int save_must_redraw = must_redraw; int save_trylevel = trylevel; @@ -536,7 +537,6 @@ check_due_timer(void) vgetc_busy = 0; called_emsg = 0; did_emsg = FALSE; - did_uncaught_emsg = FALSE; must_redraw = 0; trylevel = 0; did_throw = FALSE; @@ -555,7 +555,7 @@ check_due_timer(void) did_one = TRUE; timer_busy = save_timer_busy; vgetc_busy = save_vgetc_busy; - if (did_uncaught_emsg) + if (uncaught_emsg > prev_uncaught_emsg) ++timer->tr_emsg_count; did_emsg = save_did_emsg; called_emsg = save_called_emsg; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3341, +/**/ 3340, /**/ 3339, diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -844,12 +844,13 @@ may_restore_cmdmod(funclocal_T *funcloca } /* - * Return TRUE if an error was given or CTRL-C was pressed. + * Return TRUE if an error was given (not caught in try/catch) or CTRL-C was + * pressed. */ static int -vim9_aborting(int prev_called_emsg) +vim9_aborting(int prev_uncaught_emsg) { - return called_emsg > prev_called_emsg || got_int || did_throw; + return uncaught_emsg > prev_uncaught_emsg || got_int || did_throw; } /* @@ -882,12 +883,13 @@ call_by_name( if (ufunc == NULL) { - int called_emsg_before = called_emsg; + int prev_uncaught_emsg = uncaught_emsg; if (script_autoload(name, TRUE)) // loaded a package, search for the function again ufunc = find_func(name, FALSE, NULL); - if (vim9_aborting(called_emsg_before)) + + if (vim9_aborting(prev_uncaught_emsg)) return FAIL; // bail out if loading the script caused an error }