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
79
src/eval.c
79
src/eval.c
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user