Hello !
While trying to change Lua-5.4.4 to LJS
(https://github.com/mingodad/ljs) I found an intriguing change in
behavior/bug between Lua-5.3.6 and Lua-5.4.4, in LJS I decided to
forbid shadowing variables in the same scope and it works as intended
in LJS from LjsJit, Lua-(5.1.5 .. 5.3.6) but applying a similar check
to Lua-5.4.4 find a duplicated variable name where it shouldn't (see
code shown bellow).
Somehow this line 'local res = loadstring("a=1")' brings the 'a'
variable name to visibility for the parser in Lua-5.4.4 but not for
previous Lua versions.
It seems like the parser is parsing the string passed to 'load' when
parsing the script instead of at runtime, or something else that I'm
not seeing through the code.
Can someone shed some light on this issue ?
====
if loadstring == null then
loadstring = load;
end
function bug()
do
local a = 2;
end
print(a);
local res = loadstring("a=1"); --somehow this brings 'a' visible
internally
--res();
print(a);
--Lua-5.4.4 find the next 'a' declaration as duplicated
--local a = 3; -- but if we comment this line 'a' is printed as
'nil' bellow
print(res, a);
end
print(a);
bug();
print(a);
====
====
/*
** Create a new local variable with the given 'name'. Return its index
** in the function.
*/
static int new_localvar (LexState *ls, TString *name) {
lua_State *L = ls->L;
FuncState *fs = ls->fs;
Dyndata *dyd = ls->dyd;
Vardesc *var;
/* START Check for duplicated varibale names in local scope */
int vidx, nactvar_n;
vidx = fs->bl ? fs->bl->nactvar + fs->firstlocal : fs->firstlocal;
//nactvar_n = dyd->actvar.n;
nactvar_n = fs->nactvar;
if(nactvar_n > fs->ndebugvars) nactvar_n = fs->ndebugvars;
for (; vidx < nactvar_n; ++vidx) {
Vardesc *vd = dyd->actvar.arr+vidx;
LocVar *lv = &fs->f->locvars[vd->vd.ridx];
if (lv && name == lv->varname) {
/* allow '_' duplicates */
const char *sname = getstr(name);
if(tsslen(name) == 1 && sname[0] == '_') break;
luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
"Name [%s] already declared", sname));
}
}
/* END Check for duplicated varibale names in local scope */
checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
MAXVARS, "local variables");
luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
dyd->actvar.size, Vardesc, USHRT_MAX, "local
variables");
var = &dyd->actvar.arr[dyd->actvar.n++];
var->vd.kind = VDKREG; /* default */
var->vd.name = name;
return dyd->actvar.n - 1 - fs->firstlocal;
}
====
Cheers !