mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.0771: Vim9: cannot call a compiled closure from not compiled code
Problem: Vim9: cannot call a compiled closure from not compiled code. Solution: Pass funcexe to call_user_func().
This commit is contained in:
parent
aa5fc4ec51
commit
6f5b6dfb16
@ -246,7 +246,8 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
|
||||
|
||||
if (partial->pt_func != NULL && partial->pt_func->uf_dfunc_idx >= 0)
|
||||
{
|
||||
if (call_def_function(partial->pt_func, argc, argv, rettv) == FAIL)
|
||||
if (call_def_function(partial->pt_func, argc, argv,
|
||||
partial, rettv) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
else
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* vim9execute.c */
|
||||
int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, typval_T *rettv);
|
||||
int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, partial_T *partial, typval_T *rettv);
|
||||
void ex_disassemble(exarg_T *eap);
|
||||
int tv2bool(typval_T *tv);
|
||||
int check_not_string(typval_T *tv);
|
||||
int set_ref_in_dfunc(ufunc_T *ufunc, int copyID);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -792,5 +792,15 @@ def Test_nested_closure()
|
||||
assert_equal('text!!!', Closure('!!!'))
|
||||
enddef
|
||||
|
||||
func GetResult(Ref)
|
||||
return a:Ref('some')
|
||||
endfunc
|
||||
|
||||
def Test_call_closure_not_compiled()
|
||||
let text = 'text'
|
||||
g:Ref = {s -> s .. text}
|
||||
assert_equal('sometext', GetResult(g:Ref))
|
||||
enddef
|
||||
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
@ -1062,8 +1062,7 @@ call_user_func(
|
||||
int argcount, // nr of args
|
||||
typval_T *argvars, // arguments
|
||||
typval_T *rettv, // return value
|
||||
linenr_T firstline, // first line of range
|
||||
linenr_T lastline, // last line of range
|
||||
funcexe_T *funcexe, // context
|
||||
dict_T *selfdict) // Dictionary for "self"
|
||||
{
|
||||
sctx_T save_current_sctx;
|
||||
@ -1120,7 +1119,7 @@ call_user_func(
|
||||
current_sctx = fp->uf_script_ctx;
|
||||
|
||||
// Execute the compiled function.
|
||||
call_def_function(fp, argcount, argvars, rettv);
|
||||
call_def_function(fp, argcount, argvars, funcexe->partial, rettv);
|
||||
--depth;
|
||||
current_funccal = fc->caller;
|
||||
|
||||
@ -1194,9 +1193,9 @@ call_user_func(
|
||||
if ((fp->uf_flags & FC_NOARGS) == 0)
|
||||
{
|
||||
add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
|
||||
(varnumber_T)firstline);
|
||||
(varnumber_T)funcexe->firstline);
|
||||
add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
|
||||
(varnumber_T)lastline);
|
||||
(varnumber_T)funcexe->lastline);
|
||||
}
|
||||
for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i)
|
||||
{
|
||||
@ -1515,9 +1514,8 @@ call_user_func_check(
|
||||
did_save_redo = TRUE;
|
||||
}
|
||||
++fp->uf_calls;
|
||||
call_user_func(fp, argcount, argvars, rettv,
|
||||
funcexe->firstline, funcexe->lastline,
|
||||
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
||||
call_user_func(fp, argcount, argvars, rettv, funcexe,
|
||||
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
||||
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
|
||||
// Function was unreferenced while being used, free it now.
|
||||
func_clear_free(fp, FALSE);
|
||||
@ -4293,7 +4291,7 @@ find_hi_in_scoped_ht(char_u *name, hashtab_T **pht)
|
||||
if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL)
|
||||
return NULL;
|
||||
|
||||
// Search in parent scope which is possible to reference from lambda
|
||||
// Search in parent scope, which can be referenced from a lambda.
|
||||
current_funccal = current_funccal->func->uf_scoped;
|
||||
while (current_funccal != NULL)
|
||||
{
|
||||
|
@ -746,6 +746,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
771,
|
||||
/**/
|
||||
770,
|
||||
/**/
|
||||
|
@ -641,6 +641,7 @@ call_def_function(
|
||||
ufunc_T *ufunc,
|
||||
int argc_arg, // nr of arguments
|
||||
typval_T *argv, // arguments
|
||||
partial_T *partial, // optional partial for context
|
||||
typval_T *rettv) // return value
|
||||
{
|
||||
ectx_T ectx; // execution context
|
||||
@ -720,6 +721,12 @@ call_def_function(
|
||||
ectx.ec_frame_idx = ectx.ec_stack.ga_len;
|
||||
initial_frame_idx = ectx.ec_frame_idx;
|
||||
|
||||
if (partial != NULL)
|
||||
{
|
||||
ectx.ec_outer_stack = partial->pt_ectx_stack;
|
||||
ectx.ec_outer_frame = partial->pt_ectx_frame;
|
||||
}
|
||||
|
||||
// dummy frame entries
|
||||
for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
|
||||
{
|
||||
@ -1468,7 +1475,7 @@ call_def_function(
|
||||
{
|
||||
cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
|
||||
int r;
|
||||
typval_T partial;
|
||||
typval_T partial_tv;
|
||||
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
if (pfunc->cpf_top)
|
||||
@ -1480,12 +1487,12 @@ call_def_function(
|
||||
{
|
||||
// Get the funcref from the stack.
|
||||
--ectx.ec_stack.ga_len;
|
||||
partial = *STACK_TV_BOT(0);
|
||||
tv = &partial;
|
||||
partial_tv = *STACK_TV_BOT(0);
|
||||
tv = &partial_tv;
|
||||
}
|
||||
r = call_partial(tv, pfunc->cpf_argcount, &ectx);
|
||||
if (tv == &partial)
|
||||
clear_tv(&partial);
|
||||
if (tv == &partial_tv)
|
||||
clear_tv(&partial_tv);
|
||||
if (r == FAIL)
|
||||
goto failed;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user