Mercurial > vim
changeset 32278:f59ad8692734 v9.0.1470
patch 9.0.1470: deferred functions invoked in unexpected order
Commit: https://github.com/vim/vim/commit/1be4b81bfb3d7edf0e2ae41711d429e8fa5e0555
Author: zeertzjq <zeertzjq@outlook.com>
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)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 19 Apr 2023 15:30:04 +0200 |
parents | 272dc3dcacd3 |
children | ab1395da719e |
files | src/testdir/test_user_func.vim src/userfunc.c src/version.c |
diffstat | 3 files changed, 33 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- 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()
--- 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); } /*