mirror of
https://github.com/neovim/neovim.git
synced 2025-10-08 19:06:31 +00:00
vim-patch:9.0.0406: deferred functions not invoked when partial func exits
Problem: Deferred functions not invoked when partial func exits.
Solution: Create a funccall_T when calling a :def function.
9667b2c888
The remove_funccal() function is currently unused, but it will be used
in patch 9.0.0618.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -881,6 +881,27 @@ static void func_clear_free(ufunc_T *fp, bool force)
|
|||||||
func_free(fp);
|
func_free(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allocate a funccall_T, link it in current_funccal and fill in "fp" and "rettv".
|
||||||
|
/// Must be followed by one call to remove_funccal() or cleanup_function_call().
|
||||||
|
funccall_T *create_funccal(ufunc_T *fp, typval_T *rettv)
|
||||||
|
{
|
||||||
|
funccall_T *fc = xcalloc(1, sizeof(funccall_T));
|
||||||
|
fc->fc_caller = current_funccal;
|
||||||
|
current_funccal = fc;
|
||||||
|
fc->fc_func = fp;
|
||||||
|
func_ptr_ref(fp);
|
||||||
|
fc->fc_rettv = rettv;
|
||||||
|
return fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restore current_funccal.
|
||||||
|
void remove_funccal(void)
|
||||||
|
{
|
||||||
|
funccall_T *fc = current_funccal;
|
||||||
|
current_funccal = fc->fc_caller;
|
||||||
|
free_funccal(fc);
|
||||||
|
}
|
||||||
|
|
||||||
/// Call a user function
|
/// Call a user function
|
||||||
///
|
///
|
||||||
/// @param fp Function to call.
|
/// @param fp Function to call.
|
||||||
@@ -895,7 +916,6 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
|
|||||||
FUNC_ATTR_NONNULL_ARG(1, 3, 4)
|
FUNC_ATTR_NONNULL_ARG(1, 3, 4)
|
||||||
{
|
{
|
||||||
bool using_sandbox = false;
|
bool using_sandbox = false;
|
||||||
funccall_T *fc;
|
|
||||||
int save_did_emsg;
|
int save_did_emsg;
|
||||||
static int depth = 0;
|
static int depth = 0;
|
||||||
dictitem_T *v;
|
dictitem_T *v;
|
||||||
@@ -930,19 +950,13 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
|
|||||||
// check for CTRL-C hit
|
// check for CTRL-C hit
|
||||||
line_breakcheck();
|
line_breakcheck();
|
||||||
// prepare the funccall_T structure
|
// prepare the funccall_T structure
|
||||||
fc = xcalloc(1, sizeof(funccall_T));
|
funccall_T *fc = create_funccal(fp, rettv);
|
||||||
fc->fc_caller = current_funccal;
|
|
||||||
current_funccal = fc;
|
|
||||||
fc->fc_func = fp;
|
|
||||||
fc->fc_rettv = rettv;
|
|
||||||
fc->fc_level = ex_nesting_level;
|
fc->fc_level = ex_nesting_level;
|
||||||
// Check if this function has a breakpoint.
|
// Check if this function has a breakpoint.
|
||||||
fc->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0);
|
fc->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0);
|
||||||
fc->fc_dbg_tick = debug_tick;
|
fc->fc_dbg_tick = debug_tick;
|
||||||
|
|
||||||
// Set up fields for closure.
|
// Set up fields for closure.
|
||||||
ga_init(&fc->fc_ufuncs, sizeof(ufunc_T *), 1);
|
ga_init(&fc->fc_ufuncs, sizeof(ufunc_T *), 1);
|
||||||
func_ptr_ref(fp);
|
|
||||||
|
|
||||||
if (strncmp(fp->uf_name, "<lambda>", 8) == 0) {
|
if (strncmp(fp->uf_name, "<lambda>", 8) == 0) {
|
||||||
islambda = true;
|
islambda = true;
|
||||||
|
@@ -633,5 +633,34 @@ func Test_defer_quitall()
|
|||||||
call assert_false(filereadable('XQuitallTwo'))
|
call assert_false(filereadable('XQuitallTwo'))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_defer_quitall_in_expr_func()
|
||||||
|
throw 'Skipped: Vim9 script is N/A'
|
||||||
|
let lines =<< trim END
|
||||||
|
def DefIndex(idx: number, val: string): bool
|
||||||
|
call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
|
||||||
|
if val == 'b'
|
||||||
|
qa!
|
||||||
|
endif
|
||||||
|
return val == 'c'
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_defer_in_funcref()
|
||||||
|
assert_equal(2, indexof(['a', 'b', 'c'], funcref('g:DefIndex')))
|
||||||
|
enddef
|
||||||
|
call Test_defer_in_funcref()
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XdeferQuitallExpr', 'D')
|
||||||
|
let res = system(GetVimCommandClean() .. ' -X -S XdeferQuitallExpr')
|
||||||
|
call assert_equal(0, v:shell_error)
|
||||||
|
call assert_false(filereadable('Xentry0'))
|
||||||
|
call assert_false(filereadable('Xentry1'))
|
||||||
|
call assert_false(filereadable('Xentry2'))
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func FuncIndex(idx, val)
|
||||||
|
call writefile([a:idx .. ': ' .. a:val], 'Xentry' .. a:idx, 'D')
|
||||||
|
return a:val == 'c'
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user