mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -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'))
|
call assert_false(filereadable('XDeleteTwo'))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_defer_quitall()
|
func Test_defer_quitall_func()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
vim9script
|
|
||||||
func DeferLevelTwo()
|
func DeferLevelTwo()
|
||||||
call writefile(['text'], 'XQuitallTwo', 'D')
|
call writefile(['text'], 'XQuitallFuncTwo', 'D')
|
||||||
call writefile(['quit'], 'XQuitallThree', 'a')
|
call writefile(['quit'], 'XQuitallFuncThree', 'a')
|
||||||
qa!
|
qa!
|
||||||
endfunc
|
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()
|
def DeferLevelOne()
|
||||||
call writefile(['text'], 'XQuitallOne', 'D')
|
call writefile(['text'], 'XQuitallDefOne', 'D')
|
||||||
call DeferLevelTwo()
|
defer DeferLevelTwo()
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
DeferLevelOne()
|
DeferLevelOne()
|
||||||
END
|
END
|
||||||
call writefile(lines, 'XdeferQuitall', 'D')
|
call writefile(lines, 'XdeferQuitallDef', 'D')
|
||||||
let res = system(GetVimCommand() .. ' -X -S XdeferQuitall')
|
call system(GetVimCommand() .. ' -X -S XdeferQuitallDef')
|
||||||
call assert_equal(0, v:shell_error)
|
call assert_equal(0, v:shell_error)
|
||||||
call assert_false(filereadable('XQuitallOne'))
|
call assert_false(filereadable('XQuitallDefOne'))
|
||||||
call assert_false(filereadable('XQuitallTwo'))
|
call assert_false(filereadable('XQuitallDefTwo'))
|
||||||
call assert_equal(['quit'], readfile('XQuitallThree'))
|
call assert_equal(['quit'], readfile('XQuitallDefThree'))
|
||||||
|
|
||||||
call delete('XQuitallThree')
|
call delete('XQuitallDefThree')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_defer_quitall_in_expr_func()
|
func Test_defer_quitall_in_expr_func()
|
||||||
@@ -693,7 +718,7 @@ func Test_defer_quitall_in_expr_func()
|
|||||||
call Test_defer_in_funcref()
|
call Test_defer_in_funcref()
|
||||||
END
|
END
|
||||||
call writefile(lines, 'XdeferQuitallExpr', 'D')
|
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_equal(0, v:shell_error)
|
||||||
call assert_false(filereadable('Xentry0'))
|
call assert_false(filereadable('Xentry0'))
|
||||||
call assert_false(filereadable('Xentry1'))
|
call assert_false(filereadable('Xentry1'))
|
||||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1468,
|
||||||
/**/
|
/**/
|
||||||
1467,
|
1467,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -1063,6 +1063,10 @@ invoke_defer_funcs(ectx_T *ectx)
|
|||||||
int obj_off = functv->v_type == VAR_PARTIAL ? 1 : 0;
|
int obj_off = functv->v_type == VAR_PARTIAL ? 1 : 0;
|
||||||
int argcount = l->lv_len - 1 - obj_off;
|
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)
|
if (obj_off == 1)
|
||||||
arg_li = arg_li->li_next; // second list item is the object
|
arg_li = arg_li->li_next; // second list item is the object
|
||||||
for (i = 0; i < argcount; ++i)
|
for (i = 0; i < argcount; ++i)
|
||||||
@@ -1082,9 +1086,14 @@ invoke_defer_funcs(ectx_T *ectx)
|
|||||||
if (funcexe.fe_object != NULL)
|
if (funcexe.fe_object != NULL)
|
||||||
++funcexe.fe_object->obj_refcount;
|
++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);
|
clear_tv(&rettv);
|
||||||
|
vim_free(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user