mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.2.0071: Vim9: lambda function deleted on re-sourcing
Problem: Vim9: lambda function deleted on re-sourcing
(Mao-Yining)
Solution: Use ISN_UCALL for script-local def calls inside a lambda
(Hirohito Higashi).
fixes: #19509
closes: #19519
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
2fa34b6422
commit
c598c4de27
@@ -1473,6 +1473,31 @@ def Test_disassemble_lambda()
|
||||
instr)
|
||||
enddef
|
||||
|
||||
def s:ScriptLocalDefForLambda()
|
||||
enddef
|
||||
|
||||
def GlobalDefForLambda()
|
||||
enddef
|
||||
|
||||
def s:OuterWithLambdaCalls()
|
||||
timer_start(0, (_) => {
|
||||
ScriptLocalDefForLambda()
|
||||
g:GlobalDefForLambda()
|
||||
})
|
||||
enddef
|
||||
|
||||
def Test_disassemble_lambda_call_types()
|
||||
# Verify that inside a lambda:
|
||||
# - script-local def function call → ISN_UCALL (safe after re-sourcing)
|
||||
# - global def function call → ISN_DCALL (optimal, not deleted on re-source)
|
||||
OuterWithLambdaCalls()
|
||||
var instr = execute('disassemble OuterWithLambdaCalls')
|
||||
var name = substitute(instr, '.*\(<lambda>\d\+\).*', '\1', '')
|
||||
instr = execute('disassemble ' .. name)
|
||||
assert_match('\d UCALL <80><fd>R\d\+_ScriptLocalDefForLambda(argc 0)', instr)
|
||||
assert_match('\d DCALL GlobalDefForLambda(argc 0)', instr)
|
||||
enddef
|
||||
|
||||
def s:LambdaWithType(): number
|
||||
var Ref = (a: number) => a + 10
|
||||
return Ref(g:value)
|
||||
|
||||
@@ -1847,6 +1847,41 @@ def Test_vim9script_reload_delfunc()
|
||||
g:DoCheck(false)
|
||||
enddef
|
||||
|
||||
def Test_vim9script_reload_lambda_def_func()
|
||||
CheckFeature timers
|
||||
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
|
||||
def F()
|
||||
g:call_result += 1
|
||||
enddef
|
||||
|
||||
augroup Xtest933
|
||||
au!
|
||||
au CmdlineLeave : timer_start(0, (_) => F())
|
||||
augroup END
|
||||
END
|
||||
|
||||
g:call_result = 0
|
||||
writefile(lines, 'Xtest933.vim', 'D')
|
||||
source Xtest933.vim
|
||||
|
||||
# Simulate the CmdlineLeave event that fires before the second :so
|
||||
doautocmd CmdlineLeave :
|
||||
|
||||
# Re-source: F is redefined; without the fix this causes E933 when timer fires
|
||||
source Xtest933.vim
|
||||
|
||||
# Allow the 0ms timer to fire
|
||||
sleep 10m
|
||||
|
||||
assert_equal(1, g:call_result)
|
||||
|
||||
augroup Xtest933 | au! | augroup END
|
||||
unlet! g:call_result
|
||||
enddef
|
||||
|
||||
def Test_vim9script_reload_delvar()
|
||||
# write the script with a script-local variable
|
||||
var lines =<< trim END
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
71,
|
||||
/**/
|
||||
70,
|
||||
/**/
|
||||
|
||||
+18
-3
@@ -1909,6 +1909,23 @@ generate_BLOBAPPEND(cctx_T *cctx)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the instruction type for a function call: ISN_METHODCALL, ISN_DCALL, or
|
||||
* ISN_UCALL.
|
||||
*/
|
||||
static isntype_T
|
||||
isn_get_calltype(
|
||||
cctx_T *cctx,
|
||||
ufunc_T *ufunc,
|
||||
class_T *cl)
|
||||
{
|
||||
return cl != NULL ? ISN_METHODCALL
|
||||
: (ufunc->uf_def_status != UF_NOT_COMPILED
|
||||
&& ((cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0
|
||||
|| ufunc->uf_name[0] != K_SPECIAL))
|
||||
? ISN_DCALL : ISN_UCALL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an ISN_DCALL, ISN_UCALL or ISN_METHODCALL instruction.
|
||||
* When calling a method on an object, of which we know the interface only,
|
||||
@@ -1996,9 +2013,7 @@ generate_CALL(
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if ((isn = generate_instr(cctx, cl != NULL ? ISN_METHODCALL
|
||||
: ufunc->uf_def_status != UF_NOT_COMPILED
|
||||
? ISN_DCALL : ISN_UCALL)) == NULL)
|
||||
if ((isn = generate_instr(cctx, isn_get_calltype(cctx, ufunc, cl))) == NULL)
|
||||
return FAIL;
|
||||
if (cl != NULL /* isn->isn_type == ISN_METHODCALL */)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user