mirror of
https://github.com/vim/vim.git
synced 2025-11-13 22:54:27 -05:00
patch 9.1.1879: Crash when using a lambda funcref with :defer
Problem: Crash when using a lambda funcref with :defer
Solution: De-reference the partial correctly after invoking the deferred
functions (Yegappan Lakshmanan).
closes: #18640
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
9fff99c3c2
commit
bd9155ebb6
@@ -5232,6 +5232,23 @@ def Test_defer_invalid_func_arg()
|
||||
v9.CheckScriptFailure(lines, 'E1001: Variable not found: a', 1)
|
||||
enddef
|
||||
|
||||
" Test for using defer with a lambda funcref
|
||||
def Test_defer_lambda_funcref()
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
var lfr_result = ''
|
||||
def Foo()
|
||||
var Fn = () => {
|
||||
lfr_result = 'called'
|
||||
}
|
||||
defer Fn()
|
||||
enddef
|
||||
Foo()
|
||||
assert_equal('called', lfr_result)
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
enddef
|
||||
|
||||
" Test for using an non-existing type in a "for" statement.
|
||||
def Test_invalid_type_in_for()
|
||||
var lines =<< trim END
|
||||
|
||||
@@ -729,6 +729,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1879,
|
||||
/**/
|
||||
1878,
|
||||
/**/
|
||||
|
||||
@@ -1176,20 +1176,30 @@ invoke_defer_funcs(ectx_T *ectx)
|
||||
argvars[i] = arg_li->li_tv;
|
||||
}
|
||||
|
||||
funcexe_T funcexe;
|
||||
funcexe_T funcexe;
|
||||
char_u *name = NULL;
|
||||
partial_T *pt = NULL;
|
||||
|
||||
CLEAR_FIELD(funcexe);
|
||||
funcexe.fe_evaluate = TRUE;
|
||||
rettv.v_type = VAR_UNKNOWN;
|
||||
|
||||
if (functv->v_type == VAR_PARTIAL)
|
||||
{
|
||||
funcexe.fe_partial = functv->vval.v_partial;
|
||||
funcexe.fe_object = functv->vval.v_partial->pt_obj;
|
||||
pt = functv->vval.v_partial;
|
||||
functv->vval.v_partial = NULL;
|
||||
|
||||
name = pt->pt_func->uf_name;
|
||||
funcexe.fe_partial = pt;
|
||||
funcexe.fe_object = pt->pt_obj;
|
||||
if (funcexe.fe_object != NULL)
|
||||
++funcexe.fe_object->obj_refcount;
|
||||
}
|
||||
|
||||
char_u *name = functv->vval.v_string;
|
||||
functv->vval.v_string = NULL;
|
||||
else
|
||||
{
|
||||
name = functv->vval.v_string;
|
||||
functv->vval.v_string = NULL;
|
||||
}
|
||||
|
||||
// If the deferred function is called after an exception, then only the
|
||||
// first statement in the function will be executed (because of the
|
||||
@@ -1204,7 +1214,10 @@ invoke_defer_funcs(ectx_T *ectx)
|
||||
exception_state_restore(&estate);
|
||||
|
||||
clear_tv(&rettv);
|
||||
vim_free(name);
|
||||
if (functv->v_type == VAR_PARTIAL)
|
||||
partial_unref(pt);
|
||||
else
|
||||
vim_free(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user