luaur_require/functions/
lua_requireinternal.rs1use crate::enums::status_require_impl::Status;
2use crate::functions::lua_requirecont::{lua_requirecont, K_REQUIRE_STACK_VALUES};
3use crate::functions::resolve_require::resolve_require;
4use crate::records::luarequire_configuration::luarequire_Configuration;
5use alloc::ffi::CString;
6use core::ffi::{c_char, c_int};
7use luaur_vm::enums::lua_status::lua_Status;
8use luaur_vm::enums::lua_type::lua_Type;
9use luaur_vm::functions::lua_error::lua_error;
10use luaur_vm::functions::lua_getfield::lua_getfield;
11use luaur_vm::functions::lua_gettop::lua_gettop;
12use luaur_vm::functions::lua_l_findtable::luaL_findtable;
13use luaur_vm::functions::lua_pushstring::lua_pushstring;
14use luaur_vm::functions::lua_remove::lua_remove;
15use luaur_vm::functions::lua_settop::lua_settop;
16use luaur_vm::functions::lua_tolightuserdata::lua_tolightuserdata;
17use luaur_vm::functions::lua_tolstring::lua_tolstring;
18use luaur_vm::functions::lua_touserdata::lua_touserdata;
19use luaur_vm::functions::lua_type::lua_type;
20use luaur_vm::functions::lua_yield::lua_yield;
21use luaur_vm::macros::lua_l_checkstring::luaL_checkstring;
22use luaur_vm::macros::lua_l_error::luaL_error;
23use luaur_vm::macros::lua_pop::lua_pop;
24use luaur_vm::macros::lua_registryindex::LUA_REGISTRYINDEX;
25use luaur_vm::macros::lua_upvalueindex::lua_upvalueindex;
26use luaur_vm::records::lua_state::lua_State;
27
28const REGISTERED_CACHE_TABLE_KEY: *const c_char = c"_REGISTEREDMODULES".as_ptr();
29
30pub fn lua_requireinternal(l: *mut lua_State, requirer_chunkname: *const c_char) -> i32 {
31 unsafe {
32 lua_settop(l, 1);
33
34 let lrc = lua_touserdata(l, lua_upvalueindex(1)) as *mut luarequire_Configuration;
35 if lrc.is_null() {
36 luaL_error!(l, "unable to find require configuration");
37 return 0;
38 }
39
40 let ctx = lua_tolightuserdata(l, lua_upvalueindex(2));
41 let path = luaL_checkstring!(l, 1);
42
43 luaL_findtable(l, LUA_REGISTRYINDEX, REGISTERED_CACHE_TABLE_KEY, 1);
44 let path_bytes = core::ffi::CStr::from_ptr(path).to_bytes();
45 let mut path_lower = path_bytes.to_vec();
46 for byte in &mut path_lower {
47 if *byte >= b'A' && *byte <= b'Z' {
48 *byte += b'a' - b'A';
49 }
50 }
51 let path_lower_c = CString::new(path_lower).unwrap();
52 lua_getfield(l, -1, path_lower_c.as_ptr());
53 if lua_type(l, -1) != lua_Type::LUA_TNIL as c_int {
54 lua_remove(l, -2);
55 return 1;
56 }
57 lua_pop(l, 2);
58
59 let path_string = core::ffi::CStr::from_ptr(path)
60 .to_string_lossy()
61 .into_owned();
62 let mut resolve_error = false;
63
64 {
65 let resolved_require = resolve_require(lrc, l, ctx, requirer_chunkname, path_string);
66
67 if resolved_require.status == Status::Cached {
68 return 1;
69 }
70
71 if resolved_require.status == Status::ErrorReported {
72 let error = CString::new(resolved_require.error.replace('\0', "")).unwrap();
73 lua_pushstring(l, error.as_ptr());
74 resolve_error = true;
75 } else {
76 let cache_key = CString::new(resolved_require.cacheKey.replace('\0', "")).unwrap();
77 let chunkname = CString::new(resolved_require.chunkname.replace('\0', "")).unwrap();
78 let loadname = CString::new(resolved_require.loadname.replace('\0', "")).unwrap();
79 lua_pushstring(l, cache_key.as_ptr());
80 lua_pushstring(l, chunkname.as_ptr());
81 lua_pushstring(l, loadname.as_ptr());
82 }
83 }
84
85 if resolve_error {
86 lua_error(l);
87 }
88
89 let stack_values = lua_gettop(l);
90 luaur_common::LUAU_ASSERT!(stack_values == K_REQUIRE_STACK_VALUES);
91
92 let chunkname = lua_tolstring(l, -2, core::ptr::null_mut());
93 let loadname = lua_tolstring(l, -1, core::ptr::null_mut());
94
95 let Some(load) = (*lrc).load else {
96 luaL_error!(
97 l,
98 "require configuration is missing required function pointer: load"
99 );
100 return 0;
101 };
102
103 let num_results = load(l as *mut core::ffi::c_void, ctx, path, chunkname, loadname);
104 if num_results == -1 {
105 if lua_gettop(l) != stack_values {
106 luaL_error!(l, "stack cannot be modified when require yields");
107 return 0;
108 }
109
110 return lua_yield(l, 0);
111 }
112
113 lua_requirecont(l, lua_Status::LUA_OK as c_int)
114 }
115}