From: zeertzjq Date: Wed, 19 Apr 2023 13:21:24 +0000 (+0100) Subject: patch 9.0.1470: deferred functions invoked in unexpected order X-Git-Tag: v9.0.1470 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1be4b81bfb3d7edf0e2ae41711d429e8fa5e0555;p=thirdparty%2Fvim.git 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 index 71353c8f81..82b5f91c6b 100644 --- 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 DeferLevelFive() + defer writefile(['5'], 'XQuitallAutocmd', 'a') + qa! + endfunc - func DeferLevelTwo() - call writefile(['text'], 'XQuitallAutocmdTwo', 'D') - doautocmd User DeferAutocmdThree + 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 - autocmd User DeferAutocmdTwo ++nested call DeferLevelTwo() + autocmd User DeferAutocmdThree ++nested call DeferLevelThree() - def DeferLevelOne() - call writefile(['text'], 'XQuitallAutocmdOne', 'D') - doautocmd User DeferAutocmdTwo + 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 index 0680767d3a..fbde6edd0b 100644 --- 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 index 95cff8ead4..5f99909037 100644 --- a/src/version.c +++ b/src/version.c @@ -695,6 +695,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1470, /**/ 1469, /**/