mlua/
lua.rs

1use std::any::TypeId;
2use std::cell::{RefCell, UnsafeCell};
3use std::ffi::{CStr, CString};
4use std::fmt;
5use std::marker::PhantomData;
6use std::mem::{self, MaybeUninit};
7use std::ops::Deref;
8use std::os::raw::{c_char, c_int, c_void};
9use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe, Location};
10use std::ptr;
11use std::result::Result as StdResult;
12use std::sync::atomic::{AtomicPtr, Ordering};
13use std::sync::{Arc, Mutex};
14
15use rustc_hash::FxHashMap;
16
17use crate::chunk::{AsChunk, Chunk, ChunkMode};
18use crate::error::{Error, Result};
19use crate::function::Function;
20use crate::hook::Debug;
21use crate::memory::{MemoryState, ALLOCATOR};
22use crate::scope::Scope;
23use crate::stdlib::StdLib;
24use crate::string::String;
25use crate::table::Table;
26use crate::thread::Thread;
27use crate::types::{
28    AppData, AppDataRef, AppDataRefMut, Callback, CallbackUpvalue, DestructedUserdata, Integer,
29    LightUserData, LuaRef, MaybeSend, Number, RegistryKey, SubtypeId,
30};
31use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataCell};
32use crate::userdata_impl::{UserDataProxy, UserDataRegistry};
33use crate::util::{
34    self, assert_stack, check_stack, error_traceback, get_destructed_userdata_metatable,
35    get_gc_metatable, get_gc_userdata, get_main_state, get_userdata, init_error_registry,
36    init_gc_metatable, init_userdata_metatable, pop_error, push_gc_userdata, push_string,
37    push_table, rawset_field, safe_pcall, safe_xpcall, short_type_name, StackGuard, WrappedFailure,
38};
39use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil, Value};
40
41#[cfg(not(feature = "lua54"))]
42use crate::util::push_userdata;
43#[cfg(feature = "lua54")]
44use crate::{types::WarnCallback, userdata::USER_VALUE_MAXSLOT, util::push_userdata_uv};
45
46#[cfg(not(feature = "luau"))]
47use crate::{hook::HookTriggers, types::HookCallback};
48
49#[cfg(feature = "luau")]
50use crate::types::InterruptCallback;
51#[cfg(any(feature = "luau", doc))]
52use crate::{
53    chunk::Compiler,
54    types::{Vector, VmState},
55};
56
57#[cfg(feature = "async")]
58use {
59    crate::types::{AsyncCallback, AsyncCallbackUpvalue, AsyncPollUpvalue},
60    futures_util::future::{self, Future},
61    futures_util::task::{noop_waker_ref, Context, Poll, Waker},
62    std::ptr::NonNull,
63};
64
65#[cfg(feature = "serialize")]
66use serde::Serialize;
67
68/// Top level Lua struct which represents an instance of Lua VM.
69#[repr(transparent)]
70pub struct Lua(Arc<LuaInner>);
71
72/// An inner Lua struct which holds a raw Lua state.
73pub struct LuaInner {
74    // The state is dynamic and depends on context
75    state: AtomicPtr<ffi::lua_State>,
76    main_state: *mut ffi::lua_State,
77    extra: Arc<UnsafeCell<ExtraData>>,
78}
79
80// Data associated with the Lua.
81pub(crate) struct ExtraData {
82    // Same layout as `Lua`
83    inner: MaybeUninit<Arc<LuaInner>>,
84
85    registered_userdata: FxHashMap<TypeId, c_int>,
86    registered_userdata_mt: FxHashMap<*const c_void, Option<TypeId>>,
87    last_checked_userdata_mt: (*const c_void, Option<TypeId>),
88
89    // When Lua instance dropped, setting `None` would prevent collecting `RegistryKey`s
90    registry_unref_list: Arc<Mutex<Option<Vec<c_int>>>>,
91
92    // Container to store arbitrary data (extensions)
93    app_data: AppData,
94
95    safe: bool,
96    libs: StdLib,
97    #[cfg(feature = "module")]
98    skip_memory_check: bool,
99
100    // Auxiliary thread to store references
101    ref_thread: *mut ffi::lua_State,
102    ref_stack_size: c_int,
103    ref_stack_top: c_int,
104    ref_free: Vec<c_int>,
105
106    // Pool of `WrappedFailure` enums in the ref thread (as userdata)
107    wrapped_failure_pool: Vec<c_int>,
108    // Pool of `MultiValue` containers
109    multivalue_pool: Vec<Vec<Value<'static>>>,
110    // Pool of `Thread`s (coroutines) for async execution
111    #[cfg(feature = "async")]
112    thread_pool: Vec<c_int>,
113
114    // Address of `WrappedFailure` metatable
115    wrapped_failure_mt_ptr: *const c_void,
116
117    // Waker for polling futures
118    #[cfg(feature = "async")]
119    waker: NonNull<Waker>,
120
121    #[cfg(not(feature = "luau"))]
122    hook_callback: Option<HookCallback>,
123    #[cfg(not(feature = "luau"))]
124    hook_thread: *mut ffi::lua_State,
125    #[cfg(feature = "lua54")]
126    warn_callback: Option<WarnCallback>,
127    #[cfg(feature = "luau")]
128    interrupt_callback: Option<InterruptCallback>,
129
130    #[cfg(feature = "luau")]
131    sandboxed: bool,
132    #[cfg(feature = "luau")]
133    compiler: Option<Compiler>,
134    #[cfg(feature = "luau-jit")]
135    enable_jit: bool,
136}
137
138/// Mode of the Lua garbage collector (GC).
139///
140/// In Lua 5.4 GC can work in two modes: incremental and generational.
141/// Previous Lua versions support only incremental GC.
142///
143/// More information can be found in the Lua [documentation].
144///
145/// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
146#[derive(Clone, Copy, Debug, PartialEq, Eq)]
147pub enum GCMode {
148    Incremental,
149    /// Requires `feature = "lua54"`
150    #[cfg(feature = "lua54")]
151    #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
152    Generational,
153}
154
155/// Controls Lua interpreter behavior such as Rust panics handling.
156#[derive(Clone, Debug)]
157#[non_exhaustive]
158pub struct LuaOptions {
159    /// Catch Rust panics when using [`pcall`]/[`xpcall`].
160    ///
161    /// If disabled, wraps these functions and automatically resumes panic if found.
162    /// Also in Lua 5.1 adds ability to provide arguments to [`xpcall`] similar to Lua >= 5.2.
163    ///
164    /// If enabled, keeps [`pcall`]/[`xpcall`] unmodified.
165    /// Panics are still automatically resumed if returned to the Rust side.
166    ///
167    /// Default: **true**
168    ///
169    /// [`pcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-pcall
170    /// [`xpcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-xpcall
171    pub catch_rust_panics: bool,
172
173    /// Max size of thread (coroutine) object pool used to execute asynchronous functions.
174    ///
175    /// It works on Lua 5.4 and Luau, where [`lua_resetthread`] function
176    /// is available and allows to reuse old coroutines after resetting their state.
177    ///
178    /// Default: **0** (disabled)
179    ///
180    /// [`lua_resetthread`]: https://www.lua.org/manual/5.4/manual.html#lua_resetthread
181    #[cfg(feature = "async")]
182    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
183    pub thread_pool_size: usize,
184}
185
186impl Default for LuaOptions {
187    fn default() -> Self {
188        LuaOptions::new()
189    }
190}
191
192impl LuaOptions {
193    /// Returns a new instance of `LuaOptions` with default parameters.
194    pub const fn new() -> Self {
195        LuaOptions {
196            catch_rust_panics: true,
197            #[cfg(feature = "async")]
198            thread_pool_size: 0,
199        }
200    }
201
202    /// Sets [`catch_rust_panics`] option.
203    ///
204    /// [`catch_rust_panics`]: #structfield.catch_rust_panics
205    #[must_use]
206    pub const fn catch_rust_panics(mut self, enabled: bool) -> Self {
207        self.catch_rust_panics = enabled;
208        self
209    }
210
211    /// Sets [`thread_pool_size`] option.
212    ///
213    /// [`thread_pool_size`]: #structfield.thread_pool_size
214    #[cfg(feature = "async")]
215    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
216    #[must_use]
217    pub const fn thread_pool_size(mut self, size: usize) -> Self {
218        self.thread_pool_size = size;
219        self
220    }
221}
222
223#[cfg(feature = "async")]
224pub(crate) static ASYNC_POLL_PENDING: u8 = 0;
225pub(crate) static EXTRA_REGISTRY_KEY: u8 = 0;
226
227const WRAPPED_FAILURE_POOL_SIZE: usize = 64;
228const MULTIVALUE_POOL_SIZE: usize = 64;
229const REF_STACK_RESERVE: c_int = 1;
230
231/// Requires `feature = "send"`
232#[cfg(feature = "send")]
233#[cfg_attr(docsrs, doc(cfg(feature = "send")))]
234unsafe impl Send for Lua {}
235
236#[cfg(not(feature = "module"))]
237impl Drop for Lua {
238    fn drop(&mut self) {
239        let _ = self.gc_collect();
240    }
241}
242
243#[cfg(not(feature = "module"))]
244impl Drop for LuaInner {
245    fn drop(&mut self) {
246        unsafe {
247            let mem_state = MemoryState::get(self.main_state);
248
249            ffi::lua_close(self.main_state);
250
251            // Deallocate MemoryState
252            if !mem_state.is_null() {
253                drop(Box::from_raw(mem_state));
254            }
255        }
256    }
257}
258
259impl Drop for ExtraData {
260    fn drop(&mut self) {
261        #[cfg(feature = "module")]
262        unsafe {
263            self.inner.assume_init_drop();
264        }
265
266        *mlua_expect!(self.registry_unref_list.lock(), "unref list poisoned") = None;
267    }
268}
269
270impl fmt::Debug for Lua {
271    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
272        write!(f, "Lua({:p})", self.state())
273    }
274}
275
276impl Deref for Lua {
277    type Target = LuaInner;
278
279    #[inline]
280    fn deref(&self) -> &Self::Target {
281        &self.0
282    }
283}
284
285impl Default for Lua {
286    #[inline]
287    fn default() -> Self {
288        Lua::new()
289    }
290}
291
292impl Lua {
293    /// Creates a new Lua state and loads the **safe** subset of the standard libraries.
294    ///
295    /// # Safety
296    /// The created Lua state would have _some_ safety guarantees and would not allow to load unsafe
297    /// standard libraries or C modules.
298    ///
299    /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
300    ///
301    /// [`StdLib`]: crate::StdLib
302    pub fn new() -> Lua {
303        mlua_expect!(
304            Self::new_with(StdLib::ALL_SAFE, LuaOptions::default()),
305            "Cannot create new safe Lua state"
306        )
307    }
308
309    /// Creates a new Lua state and loads all the standard libraries.
310    ///
311    /// # Safety
312    /// The created Lua state would not have safety guarantees and would allow to load C modules.
313    pub unsafe fn unsafe_new() -> Lua {
314        Self::unsafe_new_with(StdLib::ALL, LuaOptions::default())
315    }
316
317    /// Creates a new Lua state and loads the specified safe subset of the standard libraries.
318    ///
319    /// Use the [`StdLib`] flags to specify the libraries you want to load.
320    ///
321    /// # Safety
322    /// The created Lua state would have _some_ safety guarantees and would not allow to load unsafe
323    /// standard libraries or C modules.
324    ///
325    /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
326    ///
327    /// [`StdLib`]: crate::StdLib
328    pub fn new_with(libs: StdLib, options: LuaOptions) -> Result<Lua> {
329        #[cfg(not(feature = "luau"))]
330        if libs.contains(StdLib::DEBUG) {
331            return Err(Error::SafetyError(
332                "The unsafe `debug` module can't be loaded using safe `new_with`".to_string(),
333            ));
334        }
335        #[cfg(feature = "luajit")]
336        if libs.contains(StdLib::FFI) {
337            return Err(Error::SafetyError(
338                "The unsafe `ffi` module can't be loaded using safe `new_with`".to_string(),
339            ));
340        }
341
342        let lua = unsafe { Self::inner_new(libs, options) };
343
344        if libs.contains(StdLib::PACKAGE) {
345            mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules");
346        }
347        unsafe { (*lua.extra.get()).safe = true };
348
349        Ok(lua)
350    }
351
352    /// Creates a new Lua state and loads the specified subset of the standard libraries.
353    ///
354    /// Use the [`StdLib`] flags to specify the libraries you want to load.
355    ///
356    /// # Safety
357    /// The created Lua state will not have safety guarantees and allow to load C modules.
358    ///
359    /// [`StdLib`]: crate::StdLib
360    pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
361        // Workaround to avoid stripping a few unused Lua symbols that could be imported
362        // by C modules in unsafe mode
363        let mut _symbols: Vec<*const extern "C-unwind" fn()> =
364            vec![ffi::lua_isuserdata as _, ffi::lua_tocfunction as _];
365
366        #[cfg(not(feature = "luau"))]
367        _symbols.extend_from_slice(&[
368            ffi::lua_atpanic as _,
369            ffi::luaL_loadstring as _,
370            ffi::luaL_openlibs as _,
371        ]);
372        #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
373        {
374            _symbols.push(ffi::lua_getglobal as _);
375            _symbols.push(ffi::lua_setglobal as _);
376            _symbols.push(ffi::luaL_setfuncs as _);
377        }
378
379        Self::inner_new(libs, options)
380    }
381
382    /// Creates a new Lua state with required `libs` and `options`
383    unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
384        let mem_state: *mut MemoryState = Box::into_raw(Box::default());
385        let mut state = ffi::lua_newstate(ALLOCATOR, mem_state as *mut c_void);
386        // If state is null then switch to Lua internal allocator
387        if state.is_null() {
388            drop(Box::from_raw(mem_state));
389            state = ffi::luaL_newstate();
390        }
391        assert!(!state.is_null(), "Failed to instantiate Lua VM");
392
393        ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
394        ffi::lua_pop(state, 1);
395
396        // Init Luau code generator (jit)
397        #[cfg(feature = "luau-jit")]
398        if ffi::luau_codegen_supported() != 0 {
399            ffi::luau_codegen_create(state);
400        }
401
402        let lua = Lua::init_from_ptr(state);
403        let extra = lua.extra.get();
404
405        mlua_expect!(
406            load_from_std_lib(state, libs),
407            "Error during loading standard libraries"
408        );
409        (*extra).libs |= libs;
410
411        if !options.catch_rust_panics {
412            mlua_expect!(
413                (|| -> Result<()> {
414                    let _sg = StackGuard::new(state);
415
416                    #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
417                    ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
418                    #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
419                    ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
420
421                    ffi::lua_pushcfunction(state, safe_pcall);
422                    rawset_field(state, -2, "pcall")?;
423
424                    ffi::lua_pushcfunction(state, safe_xpcall);
425                    rawset_field(state, -2, "xpcall")?;
426
427                    Ok(())
428                })(),
429                "Error during applying option `catch_rust_panics`"
430            )
431        }
432
433        #[cfg(feature = "async")]
434        if options.thread_pool_size > 0 {
435            (*extra).thread_pool.reserve_exact(options.thread_pool_size);
436        }
437
438        #[cfg(feature = "luau")]
439        mlua_expect!(lua.configure_luau(), "Error configuring Luau");
440
441        lua
442    }
443
444    /// Constructs a new Lua instance from an existing raw state.
445    ///
446    /// Once called, a returned Lua state is cached in the registry and can be retrieved
447    /// by calling this function again.
448    #[allow(clippy::missing_safety_doc, clippy::arc_with_non_send_sync)]
449    pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua {
450        assert!(!state.is_null(), "Lua state is NULL");
451        if let Some(lua) = Lua::try_from_ptr(state) {
452            return lua;
453        }
454
455        let main_state = get_main_state(state).unwrap_or(state);
456        let main_state_top = ffi::lua_gettop(main_state);
457
458        mlua_expect!(
459            (|state| {
460                init_error_registry(state)?;
461
462                // Create the internal metatables and place them in the registry
463                // to prevent them from being garbage collected.
464
465                init_gc_metatable::<Arc<UnsafeCell<ExtraData>>>(state, None)?;
466                init_gc_metatable::<Callback>(state, None)?;
467                init_gc_metatable::<CallbackUpvalue>(state, None)?;
468                #[cfg(feature = "async")]
469                {
470                    init_gc_metatable::<AsyncCallback>(state, None)?;
471                    init_gc_metatable::<AsyncCallbackUpvalue>(state, None)?;
472                    init_gc_metatable::<AsyncPollUpvalue>(state, None)?;
473                    init_gc_metatable::<Option<Waker>>(state, None)?;
474                }
475
476                // Init serde metatables
477                #[cfg(feature = "serialize")]
478                crate::serde::init_metatables(state)?;
479
480                Ok::<_, Error>(())
481            })(main_state),
482            "Error during Lua construction",
483        );
484
485        // Create ref stack thread and place it in the registry to prevent it from being garbage
486        // collected.
487        let ref_thread = mlua_expect!(
488            protect_lua!(main_state, 0, 0, |state| {
489                let thread = ffi::lua_newthread(state);
490                ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX);
491                thread
492            }),
493            "Error while creating ref thread",
494        );
495
496        let wrapped_failure_mt_ptr = {
497            get_gc_metatable::<WrappedFailure>(main_state);
498            let ptr = ffi::lua_topointer(main_state, -1);
499            ffi::lua_pop(main_state, 1);
500            ptr
501        };
502
503        // Store `error_traceback` function on the ref stack
504        #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
505        {
506            ffi::lua_pushcfunction(ref_thread, error_traceback);
507            assert_eq!(ffi::lua_gettop(ref_thread), ExtraData::ERROR_TRACEBACK_IDX);
508        }
509
510        // Create ExtraData
511        let extra = Arc::new(UnsafeCell::new(ExtraData {
512            inner: MaybeUninit::uninit(),
513            registered_userdata: FxHashMap::default(),
514            registered_userdata_mt: FxHashMap::default(),
515            last_checked_userdata_mt: (ptr::null(), None),
516            registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))),
517            app_data: AppData::default(),
518            safe: false,
519            libs: StdLib::NONE,
520            #[cfg(feature = "module")]
521            skip_memory_check: false,
522            ref_thread,
523            // We need some reserved stack space to move values in and out of the ref stack.
524            ref_stack_size: ffi::LUA_MINSTACK - REF_STACK_RESERVE,
525            ref_stack_top: ffi::lua_gettop(ref_thread),
526            ref_free: Vec::new(),
527            wrapped_failure_pool: Vec::with_capacity(WRAPPED_FAILURE_POOL_SIZE),
528            multivalue_pool: Vec::with_capacity(MULTIVALUE_POOL_SIZE),
529            #[cfg(feature = "async")]
530            thread_pool: Vec::new(),
531            wrapped_failure_mt_ptr,
532            #[cfg(feature = "async")]
533            waker: NonNull::from(noop_waker_ref()),
534            #[cfg(not(feature = "luau"))]
535            hook_callback: None,
536            #[cfg(not(feature = "luau"))]
537            hook_thread: ptr::null_mut(),
538            #[cfg(feature = "lua54")]
539            warn_callback: None,
540            #[cfg(feature = "luau")]
541            interrupt_callback: None,
542            #[cfg(feature = "luau")]
543            sandboxed: false,
544            #[cfg(feature = "luau")]
545            compiler: None,
546            #[cfg(feature = "luau-jit")]
547            enable_jit: true,
548        }));
549
550        // Store it in the registry
551        mlua_expect!(
552            set_extra_data(main_state, &extra),
553            "Error while storing extra data"
554        );
555
556        // Register `DestructedUserdata` type
557        get_destructed_userdata_metatable(main_state);
558        let destructed_mt_ptr = ffi::lua_topointer(main_state, -1);
559        let destructed_ud_typeid = TypeId::of::<DestructedUserdata>();
560        (*extra.get())
561            .registered_userdata_mt
562            .insert(destructed_mt_ptr, Some(destructed_ud_typeid));
563        ffi::lua_pop(main_state, 1);
564
565        mlua_debug_assert!(
566            ffi::lua_gettop(main_state) == main_state_top,
567            "stack leak during creation"
568        );
569        assert_stack(main_state, ffi::LUA_MINSTACK);
570
571        let inner = Arc::new(LuaInner {
572            state: AtomicPtr::new(state),
573            main_state,
574            extra: Arc::clone(&extra),
575        });
576
577        (*extra.get()).inner.write(Arc::clone(&inner));
578        #[cfg(not(feature = "module"))]
579        Arc::decrement_strong_count(Arc::as_ptr(&inner));
580
581        Lua(inner)
582    }
583
584    /// Loads the specified subset of the standard libraries into an existing Lua state.
585    ///
586    /// Use the [`StdLib`] flags to specify the libraries you want to load.
587    ///
588    /// [`StdLib`]: crate::StdLib
589    pub fn load_from_std_lib(&self, libs: StdLib) -> Result<()> {
590        let is_safe = unsafe { (*self.extra.get()).safe };
591
592        #[cfg(not(feature = "luau"))]
593        if is_safe && libs.contains(StdLib::DEBUG) {
594            return Err(Error::SafetyError(
595                "the unsafe `debug` module can't be loaded in safe mode".to_string(),
596            ));
597        }
598        #[cfg(feature = "luajit")]
599        if is_safe && libs.contains(StdLib::FFI) {
600            return Err(Error::SafetyError(
601                "the unsafe `ffi` module can't be loaded in safe mode".to_string(),
602            ));
603        }
604
605        let res = unsafe { load_from_std_lib(self.main_state, libs) };
606
607        // If `package` library loaded into a safe lua state then disable C modules
608        let curr_libs = unsafe { (*self.extra.get()).libs };
609        if is_safe && (curr_libs ^ (curr_libs | libs)).contains(StdLib::PACKAGE) {
610            mlua_expect!(self.disable_c_modules(), "Error during disabling C modules");
611        }
612        unsafe { (*self.extra.get()).libs |= libs };
613
614        res
615    }
616
617    /// Loads module `modname` into an existing Lua state using the specified entrypoint
618    /// function.
619    ///
620    /// Internally calls the Lua function `func` with the string `modname` as an argument,
621    /// sets the call result to `package.loaded[modname]` and returns copy of the result.
622    ///
623    /// If `package.loaded[modname]` value is not nil, returns copy of the value without
624    /// calling the function.
625    ///
626    /// If the function does not return a non-nil value then this method assigns true to
627    /// `package.loaded[modname]`.
628    ///
629    /// Behavior is similar to Lua's [`require`] function.
630    ///
631    /// [`require`]: https://www.lua.org/manual/5.4/manual.html#pdf-require
632    pub fn load_from_function<'lua, T>(&'lua self, modname: &str, func: Function<'lua>) -> Result<T>
633    where
634        T: FromLua<'lua>,
635    {
636        let state = self.state();
637        let loaded = unsafe {
638            let _sg = StackGuard::new(state);
639            check_stack(state, 2)?;
640            protect_lua!(state, 0, 1, fn(state) {
641                ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
642            })?;
643            Table(self.pop_ref())
644        };
645
646        let modname = self.create_string(modname)?;
647        let value = match loaded.raw_get(modname.clone())? {
648            Value::Nil => {
649                let result = match func.call(modname.clone())? {
650                    Value::Nil => Value::Boolean(true),
651                    res => res,
652                };
653                loaded.raw_set(modname, result.clone())?;
654                result
655            }
656            res => res,
657        };
658        T::from_lua(value, self)
659    }
660
661    /// Unloads module `modname`.
662    ///
663    /// Removes module from the [`package.loaded`] table which allows to load it again.
664    /// It does not support unloading binary Lua modules since they are internally cached and can be
665    /// unloaded only by closing Lua state.
666    ///
667    /// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
668    pub fn unload(&self, modname: &str) -> Result<()> {
669        let state = self.state();
670        let loaded = unsafe {
671            let _sg = StackGuard::new(state);
672            check_stack(state, 2)?;
673            protect_lua!(state, 0, 1, fn(state) {
674                ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
675            })?;
676            Table(self.pop_ref())
677        };
678
679        let modname = self.create_string(modname)?;
680        loaded.raw_remove(modname)?;
681        Ok(())
682    }
683
684    /// Consumes and leaks `Lua` object, returning a static reference `&'static Lua`.
685    ///
686    /// This function is useful when the `Lua` object is supposed to live for the remainder
687    /// of the program's life.
688    ///
689    /// Dropping the returned reference will cause a memory leak. If this is not acceptable,
690    /// the reference should first be wrapped with the [`Lua::from_static`] function producing a `Lua`.
691    /// This `Lua` object can then be dropped which will properly release the allocated memory.
692    ///
693    /// [`Lua::from_static`]: #method.from_static
694    #[doc(hidden)]
695    pub fn into_static(self) -> &'static Self {
696        Box::leak(Box::new(self))
697    }
698
699    /// Constructs a `Lua` from a static reference to it.
700    ///
701    /// # Safety
702    /// This function is unsafe because improper use may lead to memory problems or undefined behavior.
703    #[doc(hidden)]
704    pub unsafe fn from_static(lua: &'static Lua) -> Self {
705        *Box::from_raw(lua as *const Lua as *mut Lua)
706    }
707
708    // Executes module entrypoint function, which returns only one Value.
709    // The returned value then pushed onto the stack.
710    #[doc(hidden)]
711    #[cfg(not(tarpaulin_include))]
712    pub unsafe fn entrypoint<'lua, A, R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
713    where
714        A: FromLuaMulti<'lua>,
715        R: IntoLua<'lua>,
716        F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
717    {
718        let extra = self.extra.get();
719        // `self` is no longer needed and must be dropped at this point to avoid possible memory leak
720        // in case of possible longjmp (lua_error) below
721        drop(self);
722
723        callback_error_ext(state, extra, move |nargs| {
724            let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
725            let _guard = StateGuard::new(&lua.0, state);
726            let args = A::from_stack_args(nargs, 1, None, lua)?;
727            func(lua, args)?.push_into_stack(lua)?;
728            Ok(1)
729        })
730    }
731
732    // A simple module entrypoint without arguments
733    #[doc(hidden)]
734    #[cfg(not(tarpaulin_include))]
735    pub unsafe fn entrypoint1<'lua, R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
736    where
737        R: IntoLua<'lua>,
738        F: Fn(&'lua Lua) -> Result<R> + MaybeSend + 'static,
739    {
740        self.entrypoint(state, move |lua, _: ()| func(lua))
741    }
742
743    /// Skips memory checks for some operations.
744    #[doc(hidden)]
745    #[cfg(feature = "module")]
746    pub fn skip_memory_check(&self, skip: bool) {
747        unsafe { (*self.extra.get()).skip_memory_check = skip };
748    }
749
750    /// Enables (or disables) sandbox mode on this Lua instance.
751    ///
752    /// This method, in particular:
753    /// - Set all libraries to read-only
754    /// - Set all builtin metatables to read-only
755    /// - Set globals to read-only (and activates safeenv)
756    /// - Setup local environment table that performs writes locally and proxies reads
757    ///   to the global environment.
758    ///
759    /// # Examples
760    ///
761    /// ```
762    /// # use mlua::{Lua, Result};
763    /// # fn main() -> Result<()> {
764    /// let lua = Lua::new();
765    ///
766    /// lua.sandbox(true)?;
767    /// lua.load("var = 123").exec()?;
768    /// assert_eq!(lua.globals().get::<_, u32>("var")?, 123);
769    ///
770    /// // Restore the global environment (clear changes made in sandbox)
771    /// lua.sandbox(false)?;
772    /// assert_eq!(lua.globals().get::<_, Option<u32>>("var")?, None);
773    /// # Ok(())
774    /// # }
775    /// ```
776    ///
777    /// Requires `feature = "luau"`
778    #[cfg(any(feature = "luau", docsrs))]
779    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
780    pub fn sandbox(&self, enabled: bool) -> Result<()> {
781        unsafe {
782            if (*self.extra.get()).sandboxed != enabled {
783                let state = self.main_state;
784                check_stack(state, 3)?;
785                protect_lua!(state, 0, 0, |state| {
786                    if enabled {
787                        ffi::luaL_sandbox(state, 1);
788                        ffi::luaL_sandboxthread(state);
789                    } else {
790                        // Restore original `LUA_GLOBALSINDEX`
791                        ffi::lua_xpush(self.ref_thread(), state, ffi::LUA_GLOBALSINDEX);
792                        ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
793                        ffi::luaL_sandbox(state, 0);
794                    }
795                })?;
796                (*self.extra.get()).sandboxed = enabled;
797            }
798            Ok(())
799        }
800    }
801
802    /// Sets a 'hook' function that will periodically be called as Lua code executes.
803    ///
804    /// When exactly the hook function is called depends on the contents of the `triggers`
805    /// parameter, see [`HookTriggers`] for more details.
806    ///
807    /// The provided hook function can error, and this error will be propagated through the Lua code
808    /// that was executing at the time the hook was triggered. This can be used to implement a
809    /// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and
810    /// erroring once an instruction limit has been reached.
811    ///
812    /// This method sets a hook function for the current thread of this Lua instance.
813    /// If you want to set a hook function for another thread (coroutine), use [`Thread::set_hook()`] instead.
814    ///
815    /// Please note you cannot have more than one hook function set at a time for this Lua instance.
816    ///
817    /// # Example
818    ///
819    /// Shows each line number of code being executed by the Lua interpreter.
820    ///
821    /// ```
822    /// # use mlua::{Lua, HookTriggers, Result};
823    /// # fn main() -> Result<()> {
824    /// let lua = Lua::new();
825    /// lua.set_hook(HookTriggers::EVERY_LINE, |_lua, debug| {
826    ///     println!("line {}", debug.curr_line());
827    ///     Ok(())
828    /// });
829    ///
830    /// lua.load(r#"
831    ///     local x = 2 + 3
832    ///     local y = x * 63
833    ///     local z = string.len(x..", "..y)
834    /// "#).exec()
835    /// # }
836    /// ```
837    ///
838    /// [`HookTriggers`]: crate::HookTriggers
839    /// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
840    #[cfg(not(feature = "luau"))]
841    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
842    pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F)
843    where
844        F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
845    {
846        unsafe { self.set_thread_hook(self.state(), triggers, callback) };
847    }
848
849    /// Sets a 'hook' function for a thread (coroutine).
850    #[cfg(not(feature = "luau"))]
851    pub(crate) unsafe fn set_thread_hook<F>(
852        &self,
853        state: *mut ffi::lua_State,
854        triggers: HookTriggers,
855        callback: F,
856    ) where
857        F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
858    {
859        unsafe extern "C-unwind" fn hook_proc(state: *mut ffi::lua_State, ar: *mut ffi::lua_Debug) {
860            let extra = extra_data(state);
861            if (*extra).hook_thread != state {
862                // Hook was destined for a different thread, ignore
863                ffi::lua_sethook(state, None, 0, 0);
864                return;
865            }
866            callback_error_ext(state, extra, move |_| {
867                let hook_cb = (*extra).hook_callback.clone();
868                let hook_cb = mlua_expect!(hook_cb, "no hook callback set in hook_proc");
869                if Arc::strong_count(&hook_cb) > 2 {
870                    return Ok(()); // Don't allow recursion
871                }
872                let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
873                let _guard = StateGuard::new(&lua.0, state);
874                let debug = Debug::new(lua, ar);
875                hook_cb(lua, debug)
876            })
877        }
878
879        (*self.extra.get()).hook_callback = Some(Arc::new(callback));
880        (*self.extra.get()).hook_thread = state; // Mark for what thread the hook is set
881        ffi::lua_sethook(state, Some(hook_proc), triggers.mask(), triggers.count());
882    }
883
884    /// Removes any hook previously set by [`Lua::set_hook()`] or [`Thread::set_hook()`].
885    ///
886    /// This function has no effect if a hook was not previously set.
887    #[cfg(not(feature = "luau"))]
888    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
889    pub fn remove_hook(&self) {
890        unsafe {
891            let state = self.state();
892            ffi::lua_sethook(state, None, 0, 0);
893            match get_main_state(self.main_state) {
894                Some(main_state) if !ptr::eq(state, main_state) => {
895                    // If main_state is different from state, remove hook from it too
896                    ffi::lua_sethook(main_state, None, 0, 0);
897                }
898                _ => {}
899            };
900            (*self.extra.get()).hook_callback = None;
901            (*self.extra.get()).hook_thread = ptr::null_mut();
902        }
903    }
904
905    /// Sets an 'interrupt' function that will periodically be called by Luau VM.
906    ///
907    /// Any Luau code is guaranteed to call this handler "eventually"
908    /// (in practice this can happen at any function call or at any loop iteration).
909    ///
910    /// The provided interrupt function can error, and this error will be propagated through
911    /// the Luau code that was executing at the time the interrupt was triggered.
912    /// Also this can be used to implement continuous execution limits by instructing Luau VM to yield
913    /// by returning [`VmState::Yield`].
914    ///
915    /// This is similar to [`Lua::set_hook`] but in more simplified form.
916    ///
917    /// # Example
918    ///
919    /// Periodically yield Luau VM to suspend execution.
920    ///
921    /// ```
922    /// # use std::sync::{Arc, atomic::{AtomicU64, Ordering}};
923    /// # use mlua::{Lua, Result, ThreadStatus, VmState};
924    /// # fn main() -> Result<()> {
925    /// let lua = Lua::new();
926    /// let count = Arc::new(AtomicU64::new(0));
927    /// lua.set_interrupt(move |_| {
928    ///     if count.fetch_add(1, Ordering::Relaxed) % 2 == 0 {
929    ///         return Ok(VmState::Yield);
930    ///     }
931    ///     Ok(VmState::Continue)
932    /// });
933    ///
934    /// let co = lua.create_thread(
935    ///     lua.load(r#"
936    ///         local b = 0
937    ///         for _, x in ipairs({1, 2, 3}) do b += x end
938    ///     "#)
939    ///     .into_function()?,
940    /// )?;
941    /// while co.status() == ThreadStatus::Resumable {
942    ///     co.resume(())?;
943    /// }
944    /// # Ok(())
945    /// # }
946    /// ```
947    #[cfg(any(feature = "luau", docsrs))]
948    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
949    pub fn set_interrupt<F>(&self, callback: F)
950    where
951        F: Fn(&Lua) -> Result<VmState> + MaybeSend + 'static,
952    {
953        unsafe extern "C-unwind" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) {
954            if gc >= 0 {
955                // We don't support GC interrupts since they cannot survive Lua exceptions
956                return;
957            }
958            let extra = extra_data(state);
959            let result = callback_error_ext(state, extra, move |_| {
960                let interrupt_cb = (*extra).interrupt_callback.clone();
961                let interrupt_cb =
962                    mlua_expect!(interrupt_cb, "no interrupt callback set in interrupt_proc");
963                if Arc::strong_count(&interrupt_cb) > 2 {
964                    return Ok(VmState::Continue); // Don't allow recursion
965                }
966                let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
967                let _guard = StateGuard::new(&lua.0, state);
968                interrupt_cb(lua)
969            });
970            match result {
971                VmState::Continue => {}
972                VmState::Yield => {
973                    ffi::lua_yield(state, 0);
974                }
975            }
976        }
977
978        unsafe {
979            (*self.extra.get()).interrupt_callback = Some(Arc::new(callback));
980            (*ffi::lua_callbacks(self.main_state)).interrupt = Some(interrupt_proc);
981        }
982    }
983
984    /// Removes any 'interrupt' previously set by `set_interrupt`.
985    ///
986    /// This function has no effect if an 'interrupt' was not previously set.
987    #[cfg(any(feature = "luau", docsrs))]
988    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
989    pub fn remove_interrupt(&self) {
990        unsafe {
991            (*self.extra.get()).interrupt_callback = None;
992            (*ffi::lua_callbacks(self.main_state)).interrupt = None;
993        }
994    }
995
996    /// Sets the warning function to be used by Lua to emit warnings.
997    ///
998    /// Requires `feature = "lua54"`
999    #[cfg(feature = "lua54")]
1000    #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
1001    pub fn set_warning_function<F>(&self, callback: F)
1002    where
1003        F: Fn(&Lua, &str, bool) -> Result<()> + MaybeSend + 'static,
1004    {
1005        unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
1006            let extra = ud as *mut ExtraData;
1007            let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
1008            callback_error_ext(lua.state(), extra, |_| {
1009                let cb = mlua_expect!(
1010                    (*extra).warn_callback.as_ref(),
1011                    "no warning callback set in warn_proc"
1012                );
1013                let msg = std::string::String::from_utf8_lossy(CStr::from_ptr(msg).to_bytes());
1014                cb(lua, &msg, tocont != 0)
1015            });
1016        }
1017
1018        let state = self.main_state;
1019        unsafe {
1020            (*self.extra.get()).warn_callback = Some(Box::new(callback));
1021            ffi::lua_setwarnf(state, Some(warn_proc), self.extra.get() as *mut c_void);
1022        }
1023    }
1024
1025    /// Removes warning function previously set by `set_warning_function`.
1026    ///
1027    /// This function has no effect if a warning function was not previously set.
1028    ///
1029    /// Requires `feature = "lua54"`
1030    #[cfg(feature = "lua54")]
1031    #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
1032    pub fn remove_warning_function(&self) {
1033        unsafe {
1034            (*self.extra.get()).warn_callback = None;
1035            ffi::lua_setwarnf(self.main_state, None, ptr::null_mut());
1036        }
1037    }
1038
1039    /// Emits a warning with the given message.
1040    ///
1041    /// A message in a call with `incomplete` set to `true` should be continued in
1042    /// another call to this function.
1043    ///
1044    /// Requires `feature = "lua54"`
1045    #[cfg(feature = "lua54")]
1046    #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
1047    pub fn warning(&self, msg: impl AsRef<str>, incomplete: bool) {
1048        let msg = msg.as_ref();
1049        let mut bytes = vec![0; msg.len() + 1];
1050        bytes[..msg.len()].copy_from_slice(msg.as_bytes());
1051        let real_len = bytes.iter().position(|&c| c == 0).unwrap();
1052        bytes.truncate(real_len);
1053        unsafe {
1054            ffi::lua_warning(
1055                self.state(),
1056                bytes.as_ptr() as *const c_char,
1057                incomplete as c_int,
1058            );
1059        }
1060    }
1061
1062    /// Gets information about the interpreter runtime stack.
1063    ///
1064    /// This function returns [`Debug`] structure that can be used to get information about the function
1065    /// executing at a given level. Level `0` is the current running function, whereas level `n+1` is the
1066    /// function that has called level `n` (except for tail calls, which do not count in the stack).
1067    ///
1068    /// [`Debug`]: crate::hook::Debug
1069    pub fn inspect_stack(&self, level: usize) -> Option<Debug> {
1070        unsafe {
1071            let mut ar: ffi::lua_Debug = mem::zeroed();
1072            let level = level as c_int;
1073            #[cfg(not(feature = "luau"))]
1074            if ffi::lua_getstack(self.state(), level, &mut ar) == 0 {
1075                return None;
1076            }
1077            #[cfg(feature = "luau")]
1078            if ffi::lua_getinfo(self.state(), level, cstr!(""), &mut ar) == 0 {
1079                return None;
1080            }
1081            Some(Debug::new_owned(self, level, ar))
1082        }
1083    }
1084
1085    /// Returns the amount of memory (in bytes) currently used inside this Lua state.
1086    pub fn used_memory(&self) -> usize {
1087        unsafe {
1088            match MemoryState::get(self.main_state) {
1089                mem_state if !mem_state.is_null() => (*mem_state).used_memory(),
1090                _ => {
1091                    // Get data from the Lua GC
1092                    let used_kbytes = ffi::lua_gc(self.main_state, ffi::LUA_GCCOUNT, 0);
1093                    let used_kbytes_rem = ffi::lua_gc(self.main_state, ffi::LUA_GCCOUNTB, 0);
1094                    (used_kbytes as usize) * 1024 + (used_kbytes_rem as usize)
1095                }
1096            }
1097        }
1098    }
1099
1100    /// Sets a memory limit (in bytes) on this Lua state.
1101    ///
1102    /// Once an allocation occurs that would pass this memory limit,
1103    /// a `Error::MemoryError` is generated instead.
1104    /// Returns previous limit (zero means no limit).
1105    ///
1106    /// Does not work in module mode where Lua state is managed externally.
1107    pub fn set_memory_limit(&self, limit: usize) -> Result<usize> {
1108        unsafe {
1109            match MemoryState::get(self.main_state) {
1110                mem_state if !mem_state.is_null() => Ok((*mem_state).set_memory_limit(limit)),
1111                _ => Err(Error::MemoryLimitNotAvailable),
1112            }
1113        }
1114    }
1115
1116    /// Returns true if the garbage collector is currently running automatically.
1117    ///
1118    /// Requires `feature = "lua54/lua53/lua52/luau"`
1119    #[cfg(any(
1120        feature = "lua54",
1121        feature = "lua53",
1122        feature = "lua52",
1123        feature = "luau"
1124    ))]
1125    pub fn gc_is_running(&self) -> bool {
1126        unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCISRUNNING, 0) != 0 }
1127    }
1128
1129    /// Stop the Lua GC from running
1130    pub fn gc_stop(&self) {
1131        unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSTOP, 0) };
1132    }
1133
1134    /// Restarts the Lua GC if it is not running
1135    pub fn gc_restart(&self) {
1136        unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCRESTART, 0) };
1137    }
1138
1139    /// Perform a full garbage-collection cycle.
1140    ///
1141    /// It may be necessary to call this function twice to collect all currently unreachable
1142    /// objects. Once to finish the current gc cycle, and once to start and finish the next cycle.
1143    pub fn gc_collect(&self) -> Result<()> {
1144        unsafe {
1145            check_stack(self.main_state, 2)?;
1146            protect_lua!(self.main_state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
1147        }
1148    }
1149
1150    /// Steps the garbage collector one indivisible step.
1151    ///
1152    /// Returns true if this has finished a collection cycle.
1153    pub fn gc_step(&self) -> Result<bool> {
1154        self.gc_step_kbytes(0)
1155    }
1156
1157    /// Steps the garbage collector as though memory had been allocated.
1158    ///
1159    /// if `kbytes` is 0, then this is the same as calling `gc_step`. Returns true if this step has
1160    /// finished a collection cycle.
1161    pub fn gc_step_kbytes(&self, kbytes: c_int) -> Result<bool> {
1162        unsafe {
1163            check_stack(self.main_state, 3)?;
1164            protect_lua!(self.main_state, 0, 0, |state| {
1165                ffi::lua_gc(state, ffi::LUA_GCSTEP, kbytes) != 0
1166            })
1167        }
1168    }
1169
1170    /// Sets the 'pause' value of the collector.
1171    ///
1172    /// Returns the previous value of 'pause'. More information can be found in the Lua
1173    /// [documentation].
1174    ///
1175    /// For Luau this parameter sets GC goal
1176    ///
1177    /// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
1178    pub fn gc_set_pause(&self, pause: c_int) -> c_int {
1179        unsafe {
1180            #[cfg(not(feature = "luau"))]
1181            return ffi::lua_gc(self.main_state, ffi::LUA_GCSETPAUSE, pause);
1182            #[cfg(feature = "luau")]
1183            return ffi::lua_gc(self.main_state, ffi::LUA_GCSETGOAL, pause);
1184        }
1185    }
1186
1187    /// Sets the 'step multiplier' value of the collector.
1188    ///
1189    /// Returns the previous value of the 'step multiplier'. More information can be found in the
1190    /// Lua [documentation].
1191    ///
1192    /// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
1193    pub fn gc_set_step_multiplier(&self, step_multiplier: c_int) -> c_int {
1194        unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSETSTEPMUL, step_multiplier) }
1195    }
1196
1197    /// Changes the collector to incremental mode with the given parameters.
1198    ///
1199    /// Returns the previous mode (always `GCMode::Incremental` in Lua < 5.4).
1200    /// More information can be found in the Lua [documentation].
1201    ///
1202    /// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5.1
1203    pub fn gc_inc(&self, pause: c_int, step_multiplier: c_int, step_size: c_int) -> GCMode {
1204        let state = self.main_state;
1205
1206        #[cfg(any(
1207            feature = "lua53",
1208            feature = "lua52",
1209            feature = "lua51",
1210            feature = "luajit",
1211            feature = "luau"
1212        ))]
1213        unsafe {
1214            if pause > 0 {
1215                #[cfg(not(feature = "luau"))]
1216                ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, pause);
1217                #[cfg(feature = "luau")]
1218                ffi::lua_gc(state, ffi::LUA_GCSETGOAL, pause);
1219            }
1220
1221            if step_multiplier > 0 {
1222                ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, step_multiplier);
1223            }
1224
1225            #[cfg(feature = "luau")]
1226            if step_size > 0 {
1227                ffi::lua_gc(state, ffi::LUA_GCSETSTEPSIZE, step_size);
1228            }
1229            #[cfg(not(feature = "luau"))]
1230            let _ = step_size; // Ignored
1231
1232            GCMode::Incremental
1233        }
1234
1235        #[cfg(feature = "lua54")]
1236        let prev_mode =
1237            unsafe { ffi::lua_gc(state, ffi::LUA_GCINC, pause, step_multiplier, step_size) };
1238        #[cfg(feature = "lua54")]
1239        match prev_mode {
1240            ffi::LUA_GCINC => GCMode::Incremental,
1241            ffi::LUA_GCGEN => GCMode::Generational,
1242            _ => unreachable!(),
1243        }
1244    }
1245
1246    /// Changes the collector to generational mode with the given parameters.
1247    ///
1248    /// Returns the previous mode. More information about the generational GC
1249    /// can be found in the Lua 5.4 [documentation][lua_doc].
1250    ///
1251    /// Requires `feature = "lua54"`
1252    ///
1253    /// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5.2
1254    #[cfg(feature = "lua54")]
1255    #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
1256    pub fn gc_gen(&self, minor_multiplier: c_int, major_multiplier: c_int) -> GCMode {
1257        let state = self.main_state;
1258        let prev_mode =
1259            unsafe { ffi::lua_gc(state, ffi::LUA_GCGEN, minor_multiplier, major_multiplier) };
1260        match prev_mode {
1261            ffi::LUA_GCGEN => GCMode::Generational,
1262            ffi::LUA_GCINC => GCMode::Incremental,
1263            _ => unreachable!(),
1264        }
1265    }
1266
1267    /// Sets a default Luau compiler (with custom options).
1268    ///
1269    /// This compiler will be used by default to load all Lua chunks
1270    /// including via `require` function.
1271    ///
1272    /// See [`Compiler`] for details and possible options.
1273    ///
1274    /// Requires `feature = "luau"`
1275    #[cfg(any(feature = "luau", doc))]
1276    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1277    pub fn set_compiler(&self, compiler: Compiler) {
1278        unsafe { (*self.extra.get()).compiler = Some(compiler) };
1279    }
1280
1281    /// Toggles JIT compilation mode for new chunks of code.
1282    ///
1283    /// By default JIT is enabled. Changing this option does not have any effect on
1284    /// already loaded functions.
1285    #[cfg(any(feature = "luau-jit", doc))]
1286    #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1287    pub fn enable_jit(&self, enable: bool) {
1288        unsafe { (*self.extra.get()).enable_jit = enable };
1289    }
1290
1291    /// Sets Luau feature flag (global setting).
1292    ///
1293    /// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
1294    #[cfg(feature = "luau")]
1295    #[doc(hidden)]
1296    #[allow(clippy::result_unit_err)]
1297    pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
1298        if let Ok(name) = CString::new(name) {
1299            if unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 } {
1300                return Ok(());
1301            }
1302        }
1303        Err(())
1304    }
1305
1306    /// Returns Lua source code as a `Chunk` builder type.
1307    ///
1308    /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or
1309    /// similar on the returned builder. Code is not even parsed until one of these methods is
1310    /// called.
1311    ///
1312    /// [`Chunk::exec`]: crate::Chunk::exec
1313    #[track_caller]
1314    pub fn load<'lua, 'a>(&'lua self, chunk: impl AsChunk<'lua, 'a>) -> Chunk<'lua, 'a> {
1315        let caller = Location::caller();
1316        Chunk {
1317            lua: self,
1318            name: chunk.name().unwrap_or_else(|| caller.to_string()),
1319            env: chunk.environment(self),
1320            mode: chunk.mode(),
1321            source: chunk.source(),
1322            #[cfg(feature = "luau")]
1323            compiler: unsafe { (*self.extra.get()).compiler.clone() },
1324        }
1325    }
1326
1327    pub(crate) fn load_chunk<'lua>(
1328        &'lua self,
1329        name: Option<&CStr>,
1330        env: Option<Table>,
1331        mode: Option<ChunkMode>,
1332        source: &[u8],
1333    ) -> Result<Function<'lua>> {
1334        let state = self.state();
1335        unsafe {
1336            let _sg = StackGuard::new(state);
1337            check_stack(state, 1)?;
1338
1339            let mode_str = match mode {
1340                Some(ChunkMode::Binary) => cstr!("b"),
1341                Some(ChunkMode::Text) => cstr!("t"),
1342                None => cstr!("bt"),
1343            };
1344
1345            match ffi::luaL_loadbufferx(
1346                state,
1347                source.as_ptr() as *const c_char,
1348                source.len(),
1349                name.map(|n| n.as_ptr()).unwrap_or_else(ptr::null),
1350                mode_str,
1351            ) {
1352                ffi::LUA_OK => {
1353                    if let Some(env) = env {
1354                        self.push_ref(&env.0);
1355                        #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
1356                        ffi::lua_setupvalue(state, -2, 1);
1357                        #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1358                        ffi::lua_setfenv(state, -2);
1359                    }
1360
1361                    #[cfg(feature = "luau-jit")]
1362                    if (*self.extra.get()).enable_jit && ffi::luau_codegen_supported() != 0 {
1363                        ffi::luau_codegen_compile(state, -1);
1364                    }
1365
1366                    Ok(Function(self.pop_ref()))
1367                }
1368                err => Err(pop_error(state, err)),
1369            }
1370        }
1371    }
1372
1373    /// Create and return an interned Lua string. Lua strings can be arbitrary [u8] data including
1374    /// embedded nulls, so in addition to `&str` and `&String`, you can also pass plain `&[u8]`
1375    /// here.
1376    pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<String> {
1377        let state = self.state();
1378        unsafe {
1379            if self.unlikely_memory_error() {
1380                push_string(self.ref_thread(), s.as_ref(), false)?;
1381                return Ok(String(self.pop_ref_thread()));
1382            }
1383
1384            let _sg = StackGuard::new(state);
1385            check_stack(state, 3)?;
1386            push_string(state, s.as_ref(), true)?;
1387            Ok(String(self.pop_ref()))
1388        }
1389    }
1390
1391    /// Create and return a Luau [buffer] object from a byte slice of data.
1392    ///
1393    /// Requires `feature = "luau"`
1394    ///
1395    /// [buffer]: https://luau-lang.org/library#buffer-library
1396    #[cfg(feature = "luau")]
1397    pub fn create_buffer(&self, buf: impl AsRef<[u8]>) -> Result<AnyUserData> {
1398        let state = self.state();
1399        unsafe {
1400            if self.unlikely_memory_error() {
1401                crate::util::push_buffer(self.ref_thread(), buf.as_ref(), false)?;
1402                return Ok(AnyUserData(self.pop_ref_thread(), SubtypeId::Buffer));
1403            }
1404
1405            let _sg = StackGuard::new(state);
1406            check_stack(state, 4)?;
1407            crate::util::push_buffer(state, buf.as_ref(), true)?;
1408            Ok(AnyUserData(self.pop_ref(), SubtypeId::Buffer))
1409        }
1410    }
1411
1412    /// Creates and returns a new empty table.
1413    pub fn create_table(&self) -> Result<Table> {
1414        self.create_table_with_capacity(0, 0)
1415    }
1416
1417    /// Creates and returns a new empty table, with the specified capacity.
1418    /// `narr` is a hint for how many elements the table will have as a sequence;
1419    /// `nrec` is a hint for how many other elements the table will have.
1420    /// Lua may use these hints to preallocate memory for the new table.
1421    pub fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
1422        let state = self.state();
1423        unsafe {
1424            if self.unlikely_memory_error() {
1425                push_table(self.ref_thread(), narr, nrec, false)?;
1426                return Ok(Table(self.pop_ref_thread()));
1427            }
1428
1429            let _sg = StackGuard::new(state);
1430            check_stack(state, 3)?;
1431            push_table(state, narr, nrec, true)?;
1432            Ok(Table(self.pop_ref()))
1433        }
1434    }
1435
1436    /// Creates a table and fills it with values from an iterator.
1437    pub fn create_table_from<'lua, K, V, I>(&'lua self, iter: I) -> Result<Table<'lua>>
1438    where
1439        K: IntoLua<'lua>,
1440        V: IntoLua<'lua>,
1441        I: IntoIterator<Item = (K, V)>,
1442    {
1443        let state = self.state();
1444        unsafe {
1445            let _sg = StackGuard::new(state);
1446            check_stack(state, 6)?;
1447
1448            let iter = iter.into_iter();
1449            let lower_bound = iter.size_hint().0;
1450            let protect = !self.unlikely_memory_error();
1451            push_table(state, 0, lower_bound, protect)?;
1452            for (k, v) in iter {
1453                self.push(k)?;
1454                self.push(v)?;
1455                if protect {
1456                    protect_lua!(state, 3, 1, fn(state) ffi::lua_rawset(state, -3))?;
1457                } else {
1458                    ffi::lua_rawset(state, -3);
1459                }
1460            }
1461
1462            Ok(Table(self.pop_ref()))
1463        }
1464    }
1465
1466    /// Creates a table from an iterator of values, using `1..` as the keys.
1467    pub fn create_sequence_from<'lua, T, I>(&'lua self, iter: I) -> Result<Table<'lua>>
1468    where
1469        T: IntoLua<'lua>,
1470        I: IntoIterator<Item = T>,
1471    {
1472        let state = self.state();
1473        unsafe {
1474            let _sg = StackGuard::new(state);
1475            check_stack(state, 5)?;
1476
1477            let iter = iter.into_iter();
1478            let lower_bound = iter.size_hint().0;
1479            let protect = !self.unlikely_memory_error();
1480            push_table(state, lower_bound, 0, protect)?;
1481            for (i, v) in iter.enumerate() {
1482                self.push(v)?;
1483                if protect {
1484                    protect_lua!(state, 2, 1, |state| {
1485                        ffi::lua_rawseti(state, -2, (i + 1) as Integer);
1486                    })?;
1487                } else {
1488                    ffi::lua_rawseti(state, -2, (i + 1) as Integer);
1489                }
1490            }
1491
1492            Ok(Table(self.pop_ref()))
1493        }
1494    }
1495
1496    /// Wraps a Rust function or closure, creating a callable Lua function handle to it.
1497    ///
1498    /// The function's return value is always a `Result`: If the function returns `Err`, the error
1499    /// is raised as a Lua error, which can be caught using `(x)pcall` or bubble up to the Rust code
1500    /// that invoked the Lua code. This allows using the `?` operator to propagate errors through
1501    /// intermediate Lua code.
1502    ///
1503    /// If the function returns `Ok`, the contained value will be converted to one or more Lua
1504    /// values. For details on Rust-to-Lua conversions, refer to the [`IntoLua`] and [`IntoLuaMulti`]
1505    /// traits.
1506    ///
1507    /// # Examples
1508    ///
1509    /// Create a function which prints its argument:
1510    ///
1511    /// ```
1512    /// # use mlua::{Lua, Result};
1513    /// # fn main() -> Result<()> {
1514    /// # let lua = Lua::new();
1515    /// let greet = lua.create_function(|_, name: String| {
1516    ///     println!("Hello, {}!", name);
1517    ///     Ok(())
1518    /// });
1519    /// # let _ = greet;    // used
1520    /// # Ok(())
1521    /// # }
1522    /// ```
1523    ///
1524    /// Use tuples to accept multiple arguments:
1525    ///
1526    /// ```
1527    /// # use mlua::{Lua, Result};
1528    /// # fn main() -> Result<()> {
1529    /// # let lua = Lua::new();
1530    /// let print_person = lua.create_function(|_, (name, age): (String, u8)| {
1531    ///     println!("{} is {} years old!", name, age);
1532    ///     Ok(())
1533    /// });
1534    /// # let _ = print_person;    // used
1535    /// # Ok(())
1536    /// # }
1537    /// ```
1538    ///
1539    /// [`IntoLua`]: crate::IntoLua
1540    /// [`IntoLuaMulti`]: crate::IntoLuaMulti
1541    pub fn create_function<'lua, A, R, F>(&'lua self, func: F) -> Result<Function<'lua>>
1542    where
1543        A: FromLuaMulti<'lua>,
1544        R: IntoLuaMulti<'lua>,
1545        F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
1546    {
1547        self.create_callback(Box::new(move |lua, nargs| unsafe {
1548            let args = A::from_stack_args(nargs, 1, None, lua)?;
1549            func(lua, args)?.push_into_stack_multi(lua)
1550        }))
1551    }
1552
1553    /// Wraps a Rust mutable closure, creating a callable Lua function handle to it.
1554    ///
1555    /// This is a version of [`create_function`] that accepts a FnMut argument. Refer to
1556    /// [`create_function`] for more information about the implementation.
1557    ///
1558    /// [`create_function`]: #method.create_function
1559    pub fn create_function_mut<'lua, A, R, F>(&'lua self, func: F) -> Result<Function<'lua>>
1560    where
1561        A: FromLuaMulti<'lua>,
1562        R: IntoLuaMulti<'lua>,
1563        F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
1564    {
1565        let func = RefCell::new(func);
1566        self.create_function(move |lua, args| {
1567            (*func
1568                .try_borrow_mut()
1569                .map_err(|_| Error::RecursiveMutCallback)?)(lua, args)
1570        })
1571    }
1572
1573    /// Wraps a C function, creating a callable Lua function handle to it.
1574    ///
1575    /// # Safety
1576    /// This function is unsafe because provides a way to execute unsafe C function.
1577    pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
1578        let state = self.state();
1579        check_stack(state, 1)?;
1580        ffi::lua_pushcfunction(state, func);
1581        Ok(Function(self.pop_ref()))
1582    }
1583
1584    /// Wraps a Rust async function or closure, creating a callable Lua function handle to it.
1585    ///
1586    /// While executing the function Rust will poll Future and if the result is not ready, call
1587    /// `yield()` passing internal representation of a `Poll::Pending` value.
1588    ///
1589    /// The function must be called inside Lua coroutine ([`Thread`]) to be able to suspend its execution.
1590    /// An executor should be used to poll [`AsyncThread`] and mlua will take a provided Waker
1591    /// in that case. Otherwise noop waker will be used if try to call the function outside of Rust
1592    /// executors.
1593    ///
1594    /// The family of `call_async()` functions takes care about creating [`Thread`].
1595    ///
1596    /// Requires `feature = "async"`
1597    ///
1598    /// # Examples
1599    ///
1600    /// Non blocking sleep:
1601    ///
1602    /// ```
1603    /// use std::time::Duration;
1604    /// use mlua::{Lua, Result};
1605    ///
1606    /// async fn sleep(_lua: &Lua, n: u64) -> Result<&'static str> {
1607    ///     tokio::time::sleep(Duration::from_millis(n)).await;
1608    ///     Ok("done")
1609    /// }
1610    ///
1611    /// #[tokio::main]
1612    /// async fn main() -> Result<()> {
1613    ///     let lua = Lua::new();
1614    ///     lua.globals().set("sleep", lua.create_async_function(sleep)?)?;
1615    ///     let res: String = lua.load("return sleep(...)").call_async(100).await?; // Sleep 100ms
1616    ///     assert_eq!(res, "done");
1617    ///     Ok(())
1618    /// }
1619    /// ```
1620    ///
1621    /// [`Thread`]: crate::Thread
1622    /// [`AsyncThread`]: crate::AsyncThread
1623    #[cfg(feature = "async")]
1624    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1625    pub fn create_async_function<'lua, A, R, F, FR>(&'lua self, func: F) -> Result<Function<'lua>>
1626    where
1627        A: FromLuaMulti<'lua>,
1628        R: IntoLuaMulti<'lua>,
1629        F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
1630        FR: Future<Output = Result<R>> + 'lua,
1631    {
1632        self.create_async_callback(Box::new(move |lua, args| unsafe {
1633            let args = match A::from_lua_args(args, 1, None, lua) {
1634                Ok(args) => args,
1635                Err(e) => return Box::pin(future::err(e)),
1636            };
1637            let fut = func(lua, args);
1638            Box::pin(async move { fut.await?.push_into_stack_multi(lua) })
1639        }))
1640    }
1641
1642    /// Wraps a Lua function into a new thread (or coroutine).
1643    ///
1644    /// Equivalent to `coroutine.create`.
1645    pub fn create_thread<'lua>(&'lua self, func: Function) -> Result<Thread<'lua>> {
1646        self.create_thread_inner(&func)
1647    }
1648
1649    /// Wraps a Lua function into a new thread (or coroutine).
1650    ///
1651    /// Takes function by reference.
1652    fn create_thread_inner<'lua>(&'lua self, func: &Function) -> Result<Thread<'lua>> {
1653        let state = self.state();
1654        unsafe {
1655            let _sg = StackGuard::new(state);
1656            check_stack(state, 3)?;
1657
1658            let thread_state = if self.unlikely_memory_error() {
1659                ffi::lua_newthread(state)
1660            } else {
1661                protect_lua!(state, 0, 1, |state| ffi::lua_newthread(state))?
1662            };
1663            self.push_ref(&func.0);
1664            ffi::lua_xmove(state, thread_state, 1);
1665
1666            Ok(Thread::new(self.pop_ref()))
1667        }
1668    }
1669
1670    /// Wraps a Lua function into a new or recycled thread (coroutine).
1671    #[cfg(feature = "async")]
1672    pub(crate) fn create_recycled_thread<'lua>(
1673        &'lua self,
1674        func: &Function,
1675    ) -> Result<Thread<'lua>> {
1676        #[cfg(any(feature = "lua54", feature = "luau"))]
1677        unsafe {
1678            let state = self.state();
1679            let _sg = StackGuard::new(state);
1680            check_stack(state, 1)?;
1681
1682            if let Some(index) = (*self.extra.get()).thread_pool.pop() {
1683                let thread_state = ffi::lua_tothread(self.ref_thread(), index);
1684                self.push_ref(&func.0);
1685                ffi::lua_xmove(state, thread_state, 1);
1686
1687                #[cfg(feature = "luau")]
1688                {
1689                    // Inherit `LUA_GLOBALSINDEX` from the caller
1690                    ffi::lua_xpush(state, thread_state, ffi::LUA_GLOBALSINDEX);
1691                    ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
1692                }
1693
1694                return Ok(Thread::new(LuaRef::new(self, index)));
1695            }
1696        };
1697        self.create_thread_inner(func)
1698    }
1699
1700    /// Resets thread (coroutine) and returns to the pool for later use.
1701    #[cfg(feature = "async")]
1702    #[cfg(any(feature = "lua54", feature = "luau"))]
1703    pub(crate) unsafe fn recycle_thread(&self, thread: &mut Thread) -> bool {
1704        let extra = &mut *self.extra.get();
1705        if extra.thread_pool.len() < extra.thread_pool.capacity() {
1706            let thread_state = ffi::lua_tothread(extra.ref_thread, thread.0.index);
1707            #[cfg(all(feature = "lua54", not(feature = "vendored")))]
1708            let status = ffi::lua_resetthread(thread_state);
1709            #[cfg(all(feature = "lua54", feature = "vendored"))]
1710            let status = ffi::lua_closethread(thread_state, self.state());
1711            #[cfg(feature = "lua54")]
1712            if status != ffi::LUA_OK {
1713                // Error object is on top, drop it
1714                ffi::lua_settop(thread_state, 0);
1715            }
1716            #[cfg(feature = "luau")]
1717            ffi::lua_resetthread(thread_state);
1718            extra.thread_pool.push(thread.0.index);
1719            thread.0.drop = false;
1720            return true;
1721        }
1722        false
1723    }
1724
1725    /// Creates a Lua userdata object from a custom userdata type.
1726    ///
1727    /// All userdata instances of the same type `T` shares the same metatable.
1728    #[inline]
1729    pub fn create_userdata<T>(&self, data: T) -> Result<AnyUserData>
1730    where
1731        T: UserData + MaybeSend + 'static,
1732    {
1733        unsafe { self.make_userdata(UserDataCell::new(data)) }
1734    }
1735
1736    /// Creates a Lua userdata object from a custom serializable userdata type.
1737    ///
1738    /// Requires `feature = "serialize"`
1739    #[cfg(feature = "serialize")]
1740    #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
1741    #[inline]
1742    pub fn create_ser_userdata<T>(&self, data: T) -> Result<AnyUserData>
1743    where
1744        T: UserData + Serialize + MaybeSend + 'static,
1745    {
1746        unsafe { self.make_userdata(UserDataCell::new_ser(data)) }
1747    }
1748
1749    /// Creates a Lua userdata object from a custom Rust type.
1750    ///
1751    /// You can register the type using [`Lua::register_userdata_type()`] to add fields or methods
1752    /// _before_ calling this method.
1753    /// Otherwise, the userdata object will have an empty metatable.
1754    ///
1755    /// All userdata instances of the same type `T` shares the same metatable.
1756    #[inline]
1757    pub fn create_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1758    where
1759        T: MaybeSend + 'static,
1760    {
1761        unsafe { self.make_any_userdata(UserDataCell::new(data)) }
1762    }
1763
1764    /// Creates a Lua userdata object from a custom serializable Rust type.
1765    ///
1766    /// See [`Lua::create_any_userdata()`] for more details.
1767    ///
1768    /// Requires `feature = "serialize"`
1769    #[cfg(feature = "serialize")]
1770    #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
1771    #[inline]
1772    pub fn create_ser_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1773    where
1774        T: Serialize + MaybeSend + 'static,
1775    {
1776        unsafe { self.make_any_userdata(UserDataCell::new_ser(data)) }
1777    }
1778
1779    /// Registers a custom Rust type in Lua to use in userdata objects.
1780    ///
1781    /// This methods provides a way to add fields or methods to userdata objects of a type `T`.
1782    pub fn register_userdata_type<T: 'static>(
1783        &self,
1784        f: impl FnOnce(&mut UserDataRegistry<T>),
1785    ) -> Result<()> {
1786        let mut registry = UserDataRegistry::new();
1787        f(&mut registry);
1788
1789        unsafe {
1790            // Deregister the type if it already registered
1791            let type_id = TypeId::of::<T>();
1792            if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
1793                ffi::luaL_unref(self.state(), ffi::LUA_REGISTRYINDEX, table_id);
1794            }
1795
1796            // Register the type
1797            self.register_userdata_metatable(registry)?;
1798            Ok(())
1799        }
1800    }
1801
1802    /// Create a Lua userdata "proxy" object from a custom userdata type.
1803    ///
1804    /// Proxy object is an empty userdata object that has `T` metatable attached.
1805    /// The main purpose of this object is to provide access to static fields and functions
1806    /// without creating an instance of type `T`.
1807    ///
1808    /// You can get or set uservalues on this object but you cannot borrow any Rust type.
1809    ///
1810    /// # Examples
1811    ///
1812    /// ```
1813    /// # use mlua::{Lua, Result, UserData, UserDataFields, UserDataMethods};
1814    /// # fn main() -> Result<()> {
1815    /// # let lua = Lua::new();
1816    /// struct MyUserData(i32);
1817    ///
1818    /// impl UserData for MyUserData {
1819    ///     fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
1820    ///         fields.add_field_method_get("val", |_, this| Ok(this.0));
1821    ///     }
1822    ///
1823    ///     fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
1824    ///         methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
1825    ///     }
1826    /// }
1827    ///
1828    /// lua.globals().set("MyUserData", lua.create_proxy::<MyUserData>()?)?;
1829    ///
1830    /// lua.load("assert(MyUserData.new(321).val == 321)").exec()?;
1831    /// # Ok(())
1832    /// # }
1833    /// ```
1834    #[inline]
1835    pub fn create_proxy<T>(&self) -> Result<AnyUserData>
1836    where
1837        T: UserData + 'static,
1838    {
1839        unsafe { self.make_userdata(UserDataCell::new(UserDataProxy::<T>(PhantomData))) }
1840    }
1841
1842    /// Sets the metatable for a Luau builtin vector type.
1843    #[cfg(any(all(feature = "luau", feature = "unstable"), doc))]
1844    #[cfg_attr(docsrs, doc(cfg(all(feature = "luau", feature = "unstable"))))]
1845    pub fn set_vector_metatable(&self, metatable: Option<Table>) {
1846        unsafe {
1847            let state = self.state();
1848            let _sg = StackGuard::new(state);
1849            assert_stack(state, 2);
1850
1851            #[cfg(not(feature = "luau-vector4"))]
1852            ffi::lua_pushvector(state, 0., 0., 0.);
1853            #[cfg(feature = "luau-vector4")]
1854            ffi::lua_pushvector(state, 0., 0., 0., 0.);
1855            match metatable {
1856                Some(metatable) => self.push_ref(&metatable.0),
1857                None => ffi::lua_pushnil(state),
1858            };
1859            ffi::lua_setmetatable(state, -2);
1860        }
1861    }
1862
1863    /// Returns a handle to the global environment.
1864    pub fn globals(&self) -> Table {
1865        let state = self.state();
1866        unsafe {
1867            let _sg = StackGuard::new(state);
1868            assert_stack(state, 1);
1869            #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
1870            ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1871            #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1872            ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
1873            Table(self.pop_ref())
1874        }
1875    }
1876
1877    /// Returns a handle to the active `Thread`. For calls to `Lua` this will be the main Lua thread,
1878    /// for parameters given to a callback, this will be whatever Lua thread called the callback.
1879    pub fn current_thread(&self) -> Thread {
1880        let state = self.state();
1881        unsafe {
1882            let _sg = StackGuard::new(state);
1883            assert_stack(state, 1);
1884            ffi::lua_pushthread(state);
1885            Thread::new(self.pop_ref())
1886        }
1887    }
1888
1889    /// Calls the given function with a `Scope` parameter, giving the function the ability to create
1890    /// userdata and callbacks from rust types that are !Send or non-'static.
1891    ///
1892    /// The lifetime of any function or userdata created through `Scope` lasts only until the
1893    /// completion of this method call, on completion all such created values are automatically
1894    /// dropped and Lua references to them are invalidated. If a script accesses a value created
1895    /// through `Scope` outside of this method, a Lua error will result. Since we can ensure the
1896    /// lifetime of values created through `Scope`, and we know that `Lua` cannot be sent to another
1897    /// thread while `Scope` is live, it is safe to allow !Send datatypes and whose lifetimes only
1898    /// outlive the scope lifetime.
1899    ///
1900    /// Inside the scope callback, all handles created through Scope will share the same unique 'lua
1901    /// lifetime of the parent `Lua`. This allows scoped and non-scoped values to be mixed in
1902    /// API calls, which is very useful (e.g. passing a scoped userdata to a non-scoped function).
1903    /// However, this also enables handles to scoped values to be trivially leaked from the given
1904    /// callback. This is not dangerous, though!  After the callback returns, all scoped values are
1905    /// invalidated, which means that though references may exist, the Rust types backing them have
1906    /// dropped. `Function` types will error when called, and `AnyUserData` will be typeless. It
1907    /// would be impossible to prevent handles to scoped values from escaping anyway, since you
1908    /// would always be able to smuggle them through Lua state.
1909    pub fn scope<'lua, 'scope, R>(
1910        &'lua self,
1911        f: impl FnOnce(&Scope<'lua, 'scope>) -> Result<R>,
1912    ) -> Result<R>
1913    where
1914        'lua: 'scope,
1915    {
1916        f(&Scope::new(self))
1917    }
1918
1919    /// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
1920    /// behavior.
1921    ///
1922    /// To succeed, the value must be a string (in which case this is a no-op), an integer, or a
1923    /// number.
1924    pub fn coerce_string<'lua>(&'lua self, v: Value<'lua>) -> Result<Option<String<'lua>>> {
1925        Ok(match v {
1926            Value::String(s) => Some(s),
1927            v => unsafe {
1928                let state = self.state();
1929                let _sg = StackGuard::new(state);
1930                check_stack(state, 4)?;
1931
1932                self.push_value(v)?;
1933                let res = if self.unlikely_memory_error() {
1934                    ffi::lua_tolstring(state, -1, ptr::null_mut())
1935                } else {
1936                    protect_lua!(state, 1, 1, |state| {
1937                        ffi::lua_tolstring(state, -1, ptr::null_mut())
1938                    })?
1939                };
1940                if !res.is_null() {
1941                    Some(String(self.pop_ref()))
1942                } else {
1943                    None
1944                }
1945            },
1946        })
1947    }
1948
1949    /// Attempts to coerce a Lua value into an integer in a manner consistent with Lua's internal
1950    /// behavior.
1951    ///
1952    /// To succeed, the value must be an integer, a floating point number that has an exact
1953    /// representation as an integer, or a string that can be converted to an integer. Refer to the
1954    /// Lua manual for details.
1955    pub fn coerce_integer(&self, v: Value) -> Result<Option<Integer>> {
1956        Ok(match v {
1957            Value::Integer(i) => Some(i),
1958            v => unsafe {
1959                let state = self.state();
1960                let _sg = StackGuard::new(state);
1961                check_stack(state, 2)?;
1962
1963                self.push_value(v)?;
1964                let mut isint = 0;
1965                let i = ffi::lua_tointegerx(state, -1, &mut isint);
1966                if isint == 0 {
1967                    None
1968                } else {
1969                    Some(i)
1970                }
1971            },
1972        })
1973    }
1974
1975    /// Attempts to coerce a Lua value into a Number in a manner consistent with Lua's internal
1976    /// behavior.
1977    ///
1978    /// To succeed, the value must be a number or a string that can be converted to a number. Refer
1979    /// to the Lua manual for details.
1980    pub fn coerce_number(&self, v: Value) -> Result<Option<Number>> {
1981        Ok(match v {
1982            Value::Number(n) => Some(n),
1983            v => unsafe {
1984                let state = self.state();
1985                let _sg = StackGuard::new(state);
1986                check_stack(state, 2)?;
1987
1988                self.push_value(v)?;
1989                let mut isnum = 0;
1990                let n = ffi::lua_tonumberx(state, -1, &mut isnum);
1991                if isnum == 0 {
1992                    None
1993                } else {
1994                    Some(n)
1995                }
1996            },
1997        })
1998    }
1999
2000    /// Converts a value that implements `IntoLua` into a `Value` instance.
2001    pub fn pack<'lua, T: IntoLua<'lua>>(&'lua self, t: T) -> Result<Value<'lua>> {
2002        t.into_lua(self)
2003    }
2004
2005    /// Converts a `Value` instance into a value that implements `FromLua`.
2006    pub fn unpack<'lua, T: FromLua<'lua>>(&'lua self, value: Value<'lua>) -> Result<T> {
2007        T::from_lua(value, self)
2008    }
2009
2010    /// Converts a value that implements `IntoLuaMulti` into a `MultiValue` instance.
2011    pub fn pack_multi<'lua, T: IntoLuaMulti<'lua>>(&'lua self, t: T) -> Result<MultiValue<'lua>> {
2012        t.into_lua_multi(self)
2013    }
2014
2015    /// Converts a `MultiValue` instance into a value that implements `FromLuaMulti`.
2016    pub fn unpack_multi<'lua, T: FromLuaMulti<'lua>>(
2017        &'lua self,
2018        value: MultiValue<'lua>,
2019    ) -> Result<T> {
2020        T::from_lua_multi(value, self)
2021    }
2022
2023    /// Set a value in the Lua registry based on a string name.
2024    ///
2025    /// This value will be available to rust from all `Lua` instances which share the same main
2026    /// state.
2027    pub fn set_named_registry_value<'lua, T>(&'lua self, name: &str, t: T) -> Result<()>
2028    where
2029        T: IntoLua<'lua>,
2030    {
2031        let state = self.state();
2032        unsafe {
2033            let _sg = StackGuard::new(state);
2034            check_stack(state, 5)?;
2035
2036            self.push(t)?;
2037            rawset_field(state, ffi::LUA_REGISTRYINDEX, name)
2038        }
2039    }
2040
2041    /// Get a value from the Lua registry based on a string name.
2042    ///
2043    /// Any Lua instance which shares the underlying main state may call this method to
2044    /// get a value previously set by [`set_named_registry_value`].
2045    ///
2046    /// [`set_named_registry_value`]: #method.set_named_registry_value
2047    pub fn named_registry_value<'lua, T>(&'lua self, name: &str) -> Result<T>
2048    where
2049        T: FromLua<'lua>,
2050    {
2051        let state = self.state();
2052        unsafe {
2053            let _sg = StackGuard::new(state);
2054            check_stack(state, 3)?;
2055
2056            let protect = !self.unlikely_memory_error();
2057            push_string(state, name.as_bytes(), protect)?;
2058            ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
2059
2060            T::from_stack(-1, self)
2061        }
2062    }
2063
2064    /// Removes a named value in the Lua registry.
2065    ///
2066    /// Equivalent to calling [`set_named_registry_value`] with a value of Nil.
2067    ///
2068    /// [`set_named_registry_value`]: #method.set_named_registry_value
2069    pub fn unset_named_registry_value(&self, name: &str) -> Result<()> {
2070        self.set_named_registry_value(name, Nil)
2071    }
2072
2073    /// Place a value in the Lua registry with an auto-generated key.
2074    ///
2075    /// This value will be available to Rust from all `Lua` instances which share the same main
2076    /// state.
2077    ///
2078    /// Be warned, garbage collection of values held inside the registry is not automatic, see
2079    /// [`RegistryKey`] for more details.
2080    /// However, dropped [`RegistryKey`]s automatically reused to store new values.
2081    ///
2082    /// [`RegistryKey`]: crate::RegistryKey
2083    pub fn create_registry_value<'lua, T: IntoLua<'lua>>(&'lua self, t: T) -> Result<RegistryKey> {
2084        let state = self.state();
2085        unsafe {
2086            let _sg = StackGuard::new(state);
2087            check_stack(state, 4)?;
2088
2089            self.push(t)?;
2090
2091            let unref_list = (*self.extra.get()).registry_unref_list.clone();
2092
2093            // Check if the value is nil (no need to store it in the registry)
2094            if ffi::lua_isnil(state, -1) != 0 {
2095                return Ok(RegistryKey::new(ffi::LUA_REFNIL, unref_list));
2096            }
2097
2098            // Try to reuse previously allocated slot
2099            let free_registry_id = mlua_expect!(unref_list.lock(), "unref list poisoned")
2100                .as_mut()
2101                .and_then(|x| x.pop());
2102            if let Some(registry_id) = free_registry_id {
2103                // It must be safe to replace the value without triggering memory error
2104                ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2105                return Ok(RegistryKey::new(registry_id, unref_list));
2106            }
2107
2108            // Allocate a new RegistryKey slot
2109            let registry_id = if self.unlikely_memory_error() {
2110                ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
2111            } else {
2112                protect_lua!(state, 1, 0, |state| {
2113                    ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
2114                })?
2115            };
2116            Ok(RegistryKey::new(registry_id, unref_list))
2117        }
2118    }
2119
2120    /// Get a value from the Lua registry by its `RegistryKey`
2121    ///
2122    /// Any Lua instance which shares the underlying main state may call this method to get a value
2123    /// previously placed by [`create_registry_value`].
2124    ///
2125    /// [`create_registry_value`]: #method.create_registry_value
2126    pub fn registry_value<'lua, T: FromLua<'lua>>(&'lua self, key: &RegistryKey) -> Result<T> {
2127        if !self.owns_registry_value(key) {
2128            return Err(Error::MismatchedRegistryKey);
2129        }
2130
2131        let state = self.state();
2132        match key.id() {
2133            ffi::LUA_REFNIL => T::from_lua(Value::Nil, self),
2134            registry_id => unsafe {
2135                let _sg = StackGuard::new(state);
2136                check_stack(state, 1)?;
2137
2138                ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2139                T::from_stack(-1, self)
2140            },
2141        }
2142    }
2143
2144    /// Removes a value from the Lua registry.
2145    ///
2146    /// You may call this function to manually remove a value placed in the registry with
2147    /// [`create_registry_value`]. In addition to manual `RegistryKey` removal, you can also call
2148    /// [`expire_registry_values`] to automatically remove values from the registry whose
2149    /// `RegistryKey`s have been dropped.
2150    ///
2151    /// [`create_registry_value`]: #method.create_registry_value
2152    /// [`expire_registry_values`]: #method.expire_registry_values
2153    pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
2154        if !self.owns_registry_value(&key) {
2155            return Err(Error::MismatchedRegistryKey);
2156        }
2157
2158        unsafe {
2159            ffi::luaL_unref(self.state(), ffi::LUA_REGISTRYINDEX, key.take());
2160        }
2161        Ok(())
2162    }
2163
2164    /// Replaces a value in the Lua registry by its `RegistryKey`.
2165    ///
2166    /// See [`create_registry_value`] for more details.
2167    ///
2168    /// [`create_registry_value`]: #method.create_registry_value
2169    pub fn replace_registry_value<'lua, T: IntoLua<'lua>>(
2170        &'lua self,
2171        key: &RegistryKey,
2172        t: T,
2173    ) -> Result<()> {
2174        if !self.owns_registry_value(key) {
2175            return Err(Error::MismatchedRegistryKey);
2176        }
2177
2178        let t = t.into_lua(self)?;
2179
2180        let state = self.state();
2181        unsafe {
2182            let _sg = StackGuard::new(state);
2183            check_stack(state, 2)?;
2184
2185            match (t, key.id()) {
2186                (Value::Nil, ffi::LUA_REFNIL) => {
2187                    // Do nothing, no need to replace nil with nil
2188                }
2189                (Value::Nil, registry_id) => {
2190                    // Remove the value
2191                    ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, registry_id);
2192                    key.set_id(ffi::LUA_REFNIL);
2193                }
2194                (value, ffi::LUA_REFNIL) => {
2195                    // Allocate a new `RegistryKey`
2196                    let new_key = self.create_registry_value(value)?;
2197                    key.set_id(new_key.take());
2198                }
2199                (value, registry_id) => {
2200                    // It must be safe to replace the value without triggering memory error
2201                    self.push_value(value)?;
2202                    ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2203                }
2204            }
2205        }
2206        Ok(())
2207    }
2208
2209    /// Returns true if the given `RegistryKey` was created by a `Lua` which shares the underlying
2210    /// main state with this `Lua` instance.
2211    ///
2212    /// Other than this, methods that accept a `RegistryKey` will return
2213    /// `Error::MismatchedRegistryKey` if passed a `RegistryKey` that was not created with a
2214    /// matching `Lua` state.
2215    pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
2216        let registry_unref_list = unsafe { &(*self.extra.get()).registry_unref_list };
2217        Arc::ptr_eq(&key.unref_list, registry_unref_list)
2218    }
2219
2220    /// Remove any registry values whose `RegistryKey`s have all been dropped.
2221    ///
2222    /// Unlike normal handle values, `RegistryKey`s do not automatically remove themselves on Drop,
2223    /// but you can call this method to remove any unreachable registry values not manually removed
2224    /// by `Lua::remove_registry_value`.
2225    pub fn expire_registry_values(&self) {
2226        let state = self.state();
2227        unsafe {
2228            let mut unref_list = mlua_expect!(
2229                (*self.extra.get()).registry_unref_list.lock(),
2230                "unref list poisoned"
2231            );
2232            let unref_list = mem::replace(&mut *unref_list, Some(Vec::new()));
2233            for id in mlua_expect!(unref_list, "unref list not set") {
2234                ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
2235            }
2236        }
2237    }
2238
2239    /// Sets or replaces an application data object of type `T`.
2240    ///
2241    /// Application data could be accessed at any time by using [`Lua::app_data_ref()`] or [`Lua::app_data_mut()`]
2242    /// methods where `T` is the data type.
2243    ///
2244    /// # Panics
2245    ///
2246    /// Panics if the app data container is currently borrowed.
2247    ///
2248    /// # Examples
2249    ///
2250    /// ```
2251    /// use mlua::{Lua, Result};
2252    ///
2253    /// fn hello(lua: &Lua, _: ()) -> Result<()> {
2254    ///     let mut s = lua.app_data_mut::<&str>().unwrap();
2255    ///     assert_eq!(*s, "hello");
2256    ///     *s = "world";
2257    ///     Ok(())
2258    /// }
2259    ///
2260    /// fn main() -> Result<()> {
2261    ///     let lua = Lua::new();
2262    ///     lua.set_app_data("hello");
2263    ///     lua.create_function(hello)?.call(())?;
2264    ///     let s = lua.app_data_ref::<&str>().unwrap();
2265    ///     assert_eq!(*s, "world");
2266    ///     Ok(())
2267    /// }
2268    /// ```
2269    #[track_caller]
2270    pub fn set_app_data<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
2271        let extra = unsafe { &*self.extra.get() };
2272        extra.app_data.insert(data)
2273    }
2274
2275    /// Tries to set or replace an application data object of type `T`.
2276    ///
2277    /// Returns:
2278    /// - `Ok(Some(old_data))` if the data object of type `T` was successfully replaced.
2279    /// - `Ok(None)` if the data object of type `T` was successfully inserted.
2280    /// - `Err(data)` if the data object of type `T` was not inserted because the container is currently borrowed.
2281    ///
2282    /// See [`Lua::set_app_data()`] for examples.
2283    pub fn try_set_app_data<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
2284        let extra = unsafe { &*self.extra.get() };
2285        extra.app_data.try_insert(data)
2286    }
2287
2288    /// Gets a reference to an application data object stored by [`Lua::set_app_data()`] of type `T`.
2289    ///
2290    /// # Panics
2291    ///
2292    /// Panics if the data object of type `T` is currently mutably borrowed. Multiple immutable reads
2293    /// can be taken out at the same time.
2294    #[track_caller]
2295    pub fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<T>> {
2296        let extra = unsafe { &*self.extra.get() };
2297        extra.app_data.borrow()
2298    }
2299
2300    /// Gets a mutable reference to an application data object stored by [`Lua::set_app_data()`] of type `T`.
2301    ///
2302    /// # Panics
2303    ///
2304    /// Panics if the data object of type `T` is currently borrowed.
2305    #[track_caller]
2306    pub fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<T>> {
2307        let extra = unsafe { &*self.extra.get() };
2308        extra.app_data.borrow_mut()
2309    }
2310
2311    /// Removes an application data of type `T`.
2312    ///
2313    /// # Panics
2314    ///
2315    /// Panics if the app data container is currently borrowed.
2316    #[track_caller]
2317    pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
2318        let extra = unsafe { &*self.extra.get() };
2319        extra.app_data.remove()
2320    }
2321
2322    /// Pushes a value that implements `IntoLua` onto the Lua stack.
2323    ///
2324    /// Uses 2 stack spaces, does not call checkstack.
2325    #[doc(hidden)]
2326    #[inline(always)]
2327    pub unsafe fn push<'lua>(&'lua self, value: impl IntoLua<'lua>) -> Result<()> {
2328        value.push_into_stack(self)
2329    }
2330
2331    /// Pushes a `Value` onto the Lua stack.
2332    ///
2333    /// Uses 2 stack spaces, does not call checkstack.
2334    #[doc(hidden)]
2335    pub unsafe fn push_value(&self, value: Value) -> Result<()> {
2336        if let Value::Error(err) = value {
2337            let protect = !self.unlikely_memory_error();
2338            return push_gc_userdata(self.state(), WrappedFailure::Error(err), protect);
2339        }
2340        self.push_value_ref(&value)
2341    }
2342
2343    /// Pushes a `&Value` (by reference) onto the Lua stack.
2344    ///
2345    /// Similar to [`Lua::push_value`], uses 2 stack spaces, does not call checkstack.
2346    pub(crate) unsafe fn push_value_ref(&self, value: &Value) -> Result<()> {
2347        let state = self.state();
2348        match value {
2349            Value::Nil => ffi::lua_pushnil(state),
2350            Value::Boolean(b) => ffi::lua_pushboolean(state, *b as c_int),
2351            Value::LightUserData(ud) => ffi::lua_pushlightuserdata(state, ud.0),
2352            Value::Integer(i) => ffi::lua_pushinteger(state, *i),
2353            Value::Number(n) => ffi::lua_pushnumber(state, *n),
2354            #[cfg(feature = "luau")]
2355            Value::Vector(v) => {
2356                #[cfg(not(feature = "luau-vector4"))]
2357                ffi::lua_pushvector(state, v.x(), v.y(), v.z());
2358                #[cfg(feature = "luau-vector4")]
2359                ffi::lua_pushvector(state, v.x(), v.y(), v.z(), v.w());
2360            }
2361            Value::String(s) => self.push_ref(&s.0),
2362            Value::Table(t) => self.push_ref(&t.0),
2363            Value::Function(f) => self.push_ref(&f.0),
2364            Value::Thread(t) => self.push_ref(&t.0),
2365            Value::UserData(ud) => self.push_ref(&ud.0),
2366            Value::Error(err) => {
2367                let protect = !self.unlikely_memory_error();
2368                push_gc_userdata(state, WrappedFailure::Error(err.clone()), protect)?;
2369            }
2370        }
2371        Ok(())
2372    }
2373
2374    /// Pops a value from the Lua stack.
2375    ///
2376    /// Uses 2 stack spaces, does not call checkstack.
2377    #[doc(hidden)]
2378    pub unsafe fn pop_value(&self) -> Value {
2379        let state = self.state();
2380        match ffi::lua_type(state, -1) {
2381            ffi::LUA_TNIL => {
2382                ffi::lua_pop(state, 1);
2383                Nil
2384            }
2385
2386            ffi::LUA_TBOOLEAN => {
2387                let b = Value::Boolean(ffi::lua_toboolean(state, -1) != 0);
2388                ffi::lua_pop(state, 1);
2389                b
2390            }
2391
2392            ffi::LUA_TLIGHTUSERDATA => {
2393                let ud = Value::LightUserData(LightUserData(ffi::lua_touserdata(state, -1)));
2394                ffi::lua_pop(state, 1);
2395                ud
2396            }
2397
2398            #[cfg(any(feature = "lua54", feature = "lua53"))]
2399            ffi::LUA_TNUMBER => {
2400                let v = if ffi::lua_isinteger(state, -1) != 0 {
2401                    Value::Integer(ffi::lua_tointeger(state, -1))
2402                } else {
2403                    Value::Number(ffi::lua_tonumber(state, -1))
2404                };
2405                ffi::lua_pop(state, 1);
2406                v
2407            }
2408
2409            #[cfg(any(
2410                feature = "lua52",
2411                feature = "lua51",
2412                feature = "luajit",
2413                feature = "luau"
2414            ))]
2415            ffi::LUA_TNUMBER => {
2416                let n = ffi::lua_tonumber(state, -1);
2417                ffi::lua_pop(state, 1);
2418                match num_traits::cast(n) {
2419                    Some(i) if (n - (i as Number)).abs() < Number::EPSILON => Value::Integer(i),
2420                    _ => Value::Number(n),
2421                }
2422            }
2423
2424            #[cfg(feature = "luau")]
2425            ffi::LUA_TVECTOR => {
2426                let v = ffi::lua_tovector(state, -1);
2427                mlua_debug_assert!(!v.is_null(), "vector is null");
2428                #[cfg(not(feature = "luau-vector4"))]
2429                let vec = Value::Vector(Vector([*v, *v.add(1), *v.add(2)]));
2430                #[cfg(feature = "luau-vector4")]
2431                let vec = Value::Vector(Vector([*v, *v.add(1), *v.add(2), *v.add(3)]));
2432                ffi::lua_pop(state, 1);
2433                vec
2434            }
2435
2436            ffi::LUA_TSTRING => Value::String(String(self.pop_ref())),
2437
2438            ffi::LUA_TTABLE => Value::Table(Table(self.pop_ref())),
2439
2440            ffi::LUA_TFUNCTION => Value::Function(Function(self.pop_ref())),
2441
2442            ffi::LUA_TUSERDATA => {
2443                let wrapped_failure_mt_ptr = (*self.extra.get()).wrapped_failure_mt_ptr;
2444                // We must prevent interaction with userdata types other than UserData OR a WrappedError.
2445                // WrappedPanics are automatically resumed.
2446                match get_gc_userdata::<WrappedFailure>(state, -1, wrapped_failure_mt_ptr).as_mut()
2447                {
2448                    Some(WrappedFailure::Error(err)) => {
2449                        let err = err.clone();
2450                        ffi::lua_pop(state, 1);
2451                        Value::Error(err)
2452                    }
2453                    Some(WrappedFailure::Panic(panic)) => {
2454                        if let Some(panic) = panic.take() {
2455                            ffi::lua_pop(state, 1);
2456                            resume_unwind(panic);
2457                        }
2458                        // Previously resumed panic?
2459                        ffi::lua_pop(state, 1);
2460                        Nil
2461                    }
2462                    _ => Value::UserData(AnyUserData(self.pop_ref(), SubtypeId::None)),
2463                }
2464            }
2465
2466            ffi::LUA_TTHREAD => Value::Thread(Thread::new(self.pop_ref())),
2467
2468            #[cfg(feature = "luau")]
2469            ffi::LUA_TBUFFER => {
2470                // Buffer is represented as a userdata type
2471                Value::UserData(AnyUserData(self.pop_ref(), SubtypeId::Buffer))
2472            }
2473
2474            #[cfg(feature = "luajit")]
2475            ffi::LUA_TCDATA => {
2476                // CDATA is represented as a userdata type
2477                Value::UserData(AnyUserData(self.pop_ref(), SubtypeId::CData))
2478            }
2479
2480            _ => mlua_panic!("LUA_TNONE in pop_value"),
2481        }
2482    }
2483
2484    /// Returns value at given stack index without popping it.
2485    ///
2486    /// Uses 2 stack spaces, does not call checkstack.
2487    pub(crate) unsafe fn stack_value(&self, idx: c_int) -> Value {
2488        let state = self.state();
2489        match ffi::lua_type(state, idx) {
2490            ffi::LUA_TNIL => Nil,
2491
2492            ffi::LUA_TBOOLEAN => Value::Boolean(ffi::lua_toboolean(state, idx) != 0),
2493
2494            ffi::LUA_TLIGHTUSERDATA => {
2495                Value::LightUserData(LightUserData(ffi::lua_touserdata(state, idx)))
2496            }
2497
2498            #[cfg(any(feature = "lua54", feature = "lua53"))]
2499            ffi::LUA_TNUMBER => {
2500                if ffi::lua_isinteger(state, idx) != 0 {
2501                    Value::Integer(ffi::lua_tointeger(state, idx))
2502                } else {
2503                    Value::Number(ffi::lua_tonumber(state, idx))
2504                }
2505            }
2506
2507            #[cfg(any(
2508                feature = "lua52",
2509                feature = "lua51",
2510                feature = "luajit",
2511                feature = "luau"
2512            ))]
2513            ffi::LUA_TNUMBER => {
2514                let n = ffi::lua_tonumber(state, idx);
2515                match num_traits::cast(n) {
2516                    Some(i) if (n - (i as Number)).abs() < Number::EPSILON => Value::Integer(i),
2517                    _ => Value::Number(n),
2518                }
2519            }
2520
2521            #[cfg(feature = "luau")]
2522            ffi::LUA_TVECTOR => {
2523                let v = ffi::lua_tovector(state, idx);
2524                mlua_debug_assert!(!v.is_null(), "vector is null");
2525                #[cfg(not(feature = "luau-vector4"))]
2526                return Value::Vector(Vector([*v, *v.add(1), *v.add(2)]));
2527                #[cfg(feature = "luau-vector4")]
2528                return Value::Vector(Vector([*v, *v.add(1), *v.add(2), *v.add(3)]));
2529            }
2530
2531            ffi::LUA_TSTRING => {
2532                ffi::lua_xpush(state, self.ref_thread(), idx);
2533                Value::String(String(self.pop_ref_thread()))
2534            }
2535
2536            ffi::LUA_TTABLE => {
2537                ffi::lua_xpush(state, self.ref_thread(), idx);
2538                Value::Table(Table(self.pop_ref_thread()))
2539            }
2540
2541            ffi::LUA_TFUNCTION => {
2542                ffi::lua_xpush(state, self.ref_thread(), idx);
2543                Value::Function(Function(self.pop_ref_thread()))
2544            }
2545
2546            ffi::LUA_TUSERDATA => {
2547                let wrapped_failure_mt_ptr = (*self.extra.get()).wrapped_failure_mt_ptr;
2548                // We must prevent interaction with userdata types other than UserData OR a WrappedError.
2549                // WrappedPanics are automatically resumed.
2550                match get_gc_userdata::<WrappedFailure>(state, idx, wrapped_failure_mt_ptr).as_mut()
2551                {
2552                    Some(WrappedFailure::Error(err)) => Value::Error(err.clone()),
2553                    Some(WrappedFailure::Panic(panic)) => {
2554                        if let Some(panic) = panic.take() {
2555                            resume_unwind(panic);
2556                        }
2557                        // Previously resumed panic?
2558                        Value::Nil
2559                    }
2560                    _ => {
2561                        ffi::lua_xpush(state, self.ref_thread(), idx);
2562                        Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::None))
2563                    }
2564                }
2565            }
2566
2567            ffi::LUA_TTHREAD => {
2568                ffi::lua_xpush(state, self.ref_thread(), idx);
2569                Value::Thread(Thread::new(self.pop_ref_thread()))
2570            }
2571
2572            #[cfg(feature = "luau")]
2573            ffi::LUA_TBUFFER => {
2574                // Buffer is represented as a userdata type
2575                ffi::lua_xpush(state, self.ref_thread(), idx);
2576                Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::Buffer))
2577            }
2578
2579            #[cfg(feature = "luajit")]
2580            ffi::LUA_TCDATA => {
2581                // CData is represented as a userdata type
2582                ffi::lua_xpush(state, self.ref_thread(), idx);
2583                Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::CData))
2584            }
2585
2586            _ => mlua_panic!("LUA_TNONE in pop_value"),
2587        }
2588    }
2589
2590    // Pushes a LuaRef value onto the stack, uses 1 stack space, does not call checkstack
2591    pub(crate) unsafe fn push_ref(&self, lref: &LuaRef) {
2592        assert!(
2593            Arc::ptr_eq(&lref.lua.0, &self.0),
2594            "Lua instance passed Value created from a different main Lua state"
2595        );
2596        ffi::lua_xpush(self.ref_thread(), self.state(), lref.index);
2597    }
2598
2599    #[cfg(all(feature = "unstable", not(feature = "send")))]
2600    pub(crate) unsafe fn push_owned_ref(&self, loref: &crate::types::LuaOwnedRef) {
2601        assert!(
2602            Arc::ptr_eq(&loref.inner, &self.0),
2603            "Lua instance passed Value created from a different main Lua state"
2604        );
2605        ffi::lua_xpush(self.ref_thread(), self.state(), loref.index);
2606    }
2607
2608    // Pops the topmost element of the stack and stores a reference to it. This pins the object,
2609    // preventing garbage collection until the returned `LuaRef` is dropped.
2610    //
2611    // References are stored in the stack of a specially created auxiliary thread that exists only
2612    // to store reference values. This is much faster than storing these in the registry, and also
2613    // much more flexible and requires less bookkeeping than storing them directly in the currently
2614    // used stack. The implementation is somewhat biased towards the use case of a relatively small
2615    // number of short term references being created, and `RegistryKey` being used for long term
2616    // references.
2617    pub(crate) unsafe fn pop_ref(&self) -> LuaRef {
2618        ffi::lua_xmove(self.state(), self.ref_thread(), 1);
2619        let index = ref_stack_pop(self.extra.get());
2620        LuaRef::new(self, index)
2621    }
2622
2623    // Same as `pop_ref` but assumes the value is already on the reference thread
2624    pub(crate) unsafe fn pop_ref_thread(&self) -> LuaRef {
2625        let index = ref_stack_pop(self.extra.get());
2626        LuaRef::new(self, index)
2627    }
2628
2629    pub(crate) fn clone_ref(&self, lref: &LuaRef) -> LuaRef {
2630        unsafe {
2631            ffi::lua_pushvalue(self.ref_thread(), lref.index);
2632            let index = ref_stack_pop(self.extra.get());
2633            LuaRef::new(self, index)
2634        }
2635    }
2636
2637    pub(crate) fn drop_ref_index(&self, index: c_int) {
2638        unsafe {
2639            let ref_thread = self.ref_thread();
2640            ffi::lua_pushnil(ref_thread);
2641            ffi::lua_replace(ref_thread, index);
2642            (*self.extra.get()).ref_free.push(index);
2643        }
2644    }
2645
2646    #[cfg(all(feature = "unstable", not(feature = "send")))]
2647    pub(crate) fn adopt_owned_ref(&self, loref: crate::types::LuaOwnedRef) -> LuaRef {
2648        assert!(
2649            Arc::ptr_eq(&loref.inner, &self.0),
2650            "Lua instance passed Value created from a different main Lua state"
2651        );
2652        let index = loref.index;
2653        unsafe {
2654            ptr::read(&loref.inner);
2655            mem::forget(loref);
2656        }
2657        LuaRef::new(self, index)
2658    }
2659
2660    #[inline]
2661    pub(crate) unsafe fn push_error_traceback(&self) {
2662        let state = self.state();
2663        #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
2664        ffi::lua_xpush(self.ref_thread(), state, ExtraData::ERROR_TRACEBACK_IDX);
2665        // Lua 5.2+ support light C functions that does not require extra allocations
2666        #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
2667        ffi::lua_pushcfunction(state, error_traceback);
2668    }
2669
2670    unsafe fn register_userdata_metatable<'lua, T: 'static>(
2671        &'lua self,
2672        mut registry: UserDataRegistry<'lua, T>,
2673    ) -> Result<Integer> {
2674        let state = self.state();
2675        let _sg = StackGuard::new(state);
2676        check_stack(state, 13)?;
2677
2678        // Prepare metatable, add meta methods first and then meta fields
2679        let metatable_nrec = registry.meta_methods.len() + registry.meta_fields.len();
2680        #[cfg(feature = "async")]
2681        let metatable_nrec = metatable_nrec + registry.async_meta_methods.len();
2682        push_table(state, 0, metatable_nrec, true)?;
2683        for (k, m) in registry.meta_methods {
2684            self.push(self.create_callback(m)?)?;
2685            rawset_field(state, -2, MetaMethod::validate(&k)?)?;
2686        }
2687        #[cfg(feature = "async")]
2688        for (k, m) in registry.async_meta_methods {
2689            self.push(self.create_async_callback(m)?)?;
2690            rawset_field(state, -2, MetaMethod::validate(&k)?)?;
2691        }
2692        let mut has_name = false;
2693        for (k, f) in registry.meta_fields {
2694            has_name = has_name || k == MetaMethod::Type;
2695            mlua_assert!(f(self, 0)? == 1, "field function must return one value");
2696            rawset_field(state, -2, MetaMethod::validate(&k)?)?;
2697        }
2698        // Set `__name/__type` if not provided
2699        if !has_name {
2700            let type_name = short_type_name::<T>();
2701            push_string(state, type_name.as_bytes(), !self.unlikely_memory_error())?;
2702            rawset_field(state, -2, MetaMethod::Type.name())?;
2703        }
2704        let metatable_index = ffi::lua_absindex(state, -1);
2705
2706        let mut extra_tables_count = 0;
2707
2708        let fields_nrec = registry.fields.len();
2709        if fields_nrec > 0 {
2710            // If __index is a table then update it inplace
2711            let index_type = ffi::lua_getfield(state, metatable_index, cstr!("__index"));
2712            match index_type {
2713                ffi::LUA_TNIL | ffi::LUA_TTABLE => {
2714                    if index_type == ffi::LUA_TNIL {
2715                        // Create a new table
2716                        ffi::lua_pop(state, 1);
2717                        push_table(state, 0, fields_nrec, true)?;
2718                    }
2719                    for (k, f) in registry.fields {
2720                        mlua_assert!(f(self, 0)? == 1, "field function must return one value");
2721                        rawset_field(state, -2, &k)?;
2722                    }
2723                    rawset_field(state, metatable_index, "__index")?;
2724                }
2725                _ => {
2726                    ffi::lua_pop(state, 1);
2727                    // Propagate fields to the field getters
2728                    for (k, f) in registry.fields {
2729                        registry.field_getters.push((k, f))
2730                    }
2731                }
2732            }
2733        }
2734
2735        let mut field_getters_index = None;
2736        let field_getters_nrec = registry.field_getters.len();
2737        if field_getters_nrec > 0 {
2738            push_table(state, 0, field_getters_nrec, true)?;
2739            for (k, m) in registry.field_getters {
2740                self.push(self.create_callback(m)?)?;
2741                rawset_field(state, -2, &k)?;
2742            }
2743            field_getters_index = Some(ffi::lua_absindex(state, -1));
2744            extra_tables_count += 1;
2745        }
2746
2747        let mut field_setters_index = None;
2748        let field_setters_nrec = registry.field_setters.len();
2749        if field_setters_nrec > 0 {
2750            push_table(state, 0, field_setters_nrec, true)?;
2751            for (k, m) in registry.field_setters {
2752                self.push(self.create_callback(m)?)?;
2753                rawset_field(state, -2, &k)?;
2754            }
2755            field_setters_index = Some(ffi::lua_absindex(state, -1));
2756            extra_tables_count += 1;
2757        }
2758
2759        let mut methods_index = None;
2760        let methods_nrec = registry.methods.len();
2761        #[cfg(feature = "async")]
2762        let methods_nrec = methods_nrec + registry.async_methods.len();
2763        if methods_nrec > 0 {
2764            // If __index is a table then update it inplace
2765            let index_type = ffi::lua_getfield(state, metatable_index, cstr!("__index"));
2766            match index_type {
2767                ffi::LUA_TTABLE => {} // Update the existing table
2768                _ => {
2769                    // Create a new table
2770                    ffi::lua_pop(state, 1);
2771                    push_table(state, 0, methods_nrec, true)?;
2772                }
2773            }
2774            for (k, m) in registry.methods {
2775                self.push(self.create_callback(m)?)?;
2776                rawset_field(state, -2, &k)?;
2777            }
2778            #[cfg(feature = "async")]
2779            for (k, m) in registry.async_methods {
2780                self.push(self.create_async_callback(m)?)?;
2781                rawset_field(state, -2, &k)?;
2782            }
2783            match index_type {
2784                ffi::LUA_TTABLE => {
2785                    ffi::lua_pop(state, 1); // All done
2786                }
2787                ffi::LUA_TNIL => {
2788                    rawset_field(state, metatable_index, "__index")?; // Set the new table as __index
2789                }
2790                _ => {
2791                    methods_index = Some(ffi::lua_absindex(state, -1));
2792                    extra_tables_count += 1;
2793                }
2794            }
2795        }
2796
2797        #[cfg(feature = "luau")]
2798        let extra_init = None;
2799        #[cfg(not(feature = "luau"))]
2800        let extra_init: Option<fn(*mut ffi::lua_State) -> Result<()>> = Some(|state| {
2801            ffi::lua_pushcfunction(state, util::userdata_destructor::<UserDataCell<T>>);
2802            rawset_field(state, -2, "__gc")
2803        });
2804
2805        init_userdata_metatable(
2806            state,
2807            metatable_index,
2808            field_getters_index,
2809            field_setters_index,
2810            methods_index,
2811            extra_init,
2812        )?;
2813
2814        // Pop extra tables to get metatable on top of the stack
2815        ffi::lua_pop(state, extra_tables_count);
2816
2817        let mt_ptr = ffi::lua_topointer(state, -1);
2818        let id = protect_lua!(state, 1, 0, |state| {
2819            ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
2820        })?;
2821
2822        let type_id = TypeId::of::<T>();
2823        (*self.extra.get()).registered_userdata.insert(type_id, id);
2824        (*self.extra.get())
2825            .registered_userdata_mt
2826            .insert(mt_ptr, Some(type_id));
2827
2828        Ok(id as Integer)
2829    }
2830
2831    #[inline]
2832    pub(crate) unsafe fn register_raw_userdata_metatable(
2833        &self,
2834        ptr: *const c_void,
2835        type_id: Option<TypeId>,
2836    ) {
2837        (*self.extra.get())
2838            .registered_userdata_mt
2839            .insert(ptr, type_id);
2840    }
2841
2842    #[inline]
2843    pub(crate) unsafe fn deregister_raw_userdata_metatable(&self, ptr: *const c_void) {
2844        (*self.extra.get()).registered_userdata_mt.remove(&ptr);
2845        if (*self.extra.get()).last_checked_userdata_mt.0 == ptr {
2846            (*self.extra.get()).last_checked_userdata_mt = (ptr::null(), None);
2847        }
2848    }
2849
2850    // Returns `TypeId` for the `lref` userdata, checking that it's registered and not destructed.
2851    //
2852    // Returns `None` if the userdata is registered but non-static.
2853    pub(crate) unsafe fn get_userdata_ref_type_id(&self, lref: &LuaRef) -> Result<Option<TypeId>> {
2854        self.get_userdata_type_id_inner(self.ref_thread(), lref.index)
2855    }
2856
2857    // Same as `get_userdata_ref_type_id` but assumes the userdata is already on the stack.
2858    pub(crate) unsafe fn get_userdata_type_id(&self, idx: c_int) -> Result<Option<TypeId>> {
2859        self.get_userdata_type_id_inner(self.state(), idx)
2860    }
2861
2862    unsafe fn get_userdata_type_id_inner(
2863        &self,
2864        state: *mut ffi::lua_State,
2865        idx: c_int,
2866    ) -> Result<Option<TypeId>> {
2867        if ffi::lua_getmetatable(state, idx) == 0 {
2868            return Err(Error::UserDataTypeMismatch);
2869        }
2870        let mt_ptr = ffi::lua_topointer(state, -1);
2871        ffi::lua_pop(state, 1);
2872
2873        // Fast path to skip looking up the metatable in the map
2874        let (last_mt, last_type_id) = (*self.extra.get()).last_checked_userdata_mt;
2875        if last_mt == mt_ptr {
2876            return Ok(last_type_id);
2877        }
2878
2879        match (*self.extra.get()).registered_userdata_mt.get(&mt_ptr) {
2880            Some(&type_id) if type_id == Some(TypeId::of::<DestructedUserdata>()) => {
2881                Err(Error::UserDataDestructed)
2882            }
2883            Some(&type_id) => {
2884                (*self.extra.get()).last_checked_userdata_mt = (mt_ptr, type_id);
2885                Ok(type_id)
2886            }
2887            None => Err(Error::UserDataTypeMismatch),
2888        }
2889    }
2890
2891    // Pushes a LuaRef (userdata) value onto the stack, returning their `TypeId`.
2892    // Uses 1 stack space, does not call checkstack.
2893    pub(crate) unsafe fn push_userdata_ref(&self, lref: &LuaRef) -> Result<Option<TypeId>> {
2894        let type_id = self.get_userdata_type_id_inner(self.ref_thread(), lref.index)?;
2895        self.push_ref(lref);
2896        Ok(type_id)
2897    }
2898
2899    // Creates a Function out of a Callback containing a 'static Fn. This is safe ONLY because the
2900    // Fn is 'static, otherwise it could capture 'lua arguments improperly. Without ATCs, we
2901    // cannot easily deal with the "correct" callback type of:
2902    //
2903    // Box<for<'lua> Fn(&'lua Lua, MultiValue<'lua>) -> Result<MultiValue<'lua>>)>
2904    //
2905    // So we instead use a caller provided lifetime, which without the 'static requirement would be
2906    // unsafe.
2907    pub(crate) fn create_callback<'lua>(
2908        &'lua self,
2909        func: Callback<'lua, 'static>,
2910    ) -> Result<Function<'lua>> {
2911        unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
2912            // Normal functions can be scoped and therefore destroyed,
2913            // so we need to check that the first upvalue is valid
2914            let (upvalue, extra) = match ffi::lua_type(state, ffi::lua_upvalueindex(1)) {
2915                ffi::LUA_TUSERDATA => {
2916                    let upvalue = get_userdata::<CallbackUpvalue>(state, ffi::lua_upvalueindex(1));
2917                    (upvalue, (*upvalue).extra.get())
2918                }
2919                _ => (ptr::null_mut(), ptr::null_mut()),
2920            };
2921            callback_error_ext(state, extra, |nargs| {
2922                // Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
2923                if upvalue.is_null() {
2924                    return Err(Error::CallbackDestructed);
2925                }
2926
2927                let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
2928                let _guard = StateGuard::new(&lua.0, state);
2929                let func = &*(*upvalue).data;
2930
2931                func(lua, nargs)
2932            })
2933        }
2934
2935        let state = self.state();
2936        unsafe {
2937            let _sg = StackGuard::new(state);
2938            check_stack(state, 4)?;
2939
2940            let func = mem::transmute(func);
2941            let extra = Arc::clone(&self.extra);
2942            let protect = !self.unlikely_memory_error();
2943            push_gc_userdata(state, CallbackUpvalue { data: func, extra }, protect)?;
2944            if protect {
2945                protect_lua!(state, 1, 1, fn(state) {
2946                    ffi::lua_pushcclosure(state, call_callback, 1);
2947                })?;
2948            } else {
2949                ffi::lua_pushcclosure(state, call_callback, 1);
2950            }
2951
2952            Ok(Function(self.pop_ref()))
2953        }
2954    }
2955
2956    #[cfg(feature = "async")]
2957    pub(crate) fn create_async_callback<'lua>(
2958        &'lua self,
2959        func: AsyncCallback<'lua, 'static>,
2960    ) -> Result<Function<'lua>> {
2961        #[cfg(any(
2962            feature = "lua54",
2963            feature = "lua53",
2964            feature = "lua52",
2965            feature = "luau"
2966        ))]
2967        unsafe {
2968            if !(*self.extra.get()).libs.contains(StdLib::COROUTINE) {
2969                load_from_std_lib(self.main_state, StdLib::COROUTINE)?;
2970                (*self.extra.get()).libs |= StdLib::COROUTINE;
2971            }
2972        }
2973
2974        unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
2975            // Async functions cannot be scoped and therefore destroyed,
2976            // so the first upvalue is always valid
2977            let upvalue = get_userdata::<AsyncCallbackUpvalue>(state, ffi::lua_upvalueindex(1));
2978            let extra = (*upvalue).extra.get();
2979            callback_error_ext(state, extra, |nargs| {
2980                // Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
2981                let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
2982                let _guard = StateGuard::new(&lua.0, state);
2983
2984                let args = MultiValue::from_stack_multi(nargs, lua)?;
2985                let func = &*(*upvalue).data;
2986                let fut = func(lua, args);
2987                let extra = Arc::clone(&(*upvalue).extra);
2988                let protect = !lua.unlikely_memory_error();
2989                push_gc_userdata(state, AsyncPollUpvalue { data: fut, extra }, protect)?;
2990                if protect {
2991                    protect_lua!(state, 1, 1, fn(state) {
2992                        ffi::lua_pushcclosure(state, poll_future, 1);
2993                    })?;
2994                } else {
2995                    ffi::lua_pushcclosure(state, poll_future, 1);
2996                }
2997
2998                Ok(1)
2999            })
3000        }
3001
3002        unsafe extern "C-unwind" fn poll_future(state: *mut ffi::lua_State) -> c_int {
3003            let upvalue = get_userdata::<AsyncPollUpvalue>(state, ffi::lua_upvalueindex(1));
3004            let extra = (*upvalue).extra.get();
3005            callback_error_ext(state, extra, |_| {
3006                // Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
3007                let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
3008                let _guard = StateGuard::new(&lua.0, state);
3009
3010                let fut = &mut (*upvalue).data;
3011                let mut ctx = Context::from_waker(lua.waker());
3012                match fut.as_mut().poll(&mut ctx) {
3013                    Poll::Pending => {
3014                        ffi::lua_pushnil(state);
3015                        ffi::lua_pushlightuserdata(state, Lua::poll_pending().0);
3016                        Ok(2)
3017                    }
3018                    Poll::Ready(nresults) => {
3019                        match nresults? {
3020                            nresults @ 0..=2 => {
3021                                // Fast path for up to 2 results without creating a table
3022                                ffi::lua_pushinteger(state, nresults as _);
3023                                if nresults > 0 {
3024                                    ffi::lua_insert(state, -nresults - 1);
3025                                }
3026                                Ok(nresults + 1)
3027                            }
3028                            nresults => {
3029                                let results = MultiValue::from_stack_multi(nresults, lua)?;
3030                                ffi::lua_pushinteger(state, nresults as _);
3031                                lua.push(lua.create_sequence_from(results)?)?;
3032                                Ok(2)
3033                            }
3034                        }
3035                    }
3036                }
3037            })
3038        }
3039
3040        let state = self.state();
3041        let get_poll = unsafe {
3042            let _sg = StackGuard::new(state);
3043            check_stack(state, 4)?;
3044
3045            let func = mem::transmute(func);
3046            let extra = Arc::clone(&self.extra);
3047            let protect = !self.unlikely_memory_error();
3048            let upvalue = AsyncCallbackUpvalue { data: func, extra };
3049            push_gc_userdata(state, upvalue, protect)?;
3050            if protect {
3051                protect_lua!(state, 1, 1, fn(state) {
3052                    ffi::lua_pushcclosure(state, call_callback, 1);
3053                })?;
3054            } else {
3055                ffi::lua_pushcclosure(state, call_callback, 1);
3056            }
3057
3058            Function(self.pop_ref())
3059        };
3060
3061        unsafe extern "C-unwind" fn unpack(state: *mut ffi::lua_State) -> c_int {
3062            let len = ffi::lua_tointeger(state, 2);
3063            ffi::luaL_checkstack(state, len as c_int, ptr::null());
3064            for i in 1..=len {
3065                ffi::lua_rawgeti(state, 1, i);
3066            }
3067            len as c_int
3068        }
3069
3070        let coroutine = self.globals().get::<_, Table>("coroutine")?;
3071
3072        let env = self.create_table_with_capacity(0, 3)?;
3073        env.set("get_poll", get_poll)?;
3074        // Cache `yield` function
3075        env.set("yield", coroutine.get::<_, Function>("yield")?)?;
3076        unsafe {
3077            env.set("unpack", self.create_c_function(unpack)?)?;
3078        }
3079
3080        self.load(
3081            r#"
3082            local poll = get_poll(...)
3083            while true do
3084                local nres, res, res2 = poll()
3085                if nres ~= nil then
3086                    if nres == 0 then
3087                        return
3088                    elseif nres == 1 then
3089                        return res
3090                    elseif nres == 2 then
3091                        return res, res2
3092                    else
3093                        return unpack(res, nres)
3094                    end
3095                end
3096                yield(res) -- `res` is a "pending" value
3097            end
3098            "#,
3099        )
3100        .try_cache()
3101        .set_name("__mlua_async_poll")
3102        .set_environment(env)
3103        .into_function()
3104    }
3105
3106    #[cfg(feature = "async")]
3107    #[inline]
3108    pub(crate) unsafe fn waker(&self) -> &Waker {
3109        (*self.extra.get()).waker.as_ref()
3110    }
3111
3112    #[cfg(feature = "async")]
3113    #[inline]
3114    pub(crate) unsafe fn set_waker(&self, waker: NonNull<Waker>) -> NonNull<Waker> {
3115        mem::replace(&mut (*self.extra.get()).waker, waker)
3116    }
3117
3118    /// Returns internal `Poll::Pending` constant used for executing async callbacks.
3119    #[cfg(feature = "async")]
3120    #[doc(hidden)]
3121    #[inline]
3122    pub fn poll_pending() -> LightUserData {
3123        LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut c_void)
3124    }
3125
3126    pub(crate) unsafe fn make_userdata<T>(&self, data: UserDataCell<T>) -> Result<AnyUserData>
3127    where
3128        T: UserData + 'static,
3129    {
3130        self.make_userdata_with_metatable(data, || {
3131            // Check if userdata/metatable is already registered
3132            let type_id = TypeId::of::<T>();
3133            if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
3134                return Ok(table_id as Integer);
3135            }
3136
3137            // Create new metatable from UserData definition
3138            let mut registry = UserDataRegistry::new();
3139            T::add_fields(&mut registry);
3140            T::add_methods(&mut registry);
3141
3142            self.register_userdata_metatable(registry)
3143        })
3144    }
3145
3146    pub(crate) unsafe fn make_any_userdata<T>(&self, data: UserDataCell<T>) -> Result<AnyUserData>
3147    where
3148        T: 'static,
3149    {
3150        self.make_userdata_with_metatable(data, || {
3151            // Check if userdata/metatable is already registered
3152            let type_id = TypeId::of::<T>();
3153            if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
3154                return Ok(table_id as Integer);
3155            }
3156
3157            // Create empty metatable
3158            let registry = UserDataRegistry::new();
3159            self.register_userdata_metatable::<T>(registry)
3160        })
3161    }
3162
3163    unsafe fn make_userdata_with_metatable<T>(
3164        &self,
3165        data: UserDataCell<T>,
3166        get_metatable_id: impl FnOnce() -> Result<Integer>,
3167    ) -> Result<AnyUserData> {
3168        let state = self.state();
3169        let _sg = StackGuard::new(state);
3170        check_stack(state, 3)?;
3171
3172        // We push metatable first to ensure having correct metatable with `__gc` method
3173        ffi::lua_pushnil(state);
3174        ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, get_metatable_id()?);
3175        let protect = !self.unlikely_memory_error();
3176        #[cfg(not(feature = "lua54"))]
3177        push_userdata(state, data, protect)?;
3178        #[cfg(feature = "lua54")]
3179        push_userdata_uv(state, data, USER_VALUE_MAXSLOT as c_int, protect)?;
3180        ffi::lua_replace(state, -3);
3181        ffi::lua_setmetatable(state, -2);
3182
3183        // Set empty environment for Lua 5.1
3184        #[cfg(any(feature = "lua51", feature = "luajit"))]
3185        if protect {
3186            protect_lua!(state, 1, 1, fn(state) {
3187                ffi::lua_newtable(state);
3188                ffi::lua_setuservalue(state, -2);
3189            })?;
3190        } else {
3191            ffi::lua_newtable(state);
3192            ffi::lua_setuservalue(state, -2);
3193        }
3194
3195        Ok(AnyUserData(self.pop_ref(), SubtypeId::None))
3196    }
3197
3198    // Luau version located in `luau/mod.rs`
3199    #[cfg(not(feature = "luau"))]
3200    fn disable_c_modules(&self) -> Result<()> {
3201        let package: Table = self.globals().get("package")?;
3202
3203        package.set(
3204            "loadlib",
3205            self.create_function(|_, ()| -> Result<()> {
3206                Err(Error::SafetyError(
3207                    "package.loadlib is disabled in safe mode".to_string(),
3208                ))
3209            })?,
3210        )?;
3211
3212        #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
3213        let searchers: Table = package.get("searchers")?;
3214        #[cfg(any(feature = "lua51", feature = "luajit"))]
3215        let searchers: Table = package.get("loaders")?;
3216
3217        let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
3218
3219        // The third and fourth searchers looks for a loader as a C library
3220        searchers.raw_set(3, loader.clone())?;
3221        searchers.raw_remove(4)?;
3222
3223        Ok(())
3224    }
3225
3226    pub(crate) unsafe fn try_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
3227        let extra = extra_data(state);
3228        if extra.is_null() {
3229            return None;
3230        }
3231        Some(Lua(Arc::clone((*extra).inner.assume_init_ref())))
3232    }
3233
3234    #[inline]
3235    pub(crate) unsafe fn unlikely_memory_error(&self) -> bool {
3236        // MemoryInfo is empty in module mode so we cannot predict memory limits
3237        match MemoryState::get(self.main_state) {
3238            mem_state if !mem_state.is_null() => (*mem_state).memory_limit() == 0,
3239            #[cfg(feature = "module")]
3240            _ => (*self.extra.get()).skip_memory_check, // Check the special flag (only for module mode)
3241            #[cfg(not(feature = "module"))]
3242            _ => false,
3243        }
3244    }
3245
3246    #[cfg(feature = "unstable")]
3247    #[inline]
3248    pub(crate) fn clone(&self) -> Arc<LuaInner> {
3249        Arc::clone(&self.0)
3250    }
3251}
3252
3253impl LuaInner {
3254    #[inline(always)]
3255    pub(crate) fn state(&self) -> *mut ffi::lua_State {
3256        self.state.load(Ordering::Relaxed)
3257    }
3258
3259    #[cfg(feature = "luau")]
3260    #[inline(always)]
3261    pub(crate) fn main_state(&self) -> *mut ffi::lua_State {
3262        self.main_state
3263    }
3264
3265    #[inline(always)]
3266    pub(crate) fn ref_thread(&self) -> *mut ffi::lua_State {
3267        unsafe { (*self.extra.get()).ref_thread }
3268    }
3269
3270    #[inline]
3271    pub(crate) fn pop_multivalue_from_pool(&self) -> Option<Vec<Value>> {
3272        let extra = unsafe { &mut *self.extra.get() };
3273        extra.multivalue_pool.pop()
3274    }
3275
3276    #[inline]
3277    pub(crate) fn push_multivalue_to_pool(&self, mut multivalue: Vec<Value>) {
3278        let extra = unsafe { &mut *self.extra.get() };
3279        if extra.multivalue_pool.len() < MULTIVALUE_POOL_SIZE {
3280            multivalue.clear();
3281            extra
3282                .multivalue_pool
3283                .push(unsafe { mem::transmute(multivalue) });
3284        }
3285    }
3286}
3287
3288impl ExtraData {
3289    // Index of `error_traceback` function in auxiliary thread stack
3290    #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
3291    const ERROR_TRACEBACK_IDX: c_int = 1;
3292}
3293
3294struct StateGuard<'a>(&'a LuaInner, *mut ffi::lua_State);
3295
3296impl<'a> StateGuard<'a> {
3297    fn new(inner: &'a LuaInner, mut state: *mut ffi::lua_State) -> Self {
3298        state = inner.state.swap(state, Ordering::Relaxed);
3299        Self(inner, state)
3300    }
3301}
3302
3303impl<'a> Drop for StateGuard<'a> {
3304    fn drop(&mut self) {
3305        self.0.state.store(self.1, Ordering::Relaxed);
3306    }
3307}
3308
3309unsafe fn extra_data(state: *mut ffi::lua_State) -> *mut ExtraData {
3310    #[cfg(feature = "luau")]
3311    if cfg!(not(feature = "module")) {
3312        // In the main app we can use `lua_callbacks` to access ExtraData
3313        return (*ffi::lua_callbacks(state)).userdata as *mut _;
3314    }
3315
3316    let extra_key = &EXTRA_REGISTRY_KEY as *const u8 as *const c_void;
3317    if ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, extra_key) != ffi::LUA_TUSERDATA {
3318        // `ExtraData` can be null only when Lua state is foreign.
3319        // This case in used in `Lua::try_from_ptr()`.
3320        ffi::lua_pop(state, 1);
3321        return ptr::null_mut();
3322    }
3323    let extra_ptr = ffi::lua_touserdata(state, -1) as *mut Arc<UnsafeCell<ExtraData>>;
3324    ffi::lua_pop(state, 1);
3325    (*extra_ptr).get()
3326}
3327
3328unsafe fn set_extra_data(
3329    state: *mut ffi::lua_State,
3330    extra: &Arc<UnsafeCell<ExtraData>>,
3331) -> Result<()> {
3332    #[cfg(feature = "luau")]
3333    if cfg!(not(feature = "module")) {
3334        (*ffi::lua_callbacks(state)).userdata = extra.get() as *mut _;
3335        return Ok(());
3336    }
3337
3338    push_gc_userdata(state, Arc::clone(extra), true)?;
3339    protect_lua!(state, 1, 0, fn(state) {
3340        let extra_key = &EXTRA_REGISTRY_KEY as *const u8 as *const c_void;
3341        ffi::lua_rawsetp(state, ffi::LUA_REGISTRYINDEX, extra_key);
3342    })
3343}
3344
3345// Creates required entries in the metatable cache (see `util::METATABLE_CACHE`)
3346pub(crate) fn init_metatable_cache(cache: &mut FxHashMap<TypeId, u8>) {
3347    cache.insert(TypeId::of::<Arc<UnsafeCell<ExtraData>>>(), 0);
3348    cache.insert(TypeId::of::<Callback>(), 0);
3349    cache.insert(TypeId::of::<CallbackUpvalue>(), 0);
3350
3351    #[cfg(feature = "async")]
3352    {
3353        cache.insert(TypeId::of::<AsyncCallback>(), 0);
3354        cache.insert(TypeId::of::<AsyncCallbackUpvalue>(), 0);
3355        cache.insert(TypeId::of::<AsyncPollUpvalue>(), 0);
3356        cache.insert(TypeId::of::<Option<Waker>>(), 0);
3357    }
3358}
3359
3360// An optimized version of `callback_error` that does not allocate `WrappedFailure` userdata
3361// and instead reuses unsed values from previous calls (or allocates new).
3362unsafe fn callback_error_ext<F, R>(state: *mut ffi::lua_State, mut extra: *mut ExtraData, f: F) -> R
3363where
3364    F: FnOnce(c_int) -> Result<R>,
3365{
3366    if extra.is_null() {
3367        extra = extra_data(state);
3368    }
3369
3370    let nargs = ffi::lua_gettop(state);
3371
3372    enum PreallocatedFailure {
3373        New(*mut WrappedFailure),
3374        Existing(i32),
3375    }
3376
3377    impl PreallocatedFailure {
3378        unsafe fn reserve(state: *mut ffi::lua_State, extra: *mut ExtraData) -> Self {
3379            match (*extra).wrapped_failure_pool.pop() {
3380                Some(index) => PreallocatedFailure::Existing(index),
3381                None => {
3382                    // We need to check stack for Luau in case when callback is called from interrupt
3383                    // See https://github.com/Roblox/luau/issues/446 and mlua #142 and #153
3384                    #[cfg(feature = "luau")]
3385                    ffi::lua_rawcheckstack(state, 2);
3386                    // Place it to the beginning of the stack
3387                    let ud = WrappedFailure::new_userdata(state);
3388                    ffi::lua_insert(state, 1);
3389                    PreallocatedFailure::New(ud)
3390                }
3391            }
3392        }
3393
3394        unsafe fn r#use(
3395            &self,
3396            state: *mut ffi::lua_State,
3397            extra: *mut ExtraData,
3398        ) -> *mut WrappedFailure {
3399            let ref_thread = (*extra).ref_thread;
3400            match *self {
3401                PreallocatedFailure::New(ud) => {
3402                    ffi::lua_settop(state, 1);
3403                    ud
3404                }
3405                PreallocatedFailure::Existing(index) => {
3406                    ffi::lua_settop(state, 0);
3407                    #[cfg(feature = "luau")]
3408                    ffi::lua_rawcheckstack(state, 2);
3409                    ffi::lua_pushvalue(ref_thread, index);
3410                    ffi::lua_xmove(ref_thread, state, 1);
3411                    ffi::lua_pushnil(ref_thread);
3412                    ffi::lua_replace(ref_thread, index);
3413                    (*extra).ref_free.push(index);
3414                    ffi::lua_touserdata(state, -1) as *mut WrappedFailure
3415                }
3416            }
3417        }
3418
3419        unsafe fn release(self, state: *mut ffi::lua_State, extra: *mut ExtraData) {
3420            let ref_thread = (*extra).ref_thread;
3421            match self {
3422                PreallocatedFailure::New(_) => {
3423                    if (*extra).wrapped_failure_pool.len() < WRAPPED_FAILURE_POOL_SIZE {
3424                        ffi::lua_rotate(state, 1, -1);
3425                        ffi::lua_xmove(state, ref_thread, 1);
3426                        let index = ref_stack_pop(extra);
3427                        (*extra).wrapped_failure_pool.push(index);
3428                    } else {
3429                        ffi::lua_remove(state, 1);
3430                    }
3431                }
3432                PreallocatedFailure::Existing(index) => {
3433                    if (*extra).wrapped_failure_pool.len() < WRAPPED_FAILURE_POOL_SIZE {
3434                        (*extra).wrapped_failure_pool.push(index);
3435                    } else {
3436                        ffi::lua_pushnil(ref_thread);
3437                        ffi::lua_replace(ref_thread, index);
3438                        (*extra).ref_free.push(index);
3439                    }
3440                }
3441            }
3442        }
3443    }
3444
3445    // We cannot shadow Rust errors with Lua ones, so we need to reserve pre-allocated memory
3446    // to store a wrapped failure (error or panic) *before* we proceed.
3447    let prealloc_failure = PreallocatedFailure::reserve(state, extra);
3448
3449    match catch_unwind(AssertUnwindSafe(|| f(nargs))) {
3450        Ok(Ok(r)) => {
3451            // Return unused `WrappedFailure` to the pool
3452            prealloc_failure.release(state, extra);
3453            r
3454        }
3455        Ok(Err(err)) => {
3456            let wrapped_error = prealloc_failure.r#use(state, extra);
3457
3458            // Build `CallbackError` with traceback
3459            let traceback = if ffi::lua_checkstack(state, ffi::LUA_TRACEBACK_STACK) != 0 {
3460                ffi::luaL_traceback(state, state, ptr::null(), 0);
3461                let traceback = util::to_string(state, -1);
3462                ffi::lua_pop(state, 1);
3463                traceback
3464            } else {
3465                "<not enough stack space for traceback>".to_string()
3466            };
3467            let cause = Arc::new(err);
3468            ptr::write(
3469                wrapped_error,
3470                WrappedFailure::Error(Error::CallbackError { traceback, cause }),
3471            );
3472            get_gc_metatable::<WrappedFailure>(state);
3473            ffi::lua_setmetatable(state, -2);
3474
3475            ffi::lua_error(state)
3476        }
3477        Err(p) => {
3478            let wrapped_panic = prealloc_failure.r#use(state, extra);
3479            ptr::write(wrapped_panic, WrappedFailure::Panic(Some(p)));
3480            get_gc_metatable::<WrappedFailure>(state);
3481            ffi::lua_setmetatable(state, -2);
3482            ffi::lua_error(state)
3483        }
3484    }
3485}
3486
3487// Uses 3 stack spaces
3488unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<()> {
3489    #[inline(always)]
3490    pub unsafe fn requiref(
3491        state: *mut ffi::lua_State,
3492        modname: &str,
3493        openf: ffi::lua_CFunction,
3494        glb: c_int,
3495    ) -> Result<()> {
3496        let modname = mlua_expect!(CString::new(modname), "modname contains nil byte");
3497        protect_lua!(state, 0, 1, |state| {
3498            ffi::luaL_requiref(state, modname.as_ptr() as *const c_char, openf, glb)
3499        })
3500    }
3501
3502    #[cfg(feature = "luajit")]
3503    struct GcGuard(*mut ffi::lua_State);
3504
3505    #[cfg(feature = "luajit")]
3506    impl GcGuard {
3507        fn new(state: *mut ffi::lua_State) -> Self {
3508            // Stop collector during library initialization
3509            unsafe { ffi::lua_gc(state, ffi::LUA_GCSTOP, 0) };
3510            GcGuard(state)
3511        }
3512    }
3513
3514    #[cfg(feature = "luajit")]
3515    impl Drop for GcGuard {
3516        fn drop(&mut self) {
3517            unsafe { ffi::lua_gc(self.0, ffi::LUA_GCRESTART, -1) };
3518        }
3519    }
3520
3521    // Stop collector during library initialization
3522    #[cfg(feature = "luajit")]
3523    let _gc_guard = GcGuard::new(state);
3524
3525    #[cfg(any(
3526        feature = "lua54",
3527        feature = "lua53",
3528        feature = "lua52",
3529        feature = "luau"
3530    ))]
3531    {
3532        if libs.contains(StdLib::COROUTINE) {
3533            requiref(state, ffi::LUA_COLIBNAME, ffi::luaopen_coroutine, 1)?;
3534            ffi::lua_pop(state, 1);
3535        }
3536    }
3537
3538    if libs.contains(StdLib::TABLE) {
3539        requiref(state, ffi::LUA_TABLIBNAME, ffi::luaopen_table, 1)?;
3540        ffi::lua_pop(state, 1);
3541    }
3542
3543    #[cfg(not(feature = "luau"))]
3544    if libs.contains(StdLib::IO) {
3545        requiref(state, ffi::LUA_IOLIBNAME, ffi::luaopen_io, 1)?;
3546        ffi::lua_pop(state, 1);
3547    }
3548
3549    if libs.contains(StdLib::OS) {
3550        requiref(state, ffi::LUA_OSLIBNAME, ffi::luaopen_os, 1)?;
3551        ffi::lua_pop(state, 1);
3552    }
3553
3554    if libs.contains(StdLib::STRING) {
3555        requiref(state, ffi::LUA_STRLIBNAME, ffi::luaopen_string, 1)?;
3556        ffi::lua_pop(state, 1);
3557    }
3558
3559    #[cfg(any(feature = "lua54", feature = "lua53", feature = "luau"))]
3560    {
3561        if libs.contains(StdLib::UTF8) {
3562            requiref(state, ffi::LUA_UTF8LIBNAME, ffi::luaopen_utf8, 1)?;
3563            ffi::lua_pop(state, 1);
3564        }
3565    }
3566
3567    #[cfg(any(feature = "lua52", feature = "luau"))]
3568    {
3569        if libs.contains(StdLib::BIT) {
3570            requiref(state, ffi::LUA_BITLIBNAME, ffi::luaopen_bit32, 1)?;
3571            ffi::lua_pop(state, 1);
3572        }
3573    }
3574
3575    #[cfg(feature = "luajit")]
3576    {
3577        if libs.contains(StdLib::BIT) {
3578            requiref(state, ffi::LUA_BITLIBNAME, ffi::luaopen_bit, 1)?;
3579            ffi::lua_pop(state, 1);
3580        }
3581    }
3582
3583    #[cfg(feature = "luau")]
3584    if libs.contains(StdLib::BUFFER) {
3585        requiref(state, ffi::LUA_BUFFERLIBNAME, ffi::luaopen_buffer, 1)?;
3586        ffi::lua_pop(state, 1);
3587    }
3588
3589    if libs.contains(StdLib::MATH) {
3590        requiref(state, ffi::LUA_MATHLIBNAME, ffi::luaopen_math, 1)?;
3591        ffi::lua_pop(state, 1);
3592    }
3593
3594    if libs.contains(StdLib::DEBUG) {
3595        requiref(state, ffi::LUA_DBLIBNAME, ffi::luaopen_debug, 1)?;
3596        ffi::lua_pop(state, 1);
3597    }
3598
3599    #[cfg(not(feature = "luau"))]
3600    if libs.contains(StdLib::PACKAGE) {
3601        requiref(state, ffi::LUA_LOADLIBNAME, ffi::luaopen_package, 1)?;
3602        ffi::lua_pop(state, 1);
3603    }
3604    #[cfg(feature = "luau")]
3605    if libs.contains(StdLib::PACKAGE) {
3606        let lua: &Lua = mem::transmute((*extra_data(state)).inner.assume_init_ref());
3607        crate::luau::register_package_module(lua)?;
3608    }
3609
3610    #[cfg(feature = "luajit")]
3611    {
3612        if libs.contains(StdLib::JIT) {
3613            requiref(state, ffi::LUA_JITLIBNAME, ffi::luaopen_jit, 1)?;
3614            ffi::lua_pop(state, 1);
3615        }
3616
3617        if libs.contains(StdLib::FFI) {
3618            requiref(state, ffi::LUA_FFILIBNAME, ffi::luaopen_ffi, 1)?;
3619            ffi::lua_pop(state, 1);
3620        }
3621    }
3622
3623    Ok(())
3624}
3625
3626unsafe fn ref_stack_pop(extra: *mut ExtraData) -> c_int {
3627    let extra = &mut *extra;
3628    if let Some(free) = extra.ref_free.pop() {
3629        ffi::lua_replace(extra.ref_thread, free);
3630        return free;
3631    }
3632
3633    // Try to grow max stack size
3634    if extra.ref_stack_top >= extra.ref_stack_size {
3635        let mut inc = extra.ref_stack_size; // Try to double stack size
3636        while inc > 0 && ffi::lua_checkstack(extra.ref_thread, inc) == 0 {
3637            inc /= 2;
3638        }
3639        if inc == 0 {
3640            // Pop item on top of the stack to avoid stack leaking and successfully run destructors
3641            // during unwinding.
3642            ffi::lua_pop(extra.ref_thread, 1);
3643            let top = extra.ref_stack_top;
3644            // It is a user error to create enough references to exhaust the Lua max stack size for
3645            // the ref thread.
3646            panic!(
3647                "cannot create a Lua reference, out of auxiliary stack space (used {top} slots)"
3648            );
3649        }
3650        extra.ref_stack_size += inc;
3651    }
3652    extra.ref_stack_top += 1;
3653    extra.ref_stack_top
3654}
3655
3656#[cfg(test)]
3657mod assertions {
3658    use super::*;
3659
3660    // Lua has lots of interior mutability, should not be RefUnwindSafe
3661    static_assertions::assert_not_impl_any!(Lua: std::panic::RefUnwindSafe);
3662
3663    #[cfg(not(feature = "send"))]
3664    static_assertions::assert_not_impl_any!(Lua: Send);
3665    #[cfg(feature = "send")]
3666    static_assertions::assert_impl_all!(Lua: Send);
3667}