Skip to content

Commit 960cf91

Browse files
zeertzjqbrammool
authored andcommitted
patch 9.0.1469: deferred functions not called from autocommands
Problem: Deferred functions not called from autocommands. Solution: Also go through the funccal_stack. (closes #12267)
1 parent a1f2b5d commit 960cf91

3 files changed

Lines changed: 50 additions & 14 deletions

File tree

src/testdir/test_user_func.vim

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,33 @@ func Test_defer_quitall_def()
702702
call delete('XQuitallDefThree')
703703
endfunc
704704

705+
func Test_defer_quitall_autocmd()
706+
let lines =<< trim END
707+
autocmd User DeferAutocmdThree qa!
708+
709+
func DeferLevelTwo()
710+
call writefile(['text'], 'XQuitallAutocmdTwo', 'D')
711+
doautocmd User DeferAutocmdThree
712+
endfunc
713+
714+
autocmd User DeferAutocmdTwo ++nested call DeferLevelTwo()
715+
716+
def DeferLevelOne()
717+
call writefile(['text'], 'XQuitallAutocmdOne', 'D')
718+
doautocmd User DeferAutocmdTwo
719+
enddef
720+
721+
autocmd User DeferAutocmdOne ++nested call DeferLevelOne()
722+
723+
doautocmd User DeferAutocmdOne
724+
END
725+
call writefile(lines, 'XdeferQuitallAutocmd', 'D')
726+
let res = system(GetVimCommand() .. ' -X -S XdeferQuitallAutocmd')
727+
call assert_equal(0, v:shell_error)
728+
call assert_false(filereadable('XQuitallAutocmdOne'))
729+
call assert_false(filereadable('XQuitallAutocmdTwo'))
730+
endfunc
731+
705732
func Test_defer_quitall_in_expr_func()
706733
let lines =<< trim END
707734
def DefIndex(idx: number, val: string): bool

src/userfunc.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6122,27 +6122,34 @@ handle_defer_one(funccall_T *funccal)
61226122
ga_clear(&funccal->fc_defer);
61236123
}
61246124

6125+
static void
6126+
invoke_funccall_defer(funccall_T *fc)
6127+
{
6128+
if (fc->fc_ectx != NULL)
6129+
{
6130+
// :def function
6131+
unwind_def_callstack(fc->fc_ectx);
6132+
may_invoke_defer_funcs(fc->fc_ectx);
6133+
}
6134+
else
6135+
{
6136+
// legacy function
6137+
handle_defer_one(fc);
6138+
}
6139+
}
6140+
61256141
/*
61266142
* Called when exiting: call all defer functions.
61276143
*/
61286144
void
61296145
invoke_all_defer(void)
61306146
{
6131-
funccall_T *funccal;
6147+
for (funccal_entry_T *fce = funccal_stack; fce != NULL; fce = fce->next)
6148+
for (funccall_T *fc = fce->top_funccal; fc != NULL; fc = fc->fc_caller)
6149+
invoke_funccall_defer(fc);
61326150

6133-
for (funccal = current_funccal; funccal != NULL;
6134-
funccal = funccal->fc_caller)
6135-
if (funccal->fc_ectx != NULL)
6136-
{
6137-
// :def function
6138-
unwind_def_callstack(funccal->fc_ectx);
6139-
may_invoke_defer_funcs(funccal->fc_ectx);
6140-
}
6141-
else
6142-
{
6143-
// legacy function
6144-
handle_defer_one(funccal);
6145-
}
6151+
for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->fc_caller)
6152+
invoke_funccall_defer(fc);
61466153
}
61476154

61486155
/*

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ static char *(features[]) =
695695

696696
static int included_patches[] =
697697
{ /* Add new patch number below this line */
698+
/**/
699+
1469,
698700
/**/
699701
1468,
700702
/**/

0 commit comments

Comments
 (0)