Hello!
On Mon, Nov 12, 2012 at 8:57 AM, James Hurst wrote:
> Great stuff! Good to see the "abort" related features.
>
Glad you like it :)
>> refactor: avoided using "package.seeall" in Lua module
>>
>> definitions, which improves performance and also prevents
>> subtle bad side-effects.
>
> Could you elaborate on this at all? Just curious about the rationale,
>
The "package.seeall" flag makes the global environment of the first
request that does require() attach to the Lua module's environment via
the __index metamethod, which could result in the following bad
things:
1. This request's global environment table is thus leaked by this way.
2. Because OO-style Lua modules usually make the module table attach
to every object instance via __index, thus everything in the first
request's environment table is also visible to every object instance.
3. The require() built-in has the side-effect of setting an entry in
the current global environment (for example, require "foo" will set
the global variable "foo" at the same time), which adds pollution to
the module's environment and also every Lua OO instance's field space
(if any).
4. Removing "package.seeall" also encourages local-izing the Lua
builtins (like pairs, unpack, and etc) used in the Lua module scope,
making LuaJIT and Lua 5.1 generate more optimal code.
> and
> whether other user-land modules should follow the convention?
Well, this is not mandatory; but I strongly recommend it.
Also, I *strongly* recommend adding the following code snippet to the
end of every Lua module:
local class_mt = {
-- to prevent use of casual module global variables
__newindex = function (table, key, val)
error('attempt to write to undeclared variable "' .. key .. '"')
end
}
setmetatable(_M, class_mt)
This metamethod can prevent casual data sharing via (undeclared)
module-level variables among requests (which can be a disaster,
because concurrent requests can *see* each other's data by accident
under load).
Best regards,
-agentzh