@@ -2,14 +2,33 @@ use std::ffi::CStr;
2
2
use std:: os:: raw:: c_int;
3
3
4
4
use crate :: error:: Result ;
5
- use crate :: state:: { ExtraData , Lua , LuaOptions } ;
5
+ use crate :: function:: Function ;
6
+ use crate :: state:: Lua ;
6
7
7
8
pub use require:: { NavigateError , Require } ;
8
9
9
10
// Since Luau has some missing standard functions, we re-implement them here
10
11
11
12
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 < 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 < ( ) > {
13
32
let globals = self . globals ( ) ;
14
33
15
34
globals. raw_set ( "collectgarbage" , self . create_c_function ( lua_collectgarbage) ?) ?;
@@ -20,12 +39,9 @@ impl Lua {
20
39
globals. raw_set ( "_VERSION" , format ! ( "Luau {version}" ) ) ?;
21
40
}
22
41
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
+ self . globals ( )
44
+ . raw_set ( "require" , self . create_require ( require:: TextRequirer :: new ( ) ) ?) ?;
29
45
30
46
Ok ( ( ) )
31
47
}
0 commit comments