# HG changeset patch # User Bram Moolenaar # Date 1681911004 -7200 # Node ID f59ad8692734b0bc4a2bbb818612fbd9d1750d19 # Parent 272dc3dcacd3cac997bbf422f6e07a9b778597ba patch 9.0.1470: deferred functions invoked in unexpected order Commit: https://github.com/vim/vim/commit/1be4b81bfb3d7edf0e2ae41711d429e8fa5e0555 Author: zeertzjq Date: Wed Apr 19 14:21:24 2023 +0100 patch 9.0.1470: deferred functions invoked in unexpected order Problem: Deferred functions invoked in unexpected order when using :qa and autocommands. Solution: Call deferred functions for the current funccal before using the stack. (closes #12278) diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim --- a/src/testdir/test_user_func.vim +++ b/src/testdir/test_user_func.vim @@ -704,29 +704,45 @@ endfunc func Test_defer_quitall_autocmd() let lines =<< trim END - autocmd User DeferAutocmdThree qa! - - func DeferLevelTwo() - call writefile(['text'], 'XQuitallAutocmdTwo', 'D') - doautocmd User DeferAutocmdThree + func DeferLevelFive() + defer writefile(['5'], 'XQuitallAutocmd', 'a') + qa! endfunc - autocmd User DeferAutocmdTwo ++nested call DeferLevelTwo() + autocmd User DeferAutocmdFive call DeferLevelFive() + + def DeferLevelFour() + defer writefile(['4'], 'XQuitallAutocmd', 'a') + doautocmd User DeferAutocmdFive + enddef + + func DeferLevelThree() + defer writefile(['3'], 'XQuitallAutocmd', 'a') + call DeferLevelFour() + endfunc - def DeferLevelOne() - call writefile(['text'], 'XQuitallAutocmdOne', 'D') - doautocmd User DeferAutocmdTwo + autocmd User DeferAutocmdThree ++nested call DeferLevelThree() + + def DeferLevelTwo() + defer writefile(['2'], 'XQuitallAutocmd', 'a') + doautocmd User DeferAutocmdThree enddef + func DeferLevelOne() + defer writefile(['1'], 'XQuitallAutocmd', 'a') + call DeferLevelTwo() + endfunc + autocmd User DeferAutocmdOne ++nested call DeferLevelOne() doautocmd User DeferAutocmdOne END call writefile(lines, 'XdeferQuitallAutocmd', 'D') - let res = system(GetVimCommand() .. ' -X -S XdeferQuitallAutocmd') + call system(GetVimCommand() .. ' -X -S XdeferQuitallAutocmd') call assert_equal(0, v:shell_error) - call assert_false(filereadable('XQuitallAutocmdOne')) - call assert_false(filereadable('XQuitallAutocmdTwo')) + call assert_equal(['5', '4', '3', '2', '1'], readfile('XQuitallAutocmd')) + + call delete('XQuitallAutocmd') endfunc func Test_defer_quitall_in_expr_func() diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -6144,12 +6144,12 @@ invoke_funccall_defer(funccall_T *fc) void invoke_all_defer(void) { + for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->fc_caller) + invoke_funccall_defer(fc); + 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 (funccall_T *fc = current_funccal; fc != NULL; fc = fc->fc_caller) - invoke_funccall_defer(fc); } /* diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1470, +/**/ 1469, /**/ 1468,