setting the _ENV for require

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

setting the _ENV for require

Matthias Kluwe
Hi!

It's easy to "sandbox" a chunk with an environment. Let's say I have a
file

    -- mod.lua -----------
    return function()
        return a
    end
    ----------------------

Then loading it with a given environment makes it independent of
`_ENV`:

    local g = loadfile( 'mod.lua', 't', {
        a = 42
    } )()
    print( g() ) --> prints 42
    _ENV.a = 23
    print( g() ) --> prints 42

That's not the case when using `require`:

    local f = require 'mod'
    print( f() ) --> prints 23
    _ENV.a = 42
    print( f() ) --> prints 42

Is there some clever trick to achieve the same effect (meaning to make
the required module independent of `_ENV')?

Regards,
Matthias

Reply | Threaded
Open this post in threaded view
|

Re: setting the _ENV for require

Sean Conner
It was thus said that the Great Matthias Kluwe once stated:

> Hi!
>
> It's easy to "sandbox" a chunk with an environment. Let's say I have a
> file
>
>     -- mod.lua -----------
>     return function()
>         return a
>     end
>     ----------------------
>
> Then loading it with a given environment makes it independent of
> `_ENV`:
>
>     local g = loadfile( 'mod.lua', 't', {
>         a = 42
>     } )()
>     print( g() ) --> prints 42
>     _ENV.a = 23
>     print( g() ) --> prints 42
>
> That's not the case when using `require`:
>
>     local f = require 'mod'
>     print( f() ) --> prints 23
>     _ENV.a = 42
>     print( f() ) --> prints 42
>
> Is there some clever trick to achieve the same effect (meaning to make
> the required module independent of `_ENV')?

  What I do for my modules is:

        if _VERSION == "Lua 5.1" then
          module("org.conman.date")
        else
          _ENV = {} -- luacheck: ignore
        end
       
        -- body of module
       
        if _VERSION >= "Lua 5.2" then
          return _ENV -- luacheck: ignore
        end

  I did it this way to avoid having to rewrite a lot of modules.

  -spc