use omnilua::{Lua, LuaError, LuaVersion, Value, Variadic};
#[test]
fn error_raised_through_scope_keeps_its_value_rooted() {
let lua = Lua::new_versioned(LuaVersion::V51);
let result: omnilua::Result<Value> = lua.scope(|scope| {
let host = scope
.create_function_mut(&lua, |_, _: Variadic<Value>| Ok::<Value, _>(Value::Nil))?;
lua.globals().set("host", &host)?;
lua.load("error('boom')").set_name("user_script").eval::<Value>()
});
let err = result.expect_err("error('boom') must surface as Err, not Ok");
lua.load("collectgarbage('collect')")
.exec()
.expect("collectgarbage");
let msg = err.message_lossy();
assert!(
msg.contains("boom"),
"error message lost its value (swept?): {msg:?}"
);
}
#[test]
fn table_error_raised_through_scope_survives_collection_as_a_table() {
let lua = Lua::new_versioned(LuaVersion::V54);
let result: omnilua::Result<Value> = lua.scope(|scope| {
let host = scope
.create_function_mut(&lua, |_, _: Variadic<Value>| Ok::<Value, _>(Value::Nil))?;
lua.globals().set("host", &host)?;
lua.load("error({code = 403})")
.set_name("user_script")
.eval::<Value>()
});
let err = result.expect_err("error({code=403}) must surface as Err");
lua.load("collectgarbage('collect')")
.exec()
.expect("collectgarbage");
match err.as_lua_error() {
LuaError::Runtime(value) => assert!(
value.is_collectable() && value.type_name() == "table",
"error payload was not preserved as a table: {}",
value.type_name()
),
other => panic!("expected Runtime(table) payload, got {other:?}"),
}
let (kind, code): (String, i64) = lua
.load(
"local ok, e = pcall(function() error({code = 403}) end)\n\
assert(not ok)\n\
return type(e), e.code",
)
.eval()
.expect("pcall of a table error must return the table");
assert_eq!(kind, "table");
assert_eq!(code, 403);
}