Skip to content

Commit c90cac5

Browse files
committed
Add Lua::set_globals method to replace global environment.
Closes #611
1 parent c0d839d commit c90cac5

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

src/state.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,39 @@ impl Lua {
15501550
}
15511551
}
15521552

1553+
/// Sets the global environment.
1554+
///
1555+
/// This will replace the current global environment with the provided `globals` table.
1556+
///
1557+
/// For Lua 5.2+ the globals table is stored in the registry and shared between all threads.
1558+
/// For Lua 5.1 and Luau the globals table is stored in each thread.
1559+
///
1560+
/// Please note that any existing Lua functions have cached global environment and will not
1561+
/// see the changes made by this method.
1562+
/// To update the environment for existing Lua functions, use [`Function::set_environment`].
1563+
pub fn set_globals(&self, globals: Table) -> Result<()> {
1564+
let lua = self.lock();
1565+
let state = lua.state();
1566+
unsafe {
1567+
#[cfg(feature = "luau")]
1568+
if (*lua.extra.get()).sandboxed {
1569+
return Err(Error::runtime("cannot change globals in a sandboxed Lua state"));
1570+
}
1571+
1572+
let _sg = StackGuard::new(state);
1573+
check_stack(state, 1)?;
1574+
1575+
lua.push_ref(&globals.0);
1576+
1577+
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
1578+
ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1579+
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1580+
ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
1581+
}
1582+
1583+
Ok(())
1584+
}
1585+
15531586
/// Returns a handle to the active `Thread`.
15541587
///
15551588
/// For calls to `Lua` this will be the main Lua thread, for parameters given to a callback,

tests/tests.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,31 @@ fn test_eval() -> Result<()> {
147147
Ok(())
148148
}
149149

150+
#[test]
151+
fn test_replace_globals() -> Result<()> {
152+
let lua = Lua::new();
153+
154+
let globals = lua.create_table()?;
155+
globals.set("foo", "bar")?;
156+
157+
lua.set_globals(globals.clone())?;
158+
let val = lua.load("return foo").eval::<StdString>()?;
159+
assert_eq!(val, "bar");
160+
161+
// Updating globals in sandboxed Lua state is not allowed
162+
#[cfg(feature = "luau")]
163+
{
164+
lua.sandbox(true)?;
165+
match lua.set_globals(globals) {
166+
Err(Error::RuntimeError(msg))
167+
if msg.contains("cannot change globals in a sandboxed Lua state") => {}
168+
r => panic!("expected RuntimeError(...) with a specific error message, got {r:?}"),
169+
}
170+
}
171+
172+
Ok(())
173+
}
174+
150175
#[test]
151176
fn test_load_mode() -> Result<()> {
152177
let lua = unsafe { Lua::unsafe_new() };

0 commit comments

Comments
 (0)