mlua/state.rs
1//! Lua state management.
2//!
3//! This module provides the main [`Lua`] state handle together with state-specific
4//! configuration and garbage collector controls.
5
6use std::any::TypeId;
7use std::cell::{BorrowError, BorrowMutError, RefCell};
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::os::raw::{c_char, c_int};
11use std::panic::Location;
12use std::result::Result as StdResult;
13use std::{fmt, mem, ptr};
14
15use crate::chunk::{AsChunk, Chunk};
16use crate::debug::Debug;
17use crate::error::{Error, Result};
18use crate::function::Function;
19use crate::memory::MemoryState;
20use crate::multi::MultiValue;
21use crate::scope::Scope;
22use crate::stdlib::StdLib;
23use crate::string::LuaString;
24use crate::table::Table;
25use crate::thread::{Thread, ThreadEvent, ThreadTriggers};
26use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
27use crate::types::{
28 AppDataRef, AppDataRefMut, ArcReentrantMutexGuard, Integer, LuaType, MaybeSend, MaybeSync, Number,
29 ReentrantMutex, ReentrantMutexGuard, RegistryKey, VmState, XRc, XWeak,
30};
31use crate::userdata::{AnyUserData, UserData, UserDataProxy, UserDataRegistry, UserDataStorage};
32use crate::util::{StackGuard, assert_stack, check_stack, protect_lua_closure, push_string, rawset_field};
33use crate::value::{Nil, Value};
34
35#[cfg(not(feature = "luau"))]
36use crate::{debug::HookTriggers, types::HookKind};
37
38#[cfg(any(feature = "luau", doc))]
39use crate::{buffer::Buffer, chunk::Compiler};
40
41#[cfg(feature = "async")]
42use {
43 crate::types::LightUserData,
44 std::future::{self, Future},
45 std::task::Poll,
46};
47
48#[cfg(feature = "serde")]
49use serde::Serialize;
50
51pub(crate) use extra::ExtraData;
52#[doc(hidden)]
53pub use raw::RawLua;
54pub(crate) use util::callback_error_ext;
55
56/// Top level Lua struct which represents an instance of Lua VM.
57pub struct Lua {
58 pub(self) raw: XRc<ReentrantMutex<RawLua>>,
59 // Controls whether garbage collection should be run on drop
60 pub(self) collect_garbage: bool,
61}
62
63/// Weak reference to Lua instance.
64///
65/// This can used to prevent circular references between Lua and Rust objects.
66#[derive(Clone)]
67pub struct WeakLua(XWeak<ReentrantMutex<RawLua>>);
68
69pub(crate) struct LuaGuard(ArcReentrantMutexGuard<RawLua>);
70
71/// Tuning parameters for the incremental GC collector.
72///
73/// Each field is an [`Option`]: `None` leaves the corresponding parameter unchanged, while
74/// `Some(v)` sets it. Units and ranges depend on the Lua version, check the Lua reference manual
75/// for details.
76#[non_exhaustive]
77#[derive(Clone, Copy, Debug, Default)]
78pub struct GcIncParams {
79 /// Pause between successive GC cycles, expressed as a percentage of live memory.
80 #[cfg(not(feature = "luau"))]
81 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
82 pub pause: Option<c_int>,
83
84 /// Target heap size as a percentage of live data, controlling how aggressively
85 /// the GC reclaims memory (`LUA_GCSETGOAL`).
86 #[cfg(any(feature = "luau", doc))]
87 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
88 pub goal: Option<c_int>,
89
90 /// GC work performed per unit of memory allocated.
91 pub step_multiplier: Option<c_int>,
92
93 /// Granularity of each GC step.
94 ///
95 /// The unit is version-dependent, check the Lua reference manual for details.
96 #[cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))]
97 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))))]
98 pub step_size: Option<c_int>,
99}
100
101impl GcIncParams {
102 /// Sets the `pause` parameter.
103 #[cfg(not(feature = "luau"))]
104 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
105 #[must_use]
106 pub fn pause(mut self, v: c_int) -> Self {
107 self.pause = Some(v);
108 self
109 }
110
111 /// Sets the `goal` parameter.
112 #[cfg(any(feature = "luau", doc))]
113 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
114 #[must_use]
115 pub fn goal(mut self, v: c_int) -> Self {
116 self.goal = Some(v);
117 self
118 }
119
120 /// Sets the `step_multiplier` parameter.
121 #[must_use]
122 pub fn step_multiplier(mut self, v: c_int) -> Self {
123 self.step_multiplier = Some(v);
124 self
125 }
126
127 /// Sets the `step_size` parameter.
128 #[cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))]
129 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))))]
130 #[must_use]
131 pub fn step_size(mut self, v: c_int) -> Self {
132 self.step_size = Some(v);
133 self
134 }
135}
136
137/// Tuning parameters for the generational GC collector (Lua 5.4+).
138///
139/// Each field is an [`Option`]: `None` leaves the corresponding parameter unchanged, while
140/// `Some(v)` sets it. Units and ranges depend on the Lua version, check the reference manual
141/// for details.
142#[cfg(any(feature = "lua55", feature = "lua54"))]
143#[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
144#[non_exhaustive]
145#[derive(Clone, Copy, Debug, Default)]
146pub struct GcGenParams {
147 /// Frequency of minor (young-generation) collection steps.
148 pub minor_multiplier: Option<c_int>,
149
150 /// Threshold controlling how large the young generation can grow before triggering
151 /// a shift from minor to major collection.
152 pub minor_to_major: Option<c_int>,
153
154 /// Threshold controlling how much the major collection must shrink the heap before
155 /// switching back to minor (young-generation) collection.
156 #[cfg(feature = "lua55")]
157 #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
158 pub major_to_minor: Option<c_int>,
159}
160
161#[cfg(any(feature = "lua55", feature = "lua54"))]
162impl GcGenParams {
163 /// Sets the `minor_multiplier` parameter.
164 #[must_use]
165 pub fn minor_multiplier(mut self, v: c_int) -> Self {
166 self.minor_multiplier = Some(v);
167 self
168 }
169
170 /// Sets the `minor_to_major` threshold.
171 #[must_use]
172 pub fn minor_to_major(mut self, v: c_int) -> Self {
173 self.minor_to_major = Some(v);
174 self
175 }
176
177 /// Sets the `major_to_minor` parameter.
178 #[cfg(feature = "lua55")]
179 #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
180 #[must_use]
181 pub fn major_to_minor(mut self, v: c_int) -> Self {
182 self.major_to_minor = Some(v);
183 self
184 }
185}
186
187/// Lua garbage collector (GC) operating mode.
188///
189/// Use [`Lua::gc_set_mode`] to switch the collector mode and/or tune its parameters.
190#[non_exhaustive]
191#[derive(Clone, Debug)]
192pub enum GcMode {
193 /// Incremental mark-and-sweep
194 Incremental(GcIncParams),
195
196 /// Generational
197 #[cfg(any(feature = "lua55", feature = "lua54"))]
198 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
199 Generational(GcGenParams),
200}
201
202/// Controls Lua interpreter behavior such as Rust panics handling.
203#[derive(Clone, Debug)]
204#[non_exhaustive]
205pub struct LuaOptions {
206 /// Catch Rust panics when using [`pcall`]/[`xpcall`].
207 ///
208 /// If disabled, wraps these functions and automatically resumes panic if found.
209 /// Also in Lua 5.1 adds ability to provide arguments to [`xpcall`] similar to Lua >= 5.2.
210 ///
211 /// If enabled, keeps [`pcall`]/[`xpcall`] unmodified.
212 /// Panics are still automatically resumed if returned to the Rust side.
213 ///
214 /// Default: **true**
215 ///
216 /// [`pcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-pcall
217 /// [`xpcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-xpcall
218 pub catch_rust_panics: bool,
219
220 /// Max size of thread (coroutine) object pool used to execute asynchronous functions.
221 ///
222 /// Default: **0** (disabled)
223 ///
224 /// [`lua_resetthread`]: https://www.lua.org/manual/5.4/manual.html#lua_resetthread
225 #[cfg(feature = "async")]
226 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
227 pub thread_pool_size: usize,
228}
229
230impl Default for LuaOptions {
231 fn default() -> Self {
232 const { LuaOptions::new() }
233 }
234}
235
236impl LuaOptions {
237 /// Returns a new instance of `LuaOptions` with default parameters.
238 pub const fn new() -> Self {
239 LuaOptions {
240 catch_rust_panics: true,
241 #[cfg(feature = "async")]
242 thread_pool_size: 0,
243 }
244 }
245
246 /// Sets [`catch_rust_panics`] option.
247 ///
248 /// [`catch_rust_panics`]: #structfield.catch_rust_panics
249 #[must_use]
250 pub const fn catch_rust_panics(mut self, enabled: bool) -> Self {
251 self.catch_rust_panics = enabled;
252 self
253 }
254
255 /// Sets [`thread_pool_size`] option.
256 ///
257 /// [`thread_pool_size`]: #structfield.thread_pool_size
258 #[cfg(feature = "async")]
259 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
260 #[must_use]
261 pub const fn thread_pool_size(mut self, size: usize) -> Self {
262 self.thread_pool_size = size;
263 self
264 }
265}
266
267/// Luau JIT options
268#[cfg(any(feature = "luau-jit", doc))]
269#[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
270#[derive(Clone, Copy, Debug, PartialEq, Eq)]
271pub struct JitOptions {
272 inliner: bool,
273}
274
275#[cfg(any(feature = "luau-jit", doc))]
276impl Default for JitOptions {
277 fn default() -> Self {
278 const { Self::new() }
279 }
280}
281
282#[cfg(any(feature = "luau-jit", doc))]
283impl JitOptions {
284 /// Creates default JIT options.
285 pub const fn new() -> Self {
286 JitOptions { inliner: false }
287 }
288
289 /// Toggles the runtime bytecode inliner.
290 ///
291 /// Disabled by default. Enable before compiling and executing code.
292 #[must_use]
293 pub const fn inliner(mut self, enabled: bool) -> Self {
294 self.inliner = enabled;
295 self
296 }
297}
298
299impl Drop for Lua {
300 fn drop(&mut self) {
301 if self.collect_garbage {
302 let _ = self.gc_collect();
303 }
304 }
305}
306
307impl Clone for Lua {
308 #[inline]
309 fn clone(&self) -> Self {
310 Lua {
311 raw: XRc::clone(&self.raw),
312 collect_garbage: false,
313 }
314 }
315}
316
317impl fmt::Debug for Lua {
318 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319 write!(f, "Lua({:p})", self.state())
320 }
321}
322
323impl Default for Lua {
324 #[inline]
325 fn default() -> Self {
326 Lua::new()
327 }
328}
329
330impl Lua {
331 /// Creates a new Lua state and loads the **safe** subset of the standard libraries.
332 ///
333 /// # Safety
334 /// The created Lua state will have _some_ safety guarantees and will 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 pub fn new() -> Lua {
339 mlua_expect!(
340 Self::new_with(StdLib::ALL_SAFE, LuaOptions::default()),
341 "Cannot create a Lua state"
342 )
343 }
344
345 /// Creates a new Lua state and loads all the standard libraries.
346 ///
347 /// # Safety
348 /// The created Lua state will not have safety guarantees and will allow to load C modules.
349 pub unsafe fn unsafe_new() -> Lua {
350 Self::unsafe_new_with(StdLib::ALL, LuaOptions::default())
351 }
352
353 /// Creates a new Lua state and loads the specified safe subset of the standard libraries.
354 ///
355 /// Use the [`StdLib`] flags to specify the libraries you want to load.
356 ///
357 /// # Safety
358 /// The created Lua state will have _some_ safety guarantees and will not allow to load unsafe
359 /// standard libraries or C modules.
360 ///
361 /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
362 pub fn new_with(libs: StdLib, options: LuaOptions) -> Result<Lua> {
363 #[cfg(not(feature = "luau"))]
364 if libs.contains(StdLib::DEBUG) {
365 return Err(Error::SafetyError(
366 "The unsafe `debug` module can't be loaded using safe `new_with`".to_string(),
367 ));
368 }
369 #[cfg(feature = "luajit")]
370 if libs.contains(StdLib::FFI) {
371 return Err(Error::SafetyError(
372 "The unsafe `ffi` module can't be loaded using safe `new_with`".to_string(),
373 ));
374 }
375
376 let lua = unsafe { Self::inner_new(libs, options) };
377
378 #[cfg(not(feature = "luau"))]
379 if libs.contains(StdLib::PACKAGE) {
380 mlua_expect!(lua.disable_c_modules(), "Error disabling C modules");
381 }
382 lua.lock().mark_safe();
383
384 Ok(lua)
385 }
386
387 /// Creates a new Lua state and loads the specified subset of the standard libraries.
388 ///
389 /// Use the [`StdLib`] flags to specify the libraries you want to load.
390 ///
391 /// # Safety
392 /// The created Lua state will not have safety guarantees and allow to load C modules.
393 pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
394 // Workaround to avoid stripping a few unused Lua symbols that could be imported
395 // by C modules in unsafe mode
396 let mut _symbols: Vec<*const extern "C-unwind" fn()> =
397 vec![ffi::lua_isuserdata as _, ffi::lua_tocfunction as _];
398
399 #[cfg(not(feature = "luau"))]
400 _symbols.extend_from_slice(&[
401 ffi::lua_atpanic as _,
402 ffi::luaL_loadstring as _,
403 ffi::luaL_openlibs as _,
404 ]);
405 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
406 {
407 _symbols.push(ffi::lua_getglobal as _);
408 _symbols.push(ffi::lua_setglobal as _);
409 _symbols.push(ffi::luaL_setfuncs as _);
410 }
411
412 Self::inner_new(libs, options)
413 }
414
415 /// Creates a new Lua state with required `libs` and `options`
416 unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
417 let lua = Lua {
418 raw: RawLua::new(libs, &options),
419 collect_garbage: true,
420 };
421
422 #[cfg(feature = "luau")]
423 mlua_expect!(lua.configure_luau(), "Error configuring Luau");
424
425 lua
426 }
427
428 /// Returns or constructs Lua instance from a raw state.
429 ///
430 /// Once initialized, the returned Lua instance is cached in the registry and can be retrieved
431 /// by calling this function again.
432 ///
433 /// # Safety
434 /// The `Lua` must outlive the chosen lifetime `'a`.
435 #[inline]
436 pub unsafe fn get_or_init_from_ptr<'a>(state: *mut ffi::lua_State) -> &'a Lua {
437 debug_assert!(!state.is_null(), "Lua state is null");
438 match ExtraData::get(state) {
439 extra if !extra.is_null() => (*extra).lua(),
440 _ => {
441 // The `owned` flag is set to `false` as we don't own the Lua state.
442 RawLua::init_from_ptr(state, false);
443 (*ExtraData::get(state)).lua()
444 }
445 }
446 }
447
448 /// Calls provided function passing a raw lua state.
449 ///
450 /// The arguments will be pushed onto the stack before calling the function.
451 ///
452 /// This method ensures that the Lua instance is locked while the function is called
453 /// and restores Lua stack after the function returns.
454 ///
455 /// # Example
456 /// ```
457 /// # use mlua::{Lua, Result};
458 /// # fn main() -> Result<()> {
459 /// let lua = Lua::new();
460 /// let n: i32 = unsafe {
461 /// let nums = (3, 4, 5);
462 /// lua.exec_raw(nums, |state| {
463 /// let n = ffi::lua_gettop(state);
464 /// let mut sum = 0;
465 /// for i in 1..=n {
466 /// sum += ffi::lua_tointeger(state, i);
467 /// }
468 /// ffi::lua_pop(state, n);
469 /// ffi::lua_pushinteger(state, sum);
470 /// })
471 /// }?;
472 /// assert_eq!(n, 12);
473 /// # Ok(())
474 /// # }
475 /// ```
476 #[allow(clippy::missing_safety_doc)]
477 pub unsafe fn exec_raw<R: FromLuaMulti>(
478 &self,
479 args: impl IntoLuaMulti,
480 f: impl FnOnce(*mut ffi::lua_State),
481 ) -> Result<R> {
482 let lua = self.lock();
483 let state = lua.state();
484 let _sg = StackGuard::new(state);
485 let stack_start = ffi::lua_gettop(state);
486 let nargs = args.push_into_stack_multi(&lua)?;
487 check_stack(state, 3)?;
488 protect_lua_closure::<_, ()>(state, nargs, ffi::LUA_MULTRET, f)?;
489 let nresults = ffi::lua_gettop(state) - stack_start;
490 R::from_stack_multi(nresults, &lua)
491 }
492
493 /// Calls provided function passing a reference to the [`RawLua`] handle.
494 ///
495 /// Provided [`RawLua`] handle can be used to manually pushing/popping values to/from the stack.
496 ///
497 /// # Example
498 /// ```
499 /// # use mlua::{Lua, Result, FromLua, IntoLua, IntoLuaMulti};
500 /// # fn main() -> Result<()> {
501 /// let lua = Lua::new();
502 /// let n: i32 = {
503 /// let nums = (3, 4, 5);
504 /// lua.exec_raw_lua(|rawlua| unsafe {
505 /// nums.push_into_stack_multi(rawlua)?;
506 /// let mut sum = 0;
507 /// for _ in 0..3 {
508 /// sum += rawlua.pop::<i32>()?;
509 /// }
510 /// Result::Ok(sum)
511 /// })
512 /// }?;
513 /// assert_eq!(n, 12);
514 /// # Ok(())
515 /// # }
516 /// ```
517 #[doc(hidden)]
518 pub fn exec_raw_lua<R>(&self, f: impl FnOnce(&RawLua) -> R) -> R {
519 let lua = self.lock();
520 f(&lua)
521 }
522
523 /// Loads the specified subset of the standard libraries into an existing Lua state.
524 ///
525 /// Use the [`StdLib`] flags to specify the libraries you want to load.
526 pub fn load_std_libs(&self, libs: StdLib) -> Result<()> {
527 unsafe { self.lock().load_std_libs(libs) }
528 }
529
530 /// Registers module into an existing Lua state using the specified value.
531 ///
532 /// After registration, the given value will always be immediately returned when the
533 /// given module is [required].
534 ///
535 /// [required]: https://www.lua.org/manual/5.4/manual.html#pdf-require
536 pub fn register_module(&self, modname: &str, value: impl IntoLua) -> Result<()> {
537 #[cfg(not(feature = "luau"))]
538 const LOADED_MODULES_KEY: *const c_char = ffi::LUA_LOADED_TABLE;
539 #[cfg(feature = "luau")]
540 const LOADED_MODULES_KEY: *const c_char = ffi::LUA_REGISTERED_MODULES_TABLE;
541
542 if cfg!(feature = "luau") && !modname.starts_with('@') {
543 return Err(Error::runtime("module name must begin with '@'"));
544 }
545 #[cfg(feature = "luau")]
546 let modname = modname.to_ascii_lowercase();
547 unsafe {
548 self.exec_raw::<()>(value, |state| {
549 ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, LOADED_MODULES_KEY);
550 ffi::lua_pushlstring(state, modname.as_ptr() as *const c_char, modname.len() as _);
551 ffi::lua_pushvalue(state, -3);
552 ffi::lua_rawset(state, -3);
553 })
554 }
555 }
556
557 /// Preloads module into an existing Lua state using the specified loader function.
558 ///
559 /// When the module is required, the loader function will be called with module name as the
560 /// first argument.
561 ///
562 /// This is similar to setting the [`package.preload[modname]`] field.
563 ///
564 /// [`package.preload[modname]`]: <https://www.lua.org/manual/5.4/manual.html#pdf-package.preload>
565 #[cfg(not(feature = "luau"))]
566 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
567 pub fn preload_module(&self, modname: &str, func: Function) -> Result<()> {
568 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
569 let preload = unsafe {
570 self.exec_raw::<Option<Table>>((), |state| {
571 ffi::lua_getfield(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_PRELOAD_TABLE);
572 })?
573 };
574 #[cfg(any(feature = "lua51", feature = "luajit"))]
575 let preload = unsafe {
576 self.exec_raw::<Option<Table>>((), |state| {
577 if ffi::lua_getfield(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_LOADED_TABLE) != ffi::LUA_TNIL {
578 ffi::luaL_getsubtable(state, -1, ffi::LUA_LOADLIBNAME);
579 ffi::luaL_getsubtable(state, -1, cstr!("preload"));
580 ffi::lua_rotate(state, 1, 1);
581 }
582 })?
583 };
584 if let Some(preload) = preload {
585 preload.raw_set(modname, func)?;
586 }
587 Ok(())
588 }
589
590 /// Unloads module `modname`.
591 ///
592 /// This method does not support unloading binary Lua modules since they are internally cached
593 /// and can be unloaded only by closing Lua state.
594 ///
595 /// This is similar to calling [`Lua::register_module`] with `Nil` value.
596 ///
597 /// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
598 pub fn unload_module(&self, modname: &str) -> Result<()> {
599 self.register_module(modname, Nil)
600 }
601
602 // Executes module entrypoint function, which returns only one Value.
603 // The returned value then pushed onto the stack.
604 #[doc(hidden)]
605 #[cfg(not(tarpaulin_include))]
606 pub unsafe fn entrypoint<F, A, R>(state: *mut ffi::lua_State, func: F) -> c_int
607 where
608 F: FnOnce(&Lua, A) -> Result<R>,
609 A: FromLuaMulti,
610 R: IntoLua,
611 {
612 // Make sure that Lua is initialized
613 let _ = Self::get_or_init_from_ptr(state);
614
615 callback_error_ext(state, ptr::null_mut(), true, move |extra, nargs| {
616 let rawlua = (*extra).raw_lua();
617 let args = A::from_stack_args(nargs, 1, None, rawlua)?;
618 func(rawlua.lua(), args)?.push_into_stack(rawlua)?;
619 Ok(1)
620 })
621 }
622
623 // A simple module entrypoint without arguments
624 #[doc(hidden)]
625 #[cfg(not(tarpaulin_include))]
626 pub unsafe fn entrypoint1<F, R>(state: *mut ffi::lua_State, func: F) -> c_int
627 where
628 F: FnOnce(&Lua) -> Result<R>,
629 R: IntoLua,
630 {
631 Self::entrypoint(state, move |lua, _: ()| func(lua))
632 }
633
634 /// Skips memory checks for some operations.
635 #[doc(hidden)]
636 #[cfg(feature = "module")]
637 pub fn skip_memory_check(&self, skip: bool) {
638 let lua = self.lock();
639 unsafe {
640 (*lua.extra.get()).skip_memory_check = skip;
641 if MemoryState::get(lua.state()).is_null() {
642 (*lua.extra.get()).unlikely_memory_error = skip;
643 }
644 }
645 }
646
647 /// Enables (or disables) sandbox mode on this Lua instance.
648 ///
649 /// This method, in particular:
650 /// - Set all libraries to read-only
651 /// - Set all builtin metatables to read-only
652 /// - Set globals to read-only (and activates safeenv)
653 /// - Setup local environment table that performs writes locally and proxies reads to the global
654 /// environment.
655 /// - Allow only `count` mode in `collectgarbage` function.
656 ///
657 /// # Examples
658 ///
659 /// ```
660 /// # use mlua::{Lua, Result};
661 /// # #[cfg(feature = "luau")]
662 /// # fn main() -> Result<()> {
663 /// let lua = Lua::new();
664 ///
665 /// lua.sandbox(true)?;
666 /// lua.load("var = 123").exec()?;
667 /// assert_eq!(lua.globals().get::<u32>("var")?, 123);
668 ///
669 /// // Restore the global environment (clear changes made in sandbox)
670 /// lua.sandbox(false)?;
671 /// assert_eq!(lua.globals().get::<Option<u32>>("var")?, None);
672 /// # Ok(())
673 /// # }
674 ///
675 /// # #[cfg(not(feature = "luau"))]
676 /// # fn main() {}
677 /// ```
678 #[cfg(any(feature = "luau", doc))]
679 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
680 pub fn sandbox(&self, enabled: bool) -> Result<()> {
681 let lua = self.lock();
682 unsafe {
683 if (*lua.extra.get()).sandboxed != enabled {
684 let state = lua.main_state();
685 check_stack(state, 3)?;
686 protect_lua!(state, 0, 0, |state| {
687 if enabled {
688 ffi::luaL_sandbox(state, 1);
689 ffi::luaL_sandboxthread(state);
690 } else {
691 // Restore original `LUA_GLOBALSINDEX`
692 ffi::lua_xpush(lua.ref_thread(), state, ffi::LUA_GLOBALSINDEX);
693 ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
694 ffi::luaL_sandbox(state, 0);
695 }
696 })?;
697 (*lua.extra.get()).sandboxed = enabled;
698 }
699 Ok(())
700 }
701 }
702
703 /// Sets or replaces a global hook function that will periodically be called as Lua code
704 /// executes.
705 ///
706 /// All new threads created (by mlua) after this call will use the global hook function.
707 ///
708 /// For more information see [`Lua::set_hook`].
709 #[cfg(not(feature = "luau"))]
710 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
711 pub fn set_global_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
712 where
713 F: Fn(&Lua, &Debug) -> Result<VmState> + MaybeSend + 'static,
714 {
715 let lua = self.lock();
716 unsafe {
717 let _old_callback = (*lua.extra.get()).hook_callback.replace(XRc::new(callback));
718 (*lua.extra.get()).hook_triggers = triggers;
719 lua.set_thread_hook(lua.state(), HookKind::Global)
720 }
721 }
722
723 /// Sets a hook function that will periodically be called as Lua code executes.
724 ///
725 /// When exactly the hook function is called depends on the contents of the `triggers`
726 /// parameter, see [`HookTriggers`] for more details.
727 ///
728 /// The provided hook function can error, and this error will be propagated through the Lua code
729 /// that was executing at the time the hook was triggered. This can be used to implement a
730 /// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and
731 /// erroring once an instruction limit has been reached.
732 ///
733 /// This method sets a hook function for the *current* thread of this Lua instance.
734 /// If you want to set a hook function for another thread (coroutine), use
735 /// [`Thread::set_hook`] instead.
736 ///
737 /// # Example
738 ///
739 /// Shows each line number of code being executed by the Lua interpreter.
740 ///
741 /// ```
742 /// # use mlua::{Lua, HookTriggers, Result, VmState};
743 /// # fn main() -> Result<()> {
744 /// let lua = Lua::new();
745 /// lua.set_hook(HookTriggers::EVERY_LINE, |_lua, debug| {
746 /// println!("line {:?}", debug.current_line());
747 /// Ok(VmState::Continue)
748 /// });
749 ///
750 /// lua.load(r#"
751 /// local x = 2 + 3
752 /// local y = x * 63
753 /// local z = string.len(x..", "..y)
754 /// "#).exec()
755 /// # }
756 /// ```
757 ///
758 /// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
759 #[cfg(not(feature = "luau"))]
760 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
761 pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
762 where
763 F: Fn(&Lua, &Debug) -> Result<VmState> + MaybeSend + 'static,
764 {
765 let lua = self.lock();
766 unsafe { lua.set_thread_hook(lua.state(), HookKind::Thread(triggers, XRc::new(callback))) }
767 }
768
769 /// Removes a global hook previously set by [`Lua::set_global_hook`].
770 ///
771 /// This function has no effect if a hook was not previously set.
772 #[cfg(not(feature = "luau"))]
773 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
774 pub fn remove_global_hook(&self) {
775 let lua = self.lock();
776 unsafe {
777 let _old_callback = (*lua.extra.get()).hook_callback.take();
778 (*lua.extra.get()).hook_triggers = HookTriggers::default();
779 }
780 }
781
782 /// Removes any hook from the current thread.
783 ///
784 /// This function has no effect if a hook was not previously set.
785 #[cfg(not(feature = "luau"))]
786 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
787 pub fn remove_hook(&self) {
788 let lua = self.lock();
789 unsafe {
790 lua.remove_thread_hook(lua.state());
791 }
792 }
793
794 /// Sets an interrupt function that will periodically be called by Luau VM.
795 ///
796 /// Any Luau code is guaranteed to call this handler "eventually"
797 /// (in practice this can happen at any function call or at any loop iteration).
798 /// This is similar to `Lua::set_hook` but in more simplified form.
799 ///
800 /// The provided interrupt function can error, and this error will be propagated through
801 /// the Luau code that was executing at the time the interrupt was triggered.
802 /// Also this can be used to implement continuous execution limits by instructing Luau VM to
803 /// yield by returning [`VmState::Yield`]. The yield will happen only at yieldable points
804 /// of execution (not across metamethod/C-call boundaries).
805 ///
806 /// # Example
807 ///
808 /// Periodically yield Luau VM to suspend execution.
809 ///
810 /// ```
811 /// # use std::sync::{Arc, atomic::{AtomicU64, Ordering}};
812 /// # use mlua::thread::ThreadStatus;
813 /// # use mlua::{Lua, Result, VmState};
814 /// # #[cfg(feature = "luau")]
815 /// # fn main() -> Result<()> {
816 /// let lua = Lua::new();
817 /// let count = Arc::new(AtomicU64::new(0));
818 /// lua.set_interrupt(move |_| {
819 /// if count.fetch_add(1, Ordering::Relaxed) % 2 == 0 {
820 /// return Ok(VmState::Yield);
821 /// }
822 /// Ok(VmState::Continue)
823 /// });
824 ///
825 /// let co = lua.create_thread(
826 /// lua.load(r#"
827 /// local b = 0
828 /// for _, x in ipairs({1, 2, 3}) do b += x end
829 /// "#)
830 /// .into_function()?,
831 /// )?;
832 /// while co.status() == ThreadStatus::Resumable {
833 /// co.resume::<()>(())?;
834 /// }
835 /// # Ok(())
836 /// # }
837 ///
838 /// # #[cfg(not(feature = "luau"))]
839 /// # fn main() {}
840 /// ```
841 #[cfg(any(feature = "luau", doc))]
842 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
843 pub fn set_interrupt<F>(&self, callback: F)
844 where
845 F: Fn(&Lua) -> Result<VmState> + MaybeSend + 'static,
846 {
847 unsafe extern "C-unwind" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) {
848 if gc >= 0 {
849 // We don't support GC interrupts since they cannot survive Lua exceptions
850 return;
851 }
852 let result = callback_error_ext(state, ptr::null_mut(), false, move |extra, _| {
853 let interrupt_cb = (*extra).interrupt_callback.clone();
854 let interrupt_cb = mlua_expect!(interrupt_cb, "no interrupt callback set in interrupt_proc");
855 if XRc::strong_count(&interrupt_cb) > 2 {
856 return Ok(VmState::Continue); // Don't allow recursion
857 }
858 interrupt_cb((*extra).lua())
859 });
860 match result {
861 VmState::Continue => {}
862 VmState::Yield => {
863 // We can yield only at yieldable points, otherwise ignore and continue
864 if ffi::lua_isyieldable(state) != 0 {
865 ffi::lua_yield(state, 0);
866 }
867 }
868 }
869 }
870
871 // Set interrupt callback
872 let lua = self.lock();
873 unsafe {
874 let _old_callback = (*lua.extra.get()).interrupt_callback.replace(XRc::new(callback));
875 (*ffi::lua_callbacks(lua.main_state())).interrupt = Some(interrupt_proc);
876 }
877 }
878
879 /// Removes any interrupt function previously set by `set_interrupt`.
880 ///
881 /// This function has no effect if an 'interrupt' was not previously set.
882 #[cfg(any(feature = "luau", doc))]
883 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
884 pub fn remove_interrupt(&self) {
885 let lua = self.lock();
886 unsafe {
887 let _old_callback = (*lua.extra.get()).interrupt_callback.take();
888 (*ffi::lua_callbacks(lua.main_state())).interrupt = None;
889 }
890 }
891
892 /// Sets a callback invoked when thread lifecycle events occur.
893 ///
894 /// `triggers` controls which events trigger the callback, see [`ThreadTriggers`] for more
895 /// details.
896 ///
897 /// Only one callback can be registered at a time. Calling this again replaces the previous
898 /// callback and its triggers.
899 ///
900 /// If the callback returns an error, it's propagated out of the operation that triggered the
901 /// event. For a [`ThreadEvent::Yield`], the yielded values are discarded.
902 ///
903 /// # Example
904 ///
905 /// Subscribe only to yield events:
906 ///
907 /// ```
908 /// # use mlua::thread::{ThreadTriggers, ThreadEvent};
909 /// # use mlua::{Lua, Result};
910 /// # fn main() -> Result<()> {
911 /// let lua = Lua::new();
912 /// lua.set_thread_event_callback(
913 /// ThreadTriggers::ON_YIELD,
914 /// |_lua, event| {
915 /// if let ThreadEvent::Yield(thread) = event {
916 /// println!("thread yielded");
917 /// }
918 /// Ok(())
919 /// },
920 /// );
921 /// # Ok(())
922 /// # }
923 /// ```
924 pub fn set_thread_event_callback<F>(&self, triggers: ThreadTriggers, callback: F)
925 where
926 F: Fn(&Lua, ThreadEvent) -> Result<()> + MaybeSend + 'static,
927 {
928 let lua = self.lock();
929 unsafe {
930 let _old_callback = ((*lua.extra.get()).thread_event_callback).replace(XRc::new(callback));
931 (*lua.extra.get()).thread_triggers = triggers;
932 #[cfg(feature = "luau")]
933 {
934 let proc = Self::userthread_proc as _;
935 (*ffi::lua_callbacks(lua.main_state())).userthread = triggers.on_create.then_some(proc);
936 }
937 }
938 }
939
940 /// Removes the thread event callback previously set by [`Lua::set_thread_event_callback`].
941 ///
942 /// This function has no effect if a callback was not previously set.
943 pub fn remove_thread_event_callback(&self) {
944 let lua = self.lock();
945 let extra = lua.extra.get();
946 unsafe {
947 let _old_callback = (*extra).thread_event_callback.take();
948 (*extra).thread_triggers = ThreadTriggers::new();
949 #[cfg(feature = "luau")]
950 {
951 (*ffi::lua_callbacks(lua.main_state())).userthread = None;
952 }
953 }
954 }
955
956 #[cfg(feature = "luau")]
957 unsafe extern "C-unwind" fn userthread_proc(parent: *mut ffi::lua_State, child: *mut ffi::lua_State) {
958 // Only handle thread creation
959 if parent.is_null() {
960 return;
961 }
962
963 let extra = ExtraData::get(child);
964 if !(*extra).thread_triggers.on_create || !(*extra).thread_event_state.is_null() {
965 return;
966 }
967 let Some(callback) = (*extra).thread_event_callback.clone() else {
968 return;
969 };
970 ffi::lua_pushthread(child);
971 ffi::lua_xmove(child, (*extra).ref_thread, 1);
972 let Ok(thread) = ((*extra).raw_lua().try_pop_ref_thread()).map(|vref| Thread(vref, child)) else {
973 return;
974 };
975 callback_error_ext(parent, extra, false, move |extra, _| {
976 let _guard = crate::thread::ThreadEventGuard::new((*extra).raw_lua(), child);
977 callback((*extra).lua(), ThreadEvent::Create(thread))
978 })
979 }
980
981 /// Sets the warning function to be used by Lua to emit warnings.
982 #[cfg(any(feature = "lua55", feature = "lua54"))]
983 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
984 pub fn set_warning_function<F>(&self, callback: F)
985 where
986 F: Fn(&Lua, &str, bool) -> Result<()> + MaybeSend + 'static,
987 {
988 use std::ffi::CStr;
989 use std::os::raw::{c_char, c_void};
990
991 unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
992 let extra = ud as *mut ExtraData;
993 callback_error_ext((*extra).raw_lua().state(), extra, false, |extra, _| {
994 let warn_callback = (*extra).warn_callback.clone();
995 let warn_callback = mlua_expect!(warn_callback, "no warning callback set in warn_proc");
996 if XRc::strong_count(&warn_callback) > 2 {
997 return Ok(());
998 }
999 let msg = String::from_utf8_lossy(CStr::from_ptr(msg).to_bytes());
1000 warn_callback((*extra).lua(), &msg, tocont != 0)
1001 });
1002 }
1003
1004 let lua = self.lock();
1005 unsafe {
1006 let _old_callback = (*lua.extra.get()).warn_callback.replace(XRc::new(callback));
1007 ffi::lua_setwarnf(lua.state(), Some(warn_proc), lua.extra.get() as *mut c_void);
1008 }
1009 }
1010
1011 /// Removes warning function previously set by `set_warning_function`.
1012 ///
1013 /// This function has no effect if a warning function was not previously set.
1014 #[cfg(any(feature = "lua55", feature = "lua54"))]
1015 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
1016 pub fn remove_warning_function(&self) {
1017 let lua = self.lock();
1018 unsafe {
1019 let _old_callback = (*lua.extra.get()).warn_callback.take();
1020 ffi::lua_setwarnf(lua.state(), None, ptr::null_mut());
1021 }
1022 }
1023
1024 /// Emits a warning with the given message.
1025 ///
1026 /// A message in a call with `incomplete` set to `true` should be continued in
1027 /// another call to this function.
1028 #[cfg(any(feature = "lua55", feature = "lua54"))]
1029 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
1030 pub fn warning(&self, msg: impl AsRef<str>, incomplete: bool) {
1031 let msg = msg.as_ref().as_bytes();
1032 let end = msg.iter().position(|&c| c == 0).unwrap_or(msg.len());
1033 let mut bytes = Vec::with_capacity(end + 1);
1034 bytes.extend_from_slice(&msg[..end]);
1035 bytes.push(0);
1036 let lua = self.lock();
1037 unsafe {
1038 ffi::lua_warning(lua.state(), bytes.as_ptr() as *const _, incomplete as c_int);
1039 }
1040 }
1041
1042 /// Gets information about the interpreter runtime stack at the given level.
1043 ///
1044 /// This function calls callback `f`, passing the [`struct@Debug`] structure that can be used to
1045 /// get information about the function executing at a given level.
1046 /// Level `0` is the current running function, whereas level `n+1` is the function that has
1047 /// called level `n` (except for tail calls, which do not count in the stack).
1048 pub fn inspect_stack<R>(&self, level: usize, f: impl FnOnce(&Debug) -> R) -> Option<R> {
1049 let level = c_int::try_from(level).ok()?;
1050 let lua = self.lock();
1051 unsafe {
1052 let mut ar = mem::zeroed::<ffi::lua_Debug>();
1053 #[cfg(not(feature = "luau"))]
1054 if ffi::lua_getstack(lua.state(), level, &mut ar) == 0 {
1055 return None;
1056 }
1057 #[cfg(feature = "luau")]
1058 if ffi::lua_getinfo(lua.state(), level, cstr!(""), &mut ar) == 0 {
1059 return None;
1060 }
1061
1062 Some(f(&Debug::new(&lua, level, &mut ar)))
1063 }
1064 }
1065
1066 /// Creates a traceback of the call stack at the given level.
1067 ///
1068 /// The `msg` parameter, if provided, is added at the beginning of the traceback.
1069 /// The `level` parameter works the same way as in [`Lua::inspect_stack`].
1070 pub fn traceback(&self, msg: Option<&str>, level: usize) -> Result<LuaString> {
1071 let lua = self.lock();
1072 unsafe {
1073 check_stack(lua.state(), 3)?;
1074 protect_lua!(lua.state(), 0, 1, |state| {
1075 let msg = match msg {
1076 Some(s) => ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len()),
1077 None => ptr::null(),
1078 };
1079 // `protect_lua` adds its own call frame, leave room for Lua's internal increment.
1080 let level = level.saturating_add(1).min((c_int::MAX - 1) as usize) as c_int;
1081 ffi::luaL_traceback(state, state, msg, level);
1082 })?;
1083 Ok(LuaString(lua.try_pop_ref()?))
1084 }
1085 }
1086
1087 /// Returns the amount of memory (in bytes) currently used inside this Lua state.
1088 pub fn used_memory(&self) -> usize {
1089 let lua = self.lock();
1090 let state = lua.main_state();
1091 unsafe {
1092 match MemoryState::get(state) {
1093 mem_state if !mem_state.is_null() => (*mem_state).used_memory(),
1094 _ => {
1095 // Get data from the Lua GC
1096 let used_kbytes = ffi::lua_gc(state, ffi::LUA_GCCOUNT, 0);
1097 let used_kbytes_rem = ffi::lua_gc(state, ffi::LUA_GCCOUNTB, 0);
1098 (used_kbytes as usize) * 1024 + (used_kbytes_rem as usize)
1099 }
1100 }
1101 }
1102 }
1103
1104 /// Sets a memory limit (in bytes) on this Lua state.
1105 ///
1106 /// Once an allocation occurs that would pass this memory limit, a `Error::MemoryError` is
1107 /// generated instead.
1108 /// Returns previous limit (zero means no limit).
1109 ///
1110 /// Does not work in module mode where Lua state is managed externally.
1111 pub fn set_memory_limit(&self, limit: usize) -> Result<usize> {
1112 let lua = self.lock();
1113 unsafe {
1114 match MemoryState::get(lua.state()) {
1115 mem_state if !mem_state.is_null() => {
1116 let prev_limit = (*mem_state).set_memory_limit(limit);
1117 (*lua.extra.get()).unlikely_memory_error = (*mem_state).memory_limit() == 0;
1118 Ok(prev_limit)
1119 }
1120 _ => Err(Error::MemoryControlNotAvailable),
1121 }
1122 }
1123 }
1124
1125 /// Returns `true` if the garbage collector is currently running automatically.
1126 #[cfg(any(
1127 feature = "lua55",
1128 feature = "lua54",
1129 feature = "lua53",
1130 feature = "lua52",
1131 feature = "luau"
1132 ))]
1133 #[cfg_attr(
1134 docsrs,
1135 doc(cfg(any(
1136 feature = "lua55",
1137 feature = "lua54",
1138 feature = "lua53",
1139 feature = "lua52",
1140 feature = "luau"
1141 )))
1142 )]
1143 pub fn gc_is_running(&self) -> bool {
1144 let lua = self.lock();
1145 unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCISRUNNING, 0) != 0 }
1146 }
1147
1148 /// Stops the Lua GC from running.
1149 pub fn gc_stop(&self) {
1150 let lua = self.lock();
1151 unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCSTOP, 0) };
1152 }
1153
1154 /// Restarts the Lua GC if it is not running.
1155 pub fn gc_restart(&self) {
1156 let lua = self.lock();
1157 unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCRESTART, 0) };
1158 }
1159
1160 /// Performs a full garbage-collection cycle.
1161 ///
1162 /// It may be necessary to call this function twice to collect all currently unreachable
1163 /// objects. Once to finish the current gc cycle, and once to start and finish the next cycle.
1164 pub fn gc_collect(&self) -> Result<()> {
1165 let lua = self.lock();
1166 let state = lua.main_state();
1167 unsafe {
1168 check_stack(state, 2)?;
1169 protect_lua!(state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
1170 }
1171 }
1172
1173 /// Performs a basic step of garbage collection.
1174 ///
1175 /// In incremental mode, a basic step corresponds to the current step size. In generational
1176 /// mode, a basic step performs a full minor collection or an incremental step, if the collector
1177 /// has scheduled one.
1178 ///
1179 /// In incremental mode, returns `true` if this step has finished a collection cycle.
1180 /// In generational mode, returns `true` if the step finished a major collection.
1181 pub fn gc_step(&self) -> Result<bool> {
1182 let lua = self.lock();
1183 let state = lua.main_state();
1184 unsafe {
1185 check_stack(state, 3)?;
1186 protect_lua!(state, 0, 0, |state| {
1187 ffi::lua_gc(state, ffi::LUA_GCSTEP, 0) != 0
1188 })
1189 }
1190 }
1191
1192 /// Switches the GC to the given mode with the provided parameters.
1193 ///
1194 /// Returns the previous [`GcMode`]. Only the collector *mode* is reported, the returned value's
1195 /// parameter fields are always `None`.
1196 ///
1197 /// If the collector is internally stopped, the mode cannot be changed and the requested mode is
1198 /// returned as-is.
1199 ///
1200 /// # Examples
1201 ///
1202 /// Switch to generational mode (Lua 5.4+):
1203 /// ```ignore
1204 /// let prev = lua.gc_set_mode(GcMode::Generational(GcGenParams::default()));
1205 /// ```
1206 ///
1207 /// Switch to incremental mode with custom parameters:
1208 /// ```ignore
1209 /// lua.gc_set_mode(GcMode::Incremental(
1210 /// GcIncParams::default().step_multiplier(100)
1211 /// ));
1212 /// ```
1213 pub fn gc_set_mode(&self, mode: GcMode) -> GcMode {
1214 let lua = self.lock();
1215 let state = lua.main_state();
1216
1217 match mode {
1218 #[cfg(feature = "lua55")]
1219 GcMode::Incremental(params) => unsafe {
1220 if let Some(v) = params.pause {
1221 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPPAUSE, v);
1222 }
1223 if let Some(v) = params.step_multiplier {
1224 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPMUL, v);
1225 }
1226 if let Some(v) = params.step_size {
1227 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPSIZE, v);
1228 }
1229 match ffi::lua_gc(state, ffi::LUA_GCINC) {
1230 ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1231 _ => GcMode::Incremental(GcIncParams::default()),
1232 }
1233 },
1234 #[cfg(feature = "lua54")]
1235 GcMode::Incremental(params) => unsafe {
1236 let pause = params.pause.unwrap_or(0);
1237 let step_mul = params.step_multiplier.unwrap_or(0);
1238 let step_size = params.step_size.unwrap_or(0);
1239 match ffi::lua_gc(state, ffi::LUA_GCINC, pause, step_mul, step_size) {
1240 ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1241 _ => GcMode::Incremental(GcIncParams::default()),
1242 }
1243 },
1244 #[cfg(any(feature = "lua53", feature = "lua52", feature = "lua51", feature = "luajit"))]
1245 GcMode::Incremental(params) => unsafe {
1246 if let Some(v) = params.pause {
1247 ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, v);
1248 }
1249 if let Some(v) = params.step_multiplier {
1250 ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1251 }
1252 GcMode::Incremental(GcIncParams::default())
1253 },
1254 #[cfg(feature = "luau")]
1255 GcMode::Incremental(params) => unsafe {
1256 if let Some(v) = params.goal {
1257 ffi::lua_gc(state, ffi::LUA_GCSETGOAL, v);
1258 }
1259 if let Some(v) = params.step_multiplier {
1260 ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1261 }
1262 if let Some(v) = params.step_size {
1263 ffi::lua_gc(state, ffi::LUA_GCSETSTEPSIZE, v);
1264 }
1265 GcMode::Incremental(GcIncParams::default())
1266 },
1267
1268 #[cfg(feature = "lua55")]
1269 GcMode::Generational(params) => unsafe {
1270 if let Some(v) = params.minor_multiplier {
1271 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMUL, v);
1272 }
1273 if let Some(v) = params.minor_to_major {
1274 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMAJOR, v);
1275 }
1276 if let Some(v) = params.major_to_minor {
1277 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMAJORMINOR, v);
1278 }
1279 match ffi::lua_gc(state, ffi::LUA_GCGEN) {
1280 ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1281 _ => GcMode::Generational(GcGenParams::default()),
1282 }
1283 },
1284 #[cfg(feature = "lua54")]
1285 GcMode::Generational(params) => unsafe {
1286 let minor = params.minor_multiplier.unwrap_or(0);
1287 let minor_to_major = params.minor_to_major.unwrap_or(0);
1288 match ffi::lua_gc(state, ffi::LUA_GCGEN, minor, minor_to_major) {
1289 ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1290 _ => GcMode::Generational(GcGenParams::default()),
1291 }
1292 },
1293 }
1294 }
1295
1296 /// Sets a default Luau compiler (with custom options).
1297 ///
1298 /// This compiler will be used by default to load all Lua chunks
1299 /// including via `require` function.
1300 ///
1301 /// See [`Compiler`] for details and possible options.
1302 #[cfg(any(feature = "luau", doc))]
1303 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1304 pub fn set_compiler(&self, compiler: Compiler) {
1305 let lua = self.lock();
1306 unsafe { (*lua.extra.get()).compiler = Some(compiler) };
1307 }
1308
1309 /// Toggles JIT compilation mode for new chunks of code.
1310 ///
1311 /// By default JIT is enabled. Changing this option does not have any effect on
1312 /// already loaded functions.
1313 #[cfg(any(feature = "luau-jit", doc))]
1314 #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1315 pub fn enable_jit(&self, enable: bool) {
1316 let lua = self.lock();
1317 unsafe { (*lua.extra.get()).enable_jit = enable };
1318 }
1319
1320 /// Configures JIT options for this Lua VM.
1321 #[cfg(any(feature = "luau-jit", doc))]
1322 #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1323 pub fn set_jit_options(&self, options: JitOptions) {
1324 let lua = self.lock();
1325 unsafe {
1326 let state = lua.main_state();
1327 if options.inliner {
1328 ffi::luau_enable_jit_inliner(state);
1329 } else {
1330 ffi::luau_disable_jit_inliner(state);
1331 }
1332 }
1333 }
1334
1335 /// Sets Luau feature flag (global setting).
1336 ///
1337 /// Flags must be configured before creating any Lua VMs or compiling any Luau code.
1338 /// This function must not run concurrently with any other Luau operation, including itself.
1339 /// Changing flags later can cause data races or invalidate compiled bytecode.
1340 ///
1341 /// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
1342 #[cfg(feature = "luau")]
1343 #[doc(hidden)]
1344 #[allow(clippy::result_unit_err)]
1345 pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
1346 // TODO: Make this function unsafe in the next breaking release.
1347 if let Ok(name) = std::ffi::CString::new(name)
1348 && unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 }
1349 {
1350 return Ok(());
1351 }
1352 Err(())
1353 }
1354
1355 /// Returns Lua source code as a `Chunk` builder type.
1356 ///
1357 /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or
1358 /// similar on the returned builder. Code is not even parsed until one of these methods is
1359 /// called.
1360 ///
1361 /// [`Chunk::exec`]: crate::chunk::Chunk::exec
1362 #[track_caller]
1363 pub fn load<'a>(&self, chunk: impl AsChunk + 'a) -> Chunk<'a> {
1364 self.load_with_location(chunk, Location::caller())
1365 }
1366
1367 pub(crate) fn load_with_location<'a>(
1368 &self,
1369 chunk: impl AsChunk + 'a,
1370 location: &'static Location<'static>,
1371 ) -> Chunk<'a> {
1372 Chunk {
1373 lua: self.weak(),
1374 name: chunk
1375 .name()
1376 .unwrap_or_else(|| format!("@{}:{}", location.file(), location.line())),
1377 env: chunk.environment(self),
1378 mode: chunk.mode(),
1379 source: chunk.source(),
1380 #[cfg(feature = "luau")]
1381 compiler: unsafe { (*self.lock().extra.get()).compiler.clone() },
1382 }
1383 }
1384
1385 /// Creates and returns an interned Lua string.
1386 ///
1387 /// Lua strings can be arbitrary `[u8]` data including embedded nulls, so in addition to `&str`
1388 /// and `&String`, you can also pass plain `&[u8]` here.
1389 #[inline]
1390 pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<LuaString> {
1391 unsafe { self.lock().create_string(s.as_ref()) }
1392 }
1393
1394 /// Creates and returns an external Lua string.
1395 ///
1396 /// External string is a string where the memory is managed by Rust code, and Lua only holds a
1397 /// reference to it. This can be used to avoid copying large strings into Lua memory.
1398 #[cfg(feature = "lua55")]
1399 #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
1400 #[inline]
1401 pub fn create_external_string(&self, s: impl Into<Vec<u8>>) -> Result<LuaString> {
1402 unsafe { self.lock().create_external_string(s.into()) }
1403 }
1404
1405 /// Creates and returns a Luau [buffer] object from a byte slice of data.
1406 ///
1407 /// [buffer]: https://luau.org/library#buffer-library
1408 #[cfg(any(feature = "luau", doc))]
1409 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1410 pub fn create_buffer(&self, data: impl AsRef<[u8]>) -> Result<Buffer> {
1411 let lua = self.lock();
1412 let data = data.as_ref();
1413 unsafe {
1414 let (ptr, buffer) = lua.create_buffer_with_capacity(data.len())?;
1415 ptr.copy_from_nonoverlapping(data.as_ptr(), data.len());
1416 Ok(buffer)
1417 }
1418 }
1419
1420 /// Creates and returns a Luau [buffer] object with the specified size.
1421 ///
1422 /// Size limit is 1GB. All bytes will be initialized to zero.
1423 ///
1424 /// [buffer]: https://luau.org/library#buffer-library
1425 #[cfg(any(feature = "luau", doc))]
1426 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1427 pub fn create_buffer_with_capacity(&self, size: usize) -> Result<Buffer> {
1428 unsafe { Ok(self.lock().create_buffer_with_capacity(size)?.1) }
1429 }
1430
1431 /// Creates and returns a new empty table.
1432 #[inline]
1433 pub fn create_table(&self) -> Result<Table> {
1434 self.create_table_with_capacity(0, 0)
1435 }
1436
1437 /// Creates and returns a new empty table, with the specified capacity.
1438 ///
1439 /// - `narr` is a hint for how many elements the table will have as a sequence.
1440 /// - `nrec` is a hint for how many other elements the table will have.
1441 ///
1442 /// Lua may use these hints to preallocate memory for the new table.
1443 pub fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
1444 unsafe { self.lock().create_table_with_capacity(narr, nrec) }
1445 }
1446
1447 /// Creates a table and fills it with values from an iterator.
1448 pub fn create_table_from<K, V>(&self, iter: impl IntoIterator<Item = (K, V)>) -> Result<Table>
1449 where
1450 K: IntoLua,
1451 V: IntoLua,
1452 {
1453 unsafe { self.lock().create_table_from(iter) }
1454 }
1455
1456 /// Creates a table from an iterator of values, using `1..` as the keys.
1457 pub fn create_sequence_from<T>(&self, iter: impl IntoIterator<Item = T>) -> Result<Table>
1458 where
1459 T: IntoLua,
1460 {
1461 unsafe { self.lock().create_sequence_from(iter) }
1462 }
1463
1464 /// Wraps a Rust function or closure, creating a callable Lua function handle to it.
1465 ///
1466 /// The function's return value is always a `Result`: If the function returns `Err`, the error
1467 /// is raised as a Lua error, which can be caught using `(x)pcall` or bubble up to the Rust code
1468 /// that invoked the Lua code. This allows using the `?` operator to propagate errors through
1469 /// intermediate Lua code.
1470 ///
1471 /// If the function returns `Ok`, the contained value will be converted to one or more Lua
1472 /// values. For details on Rust-to-Lua conversions, refer to the [`IntoLua`] and
1473 /// [`IntoLuaMulti`] traits.
1474 ///
1475 /// # Examples
1476 ///
1477 /// Create a function which prints its argument:
1478 ///
1479 /// ```
1480 /// # use mlua::{Lua, Result};
1481 /// # fn main() -> Result<()> {
1482 /// # let lua = Lua::new();
1483 /// let greet = lua.create_function(|_, name: String| {
1484 /// println!("Hello, {}!", name);
1485 /// Ok(())
1486 /// });
1487 /// # let _ = greet; // used
1488 /// # Ok(())
1489 /// # }
1490 /// ```
1491 ///
1492 /// Use tuples to accept multiple arguments:
1493 ///
1494 /// ```
1495 /// # use mlua::{Lua, Result};
1496 /// # fn main() -> Result<()> {
1497 /// # let lua = Lua::new();
1498 /// let print_person = lua.create_function(|_, (name, age): (String, u8)| {
1499 /// println!("{} is {} years old!", name, age);
1500 /// Ok(())
1501 /// });
1502 /// # let _ = print_person; // used
1503 /// # Ok(())
1504 /// # }
1505 /// ```
1506 pub fn create_function<F, A, R>(&self, func: F) -> Result<Function>
1507 where
1508 F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
1509 A: FromLuaMulti,
1510 R: IntoLuaMulti,
1511 {
1512 (self.lock()).create_callback(Box::new(move |rawlua, nargs| unsafe {
1513 let args = A::from_stack_args(nargs, 1, None, rawlua)?;
1514 func(rawlua.lua(), args)?.push_into_stack_multi(rawlua)
1515 }))
1516 }
1517
1518 /// Wraps a Rust mutable closure, creating a callable Lua function handle to it.
1519 ///
1520 /// This is a version of [`Lua::create_function`] that accepts a `FnMut` argument.
1521 pub fn create_function_mut<F, A, R>(&self, func: F) -> Result<Function>
1522 where
1523 F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
1524 A: FromLuaMulti,
1525 R: IntoLuaMulti,
1526 {
1527 let func = RefCell::new(func);
1528 self.create_function(move |lua, args| {
1529 (*func.try_borrow_mut().map_err(|_| Error::RecursiveMutCallback)?)(lua, args)
1530 })
1531 }
1532
1533 /// Wraps a C function, creating a callable Lua function handle to it.
1534 ///
1535 /// # Safety
1536 /// This function is unsafe because provides a way to execute unsafe C function.
1537 pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
1538 let lua = self.lock();
1539 if cfg!(any(
1540 feature = "lua55",
1541 feature = "lua54",
1542 feature = "lua53",
1543 feature = "lua52"
1544 )) {
1545 ffi::lua_pushcfunction(lua.ref_thread(), func);
1546 return Ok(Function(lua.try_pop_ref_thread()?));
1547 }
1548
1549 // Lua <5.2 requires memory allocation to push a C function
1550 let state = lua.state();
1551 {
1552 let _sg = StackGuard::new(state);
1553 check_stack(state, 3)?;
1554
1555 protect_lua_mem!(lua, 0, 1, |state| ffi::lua_pushcfunction(state, func))?;
1556 Ok(Function(lua.try_pop_ref()?))
1557 }
1558 }
1559
1560 /// Wraps a Rust async function or closure, creating a callable Lua function handle to it.
1561 ///
1562 /// While executing the function Rust will poll the Future and if the result is not ready,
1563 /// call `yield()` passing internal representation of a `Poll::Pending` value.
1564 ///
1565 /// The function must be called inside Lua coroutine ([`Thread`]) to be able to suspend its
1566 /// execution. An executor should be used to poll [`AsyncThread`] and mlua will take a provided
1567 /// Waker in that case. Otherwise noop waker will be used if try to call the function outside of
1568 /// Rust executors.
1569 ///
1570 /// The family of `call_async()` functions takes care about creating [`Thread`].
1571 ///
1572 /// # Examples
1573 ///
1574 /// Non blocking sleep:
1575 ///
1576 /// ```
1577 /// use std::time::Duration;
1578 /// use mlua::{Lua, Result};
1579 ///
1580 /// async fn sleep(_lua: Lua, n: u64) -> Result<&'static str> {
1581 /// tokio::time::sleep(Duration::from_millis(n)).await;
1582 /// Ok("done")
1583 /// }
1584 ///
1585 /// #[tokio::main]
1586 /// async fn main() -> Result<()> {
1587 /// let lua = Lua::new();
1588 /// lua.globals().set("sleep", lua.create_async_function(sleep)?)?;
1589 /// let res: String = lua.load("return sleep(...)").call_async(100).await?; // Sleep 100ms
1590 /// assert_eq!(res, "done");
1591 /// Ok(())
1592 /// }
1593 /// ```
1594 ///
1595 /// [`AsyncThread`]: crate::thread::AsyncThread
1596 #[cfg(feature = "async")]
1597 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1598 pub fn create_async_function<F, A, FR, R>(&self, func: F) -> Result<Function>
1599 where
1600 F: Fn(Lua, A) -> FR + MaybeSend + 'static,
1601 A: FromLuaMulti,
1602 FR: Future<Output = Result<R>> + MaybeSend + 'static,
1603 R: IntoLuaMulti,
1604 {
1605 // In future we should switch to async closures when they are stable to capture `&Lua`
1606 // See https://rust-lang.github.io/rfcs/3668-async-closures.html
1607 (self.lock()).create_async_callback(Box::new(move |rawlua, nargs| unsafe {
1608 let args = match A::from_stack_args(nargs, 1, None, rawlua) {
1609 Ok(args) => args,
1610 Err(e) => return Box::pin(future::ready(Err(e))),
1611 };
1612 let lua = rawlua.lua();
1613 let fut = func(lua.clone(), args);
1614 Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
1615 }))
1616 }
1617
1618 /// Wraps a Lua function into a new thread (or coroutine).
1619 ///
1620 /// Equivalent to `coroutine.create`.
1621 pub fn create_thread(&self, func: Function) -> Result<Thread> {
1622 unsafe { self.lock().create_thread(&func) }
1623 }
1624
1625 /// Creates a Lua userdata object from a custom userdata type.
1626 ///
1627 /// All userdata instances of the same type `T` shares the same metatable.
1628 #[inline]
1629 pub fn create_userdata<T>(&self, data: T) -> Result<AnyUserData>
1630 where
1631 T: UserData + MaybeSend + MaybeSync + 'static,
1632 {
1633 unsafe { self.lock().make_userdata(UserDataStorage::new(data)) }
1634 }
1635
1636 /// Creates a Lua userdata object from a custom serializable userdata type.
1637 #[cfg(feature = "serde")]
1638 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1639 #[inline]
1640 pub fn create_ser_userdata<T>(&self, data: T) -> Result<AnyUserData>
1641 where
1642 T: UserData + Serialize + MaybeSend + MaybeSync + 'static,
1643 {
1644 unsafe { self.lock().make_userdata(UserDataStorage::new_ser(data)) }
1645 }
1646
1647 /// Creates a Lua userdata object from a custom Rust type.
1648 ///
1649 /// You can register the type using [`Lua::register_userdata_type`] to add fields or methods
1650 /// _before_ calling this method.
1651 /// Otherwise, the userdata object will have an empty metatable.
1652 ///
1653 /// All userdata instances of the same type `T` shares the same metatable.
1654 #[inline]
1655 pub fn create_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1656 where
1657 T: MaybeSend + MaybeSync + 'static,
1658 {
1659 unsafe { self.lock().make_any_userdata(UserDataStorage::new(data)) }
1660 }
1661
1662 /// Creates a Lua userdata object from a custom serializable Rust type.
1663 ///
1664 /// See [`Lua::create_any_userdata`] for more details.
1665 #[cfg(feature = "serde")]
1666 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1667 #[inline]
1668 pub fn create_ser_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1669 where
1670 T: Serialize + MaybeSend + MaybeSync + 'static,
1671 {
1672 unsafe { (self.lock()).make_any_userdata(UserDataStorage::new_ser(data)) }
1673 }
1674
1675 /// Registers a custom Rust type in Lua to use in userdata objects.
1676 ///
1677 /// This methods provides a way to add fields or methods to userdata objects of a type `T`.
1678 pub fn register_userdata_type<T: 'static>(&self, f: impl FnOnce(&mut UserDataRegistry<T>)) -> Result<()> {
1679 let type_id = TypeId::of::<T>();
1680 let mut registry = UserDataRegistry::new(self);
1681 f(&mut registry);
1682
1683 let lua = self.lock();
1684 unsafe {
1685 // Deregister the type if it already registered
1686 if let Some(table_id) = (*lua.extra.get()).registered_userdata_t.remove(&type_id) {
1687 ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, table_id);
1688 }
1689
1690 // Add to "pending" registration map
1691 ((*lua.extra.get()).pending_userdata_reg).insert(type_id, registry.into_raw());
1692 }
1693 Ok(())
1694 }
1695
1696 /// Create a Lua userdata "proxy" object from a custom userdata type.
1697 ///
1698 /// Proxy object is an empty userdata object that has `T` metatable attached.
1699 /// The main purpose of this object is to provide access to static fields and functions
1700 /// without creating an instance of type `T`.
1701 ///
1702 /// You can get or set uservalues on this object but you cannot borrow any Rust type.
1703 ///
1704 /// # Examples
1705 ///
1706 /// ```
1707 /// # use mlua::{Lua, Result, UserData, UserDataFields, UserDataMethods};
1708 /// # fn main() -> Result<()> {
1709 /// # let lua = Lua::new();
1710 /// struct MyUserData(i32);
1711 ///
1712 /// impl UserData for MyUserData {
1713 /// fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
1714 /// fields.add_field_method_get("val", |_, this| Ok(this.0));
1715 /// }
1716 ///
1717 /// fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
1718 /// methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
1719 /// }
1720 /// }
1721 ///
1722 /// lua.globals().set("MyUserData", lua.create_proxy::<MyUserData>()?)?;
1723 ///
1724 /// lua.load("assert(MyUserData.new(321).val == 321)").exec()?;
1725 /// # Ok(())
1726 /// # }
1727 /// ```
1728 #[inline]
1729 pub fn create_proxy<T>(&self) -> Result<AnyUserData>
1730 where
1731 T: UserData + 'static,
1732 {
1733 let ud = UserDataProxy::<T>(PhantomData);
1734 unsafe { self.lock().make_userdata(UserDataStorage::new(ud)) }
1735 }
1736
1737 /// Gets the metatable of a Lua built-in (primitive) type.
1738 ///
1739 /// The metatable is shared by all values of the given type.
1740 ///
1741 /// See [`Lua::set_type_metatable`] for examples.
1742 #[allow(private_bounds)]
1743 pub fn type_metatable<T: LuaType>(&self) -> Option<Table> {
1744 let lua = self.lock();
1745 let state = lua.state();
1746 unsafe {
1747 let _sg = StackGuard::new(state);
1748 assert_stack(state, 2);
1749
1750 if lua.push_primitive_type::<T>() && ffi::lua_getmetatable(state, -1) != 0 {
1751 return Some(Table(lua.pop_ref()));
1752 }
1753 }
1754 None
1755 }
1756
1757 /// Sets the metatable for a Lua built-in (primitive) type.
1758 ///
1759 /// The metatable will be shared by all values of the given type.
1760 ///
1761 /// # Examples
1762 ///
1763 /// Change metatable for Lua boolean type:
1764 ///
1765 /// ```
1766 /// # use mlua::{Lua, Result, Function};
1767 /// # fn main() -> Result<()> {
1768 /// # let lua = Lua::new();
1769 /// let mt = lua.create_table()?;
1770 /// mt.set("__tostring", lua.create_function(|_, b: bool| Ok(if b { "2" } else { "0" }))?)?;
1771 /// lua.set_type_metatable::<bool>(Some(mt));
1772 /// lua.load("assert(tostring(true) == '2')").exec()?;
1773 /// # Ok(())
1774 /// # }
1775 /// ```
1776 #[allow(private_bounds)]
1777 pub fn set_type_metatable<T: LuaType>(&self, metatable: Option<Table>) {
1778 let lua = self.lock();
1779 let state = lua.state();
1780 unsafe {
1781 let _sg = StackGuard::new(state);
1782 assert_stack(state, 2);
1783
1784 if lua.push_primitive_type::<T>() {
1785 match metatable {
1786 Some(metatable) => lua.push_ref(&metatable.0),
1787 None => ffi::lua_pushnil(state),
1788 }
1789 ffi::lua_setmetatable(state, -2);
1790 }
1791 }
1792 }
1793
1794 // Like `globals`, but returns an error if the stack cannot grow.
1795 pub(crate) fn try_globals(&self) -> Result<Table> {
1796 let lua = self.lock();
1797 unsafe {
1798 check_stack(lua.state(), 1)?;
1799 ffi::lua_pushglobaltable(lua.state());
1800 Ok(Table(lua.try_pop_ref()?))
1801 }
1802 }
1803
1804 /// Returns a handle to the global environment.
1805 pub fn globals(&self) -> Table {
1806 let lua = self.lock();
1807 let state = lua.state();
1808 unsafe {
1809 let _sg = StackGuard::new(state);
1810 assert_stack(state, 1);
1811 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1812 ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1813 #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1814 ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
1815 Table(lua.pop_ref())
1816 }
1817 }
1818
1819 /// Sets the global environment.
1820 ///
1821 /// This will replace the current global environment with the provided `globals` table.
1822 ///
1823 /// For Lua 5.2+ the globals table is stored in the registry and shared between all threads.
1824 /// For Lua 5.1 and Luau the globals table is stored in each thread.
1825 ///
1826 /// Please note that any existing Lua functions have cached global environment and will not
1827 /// see the changes made by this method.
1828 /// To update the environment for existing Lua functions, use [`Function::set_environment`].
1829 pub fn set_globals(&self, globals: Table) -> Result<()> {
1830 let lua = self.lock();
1831 let state = lua.state();
1832 unsafe {
1833 #[cfg(feature = "luau")]
1834 if (*lua.extra.get()).sandboxed {
1835 return Err(Error::runtime("cannot change globals in a sandboxed Lua state"));
1836 }
1837
1838 let _sg = StackGuard::new(state);
1839 check_stack(state, 1)?;
1840
1841 lua.push_ref(&globals.0);
1842
1843 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1844 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1845 #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1846 ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
1847 }
1848
1849 Ok(())
1850 }
1851
1852 /// Returns a handle to the active `Thread`.
1853 ///
1854 /// For calls to `Lua` this will be the main Lua thread, for parameters given to a callback,
1855 /// this will be whatever Lua thread called the callback.
1856 pub fn current_thread(&self) -> Thread {
1857 let lua = self.lock();
1858 let state = lua.state();
1859 unsafe {
1860 // If this thread is implicit (created by `call_async`), return the root user-owned
1861 // thread instead.
1862 #[cfg(feature = "async")]
1863 if let Some(&owner) = (*lua.extra.get()).thread_ownership_map.get(&state) {
1864 assert_stack(owner, 1);
1865 ffi::lua_pushthread(owner);
1866 ffi::lua_xmove(owner, lua.ref_thread(), 1);
1867 return Thread(lua.pop_ref_thread(), owner);
1868 }
1869
1870 let _sg = StackGuard::new(state);
1871 assert_stack(state, 1);
1872 ffi::lua_pushthread(state);
1873 Thread(lua.pop_ref(), state)
1874 }
1875 }
1876
1877 /// Calls the given function with a [`Scope`] parameter, giving the function the ability to
1878 /// create userdata and callbacks from Rust types that are `!Send` or non-`'static`.
1879 ///
1880 /// The lifetime of any function or userdata created through [`Scope`] lasts only until the
1881 /// completion of this method call, on completion all such created values are automatically
1882 /// dropped and Lua references to them are invalidated. If a script accesses a value created
1883 /// through [`Scope`] outside of this method, a Lua error will result. The Lua lock is held
1884 /// until all scoped values are invalidated, preventing other threads from accessing them.
1885 /// This allows `!Send` data types whose lifetimes only outlive the scope lifetime.
1886 pub fn scope<'env, R>(
1887 &self,
1888 f: impl for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> Result<R>,
1889 ) -> Result<R> {
1890 f(&Scope::new(self.lock_arc()))
1891 }
1892
1893 /// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
1894 /// behavior.
1895 ///
1896 /// To succeed, the value must be a string (in which case this is a no-op), an integer, or a
1897 /// number.
1898 pub fn coerce_string(&self, v: Value) -> Result<Option<LuaString>> {
1899 Ok(match v {
1900 Value::String(s) => Some(s),
1901 v => unsafe {
1902 let lua = self.lock();
1903 let state = lua.state();
1904 let _sg = StackGuard::new(state);
1905 check_stack(state, 4)?;
1906
1907 lua.push_value(&v)?;
1908 let res = protect_lua_mem!(lua, 1, 1, |state| {
1909 ffi::lua_tolstring(state, -1, ptr::null_mut())
1910 })?;
1911 if !res.is_null() {
1912 Some(LuaString(lua.try_pop_ref()?))
1913 } else {
1914 None
1915 }
1916 },
1917 })
1918 }
1919
1920 /// Attempts to coerce a Lua value into an integer in a manner consistent with Lua's internal
1921 /// behavior.
1922 ///
1923 /// To succeed, the value must be an integer, a floating point number that has an exact
1924 /// representation as an integer, or a string that can be converted to an integer. Refer to the
1925 /// Lua manual for details.
1926 pub fn coerce_integer(&self, v: Value) -> Result<Option<Integer>> {
1927 Ok(match v {
1928 Value::Integer(i) => Some(i),
1929 v => unsafe {
1930 let lua = self.lock();
1931 let state = lua.state();
1932 let _sg = StackGuard::new(state);
1933 check_stack(state, 2)?;
1934
1935 lua.push_value(&v)?;
1936 let mut isint = 0;
1937 let i = ffi::lua_tointegerx(state, -1, &mut isint);
1938 (isint != 0).then_some(i)
1939 },
1940 })
1941 }
1942
1943 /// Attempts to coerce a Lua value into a Number in a manner consistent with Lua's internal
1944 /// behavior.
1945 ///
1946 /// To succeed, the value must be a number or a string that can be converted to a number. Refer
1947 /// to the Lua manual for details.
1948 pub fn coerce_number(&self, v: Value) -> Result<Option<Number>> {
1949 Ok(match v {
1950 Value::Number(n) => Some(n),
1951 v => unsafe {
1952 let lua = self.lock();
1953 let state = lua.state();
1954 let _sg = StackGuard::new(state);
1955 check_stack(state, 2)?;
1956
1957 lua.push_value(&v)?;
1958 let mut isnum = 0;
1959 let n = ffi::lua_tonumberx(state, -1, &mut isnum);
1960 (isnum != 0).then_some(n)
1961 },
1962 })
1963 }
1964
1965 /// Converts a value that implements [`IntoLua`] into a [`Value`] instance.
1966 #[inline]
1967 pub fn pack(&self, t: impl IntoLua) -> Result<Value> {
1968 t.into_lua(self)
1969 }
1970
1971 /// Converts a [`Value`] instance into a value that implements [`FromLua`].
1972 #[inline]
1973 pub fn unpack<T: FromLua>(&self, value: Value) -> Result<T> {
1974 T::from_lua(value, self)
1975 }
1976
1977 /// Converts a value that implements [`IntoLua`] into a [`FromLua`] variant.
1978 #[inline]
1979 pub fn convert<U: FromLua>(&self, value: impl IntoLua) -> Result<U> {
1980 U::from_lua(value.into_lua(self)?, self)
1981 }
1982
1983 /// Converts a value that implements [`IntoLuaMulti`] into a [`MultiValue`] instance.
1984 #[inline]
1985 pub fn pack_multi(&self, t: impl IntoLuaMulti) -> Result<MultiValue> {
1986 t.into_lua_multi(self)
1987 }
1988
1989 /// Converts a [`MultiValue`] instance into a value that implements [`FromLuaMulti`].
1990 #[inline]
1991 pub fn unpack_multi<T: FromLuaMulti>(&self, value: MultiValue) -> Result<T> {
1992 T::from_lua_multi(value, self)
1993 }
1994
1995 /// Set a value in the Lua registry based on a string key.
1996 ///
1997 /// This value will be available to Rust from all Lua instances which share the same main
1998 /// state.
1999 pub fn set_named_registry_value(&self, key: &str, t: impl IntoLua) -> Result<()> {
2000 let lua = self.lock();
2001 let state = lua.state();
2002 unsafe {
2003 let _sg = StackGuard::new(state);
2004 check_stack(state, 5)?;
2005
2006 lua.push(t)?;
2007 rawset_field(state, ffi::LUA_REGISTRYINDEX, key)
2008 }
2009 }
2010
2011 /// Get a value from the Lua registry based on a string key.
2012 ///
2013 /// Any Lua instance which shares the underlying main state may call this method to
2014 /// get a value previously set by [`Lua::set_named_registry_value`].
2015 pub fn named_registry_value<T>(&self, key: &str) -> Result<T>
2016 where
2017 T: FromLua,
2018 {
2019 let lua = self.lock();
2020 let state = lua.state();
2021 unsafe {
2022 let _sg = StackGuard::new(state);
2023 check_stack(state, 3)?;
2024
2025 let protect = !lua.unlikely_memory_error();
2026 push_string(state, key.as_bytes(), protect)?;
2027 ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
2028
2029 T::from_stack(-1, &lua)
2030 }
2031 }
2032
2033 /// Removes a named value in the Lua registry.
2034 ///
2035 /// Equivalent to calling [`Lua::set_named_registry_value`] with a value of [`Nil`].
2036 #[inline]
2037 pub fn unset_named_registry_value(&self, key: &str) -> Result<()> {
2038 self.set_named_registry_value(key, Nil)
2039 }
2040
2041 /// Place a value in the Lua registry with an auto-generated key.
2042 ///
2043 /// This value will be available to Rust from all Lua instances which share the same main
2044 /// state.
2045 ///
2046 /// Be warned, garbage collection of values held inside the registry is not automatic, see
2047 /// [`RegistryKey`] for more details.
2048 /// However, dropped [`RegistryKey`]s automatically reused to store new values.
2049 pub fn create_registry_value(&self, t: impl IntoLua) -> Result<RegistryKey> {
2050 let lua = self.lock();
2051 let state = lua.state();
2052 unsafe {
2053 let _sg = StackGuard::new(state);
2054 check_stack(state, 4)?;
2055
2056 lua.push(t)?;
2057
2058 let unref_list = (*lua.extra.get()).registry_unref_list.clone();
2059
2060 // Check if the value is nil (no need to store it in the registry)
2061 if ffi::lua_isnil(state, -1) != 0 {
2062 return Ok(RegistryKey::new(ffi::LUA_REFNIL, unref_list));
2063 }
2064
2065 // Try to reuse previously allocated slot
2066 let free_registry_id = unref_list.lock().as_mut().and_then(|x| x.pop());
2067 if let Some(registry_id) = free_registry_id {
2068 // It must be safe to replace the value without triggering memory error
2069 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2070 return Ok(RegistryKey::new(registry_id, unref_list));
2071 }
2072
2073 // Allocate a new RegistryKey slot
2074 let registry_id = protect_lua_mem!(lua, 1, 0, |state| {
2075 ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
2076 })?;
2077 Ok(RegistryKey::new(registry_id, unref_list))
2078 }
2079 }
2080
2081 /// Get a value from the Lua registry by its [`RegistryKey`]
2082 ///
2083 /// Any Lua instance which shares the underlying main state may call this method to get a value
2084 /// previously placed by [`Lua::create_registry_value`].
2085 pub fn registry_value<T: FromLua>(&self, key: &RegistryKey) -> Result<T> {
2086 let lua = self.lock();
2087 if !lua.owns_registry_value(key) {
2088 return Err(Error::MismatchedRegistryKey);
2089 }
2090
2091 let state = lua.state();
2092 match key.id() {
2093 ffi::LUA_REFNIL => T::from_lua(Value::Nil, self),
2094 registry_id => unsafe {
2095 let _sg = StackGuard::new(state);
2096 check_stack(state, 1)?;
2097
2098 ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2099 T::from_stack(-1, &lua)
2100 },
2101 }
2102 }
2103
2104 /// Removes a value from the Lua registry.
2105 ///
2106 /// You may call this function to manually remove a value placed in the registry with
2107 /// [`Lua::create_registry_value`]. In addition to manual [`RegistryKey`] removal, you can also
2108 /// call [`Lua::expire_registry_values`] to automatically remove values from the registry
2109 /// whose [`RegistryKey`]s have been dropped.
2110 pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
2111 let lua = self.lock();
2112 if !lua.owns_registry_value(&key) {
2113 return Err(Error::MismatchedRegistryKey);
2114 }
2115
2116 unsafe { ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, key.take()) };
2117 Ok(())
2118 }
2119
2120 /// Replaces a value in the Lua registry by its [`RegistryKey`].
2121 ///
2122 /// An identifier used in [`RegistryKey`] may possibly be changed to a new value.
2123 ///
2124 /// See [`Lua::create_registry_value`] for more details.
2125 pub fn replace_registry_value(&self, key: &mut RegistryKey, t: impl IntoLua) -> Result<()> {
2126 let lua = self.lock();
2127 if !lua.owns_registry_value(key) {
2128 return Err(Error::MismatchedRegistryKey);
2129 }
2130
2131 let t = t.into_lua(self)?;
2132
2133 let state = lua.state();
2134 unsafe {
2135 let _sg = StackGuard::new(state);
2136 check_stack(state, 2)?;
2137
2138 match (t, key.id()) {
2139 (Value::Nil, ffi::LUA_REFNIL) => {
2140 // Do nothing, no need to replace nil with nil
2141 }
2142 (Value::Nil, registry_id) => {
2143 // Remove the value
2144 ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, registry_id);
2145 key.set_id(ffi::LUA_REFNIL);
2146 }
2147 (value, ffi::LUA_REFNIL) => {
2148 // Allocate a new `RegistryKey`
2149 let new_key = self.create_registry_value(value)?;
2150 key.set_id(new_key.take());
2151 }
2152 (value, registry_id) => {
2153 // It must be safe to replace the value without triggering memory error
2154 lua.push_value(&value)?;
2155 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2156 }
2157 }
2158 }
2159 Ok(())
2160 }
2161
2162 /// Returns true if the given [`RegistryKey`] was created by a Lua which shares the
2163 /// underlying main state with this Lua instance.
2164 ///
2165 /// Other than this, methods that accept a [`RegistryKey`] will return
2166 /// [`Error::MismatchedRegistryKey`] if passed a [`RegistryKey`] that was not created with a
2167 /// matching [`Lua`] state.
2168 #[inline]
2169 pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
2170 self.lock().owns_registry_value(key)
2171 }
2172
2173 /// Remove any registry values whose [`RegistryKey`]s have all been dropped.
2174 ///
2175 /// Unlike normal handle values, [`RegistryKey`]s do not automatically remove themselves on
2176 /// Drop, but you can call this method to remove any unreachable registry values not
2177 /// manually removed by [`Lua::remove_registry_value`].
2178 pub fn expire_registry_values(&self) {
2179 let lua = self.lock();
2180 let state = lua.state();
2181 unsafe {
2182 let mut unref_list = (*lua.extra.get()).registry_unref_list.lock();
2183 let unref_list = unref_list.replace(Vec::new());
2184 for id in mlua_expect!(unref_list, "unref list is not set") {
2185 ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
2186 }
2187 }
2188 }
2189
2190 /// Sets or replaces an application data object of type `T`.
2191 ///
2192 /// Application data could be accessed at any time by using [`Lua::app_data_ref`] or
2193 /// [`Lua::app_data_mut`] methods where `T` is the data type.
2194 ///
2195 /// # Panics
2196 ///
2197 /// Panics if the app data container is currently borrowed.
2198 ///
2199 /// # Examples
2200 ///
2201 /// ```
2202 /// use mlua::{Lua, Result};
2203 ///
2204 /// fn hello(lua: &Lua, _: ()) -> Result<()> {
2205 /// let mut s = lua.app_data_mut::<&str>().unwrap();
2206 /// assert_eq!(*s, "hello");
2207 /// *s = "world";
2208 /// Ok(())
2209 /// }
2210 ///
2211 /// fn main() -> Result<()> {
2212 /// let lua = Lua::new();
2213 /// lua.set_app_data("hello");
2214 /// lua.create_function(hello)?.call::<()>(())?;
2215 /// let s = lua.app_data_ref::<&str>().unwrap();
2216 /// assert_eq!(*s, "world");
2217 /// Ok(())
2218 /// }
2219 /// ```
2220 #[track_caller]
2221 pub fn set_app_data<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
2222 let lua = self.lock();
2223 let extra = unsafe { &*lua.extra.get() };
2224 extra.app_data.insert(data)
2225 }
2226
2227 /// Tries to set or replace an application data object of type `T`.
2228 ///
2229 /// Returns:
2230 /// - `Ok(Some(old_data))` if the data object of type `T` was successfully replaced.
2231 /// - `Ok(None)` if the data object of type `T` was successfully inserted.
2232 /// - `Err(data)` if the data object of type `T` was not inserted because the container is
2233 /// currently borrowed.
2234 ///
2235 /// See [`Lua::set_app_data`] for examples.
2236 pub fn try_set_app_data<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
2237 let lua = self.lock();
2238 let extra = unsafe { &*lua.extra.get() };
2239 extra.app_data.try_insert(data)
2240 }
2241
2242 /// Gets a reference to an application data object stored by [`Lua::set_app_data`] of type
2243 /// `T`.
2244 ///
2245 /// # Panics
2246 ///
2247 /// Panics if the data object of type `T` is currently mutably borrowed. Multiple immutable
2248 /// reads can be taken out at the same time.
2249 #[track_caller]
2250 pub fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<'_, T>> {
2251 let guard = self.lock_arc();
2252 let extra = unsafe { &*guard.extra.get() };
2253 extra.app_data.borrow(Some(guard))
2254 }
2255
2256 /// Tries to get a reference to an application data object stored by [`Lua::set_app_data`] of
2257 /// type `T`.
2258 pub fn try_app_data_ref<T: 'static>(&self) -> StdResult<Option<AppDataRef<'_, T>>, BorrowError> {
2259 let guard = self.lock_arc();
2260 let extra = unsafe { &*guard.extra.get() };
2261 extra.app_data.try_borrow(Some(guard))
2262 }
2263
2264 /// Gets a mutable reference to an application data object stored by [`Lua::set_app_data`] of
2265 /// type `T`.
2266 ///
2267 /// # Panics
2268 ///
2269 /// Panics if the data object of type `T` is currently borrowed.
2270 #[track_caller]
2271 pub fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<'_, T>> {
2272 let guard = self.lock_arc();
2273 let extra = unsafe { &*guard.extra.get() };
2274 extra.app_data.borrow_mut(Some(guard))
2275 }
2276
2277 /// Tries to get a mutable reference to an application data object stored by
2278 /// [`Lua::set_app_data`] of type `T`.
2279 pub fn try_app_data_mut<T: 'static>(&self) -> StdResult<Option<AppDataRefMut<'_, T>>, BorrowMutError> {
2280 let guard = self.lock_arc();
2281 let extra = unsafe { &*guard.extra.get() };
2282 extra.app_data.try_borrow_mut(Some(guard))
2283 }
2284
2285 /// Removes an application data of type `T`.
2286 ///
2287 /// # Panics
2288 ///
2289 /// Panics if the app data container is currently borrowed.
2290 #[track_caller]
2291 pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
2292 let lua = self.lock();
2293 let extra = unsafe { &*lua.extra.get() };
2294 extra.app_data.remove()
2295 }
2296
2297 /// Returns an internal `Poll::Pending` constant used for executing async callbacks.
2298 ///
2299 /// Every time when [`Future`] is Pending, Lua corotine is suspended with this constant.
2300 #[cfg(feature = "async")]
2301 #[doc(hidden)]
2302 #[inline(always)]
2303 pub fn poll_pending() -> LightUserData {
2304 static ASYNC_POLL_PENDING: u8 = 0;
2305 LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut std::os::raw::c_void)
2306 }
2307
2308 #[cfg(feature = "async")]
2309 #[inline(always)]
2310 pub(crate) fn poll_terminate() -> LightUserData {
2311 static ASYNC_POLL_TERMINATE: u8 = 0;
2312 LightUserData(&ASYNC_POLL_TERMINATE as *const u8 as *mut std::os::raw::c_void)
2313 }
2314
2315 #[cfg(feature = "async")]
2316 #[inline(always)]
2317 pub(crate) fn poll_yield() -> LightUserData {
2318 static ASYNC_POLL_YIELD: u8 = 0;
2319 LightUserData(&ASYNC_POLL_YIELD as *const u8 as *mut std::os::raw::c_void)
2320 }
2321
2322 /// Suspends the current async function, returning the provided arguments to caller.
2323 ///
2324 /// This function is similar to [`coroutine.yield`] but allow yielding Rust functions
2325 /// and passing values to the caller.
2326 /// Please note that you cannot cross [`Thread`] boundaries (e.g. calling `yield_with` on one
2327 /// thread and resuming on another).
2328 ///
2329 /// # Examples
2330 ///
2331 /// Async iterator:
2332 ///
2333 /// ```
2334 /// # use mlua::{Lua, Result};
2335 /// #
2336 /// async fn generator(lua: Lua, _: ()) -> Result<()> {
2337 /// for i in 0..10 {
2338 /// lua.yield_with::<()>(i).await?;
2339 /// }
2340 /// Ok(())
2341 /// }
2342 ///
2343 /// fn main() -> Result<()> {
2344 /// let lua = Lua::new();
2345 /// lua.globals().set("generator", lua.create_async_function(generator)?)?;
2346 ///
2347 /// lua.load(r#"
2348 /// local n = 0
2349 /// for i in coroutine.wrap(generator) do
2350 /// n = n + i
2351 /// end
2352 /// assert(n == 45)
2353 /// "#)
2354 /// .exec()
2355 /// }
2356 /// ```
2357 ///
2358 /// Exchange values on yield:
2359 ///
2360 /// ```
2361 /// # use mlua::{Lua, Result, Value};
2362 /// #
2363 /// async fn pingpong(lua: Lua, mut val: i32) -> Result<()> {
2364 /// loop {
2365 /// val = lua.yield_with::<i32>(val).await? + 1;
2366 /// }
2367 /// Ok(())
2368 /// }
2369 ///
2370 /// # fn main() -> Result<()> {
2371 /// let lua = Lua::new();
2372 ///
2373 /// let co = lua.create_thread(lua.create_async_function(pingpong)?)?;
2374 /// assert_eq!(co.resume::<i32>(1)?, 1);
2375 /// assert_eq!(co.resume::<i32>(2)?, 3);
2376 /// assert_eq!(co.resume::<i32>(3)?, 4);
2377 ///
2378 /// # Ok(())
2379 /// # }
2380 /// ```
2381 ///
2382 /// [`coroutine.yield`]: https://www.lua.org/manual/5.4/manual.html#pdf-coroutine.yield
2383 #[cfg(feature = "async")]
2384 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
2385 pub async fn yield_with<R: FromLuaMulti>(&self, args: impl IntoLuaMulti) -> Result<R> {
2386 let mut args = Some(args.into_lua_multi(self)?);
2387 future::poll_fn(move |_cx| match args.take() {
2388 Some(args) => unsafe {
2389 let lua = self.lock();
2390 lua.push(Self::poll_yield())?; // yield marker
2391 if args.len() <= 1 {
2392 lua.push(args.front())?;
2393 } else {
2394 lua.push(lua.create_sequence_from(&args)?)?;
2395 }
2396 lua.push(args.len())?;
2397 Poll::Pending
2398 },
2399 None => unsafe {
2400 let lua = self.lock();
2401 let state = lua.state();
2402 let top = ffi::lua_gettop(state);
2403 if top == 0 || ffi::lua_type(state, 1) != ffi::LUA_TUSERDATA {
2404 // This must be impossible scenario if used correctly
2405 return Poll::Ready(R::from_stack_multi(0, &lua));
2406 }
2407 let _sg = StackGuard::with_top(state, 1);
2408 Poll::Ready(R::from_stack_multi(top - 1, &lua))
2409 },
2410 })
2411 .await
2412 }
2413
2414 /// Returns a pointer to the underlying Lua state.
2415 #[doc(hidden)]
2416 pub fn state(&self) -> *mut ffi::lua_State {
2417 self.lock().state()
2418 }
2419
2420 /// Returns a weak reference to the Lua instance.
2421 ///
2422 /// This is useful for creating a reference to the Lua instance that does not prevent it from
2423 /// being deallocated.
2424 #[inline(always)]
2425 pub fn weak(&self) -> WeakLua {
2426 WeakLua(XRc::downgrade(&self.raw))
2427 }
2428
2429 #[cfg(not(feature = "luau"))]
2430 fn disable_c_modules(&self) -> Result<()> {
2431 let package: Table = self.try_globals()?.get("package")?;
2432
2433 package.set(
2434 "loadlib",
2435 self.create_function(|_, ()| -> Result<()> {
2436 Err(Error::SafetyError(
2437 "package.loadlib is disabled in safe mode".to_string(),
2438 ))
2439 })?,
2440 )?;
2441
2442 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
2443 let searchers: Table = package.get("searchers")?;
2444 #[cfg(any(feature = "lua51", feature = "luajit"))]
2445 let searchers: Table = package.get("loaders")?;
2446
2447 let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
2448
2449 // The third and fourth searchers looks for a loader as a C library
2450 searchers.raw_set(3, loader)?;
2451 if searchers.raw_len() >= 4 {
2452 searchers.raw_remove(4)?;
2453 }
2454
2455 Ok(())
2456 }
2457
2458 #[inline(always)]
2459 pub(crate) fn lock(&self) -> ReentrantMutexGuard<'_, RawLua> {
2460 let rawlua = self.raw.lock();
2461 #[cfg(feature = "luau")]
2462 if rawlua.is_running_gc() {
2463 panic!("Luau VM is suspended while GC is running");
2464 }
2465 rawlua
2466 }
2467
2468 #[inline(always)]
2469 pub(crate) fn lock_arc(&self) -> LuaGuard {
2470 let guard = LuaGuard(self.raw.lock_arc());
2471 #[cfg(feature = "luau")]
2472 if guard.is_running_gc() {
2473 panic!("Luau VM is suspended while GC is running");
2474 }
2475 guard
2476 }
2477
2478 /// Returns a handle to the unprotected Lua state without any synchronization.
2479 ///
2480 /// This is useful where we know that the lock is already held by the caller.
2481 #[cfg(feature = "async")]
2482 #[inline(always)]
2483 pub(crate) unsafe fn raw_lua(&self) -> &RawLua {
2484 &*self.raw.data_ptr()
2485 }
2486}
2487
2488impl WeakLua {
2489 #[track_caller]
2490 #[inline(always)]
2491 pub(crate) fn lock(&self) -> LuaGuard {
2492 let guard = LuaGuard::new(self.0.upgrade().expect("Lua instance is destroyed"));
2493 #[cfg(feature = "luau")]
2494 if guard.is_running_gc() {
2495 panic!("Luau VM is suspended while GC is running");
2496 }
2497 guard
2498 }
2499
2500 #[inline(always)]
2501 pub(crate) fn try_lock(&self) -> Option<LuaGuard> {
2502 // Reference cleanup must remain possible during Luau GC.
2503 Some(LuaGuard::new(self.0.upgrade()?))
2504 }
2505
2506 /// Upgrades the weak Lua reference to a strong reference.
2507 ///
2508 /// # Panics
2509 ///
2510 /// Panics if the Lua instance is destroyed.
2511 #[track_caller]
2512 #[inline(always)]
2513 pub fn upgrade(&self) -> Lua {
2514 Lua {
2515 raw: self.0.upgrade().expect("Lua instance is destroyed"),
2516 collect_garbage: false,
2517 }
2518 }
2519
2520 /// Tries to upgrade the weak Lua reference to a strong reference.
2521 ///
2522 /// Returns `None` if the Lua instance is destroyed.
2523 #[inline(always)]
2524 pub fn try_upgrade(&self) -> Option<Lua> {
2525 Some(Lua {
2526 raw: self.0.upgrade()?,
2527 collect_garbage: false,
2528 })
2529 }
2530}
2531
2532impl PartialEq for WeakLua {
2533 fn eq(&self, other: &Self) -> bool {
2534 XWeak::ptr_eq(&self.0, &other.0)
2535 }
2536}
2537
2538impl Eq for WeakLua {}
2539
2540impl LuaGuard {
2541 #[cfg(feature = "send")]
2542 pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2543 LuaGuard(handle.lock_arc())
2544 }
2545
2546 #[cfg(not(feature = "send"))]
2547 pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2548 LuaGuard(handle.into_lock_arc())
2549 }
2550}
2551
2552impl Deref for LuaGuard {
2553 type Target = RawLua;
2554
2555 fn deref(&self) -> &Self::Target {
2556 &self.0
2557 }
2558}
2559
2560pub(crate) mod extra;
2561mod raw;
2562pub(crate) mod util;
2563
2564#[cfg(test)]
2565mod assertions {
2566 use super::*;
2567
2568 // Lua has lots of interior mutability, should not be RefUnwindSafe
2569 static_assertions::assert_not_impl_any!(Lua: std::panic::RefUnwindSafe);
2570
2571 #[cfg(not(feature = "send"))]
2572 static_assertions::assert_not_impl_any!(Lua: Send);
2573 #[cfg(feature = "send")]
2574 static_assertions::assert_impl_all!(Lua: Send, Sync);
2575}