Skip to main content

luaur_vm/functions/
lua_b_xpcallcont.rs

1use crate::enums::lua_status::lua_Status;
2use crate::functions::lua_d_pcall::luaD_pcall;
3use crate::functions::lua_d_seterrorobj::luaD_seterrorobj;
4use crate::functions::lua_gettop::lua_gettop;
5use crate::functions::lua_pushboolean::lua_pushboolean;
6use crate::functions::lua_pushvalue::lua_pushvalue;
7use crate::functions::lua_rawcheckstack::lua_rawcheckstack;
8use crate::functions::lua_replace::lua_replace;
9use crate::macros::restorestack::restorestack;
10use crate::macros::savestack::savestack;
11use crate::type_aliases::lua_state::lua_State;
12use crate::type_aliases::stk_id::StkId;
13
14#[allow(non_snake_case)]
15pub unsafe fn lua_b_xpcallcont(L: *mut lua_State, status: i32) -> i32 {
16    if status == 0 {
17        lua_rawcheckstack(L, 1);
18        lua_pushboolean(L, 1);
19        lua_replace(L, 1);
20        lua_gettop(L)
21    } else {
22        lua_rawcheckstack(L, 3);
23        lua_pushboolean(L, 0);
24        lua_pushvalue(L, 1);
25        lua_pushvalue(L, -3);
26
27        let errf: StkId = (*L).top.offset(-2);
28        let oldtopoffset = savestack!(L, errf);
29
30        // C: `luaD_pcall(L, luaB_xpcallerr, errf, oldtopoffset, 0)` — run the error
31        // HANDLER (errf) over the error object. Passing None never invoked it, so the
32        // handler result was lost and the raw error + handler fn leaked out, breaking
33        // xpcall's error path whenever it ran via this continuation (i.e. in any coroutine).
34        let err = luaD_pcall(
35            L,
36            Some(crate::functions::lua_b_xpcallerr::luaB_xpcallerr),
37            errf as *mut core::ffi::c_void,
38            oldtopoffset as isize,
39            0,
40        );
41
42        if err != 0 {
43            let mut errstatus = status;
44
45            if status == lua_Status::LUA_ERRMEM as i32 && err == lua_Status::LUA_ERRMEM as i32 {
46                errstatus = lua_Status::LUA_ERRMEM as i32;
47            } else {
48                errstatus = lua_Status::LUA_ERRERR as i32;
49            }
50
51            let oldtop = restorestack!(L, oldtopoffset);
52            luaD_seterrorobj(L, errstatus, oldtop);
53        }
54
55        2
56    }
57}