]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1469: deferred functions not called from autocommands v9.0.1469
authorzeertzjq <zeertzjq@outlook.com>
Tue, 18 Apr 2023 20:52:54 +0000 (21:52 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 18 Apr 2023 20:52:54 +0000 (21:52 +0100)
Problem:    Deferred functions not called from autocommands.
Solution:   Also go through the funccal_stack. (closes #12267)

src/testdir/test_user_func.vim
src/userfunc.c
src/version.c

index 51d575433b3112443a120bf358ac0edbaf1d1121..71353c8f8184eae7b22c9fd7df2ee131e2c9b605 100644 (file)
@@ -702,6 +702,33 @@ func Test_defer_quitall_def()
   call delete('XQuitallDefThree')
 endfunc
 
+func Test_defer_quitall_autocmd()
+  let lines =<< trim END
+      autocmd User DeferAutocmdThree qa!
+
+      func DeferLevelTwo()
+        call writefile(['text'], 'XQuitallAutocmdTwo', 'D')
+        doautocmd User DeferAutocmdThree
+      endfunc
+
+      autocmd User DeferAutocmdTwo ++nested call DeferLevelTwo()
+
+      def DeferLevelOne()
+        call writefile(['text'], 'XQuitallAutocmdOne', 'D')
+        doautocmd User DeferAutocmdTwo
+      enddef
+
+      autocmd User DeferAutocmdOne ++nested call DeferLevelOne()
+
+      doautocmd User DeferAutocmdOne
+  END
+  call writefile(lines, 'XdeferQuitallAutocmd', 'D')
+  let res = system(GetVimCommand() .. ' -X -S XdeferQuitallAutocmd')
+  call assert_equal(0, v:shell_error)
+  call assert_false(filereadable('XQuitallAutocmdOne'))
+  call assert_false(filereadable('XQuitallAutocmdTwo'))
+endfunc
+
 func Test_defer_quitall_in_expr_func()
   let lines =<< trim END
       def DefIndex(idx: number, val: string): bool
index a506d72c894c87f18642c9b9b73e24eb1a6d2baa..0680767d3aa46863e93ae14ccc13ac584de83554 100644 (file)
@@ -6122,27 +6122,34 @@ handle_defer_one(funccall_T *funccal)
     ga_clear(&funccal->fc_defer);
 }
 
+    static void
+invoke_funccall_defer(funccall_T *fc)
+{
+    if (fc->fc_ectx != NULL)
+    {
+       // :def function
+       unwind_def_callstack(fc->fc_ectx);
+       may_invoke_defer_funcs(fc->fc_ectx);
+    }
+    else
+    {
+       // legacy function
+       handle_defer_one(fc);
+    }
+}
+
 /*
  * Called when exiting: call all defer functions.
  */
     void
 invoke_all_defer(void)
 {
-    funccall_T *funccal;
+    for (funccal_entry_T *fce = funccal_stack; fce != NULL; fce = fce->next)
+       for (funccall_T *fc = fce->top_funccal; fc != NULL; fc = fc->fc_caller)
+           invoke_funccall_defer(fc);
 
-    for (funccal = current_funccal; funccal != NULL;
-                                                 funccal = funccal->fc_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);
-       }
+    for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->fc_caller)
+       invoke_funccall_defer(fc);
 }
 
 /*
index 6ff6bf6539de6311ad5fd15ae5049018e74a9dac..95cff8ead4fe6da434ae7763d928132644da429a 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1469,
 /**/
     1468,
 /**/