Allow require() modules into a custom environment

As a Roblox developer, it is currently impossible to require() a ModuleScript into a custom environment.
Based on this support post I made a day ago.

It would be amazing if there’s a way to, for example require(ModuleScript script, table environment) where the environment can be a sandbox made by the developer.

Why?
This would enable developers to securely allow fan made maps with ModuleScripts to be added to their game by the InsertService and also allow the developers to make their own API given that the developer has taken the model into their account inventory.

Another use of this is that if Roblox allows private modules again, advance developer who want to use private modules can sandbox them and will be able keep track of what the module calls and blacklisting functions that developers doesn’t want.

If I’ve made a mistake somewhere please inform me. I really want a way to set the environment of the ModuleScript because it will then allow me to give secure access of my game’s framework for custom maps in my game.

Thanks a lot for reading!
~Khronos

5 Likes

What if I call require on the module from two different scripts with different environment tables? Would it yield two separate instantiations of that module with different environments? This seems like it could introduce unexpected/strange behavior.

1 Like

What if that could be a feature. Considering that if developers who want to use a different environment so that they can have multiple instances of the module running are given the option to to do so.

It can be beneficial for some situation where if the module has it’s own static variable and the developer wants to have two instances of the module with their own static variable. Although, I can’t think of application reasons for it but having the option is always a good thing.

As for the issues, I believe debugging the two instances would take more time and may have some unexpected issues.

It will be somewhat non-trivial to specify that you want the same instance across different scripts.

Suppose one script:

local module = require(module, {a = 1})

And another:

local module = require(module, {a = 1})

Since {a = 1} is actually a different lua table each time (tables are not value classes), this should also return 2 different instances unless they add some kind of rule that it deep-compares the table being passed with existing instantiations.

So to get the desired behavior, assuming they don’t add any special rules, you would need to then do something like this:

Environment.lua:

return {a = 1}

And then each script would be:

local module = require(module, require(Environment))

That way the table being passed is the same because you pass it by reference in each.

Maybe you actually want the barebones situation, or maybe you want the deep-compare one. I’m guessing it would be the barebones one. All in all it seems like some arbitrary design choices have to be made to make this work. I’m not sure if I’m a fan.

3 Likes