From 76a8f8cc71082c6195f7cfaf15d16612cf123b3d Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Tue, 27 May 2025 01:31:54 +0100 Subject: [PATCH] Add `__type` to Error's userdata metatable. Close #585 --- src/util/error.rs | 6 +++++- src/util/userdata.rs | 10 +++++----- tests/luau.rs | 11 +++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/util/error.rs b/src/util/error.rs index 899522d..8629f11 100644 --- a/src/util/error.rs +++ b/src/util/error.rs @@ -349,7 +349,11 @@ pub(crate) unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<( state, Some(|state| { ffi::lua_pushcfunction(state, error_tostring); - rawset_field(state, -2, "__tostring") + ffi::lua_setfield(state, -2, cstr!("__tostring")); + + // This is mostly for Luau typeof() function + ffi::lua_pushstring(state, cstr!("error")); + ffi::lua_setfield(state, -2, cstr!("__type")); }), )?; diff --git a/src/util/userdata.rs b/src/util/userdata.rs index 2edbf0b..5e8d611 100644 --- a/src/util/userdata.rs +++ b/src/util/userdata.rs @@ -47,7 +47,7 @@ pub(crate) unsafe fn get_internal_metatable(state: *mut ffi::lua_Sta // Uses 6 stack spaces and calls checkstack. pub(crate) unsafe fn init_internal_metatable( state: *mut ffi::lua_State, - customize_fn: Option Result<()>>, + customize_fn: Option, ) -> Result<()> { check_stack(state, 6)?; @@ -62,11 +62,11 @@ pub(crate) unsafe fn init_internal_metatable( ffi::lua_pushboolean(state, 0); rawset_field(state, -2, "__metatable")?; - if let Some(f) = customize_fn { - f(state)?; - } - protect_lua!(state, 1, 0, |state| { + if let Some(f) = customize_fn { + f(state); + } + ffi::lua_rawsetp(state, ffi::LUA_REGISTRYINDEX, T::type_key()); })?; diff --git a/tests/luau.rs b/tests/luau.rs index 1b2cfc1..20fbee6 100644 --- a/tests/luau.rs +++ b/tests/luau.rs @@ -436,5 +436,16 @@ fn test_loadstring() -> Result<()> { Ok(()) } +#[test] +fn test_typeof_error() -> Result<()> { + let lua = Lua::new(); + + let err = Error::runtime("just a test error"); + let res = lua.load("return typeof(...)").call::(err)?; + assert_eq!(res, "error"); + + Ok(()) +} + #[path = "luau/require.rs"] mod require;