1
0
forked from aniani/vim

patch 9.1.0360: Vim9: does not handle autoloaded variables well

Problem:  Vim9: does not handle autoloaded variables well
Solution: Better handle script-level exported variable references from
          autoload files (Ernie Rael).

fixes: #14591
closes: #14607

Signed-off-by: Ernie Rael <errael@raelity.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Ernie Rael
2024-04-21 14:45:48 +02:00
committed by Christian Brabandt
parent 158673680f
commit 84f6dc7ed2
4 changed files with 128 additions and 14 deletions

View File

@@ -3340,12 +3340,31 @@ find_var(char_u *name, hashtab_T **htp, int no_autoload)
}
}
// and finally try
return find_var_autoload_prefix(name, 0, htp, NULL);
}
/*
* Find variable "name" with sn_autoload_prefix.
* Return a pointer to it if found, NULL if not found.
* When "sid" > 0, use it otherwise use "current_sctx.sc_sid".
* When "htp" is not NULL set "htp" to the hashtab_T used.
* When "namep" is not NULL set "namep" to the generated name, and
* then the caller gets ownership and is responsible for freeing the name.
*/
dictitem_T *
find_var_autoload_prefix(char_u *name, int sid, hashtab_T **htp,
char_u **namep)
{
hashtab_T *ht;
dictitem_T *ret = NULL;
// When using "vim9script autoload" script-local items are prefixed but can
// be used with s:name.
if (SCRIPT_ID_VALID(current_sctx.sc_sid)
int check_sid = sid > 0 ? sid : current_sctx.sc_sid;
if (SCRIPT_ID_VALID(check_sid)
&& (in_vim9script() || (name[0] == 's' && name[1] == ':')))
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
scriptitem_T *si = SCRIPT_ITEM(check_sid);
if (si->sn_autoload_prefix != NULL)
{
@@ -3355,20 +3374,26 @@ find_var(char_u *name, hashtab_T **htp, int no_autoload)
if (auto_name != NULL)
{
int free_auto_name = TRUE;
ht = &globvarht;
ret = find_var_in_ht(ht, 'g', auto_name, TRUE);
vim_free(auto_name);
if (ret != NULL)
{
if (htp != NULL)
*htp = ht;
return ret;
if (namep != NULL)
{
free_auto_name = FALSE;
*namep = auto_name;
}
}
if (free_auto_name)
vim_free(auto_name);
}
}
}
return NULL;
return ret;
}
/*
@@ -3508,7 +3533,11 @@ lookup_scriptitem(
hi = hash_find(ht, p);
res = HASHITEM_EMPTY(hi) ? FAIL : OK;
// if not script-local, then perhaps imported
// if not script-local, then perhaps autoload-exported
if (res == FAIL && find_var_autoload_prefix(p, 0, NULL, NULL) != NULL)
res = OK;
// if not script-local or autoload, then perhaps imported
if (res == FAIL && find_imported(p, 0, FALSE) != NULL)
res = OK;
if (p != buffer)
@@ -3904,23 +3933,40 @@ set_var_const(
if (sid != 0)
{
varname = NULL;
if (SCRIPT_ID_VALID(sid))
ht = &SCRIPT_VARS(sid);
varname = name;
{
char_u *auto_name = NULL;
if (find_var_autoload_prefix(name, sid, &ht, &auto_name) != NULL)
{
var_in_autoload = TRUE;
varname = auto_name;
name_tofree = varname;
}
else
ht = &SCRIPT_VARS(sid);
}
if (varname == NULL)
varname = name;
}
else
{
scriptitem_T *si;
scriptitem_T *si;
char_u *auto_name = NULL;
if (in_vim9script() && is_export
&& SCRIPT_ID_VALID(current_sctx.sc_sid)
&& (si = SCRIPT_ITEM(current_sctx.sc_sid))
->sn_autoload_prefix != NULL)
if (in_vim9script()
&& SCRIPT_ID_VALID(current_sctx.sc_sid)
&& (si = SCRIPT_ITEM(current_sctx.sc_sid))
->sn_autoload_prefix != NULL
&& (is_export
|| find_var_autoload_prefix(name, 0, NULL, &auto_name)
!= NULL))
{
// In a vim9 autoload script an exported variable is put in the
// global namespace with the autoload prefix.
var_in_autoload = TRUE;
varname = concat_str(si->sn_autoload_prefix, name);
varname = auto_name != NULL ? auto_name
: concat_str(si->sn_autoload_prefix, name);
if (varname == NULL)
goto failed;
name_tofree = varname;