Add unload() to remove module

This commit is contained in:
Alexander Polakov 2021-11-23 18:20:54 +03:00
parent 170818c469
commit d49757c7db
2 changed files with 51 additions and 0 deletions

View file

@ -650,6 +650,26 @@ impl Lua {
T::from_lua(value, self)
}
/// Unloads module `modname`
/// Internally removes `modname` from package.loaded table.
pub fn unload<'lua, S>(&'lua self, modname: &S) -> Result<()>
where
S: AsRef<[u8]> + ?Sized,
{
let loaded = unsafe {
let _sg = StackGuard::new(self.state);
check_stack(self.state, 2)?;
protect_lua!(self.state, 0, 1, fn(state) {
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
})?;
Table(self.pop_ref())
};
let modname = self.create_string(modname)?;
loaded.raw_remove(modname)?;
Ok(())
}
/// Consumes and leaks `Lua` object, returning a static reference `&'static Lua`.
///
/// This function is useful when the `Lua` object is supposed to live for the remainder

View file

@ -1151,6 +1151,37 @@ fn test_load_from_function() -> Result<()> {
Ok(())
}
#[test]
fn test_unload() -> Result<()> {
let lua = Lua::new();
let i = Arc::new(AtomicU32::new(0));
let i2 = i.clone();
let func = lua.create_function(move |lua, modname: String| {
i2.fetch_add(1, Ordering::Relaxed);
let t = lua.create_table()?;
t.set("__name", modname)?;
Ok(t)
})?;
let t: Table = lua.load_from_function("my_module", func.clone())?;
assert_eq!(t.get::<_, String>("__name")?, "my_module");
assert_eq!(i.load(Ordering::Relaxed), 1);
let _: Value = lua.load_from_function("my_module", func.clone())?;
assert_eq!(i.load(Ordering::Relaxed), 1);
let _: () = lua.unload("my_module")?;
assert_eq!(i.load(Ordering::Relaxed), 1);
let _: Value = lua.load_from_function("my_module", func)?;
assert_eq!(i.load(Ordering::Relaxed), 2);
let _: () = lua.unload("my_module42")?;
Ok(())
}
#[test]
fn test_inspect_stack() -> Result<()> {
let lua = Lua::new();