Introduction
In Lune, we currently have no way to dynamically run source/bytecode whatsoever; loadstring()
is omitted from the environment afaik.
In standalone Luau, due to multiple sandboxing reasons, loadstring()
can only run direct source code. (as opposed to loading raw bytecode in vanilla Lua) The function also deoptimizes the environment of the loaded closure, as it's directly returned and can be modifed/manipulated in any way:
local Closure = loadstring("print('hello world')")
-- Modifying the global env etc
setfenv(Closure, {})
Closure() -- Will err as "print" now doesn't exist in the env!
Proposition
This default behavior isn't even intended for most using loadstring()
, and disables safeenv
internally in the VM.
I propose some sort of built-in library for Lune like "luau
", which could provide some fairly basic functions and utils for compiling/loading source code or bytecode as-is, as we don't really need to sandbox for this seperate behavior.
(Potential) API
Also, these should probably all error for basic logical reasons, like incorrect type input etc. They shouldn't error by themselves though, as these functions would be how a script generally knows if compilation is successful.
-
Compile Luau Source Code to Bytecode
function luau.compile(
source: string,
options: {
optimizationLevel: number = 1?,
debugLevel: number = 1?,
}?
): (
bytecode: string | nil,
compileError: string | nil
)
It would take in input source code, as well as an optional options
table for certain basic Luau::Compile
compilation options. If successful, it'd return the binary bytecode file/chunk as a string, and no compiler error ofcourse. (string, nil
) Otherwise, it'd just return nil, string
; string
being the Luau compiler error.
Example Usage:
local Bytecode, Error = luau.compile("do end", {
optimizationLevel = 2,
debugLevel = 0,
})
if not Bytecode and Error then
print("Compiler Error: " .. Error)
stdio.exit(1)
end
...
-
Load & Run Source/Bytecode
function luau.load(
source: string,
options: {
debugString: string | nil = nil?,
safeLoad: boolean = false?,
}?
): (
closure: (...any) -> (...any) | nil,
compileError: string | nil
)
This would be almost identical to loadstring()
's API, but also accepting bytecode for source
, just like vanilla Lua. (Luau doesn't have this behavior at all, it wouldn't be default expected behavior)
It would just return the closure as-is, like normal loadstring would. By default, this would mean safeenv
would naturally be disabled in the VM internally for this closure env. However, if options.safeLoad
is set to true
, the closure
return will just proxy back the return of a call, similarly to how require()
would, and not allow the raw closure environment to be modified from outside of itself. This would solve any safeenv VM optimization issues.
-
Set safeenv
for VM on Current Environment
function luau.setSafeEnv(newValue: boolean)
(Suggested from @TheGreatSageEqualToHeaven) Sets L->safeenv
directly on the current L
state.
Conclusion
There should probably be much more added to interact with low level Luau APIs, but these are just basic suggestions for such a library. If you have any disagreements or issues with these ideas, please lmk!