lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


For one of my projects I need to reliably change the environment of a function*
While doing some experimenting to see how this could best be done in a way
that works in both LuaJIT and 5.3, I came across the following behavior:

Lua 5.3.4  Copyright (C) 1994-2017 Lua.org, PUC-Rio
> do
>> local l = 20
>> function test()
>> return l, _ENV
>> end
>> end
> test()
20      table: 007e18b0
> load(string.dump(test), '', 'b', _ENV)()
table: 007e18b0 nil

As you can see, if a normal upvalue is used before any "global" variable, _ENV
is not the first upvalue. While the reference manual doesn't really state that
_ENV has to be the first upvalue, the load function does seem to assume this
and while digging through the archive, there was another thread where everyone
seemed to be taking it for granted that _ENV is always the first upvalue.

Is this supposed to behave like this, or is it a bug? It seems that this
behavior completely defeats the purpose of the load function, as a it completely
breaks for functions like the following:

local original = true
function broken()
if original then
 print "I am the original"
else
 print "I was dumped and re-loaded"
end
end

The intended behavior shouldn't need explanation, but in reality, when dumping
and re-loading this function, it would throw an "attempt to index nil" error.

As for my tests: I have tried this on Lua 5.3.4 on windows, compiled with mingw.
I have also tried it on the online demo at https://www.lua.org/cgi-bin/demo and
the result was the same.

* background: I am trying to achieve an HTML generation syntax similar to that
used in the Lapis framework. This means that I need to pass a new environment
to a function that is provided by the user and, while I can assume that the
function makes use of _ENV, I cannot know if it uses some upvalue first.