mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 9.0.2015: Vim9: does not handle islocked() from a method correctly
Problem: Vim9: does not handle islocked() from a method correctly Solution: Handle islocked() builtin from a method. - Setup `lval_root` from `f_islocked()`. - Add function `fill_exec_lval_root()` to get info about executing method. - `sync_root` added in get_lval to handle method member access. - Conservative approach to reference counting. closes: #13309 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Ernie Rael <errael@raelity.com>
This commit is contained in:
committed by
Christian Brabandt
parent
c97b3febc8
commit
4c8da025ef
@@ -925,6 +925,41 @@ in_def_function(void)
|
||||
return current_ectx != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If executing a class/object method, then fill in the lval_T.
|
||||
* Set lr_tv to the executing item, and lr_exec_class to the executing class;
|
||||
* use free_tv and class_unref when finished with the lval_root.
|
||||
* For use by builtin functions.
|
||||
*
|
||||
* Return FAIL and do nothing if not executing in a class; otherwise OK.
|
||||
*/
|
||||
int
|
||||
fill_exec_lval_root(lval_root_T *root)
|
||||
{
|
||||
ectx_T *ectx = current_ectx;
|
||||
if (ectx != NULL)
|
||||
{
|
||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ current_ectx->ec_dfunc_idx;
|
||||
ufunc_T *ufunc = dfunc->df_ufunc;
|
||||
if (ufunc->uf_class != NULL) // executing a method?
|
||||
{
|
||||
typval_T *tv = alloc_tv();
|
||||
if (tv != NULL)
|
||||
{
|
||||
CLEAR_POINTER(root);
|
||||
root->lr_tv = tv;
|
||||
copy_tv(STACK_TV_VAR(0), root->lr_tv);
|
||||
root->lr_cl_exec = ufunc->uf_class;
|
||||
++root->lr_cl_exec->class_refcount;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear "current_ectx" and return the previous value. To be used when calling
|
||||
* a user function.
|
||||
@@ -4185,21 +4220,20 @@ exec_instructions(ectx_T *ectx)
|
||||
|
||||
case ISN_LOCKUNLOCK:
|
||||
{
|
||||
lval_root_T *lval_root_save = lval_root;
|
||||
int res;
|
||||
#ifdef LOG_LOCKVAR
|
||||
ch_log(NULL, "LKVAR: execute INS_LOCKUNLOCK isn_arg %s",
|
||||
iptr->isn_arg.string);
|
||||
#endif
|
||||
lval_root_T *lval_root_save = lval_root;
|
||||
|
||||
// Stack has the local variable, argument the whole :lock
|
||||
// or :unlock command, like ISN_EXEC.
|
||||
--ectx->ec_stack.ga_len;
|
||||
lval_root_T root = { STACK_TV_BOT(0),
|
||||
iptr->isn_arg.lockunlock.lu_cl_exec,
|
||||
iptr->isn_arg.lockunlock.lu_is_arg };
|
||||
lval_root_T root = { .lr_tv = STACK_TV_BOT(0),
|
||||
.lr_cl_exec = iptr->isn_arg.lockunlock.lu_cl_exec,
|
||||
.lr_is_arg = iptr->isn_arg.lockunlock.lu_is_arg };
|
||||
lval_root = &root;
|
||||
res = exec_command(iptr,
|
||||
int res = exec_command(iptr,
|
||||
iptr->isn_arg.lockunlock.lu_string);
|
||||
clear_tv(root.lr_tv);
|
||||
lval_root = lval_root_save;
|
||||
|
Reference in New Issue
Block a user