0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 9.0.0399: using :defer in expression funcref not tested

Problem:    Using :defer in expression funcref not tested.
Solution:   Add a test.  Fix uncovered problems.
This commit is contained in:
Bram Moolenaar
2022-09-06 21:02:35 +01:00
parent ca16c60f33
commit 98aff658d5
5 changed files with 69 additions and 4 deletions

View File

@@ -4,6 +4,8 @@ void update_has_breakpoint(ufunc_T *ufunc);
void funcstack_check_refcount(funcstack_T *funcstack); void funcstack_check_refcount(funcstack_T *funcstack);
int set_ref_in_funcstacks(int copyID); int set_ref_in_funcstacks(int copyID);
int in_def_function(void); int in_def_function(void);
ectx_T *clear_currrent_ectx(void);
void restore_current_ectx(ectx_T *ectx);
int add_defer_function(char_u *name, int argcount, typval_T *argvars); int add_defer_function(char_u *name, int argcount, typval_T *argvars);
char_u *char_from_string(char_u *str, varnumber_T index); char_u *char_from_string(char_u *str, varnumber_T index);
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive); char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive);

View File

@@ -625,5 +625,37 @@ func Test_defer_quitall()
call assert_false(filereadable('XQuitallTwo')) call assert_false(filereadable('XQuitallTwo'))
endfunc endfunc
func FuncIndex(idx, val)
call writefile([a:idx .. ': ' .. a:val], 'Xentry' .. a:idx, 'D')
return a:val == 'c'
endfunc
def DefIndex(idx: number, val: string): bool
call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
return val == 'c'
enddef
def Test_defer_in_funcref()
assert_equal(2, indexof(['a', 'b', 'c'], function('g:FuncIndex')))
assert_false(filereadable('Xentry0'))
assert_false(filereadable('Xentry1'))
assert_false(filereadable('Xentry2'))
assert_equal(2, indexof(['a', 'b', 'c'], g:DefIndex))
assert_false(filereadable('Xentry0'))
assert_false(filereadable('Xentry1'))
assert_false(filereadable('Xentry2'))
assert_equal(2, indexof(['a', 'b', 'c'], function('g:DefIndex')))
assert_false(filereadable('Xentry0'))
assert_false(filereadable('Xentry1'))
assert_false(filereadable('Xentry2'))
assert_equal(2, indexof(['a', 'b', 'c'], funcref(g:DefIndex)))
assert_false(filereadable('Xentry0'))
assert_false(filereadable('Xentry1'))
assert_false(filereadable('Xentry2'))
enddef
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -2593,6 +2593,7 @@ call_user_func(
dict_T *selfdict) // Dictionary for "self" dict_T *selfdict) // Dictionary for "self"
{ {
sctx_T save_current_sctx; sctx_T save_current_sctx;
ectx_T *save_current_ectx;
int using_sandbox = FALSE; int using_sandbox = FALSE;
int save_sticky_cmdmod_flags = sticky_cmdmod_flags; int save_sticky_cmdmod_flags = sticky_cmdmod_flags;
funccall_T *fc; funccall_T *fc;
@@ -2669,9 +2670,9 @@ call_user_func(
islambda = fp->uf_flags & FC_LAMBDA; islambda = fp->uf_flags & FC_LAMBDA;
/* /*
* Note about using fc->fc_fixvar[]: This is an array of FIXVAR_CNT variables * Note about using fc->fc_fixvar[]: This is an array of FIXVAR_CNT
* with names up to VAR_SHORT_LEN long. This avoids having to alloc/free * variables with names up to VAR_SHORT_LEN long. This avoids having to
* each argument variable and saves a lot of time. * alloc/free each argument variable and saves a lot of time.
*/ */
/* /*
* Init l: variables. * Init l: variables.
@@ -2885,6 +2886,11 @@ call_user_func(
// "legacy" does not apply to commands in the function // "legacy" does not apply to commands in the function
sticky_cmdmod_flags = 0; sticky_cmdmod_flags = 0;
// If called from a compiled :def function the execution context must be
// hidden, any deferred functions need to be added to the function being
// executed here.
save_current_ectx = clear_currrent_ectx();
save_current_sctx = current_sctx; save_current_sctx = current_sctx;
current_sctx = fp->uf_script_ctx; current_sctx = fp->uf_script_ctx;
save_did_emsg = did_emsg; save_did_emsg = did_emsg;
@@ -2974,6 +2980,8 @@ call_user_func(
ESTACK_CHECK_NOW ESTACK_CHECK_NOW
estack_pop(); estack_pop();
current_sctx = save_current_sctx; current_sctx = save_current_sctx;
restore_current_ectx(save_current_ectx);
#ifdef FEAT_PROFILE #ifdef FEAT_PROFILE
if (do_profiling == PROF_YES) if (do_profiling == PROF_YES)
script_prof_restore(&profile_info.pi_wait_start); script_prof_restore(&profile_info.pi_wait_start);

View File

@@ -703,6 +703,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 */
/**/
399,
/**/ /**/
398, 398,
/**/ /**/

View File

@@ -859,6 +859,27 @@ in_def_function(void)
return current_ectx != NULL; return current_ectx != NULL;
} }
/*
* Clear "current_ectx" and return the previous value. To be used when calling
* a user function.
*/
ectx_T *
clear_currrent_ectx(void)
{
ectx_T *r = current_ectx;
current_ectx = NULL;
return r;
}
void
restore_current_ectx(ectx_T *ectx)
{
if (current_ectx != NULL)
iemsg("Restoring current_ectx while it is not NULL");
current_ectx = ectx;
}
/* /*
* Add an entry for a deferred function call to the currently executing * Add an entry for a deferred function call to the currently executing
* function. * function.