mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 9.0.1468: recursively calling :defer function if it does :qa
Problem: Recursively calling :defer function if it does :qa in a compiled function. Solution: Clear the defer entry before calling the function. (closes #12271)
This commit is contained in:
@@ -651,30 +651,55 @@ func Test_defer_throw()
|
||||
call assert_false(filereadable('XDeleteTwo'))
|
||||
endfunc
|
||||
|
||||
func Test_defer_quitall()
|
||||
func Test_defer_quitall_func()
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
func DeferLevelTwo()
|
||||
call writefile(['text'], 'XQuitallTwo', 'D')
|
||||
call writefile(['quit'], 'XQuitallThree', 'a')
|
||||
call writefile(['text'], 'XQuitallFuncTwo', 'D')
|
||||
call writefile(['quit'], 'XQuitallFuncThree', 'a')
|
||||
qa!
|
||||
endfunc
|
||||
|
||||
func DeferLevelOne()
|
||||
call writefile(['text'], 'XQuitalFunclOne', 'D')
|
||||
defer DeferLevelTwo()
|
||||
endfunc
|
||||
|
||||
call DeferLevelOne()
|
||||
END
|
||||
call writefile(lines, 'XdeferQuitallFunc', 'D')
|
||||
call system(GetVimCommand() .. ' -X -S XdeferQuitallFunc')
|
||||
call assert_equal(0, v:shell_error)
|
||||
call assert_false(filereadable('XQuitallFuncOne'))
|
||||
call assert_false(filereadable('XQuitallFuncTwo'))
|
||||
call assert_equal(['quit'], readfile('XQuitallFuncThree'))
|
||||
|
||||
call delete('XQuitallFuncThree')
|
||||
endfunc
|
||||
|
||||
func Test_defer_quitall_def()
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
def DeferLevelTwo()
|
||||
call writefile(['text'], 'XQuitallDefTwo', 'D')
|
||||
call writefile(['quit'], 'XQuitallDefThree', 'a')
|
||||
qa!
|
||||
enddef
|
||||
|
||||
def DeferLevelOne()
|
||||
call writefile(['text'], 'XQuitallOne', 'D')
|
||||
call DeferLevelTwo()
|
||||
call writefile(['text'], 'XQuitallDefOne', 'D')
|
||||
defer DeferLevelTwo()
|
||||
enddef
|
||||
|
||||
DeferLevelOne()
|
||||
END
|
||||
call writefile(lines, 'XdeferQuitall', 'D')
|
||||
let res = system(GetVimCommand() .. ' -X -S XdeferQuitall')
|
||||
call writefile(lines, 'XdeferQuitallDef', 'D')
|
||||
call system(GetVimCommand() .. ' -X -S XdeferQuitallDef')
|
||||
call assert_equal(0, v:shell_error)
|
||||
call assert_false(filereadable('XQuitallOne'))
|
||||
call assert_false(filereadable('XQuitallTwo'))
|
||||
call assert_equal(['quit'], readfile('XQuitallThree'))
|
||||
call assert_false(filereadable('XQuitallDefOne'))
|
||||
call assert_false(filereadable('XQuitallDefTwo'))
|
||||
call assert_equal(['quit'], readfile('XQuitallDefThree'))
|
||||
|
||||
call delete('XQuitallThree')
|
||||
call delete('XQuitallDefThree')
|
||||
endfunc
|
||||
|
||||
func Test_defer_quitall_in_expr_func()
|
||||
@@ -693,7 +718,7 @@ func Test_defer_quitall_in_expr_func()
|
||||
call Test_defer_in_funcref()
|
||||
END
|
||||
call writefile(lines, 'XdeferQuitallExpr', 'D')
|
||||
let res = system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
|
||||
call system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
|
||||
call assert_equal(0, v:shell_error)
|
||||
call assert_false(filereadable('Xentry0'))
|
||||
call assert_false(filereadable('Xentry1'))
|
||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1468,
|
||||
/**/
|
||||
1467,
|
||||
/**/
|
||||
|
@@ -1063,6 +1063,10 @@ invoke_defer_funcs(ectx_T *ectx)
|
||||
int obj_off = functv->v_type == VAR_PARTIAL ? 1 : 0;
|
||||
int argcount = l->lv_len - 1 - obj_off;
|
||||
|
||||
if (functv->vval.v_string == NULL)
|
||||
// already being called, can happen if function does ":qa"
|
||||
continue;
|
||||
|
||||
if (obj_off == 1)
|
||||
arg_li = arg_li->li_next; // second list item is the object
|
||||
for (i = 0; i < argcount; ++i)
|
||||
@@ -1082,9 +1086,14 @@ invoke_defer_funcs(ectx_T *ectx)
|
||||
if (funcexe.fe_object != NULL)
|
||||
++funcexe.fe_object->obj_refcount;
|
||||
}
|
||||
(void)call_func(functv->vval.v_string, -1,
|
||||
&rettv, argcount, argvars, &funcexe);
|
||||
|
||||
char_u *name = functv->vval.v_string;
|
||||
functv->vval.v_string = NULL;
|
||||
|
||||
(void)call_func(name, -1, &rettv, argcount, argvars, &funcexe);
|
||||
|
||||
clear_tv(&rettv);
|
||||
vim_free(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user