Mercurial > vim
diff src/userfunc.c @ 30122:458162398682 v9.0.0397
patch 9.0.0397: :defer not tested with exceptions and ":qa!"
Commit: https://github.com/vim/vim/commit/58779858fb5a82a3233af5d4237a3cece88c10d4
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Sep 6 18:31:14 2022 +0100
patch 9.0.0397: :defer not tested with exceptions and ":qa!"
Problem: :defer not tested with exceptions and ":qa!".
Solution: Test :defer works when exceptions are thrown and when ":qa!" is
used. Invoke the deferred calls on exit.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 06 Sep 2022 19:45:04 +0200 |
parents | 0352577f1ba5 |
children | 9874afdacb5f |
line wrap: on
line diff
--- a/src/userfunc.c +++ b/src/userfunc.c @@ -33,6 +33,7 @@ static void funccal_unref(funccall_T *fc static void func_clear(ufunc_T *fp, int force); static int func_free(ufunc_T *fp, int force); static char_u *untrans_function_name(char_u *name); +static void handle_defer_one(funccall_T *funccal); void func_init() @@ -2651,7 +2652,8 @@ call_user_func( profile_may_start_func(&profile_info, fp, caller); #endif sticky_cmdmod_flags = 0; - call_def_function(fp, argcount, argvars, funcexe->fe_partial, rettv); + call_def_function(fp, argcount, argvars, funcexe->fe_partial, + fc, rettv); funcdepth_decrement(); #ifdef FEAT_PROFILE if (do_profiling == PROF_YES && (fp->uf_profiling @@ -2906,7 +2908,7 @@ call_user_func( DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); // Invoke functions added with ":defer". - handle_defer(); + handle_defer_one(current_funccal); --RedrawingDisabled; @@ -5660,16 +5662,16 @@ theend: /* * Invoked after a functions has finished: invoke ":defer" functions. */ - void -handle_defer(void) + static void +handle_defer_one(funccall_T *funccal) { int idx; - for (idx = current_funccal->fc_defer.ga_len - 1; idx >= 0; --idx) + for (idx = funccal->fc_defer.ga_len - 1; idx >= 0; --idx) { funcexe_T funcexe; typval_T rettv; - defer_T *dr = ((defer_T *)current_funccal->fc_defer.ga_data) + idx; + defer_T *dr = ((defer_T *)funccal->fc_defer.ga_data) + idx; int i; CLEAR_FIELD(funcexe); @@ -5683,7 +5685,29 @@ handle_defer(void) for (i = dr->dr_argcount - 1; i >= 0; --i) clear_tv(&dr->dr_argvars[i]); } - ga_clear(¤t_funccal->fc_defer); + ga_clear(&funccal->fc_defer); +} + +/* + * Called when exiting: call all defer functions. + */ + void +invoke_all_defer(void) +{ + funccall_T *funccal; + + for (funccal = current_funccal; funccal != NULL; funccal = funccal->caller) + if (funccal->fc_ectx != NULL) + { + // :def function + unwind_def_callstack(funccal->fc_ectx); + may_invoke_defer_funcs(funccal->fc_ectx); + } + else + { + // legacy function + handle_defer_one(funccal); + } } /*