factorio_mlua/
lua.rs

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