Skip to content

Commit 21fc924

Browse files
committed
Add Lua::create_require_function method
1 parent 30d5e08 commit 21fc924

File tree

3 files changed

+27
-42
lines changed

3 files changed

+27
-42
lines changed

src/luau/mod.rs

+24-8
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,33 @@ use std::ffi::CStr;
22
use std::os::raw::c_int;
33

44
use crate::error::Result;
5-
use crate::state::{ExtraData, Lua, LuaOptions};
5+
use crate::function::Function;
6+
use crate::state::Lua;
67

78
pub use require::{NavigateError, Require};
89

910
// Since Luau has some missing standard functions, we re-implement them here
1011

1112
impl Lua {
12-
pub(crate) unsafe fn configure_luau(&self, mut options: LuaOptions) -> Result<()> {
13+
/// Create a custom Luau `require` function using provided [`Require`] implementation to find
14+
/// 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.
18+
#[cfg(any(feature = "luau", doc))]
19+
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
20+
pub fn create_require_function<R: Require + 'static>(&self, require: R) -> Result<Function> {
21+
unsafe {
22+
self.exec_raw((), move |state| {
23+
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 _);
27+
})
28+
}
29+
}
30+
31+
pub(crate) unsafe fn configure_luau(&self) -> Result<()> {
1332
let globals = self.globals();
1433

1534
globals.raw_set("collectgarbage", self.create_c_function(lua_collectgarbage)?)?;
@@ -20,12 +39,9 @@ impl Lua {
2039
globals.raw_set("_VERSION", format!("Luau {version}"))?;
2140
}
2241

23-
// Enable `require` function
24-
let requirer = (options.requirer.take()).unwrap_or_else(|| Box::new(require::TextRequirer::new()));
25-
self.exec_raw::<()>((), |state| {
26-
let requirer_ptr = (*ExtraData::get(state)).set_requirer(requirer);
27-
ffi::luaopen_require(state, require::init_config, requirer_ptr as *mut _);
28-
})?;
42+
// Enable default `require` implementation
43+
let require = self.create_require_function(require::TextRequirer::new())?;
44+
self.globals().raw_set("require", require)?;
2945

3046
Ok(())
3147
}

src/state.rs

+2-20
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ pub enum GCMode {
8282
}
8383

8484
/// Controls Lua interpreter behavior such as Rust panics handling.
85-
#[derive(Debug)]
85+
#[derive(Clone, Debug)]
8686
#[non_exhaustive]
8787
pub struct LuaOptions {
8888
/// Catch Rust panics when using [`pcall`]/[`xpcall`].
@@ -107,11 +107,6 @@ pub struct LuaOptions {
107107
#[cfg(feature = "async")]
108108
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
109109
pub thread_pool_size: usize,
110-
111-
/// A custom [`crate::Require`] trait object to load Luau modules.
112-
#[cfg(feature = "luau")]
113-
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
114-
pub requirer: Option<Box<dyn crate::Require>>,
115110
}
116111

117112
impl Default for LuaOptions {
@@ -127,8 +122,6 @@ impl LuaOptions {
127122
catch_rust_panics: true,
128123
#[cfg(feature = "async")]
129124
thread_pool_size: 0,
130-
#[cfg(feature = "luau")]
131-
requirer: None,
132125
}
133126
}
134127

@@ -151,17 +144,6 @@ impl LuaOptions {
151144
self.thread_pool_size = size;
152145
self
153146
}
154-
155-
/// Sets a custom [`crate::Require`] trait object to load Luau modules.
156-
///
157-
/// By default, the standard Luau `ReplRequirer` implementation is used.
158-
#[cfg(feature = "luau")]
159-
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
160-
#[must_use]
161-
pub fn with_requirer<R: crate::Require + 'static>(mut self, requirer: R) -> Self {
162-
self.requirer = Some(Box::new(requirer));
163-
self
164-
}
165147
}
166148

167149
impl Drop for Lua {
@@ -288,7 +270,7 @@ impl Lua {
288270
};
289271

290272
#[cfg(feature = "luau")]
291-
mlua_expect!(lua.configure_luau(options), "Error configuring Luau");
273+
mlua_expect!(lua.configure_luau(), "Error configuring Luau");
292274

293275
lua
294276
}

src/state/extra.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,6 @@ pub(crate) struct ExtraData {
9393
pub(super) compiler: Option<Compiler>,
9494
#[cfg(feature = "luau-jit")]
9595
pub(super) enable_jit: bool,
96-
#[cfg(feature = "luau")]
97-
pub(super) requirer: Option<Box<dyn crate::luau::Require>>,
9896
}
9997

10098
impl Drop for ExtraData {
@@ -196,8 +194,6 @@ impl ExtraData {
196194
enable_jit: true,
197195
#[cfg(feature = "luau")]
198196
running_gc: false,
199-
#[cfg(feature = "luau")]
200-
requirer: None,
201197
}));
202198

203199
// Store it in the registry
@@ -214,7 +210,7 @@ impl ExtraData {
214210
self.weak.write(WeakLua(XRc::downgrade(raw)));
215211
}
216212

217-
pub(crate) unsafe fn get(state: *mut ffi::lua_State) -> *mut Self {
213+
pub(super) unsafe fn get(state: *mut ffi::lua_State) -> *mut Self {
218214
#[cfg(feature = "luau")]
219215
if cfg!(not(feature = "module")) {
220216
// In the main app we can use `lua_callbacks` to access ExtraData
@@ -261,13 +257,4 @@ impl ExtraData {
261257
pub(super) unsafe fn weak(&self) -> &WeakLua {
262258
self.weak.assume_init_ref()
263259
}
264-
265-
#[cfg(feature = "luau")]
266-
pub(crate) fn set_requirer(
267-
&mut self,
268-
requirer: Box<dyn crate::luau::Require>,
269-
) -> *mut Box<dyn crate::luau::Require> {
270-
self.requirer.replace(requirer);
271-
self.requirer.as_mut().unwrap()
272-
}
273260
}

0 commit comments

Comments
 (0)