0
0
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:
Ernie Rael
2023-10-11 21:35:11 +02:00
committed by Christian Brabandt
parent c97b3febc8
commit 4c8da025ef
7 changed files with 461 additions and 26 deletions

View File

@@ -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;