mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
Add environment option to luau load built-in
This commit is contained in:
parent
bb23d0a9cd
commit
f620f453f2
5 changed files with 86 additions and 8 deletions
|
@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
print(now:toUniversalTime())
|
print(now:toUniversalTime())
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Added support for setting a custom environment in load options for `luau.load`, not subject to `getfenv` / `setfenv` deoptimizations
|
||||||
- Added [Terrain:GetMaterialColor](https://create.roblox.com/docs/reference/engine/classes/Terrain#GetMaterialColor) and [Terrain:SetMaterialColor](https://create.roblox.com/docs/reference/engine/classes/Terrain#SetMaterialColor) ([#93])
|
- Added [Terrain:GetMaterialColor](https://create.roblox.com/docs/reference/engine/classes/Terrain#GetMaterialColor) and [Terrain:SetMaterialColor](https://create.roblox.com/docs/reference/engine/classes/Terrain#SetMaterialColor) ([#93])
|
||||||
- Added support for a variable number of arguments for CFrame methods ([#85])
|
- Added support for a variable number of arguments for CFrame methods ([#85])
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,27 @@ fn load_source<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
(source, options): (LuaString<'lua>, LuauLoadOptions),
|
(source, options): (LuaString<'lua>, LuauLoadOptions),
|
||||||
) -> LuaResult<LuaFunction<'lua>> {
|
) -> LuaResult<LuaFunction<'lua>> {
|
||||||
lua.load(source.as_bytes())
|
let mut chunk = lua.load(source.as_bytes()).set_name(options.debug_name);
|
||||||
.set_name(options.debug_name)
|
|
||||||
.into_function()
|
if let Some(environment) = options.environment {
|
||||||
|
let environment_with_globals = lua.create_table()?;
|
||||||
|
|
||||||
|
if let Some(meta) = environment.get_metatable() {
|
||||||
|
environment_with_globals.set_metatable(Some(meta));
|
||||||
|
}
|
||||||
|
|
||||||
|
for pair in lua.globals().pairs() {
|
||||||
|
let (key, value): (LuaValue, LuaValue) = pair?;
|
||||||
|
environment_with_globals.set(key, value)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for pair in environment.pairs() {
|
||||||
|
let (key, value): (LuaValue, LuaValue) = pair?;
|
||||||
|
environment_with_globals.set(key, value)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = chunk.set_environment(environment_with_globals);
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk.into_function()
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,19 +73,21 @@ impl<'lua> FromLua<'lua> for LuauCompileOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LuauLoadOptions {
|
pub struct LuauLoadOptions<'lua> {
|
||||||
pub(crate) debug_name: String,
|
pub(crate) debug_name: String,
|
||||||
|
pub(crate) environment: Option<LuaTable<'lua>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LuauLoadOptions {
|
impl Default for LuauLoadOptions<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
debug_name: DEFAULT_DEBUG_NAME.to_string(),
|
debug_name: DEFAULT_DEBUG_NAME.to_string(),
|
||||||
|
environment: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> FromLua<'lua> for LuauLoadOptions {
|
impl<'lua> FromLua<'lua> for LuauLoadOptions<'lua> {
|
||||||
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
|
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
|
||||||
Ok(match value {
|
Ok(match value {
|
||||||
LuaValue::Nil => Self::default(),
|
LuaValue::Nil => Self::default(),
|
||||||
|
@ -96,10 +98,15 @@ impl<'lua> FromLua<'lua> for LuauLoadOptions {
|
||||||
options.debug_name = debug_name;
|
options.debug_name = debug_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(environment) = t.get("environment")? {
|
||||||
|
options.environment = Some(environment);
|
||||||
|
}
|
||||||
|
|
||||||
options
|
options
|
||||||
}
|
}
|
||||||
LuaValue::String(s) => Self {
|
LuaValue::String(s) => Self {
|
||||||
debug_name: s.to_string_lossy().to_string(),
|
debug_name: s.to_string_lossy().to_string(),
|
||||||
|
environment: None,
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(LuaError::FromLuaConversionError {
|
return Err(LuaError::FromLuaConversionError {
|
||||||
|
|
|
@ -31,3 +31,51 @@ local success = pcall(function()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
assert(success, "expected `luau.load` to be able to process the result of `luau.compile`")
|
assert(success, "expected `luau.load` to be able to process the result of `luau.compile`")
|
||||||
|
|
||||||
|
local CUSTOM_SOURCE_WITH_FOO_FN = "return foo()"
|
||||||
|
|
||||||
|
-- NOTE: We use newproxy here to make a userdata to ensure
|
||||||
|
-- we get the *exact* same value sent back, not some copy
|
||||||
|
local fooValue = newproxy(false)
|
||||||
|
local fooFn = luau.load(CUSTOM_SOURCE_WITH_FOO_FN, {
|
||||||
|
environment = {
|
||||||
|
foo = function()
|
||||||
|
return fooValue
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local fooFnRet = fooFn()
|
||||||
|
assert(fooFnRet == fooValue, "expected `luau.load` with custom environment to return proper values")
|
||||||
|
|
||||||
|
local CUSTOM_SOURCE_WITH_PRINT_FN = "return print()"
|
||||||
|
|
||||||
|
-- NOTE: Same as what we did above, new userdata to guarantee unique-ness
|
||||||
|
local overriddenValue = newproxy(false)
|
||||||
|
local overriddenFn = luau.load(CUSTOM_SOURCE_WITH_PRINT_FN, {
|
||||||
|
environment = {
|
||||||
|
print = function()
|
||||||
|
return overriddenValue
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local overriddenFnRet = overriddenFn()
|
||||||
|
assert(
|
||||||
|
overriddenFnRet == overriddenValue,
|
||||||
|
"expected `luau.load` with overridden environment to return proper values"
|
||||||
|
)
|
||||||
|
|
||||||
|
local CUSTOM_SOURCE_WITH_DEFAULT_FN = "return string.lower(...)"
|
||||||
|
|
||||||
|
local overriddenFn2 = luau.load(CUSTOM_SOURCE_WITH_DEFAULT_FN, {
|
||||||
|
environment = {
|
||||||
|
hello = "world",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local overriddenFn2Ret = overriddenFn2("LOWERCASE")
|
||||||
|
assert(
|
||||||
|
overriddenFn2Ret == "lowercase",
|
||||||
|
"expected `luau.load` with overridden environment to contain default globals"
|
||||||
|
)
|
||||||
|
|
|
@ -27,10 +27,12 @@ export type CompileOptions = {
|
||||||
|
|
||||||
This is a dictionary that may contain one or more of the following values:
|
This is a dictionary that may contain one or more of the following values:
|
||||||
|
|
||||||
* `debugName` - The debug name of the closure. Defaults to `string ["..."]`
|
* `debugName` - The debug name of the closure. Defaults to `luau.load(...)`
|
||||||
|
* `environment` - Environment values to set and/or override. Includes default globals unless overwritten.
|
||||||
]=]
|
]=]
|
||||||
export type LoadOptions = {
|
export type LoadOptions = {
|
||||||
debugName: string,
|
debugName: string?,
|
||||||
|
environment: { [string]: any }?,
|
||||||
}
|
}
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
|
Loading…
Reference in a new issue