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

@@ -1050,11 +1050,14 @@ flag_string_T glv_flag_strings[] = {
* execute_instructions: ISN_LOCKUNLOCK - sets lval_root from stack.
*/
static void
get_lval_root(lval_T *lp, lval_root_T *lr)
fill_lval_from_lval_root(lval_T *lp, lval_root_T *lr)
{
#ifdef LOG_LOCKVAR
ch_log(NULL, "LKVAR: get_lval_root(): name %s", lp->ll_name);
ch_log(NULL, "LKVAR: fill_lval_from_lval_root(): name %s, tv %p",
lp->ll_name, (void*)lr->lr_tv);
#endif
if (lr->lr_tv == NULL)
return;
if (!lr->lr_is_arg && lr->lr_tv->v_type == VAR_CLASS)
{
if (lr->lr_tv->vval.v_class != NULL)
@@ -1177,15 +1180,14 @@ get_lval(
#ifdef LOG_LOCKVAR
if (lval_root == NULL)
ch_log(NULL,
"LKVAR: get_lval(): name %s, lval_root (nil)", name);
ch_log(NULL, "LKVAR: get_lval(): name: %s, lval_root (nil)", name);
else
ch_log(NULL,
"LKVAR: get_lval(): name %s, lr_tv %p lr_is_arg %d",
name, (void*)lval_root->lr_tv, lval_root->lr_is_arg);
ch_log(NULL, "LKVAR: get_lval(): name: %s, lr_tv %p lr_is_arg %d",
name, (void*)lval_root->lr_tv, lval_root->lr_is_arg);
char buf[80];
ch_log(NULL, "LKVAR: ...: GLV flags %s",
ch_log(NULL, "LKVAR: ...: GLV flags: %s",
flags_tostring(flags, glv_flag_strings, buf, sizeof(buf)));
int log_sync_root_key = FALSE;
#endif
// Clear everything in "lp".
@@ -1324,20 +1326,26 @@ get_lval(
}
}
// Without [idx] or .key we are done.
if ((*p != '[' && *p != '.'))
int sync_root = FALSE;
if (vim9script && lval_root != NULL)
{
cl_exec = lval_root->lr_cl_exec;
sync_root = lval_root->lr_sync_root;
}
// Without [idx] or .key we are done, unless doing sync_root.
if (*p != '[' && *p != '.' && (*name == NUL || !sync_root))
{
if (lval_root != NULL)
get_lval_root(lp, lval_root);
fill_lval_from_lval_root(lp, lval_root);
return p;
}
if (vim9script && lval_root != NULL)
if (vim9script && lval_root != NULL && lval_root->lr_tv != NULL)
{
// using local variable
lp->ll_tv = lval_root->lr_tv;
v = NULL;
cl_exec = lval_root->lr_cl_exec;
}
else
{
@@ -1367,7 +1375,7 @@ get_lval(
*/
var1.v_type = VAR_UNKNOWN;
var2.v_type = VAR_UNKNOWN;
while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.'))
while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.') || sync_root)
{
vartype_T v_type = lp->ll_tv->v_type;
@@ -1407,6 +1415,10 @@ get_lval(
emsg(_(e_slice_must_come_last));
return NULL;
}
#ifdef LOG_LOCKVAR
ch_log(NULL, "LKVAR: get_lval() loop: p: %s, type: %s", p,
vartype_name(v_type));
#endif
if (vim9script && lp->ll_valtype == NULL
&& v != NULL
@@ -1417,11 +1429,29 @@ get_lval(
// Vim9 script local variable: get the type
if (sv != NULL)
{
lp->ll_valtype = sv->sv_type;
#ifdef LOG_LOCKVAR
ch_log(NULL, "LKVAR: ... loop: vim9 assign type: %s",
vartype_name(lp->ll_valtype->tt_type));
#endif
}
}
len = -1;
if (*p == '.')
if (sync_root)
{
// For example, the first token is a member variable name and
// lp->ll_tv is a class/object.
// Process it directly without looking for "[idx]" or ".name".
key = name;
sync_root = FALSE; // only first time through
#ifdef LOG_LOCKVAR
log_sync_root_key = TRUE;
ch_log(NULL, "LKVAR: ... loop: name: %s, sync_root", name);
#endif
}
else if (*p == '.')
{
key = p + 1;
for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
@@ -1512,6 +1542,17 @@ get_lval(
// Skip to past ']'.
++p;
}
#ifdef LOG_LOCKVAR
if (log_sync_root_key)
ch_log(NULL, "LKVAR: ... loop: p: %s, sync_root key: %s", p,
key);
else if (len == -1)
ch_log(NULL, "LKVAR: ... loop: p: %s, '[' key: %s", p,
empty1 ? ":" : (char*)tv_get_string(&var1));
else
ch_log(NULL, "LKVAR: ... loop: p: %s, '.' key: %s", p, key);
log_sync_root_key = FALSE;
#endif
if (v_type == VAR_DICT)
{
@@ -1700,8 +1741,14 @@ get_lval(
lp->ll_list = NULL;
class_T *cl;
if (v_type == VAR_OBJECT && lp->ll_tv->vval.v_object != NULL)
if (v_type == VAR_OBJECT)
{
if (lp->ll_tv->vval.v_object == NULL)
{
if (!quiet)
emsg(_(e_using_null_object));
return NULL;
}
cl = lp->ll_tv->vval.v_object->obj_class;
lp->ll_object = lp->ll_tv->vval.v_object;
}