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.
diff --git a/src/userfunc.c b/src/userfunc.c
index 0ee276b..8956b82 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -33,6 +33,7 @@
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 @@
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 @@
DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
// Invoke functions added with ":defer".
- handle_defer();
+ handle_defer_one(current_funccal);
--RedrawingDisabled;
@@ -5660,16 +5662,16 @@
/*
* 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 @@
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);
+ }
}
/*