Skip to content

Commit a8a4aa8

Browse files
committed
Switch to "proxyrequire" function (follow up Luau 0.671)
1 parent 9fda2ec commit a8a4aa8

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed

src/luau/mod.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::ffi::CStr;
2+
use std::mem;
23
use std::os::raw::c_int;
34

45
use crate::error::Result;
@@ -12,18 +13,27 @@ pub use require::{NavigateError, Require};
1213
impl Lua {
1314
/// Create a custom Luau `require` function using provided [`Require`] implementation to find
1415
/// and load modules.
15-
///
16-
/// The provided object is stored in the Lua registry and will not be garbage collected
17-
/// until the Lua state is closed.
1816
#[cfg(any(feature = "luau", doc))]
1917
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
2018
pub fn create_require_function<R: Require + 'static>(&self, require: R) -> Result<Function> {
19+
unsafe extern "C-unwind" fn mlua_require(state: *mut ffi::lua_State) -> c_int {
20+
let mut ar: ffi::lua_Debug = mem::zeroed();
21+
if ffi::lua_getinfo(state, 1, cstr!("s"), &mut ar) == 0 {
22+
ffi::luaL_error(state, cstr!("require is not supported in this context"));
23+
}
24+
let top = ffi::lua_gettop(state);
25+
ffi::lua_pushvalue(state, ffi::lua_upvalueindex(2)); // the "proxy" require function
26+
ffi::lua_pushvalue(state, 1); // require path
27+
ffi::lua_pushstring(state, ar.source); // current file
28+
ffi::lua_call(state, 2, ffi::LUA_MULTRET);
29+
ffi::lua_gettop(state) - top
30+
}
31+
2132
unsafe {
2233
self.exec_raw((), move |state| {
2334
let requirer_ptr = ffi::lua_newuserdata_t::<Box<dyn Require>>(state, Box::new(require));
24-
// Keep the require object in the registry to prevent it from being garbage collected
25-
ffi::lua_rawsetp(state, ffi::LUA_REGISTRYINDEX, requirer_ptr as *const _);
26-
ffi::lua_pushrequire(state, require::init_config, requirer_ptr as *mut _);
35+
ffi::luarequire_pushproxyrequire(state, require::init_config, requirer_ptr as *mut _);
36+
ffi::lua_pushcclosured(state, mlua_require, cstr!("require"), 2);
2737
})
2838
}
2939
}

src/luau/require.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ pub trait Require: MaybeSend {
8686
fn config(&self) -> IoResult<Vec<u8>>;
8787

8888
/// Loads the module and returns the result (function or table).
89-
fn load(&self, lua: &Lua, chunk_name: &str, content: &[u8]) -> Result<Value> {
89+
fn load(&self, lua: &Lua, path: &str, chunk_name: &str, content: &[u8]) -> Result<Value> {
90+
let _ = path;
9091
lua.load(content).set_name(chunk_name).call(())
9192
}
9293
}
@@ -413,15 +414,17 @@ pub(super) unsafe extern "C" fn init_config(config: *mut ffi::luarequire_Configu
413414
unsafe extern "C-unwind" fn load(
414415
state: *mut ffi::lua_State,
415416
ctx: *mut c_void,
417+
path: *const c_char,
416418
chunk_name: *const c_char,
417419
contents: *const c_char,
418420
) -> c_int {
419421
let this = &*(ctx as *const Box<dyn Require>);
422+
let path = CStr::from_ptr(path).to_string_lossy();
420423
let chunk_name = CStr::from_ptr(chunk_name).to_string_lossy();
421424
let contents = CStr::from_ptr(contents).to_bytes();
422425
let lua = Lua::get_or_init_from_ptr(state);
423426
callback_error_ext(state, ptr::null_mut(), false, move |_extra, _| {
424-
match this.load(lua, &chunk_name, contents)? {
427+
match this.load(lua, &path, &chunk_name, contents)? {
425428
Value::Nil => lua.lock().push(true)?,
426429
value => lua.lock().push(value)?,
427430
};

0 commit comments

Comments
 (0)