diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-04-19 14:21:24 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2023-04-19 14:21:24 +0100 |
commit | 1be4b81bfb3d7edf0e2ae41711d429e8fa5e0555 (patch) | |
tree | 716eb27d91cb33a19ce16127f73cec3fdffd1e89 | |
parent | 960cf9119e3f4922ca9719feb5e0c0bc5e3b9840 (diff) | |
download | vim-git-1be4b81bfb3d7edf0e2ae41711d429e8fa5e0555.tar.gz |
patch 9.0.1470: deferred functions invoked in unexpected orderv9.0.1470
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)
-rw-r--r-- | src/testdir/test_user_func.vim | 38 | ||||
-rw-r--r-- | src/userfunc.c | 6 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 32 insertions, 14 deletions
diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim index 71353c8f8..82b5f91c6 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 0680767d3..fbde6edd0 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 95cff8ead..5f9990903 100644 --- 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, |