lua-users home
lua-l archive

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

On Thu, 4 Mar 2010 23:05:01 -0500, David Manura <> wrote:
> On Thu, Feb 25, 2010 at 1:40 PM, Jonathan Castello wrote:
>> On a related note, could loadstring/loadfile be modified slightly to
>> load into the currently active environment,
> Some of us have not liked the behavior of `load` and its variants
> applying the global environment `_G` when the current environment is
> not `_G`

I favor the following approach (and have implemented it in a small project called Darwin [1]):

1. Generalize the notion of '_G' from meaning a single global environment to meaning 'the current global environment'.  It may sound like a tortured use of the word 'global', but it is precise in the sense that all objects in a given _G believe that _G is the one and only global environment.

2. The various 'load' functions evaluate code in the current _G.

3. Every module has its own _G.  To use a module, you 'open' it.  Opening a module copies the module bindings into the environment from which the module is opened.  Every consumer of a module has its own copy of the module bindings, so modules A and B can both use C, and yet A and B cannot interfere with each other or even know of each other [2].

This approach can be used to implement a secure Lua run-time in which module code can be properly isolated.  You have to drop some Lua functions like getfenv and setfenv to do this, or re-implement them so that they do not work on imported bindings.  Look at Jonathan Rees' dissertation for a treatise on the subject of securing a run-time environment [3].

The immediate benefit of such 'security' is actually reliability.  When modules cannot interfere with each other or with user code, certain classes of bugs are simply eliminated. 

Finally, note that this module paradigm (as suggested by Rees and implemented in Scheme48) can nicely co-exist with the current Lua module system.  Darwin, in which I took a Lua-ish approach to the idea, demonstrates this:  Modules written with the Lua 5.1.4 module system can be used without change.  Further, a simple module declaration allows you to take a Lua module and load it as a Darwin module (i.e. isolated into its own environment with no ability to reference other code or objects).  To this end, Darwin adds a package searcher that looks for a Darwin module first.

If the Lua implementation supported items 1-3 above, it would enable a lot of desirable behavior around modules and code loading.


[1] See  The implementation is pure Lua (for 5.1.4) and it works.  I use it every day.  However, I had to rewrite in Lua most of loadlib.  With some small implementation changes to Lua, I could avoid this and use the real loadlib, eliminating 250 lines of Lua code, which is about 25% of my implementation.

[2] Of course, if module C has state, then A and B share it.  A proper module should not maintain global state, however.  A factory pattern should be followed so that the module user can obtain her own private instance of any state needed by the module.  This state is returned by a module function call and is passed back into subsequent calls.