mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 75a15ceabf | |||
| 60730fd068 | |||
| df778b7b33 | |||
| 45299c0ef1 | |||
| 38eec1236c | |||
| 145c5b316b | |||
| e97e69a309 | |||
| 2ac7b23596 | |||
| 8200bee467 | |||
| fe6ab250bf | |||
| 804972b099 | |||
| 727f99ee4d | |||
| 3c801e7b17 | |||
| a38e484fe9 | |||
| eed48889cd | |||
| b5896173fd | |||
| 205989f569 | |||
| 12472de1d2 | |||
| a68708c12e | |||
| 4c0474d573 | |||
| 60e859f643 | |||
| 9ed0d90746 | |||
| 514ec24252 | |||
| 244e6c9c12 | |||
| 4749e3a22a | |||
| cf153f38de | |||
| c0a0983025 | |||
| 69ff0c5509 | |||
| bf79d6c212 | |||
| 0b9a85e183 | |||
| 59974d7bde | |||
| 61e846326c | |||
| 3547985bb0 | |||
| 4c92580201 | |||
| e3f34f319c | |||
| b16f3895a0 | |||
| a4c919231c | |||
| e4d6e92287 | |||
| 642201a7e0 | |||
| c36808b251 |
@@ -206,6 +206,29 @@ jobs:
|
||||
(cd tests/module && cargo build --release --features "${{ matrix.lua }}")
|
||||
(cd tests/module/loader && cargo test --release --features "${{ matrix.lua }}")
|
||||
|
||||
test_wasm32_emscripten:
|
||||
name: Test on wasm32-unknown-emscripten
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
lua: [lua54, lua53, lua52, lua51, luau]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-emscripten
|
||||
- name: Install Emscripten
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends emscripten
|
||||
- name: Run ${{ matrix.lua }} tests
|
||||
run: |
|
||||
cargo test --tests --features "${{ matrix.lua }},vendored"
|
||||
cargo test --tests --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
cargo test --tests --features "${{ matrix.lua }},vendored,async,serialize,macros,parking_lot,unstable"
|
||||
|
||||
rustfmt:
|
||||
name: Rustfmt
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
## v0.9.5
|
||||
|
||||
- Minimal Luau updated to 0.609
|
||||
- Luau max stack size increased to 1M (from 100K)
|
||||
- Implemented `IntoLua` for refs to `String`/`Table`/`Function`/`AnyUserData`/`Thread` + `RegistryKey`
|
||||
- Implemented `IntoLua` and `FromLua` for `OwnedThread`/`OwnedString`
|
||||
- Fixed `FromLua` derive proc macro to cover more cases
|
||||
|
||||
## v0.9.4
|
||||
|
||||
- Fixed loading all-in-one modules under mixed states (eg. main state and coroutines)
|
||||
|
||||
## v0.9.3
|
||||
|
||||
- WebAssembly support (`wasm32-unknown-emscripten` target)
|
||||
- Performance improvements (faster Lua function calls for lua51/jit/luau)
|
||||
|
||||
## v0.9.2
|
||||
|
||||
- Added binary modules support to Luau
|
||||
|
||||
+11
-8
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "mlua"
|
||||
version = "0.9.2" # remember to update mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@chucklefish.org>"]
|
||||
version = "0.9.5" # remember to update mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@kyju.org>"]
|
||||
rust-version = "1.71"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/khvzak/mlua"
|
||||
@@ -44,36 +44,39 @@ macros = ["mlua_derive/macros"]
|
||||
unstable = []
|
||||
|
||||
[dependencies]
|
||||
mlua_derive = { version = "=0.9.0", optional = true, path = "mlua_derive" }
|
||||
mlua_derive = { version = "=0.9.2", optional = true, path = "mlua_derive" }
|
||||
bstr = { version = "1.0", features = ["std"], default_features = false }
|
||||
once_cell = { version = "1.0" }
|
||||
num-traits = { version = "0.2.14" }
|
||||
rustc-hash = "1.0"
|
||||
futures-util = { version = "0.3", optional = true, default-features = false, features = ["std"] }
|
||||
serde = { version = "1.0", optional = true }
|
||||
erased-serde = { version = "0.3", optional = true }
|
||||
erased-serde = { version = "0.4", optional = true }
|
||||
serde-value = { version = "0.7", optional = true }
|
||||
parking_lot = { version = "0.12", optional = true }
|
||||
|
||||
ffi = { package = "mlua-sys", version = "0.4.0", path = "mlua-sys" }
|
||||
ffi = { package = "mlua-sys", version = "0.5.1", path = "mlua-sys" }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libloading = { version = "0.8", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rustyline = "12.0"
|
||||
criterion = { version = "0.5", features = ["async_tokio"] }
|
||||
trybuild = "1.0"
|
||||
futures = "0.3.5"
|
||||
hyper = { version = "0.14", features = ["client", "server"] }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tokio = { version = "1.0", features = ["macros", "rt", "time"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
maplit = "1.0"
|
||||
tempfile = "3"
|
||||
static_assertions = "1.0"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||
criterion = { version = "0.5", features = ["async_tokio"] }
|
||||
rustyline = "13.0"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
|
||||
[[bench]]
|
||||
name = "benchmark"
|
||||
harness = false
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
[crates.io]: https://crates.io/crates/mlua
|
||||
[API Documentation]: https://docs.rs/mlua/badge.svg
|
||||
[docs.rs]: https://docs.rs/mlua
|
||||
[Coverage Status]: https://codecov.io/gh/khvzak/mlua/branch/master/graph/badge.svg?token=99339FS1CG
|
||||
[codecov.io]: https://codecov.io/gh/khvzak/mlua
|
||||
[Coverage Status]: https://codecov.io/gh/mlua-rs/mlua/branch/master/graph/badge.svg?token=99339FS1CG
|
||||
[codecov.io]: https://codecov.io/gh/mlua-rs/mlua
|
||||
[MSRV]: https://img.shields.io/badge/rust-1.71+-brightgreen.svg?&logo=rust
|
||||
|
||||
[Guided Tour] | [Benchmarks] | [FAQ]
|
||||
@@ -28,6 +28,8 @@ Started as `rlua` fork, `mlua` supports Lua 5.4, 5.3, 5.2, 5.1 (including LuaJIT
|
||||
|
||||
`mlua` tested on Windows/macOS/Linux including module mode in [GitHub Actions] on `x86_64` platform and cross-compilation to `aarch64` (other targets are also supported).
|
||||
|
||||
WebAssembly (WASM) is supported through `wasm32-unknown-emscripten` target for all Lua versions excluding JIT.
|
||||
|
||||
[GitHub Actions]: https://github.com/khvzak/mlua/actions
|
||||
[Roblox Luau]: https://luau-lang.org
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ impl UserData for BodyReader {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use mlua::{chunk, ExternalResult, Lua, LuaSerdeExt, Result};
|
||||
|
||||
#[tokio::main]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ fn main() -> Result<()> {
|
||||
|
||||
// You can load and evaluate Lua code. The returned type of `Lua::load` is a builder
|
||||
// that allows you to change settings before running Lua code. Here, we are using it to set
|
||||
// the name of the laoded chunk to "example code", which will be used when Lua error
|
||||
// the name of the loaded chunk to "example code", which will be used when Lua error
|
||||
// messages are printed.
|
||||
|
||||
lua.load(
|
||||
@@ -89,7 +89,7 @@ fn main() -> Result<()> {
|
||||
let print: Function = globals.get("print")?;
|
||||
print.call::<_, ()>("hello from rust")?;
|
||||
|
||||
// This API generally handles variadics using tuples. This is one way to call a function with
|
||||
// This API generally handles variadic using tuples. This is one way to call a function with
|
||||
// multiple parameters:
|
||||
|
||||
print.call::<_, ()>(("hello", "again", "from", "rust"))?;
|
||||
@@ -100,7 +100,7 @@ fn main() -> Result<()> {
|
||||
["hello", "yet", "again", "from", "rust"].iter().cloned(),
|
||||
))?;
|
||||
|
||||
// You can bind rust functions to Lua as well. Callbacks receive the Lua state inself as their
|
||||
// You can bind rust functions to Lua as well. Callbacks receive the Lua state itself as their
|
||||
// first parameter, and the arguments given to the function as the second parameter. The type
|
||||
// of the arguments can be anything that is convertible from the parameters given by Lua, in
|
||||
// this case, the function expects two string sequences.
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua-sys"
|
||||
version = "0.4.0"
|
||||
version = "0.5.1"
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>"]
|
||||
rust-version = "1.71"
|
||||
edition = "2021"
|
||||
@@ -38,6 +38,6 @@ module = []
|
||||
cc = "1.0"
|
||||
cfg-if = "1.0"
|
||||
pkg-config = "0.3.17"
|
||||
lua-src = { version = ">= 546.0.0, < 546.1.0", optional = true }
|
||||
lua-src = { version = ">= 546.0.2, < 546.1.0", optional = true }
|
||||
luajit-src = { version = ">= 210.5.0, < 210.6.0", optional = true }
|
||||
luau0-src = { version = "0.7.8", optional = true }
|
||||
luau0-src = { version = "0.8.0", optional = true }
|
||||
|
||||
@@ -4,6 +4,12 @@ use std::env;
|
||||
use std::ops::Bound;
|
||||
|
||||
pub fn probe_lua() {
|
||||
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
if target_arch == "wasm32" && cfg!(not(feature = "vendored")) {
|
||||
panic!("Please enable `vendored` feature to build for wasm32");
|
||||
}
|
||||
|
||||
let lib_dir = env::var("LUA_LIB").unwrap_or_default();
|
||||
let lua_lib = env::var("LUA_LIB_NAME").unwrap_or_default();
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ pub fn probe_lua() {
|
||||
#[cfg(feature = "luau")]
|
||||
let artifacts = luau0_src::Build::new()
|
||||
.enable_codegen(cfg!(feature = "luau-codegen"))
|
||||
.set_max_cstack_size(1000000)
|
||||
.set_vector_size(if cfg!(feature = "luau-vector4") { 4 } else { 3 })
|
||||
.build();
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ pub const SYS_MIN_ALIGN: usize = 8;
|
||||
target_arch = "sparc64",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "wasm64",
|
||||
target_arch = "loongarch64",
|
||||
))]
|
||||
#[doc(hidden)]
|
||||
pub const SYS_MIN_ALIGN: usize = 16;
|
||||
|
||||
@@ -43,7 +43,7 @@ extern "C-unwind" {
|
||||
pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
|
||||
|
||||
pub fn luaL_where(L: *mut lua_State, lvl: c_int);
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> c_int;
|
||||
|
||||
pub fn luaL_checkoption(
|
||||
L: *mut lua_State,
|
||||
|
||||
@@ -228,13 +228,23 @@ extern "C-unwind" {
|
||||
//
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_error(L: *mut lua_State) -> !;
|
||||
#[link_name = "lua_error"]
|
||||
fn lua_error_(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||
pub fn lua_getallocf(L: *mut lua_State, ud: *mut *mut c_void) -> lua_Alloc;
|
||||
pub fn lua_setallocf(L: *mut lua_State, f: lua_Alloc, ud: *mut c_void);
|
||||
}
|
||||
|
||||
// lua_error does not return but is declared to return int, and Rust translates
|
||||
// ! to void which can cause link-time errors if the platform linker is aware
|
||||
// of return types and requires they match (for example: wasm does this).
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_error(L: *mut lua_State) -> ! {
|
||||
lua_error_(L);
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
//
|
||||
// Some useful macros (implemented as Rust functions)
|
||||
//
|
||||
@@ -318,6 +328,14 @@ pub unsafe fn lua_getglobal_(L: *mut lua_State, var: *const c_char) {
|
||||
lua_getfield_(L, LUA_GLOBALSINDEX, var)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tolightuserdata(L: *mut lua_State, idx: c_int) -> *mut c_void {
|
||||
if lua_islightuserdata(L, idx) != 0 {
|
||||
return lua_touserdata(L, idx);
|
||||
}
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
lua_tolstring(L, i, ptr::null_mut())
|
||||
|
||||
@@ -49,7 +49,7 @@ extern "C-unwind" {
|
||||
pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
|
||||
|
||||
pub fn luaL_where(L: *mut lua_State, lvl: c_int);
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> c_int;
|
||||
|
||||
pub fn luaL_checkoption(
|
||||
L: *mut lua_State,
|
||||
|
||||
@@ -308,7 +308,8 @@ extern "C-unwind" {
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
pub fn lua_error(L: *mut lua_State) -> !;
|
||||
#[link_name = "lua_error"]
|
||||
fn lua_error_(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||
pub fn lua_len(L: *mut lua_State, idx: c_int);
|
||||
@@ -316,6 +317,15 @@ extern "C-unwind" {
|
||||
pub fn lua_setallocf(L: *mut lua_State, f: lua_Alloc, ud: *mut c_void);
|
||||
}
|
||||
|
||||
// lua_error does not return but is declared to return int, and Rust translates
|
||||
// ! to void which can cause link-time errors if the platform linker is aware
|
||||
// of return types and requires they match (for example: wasm does this).
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_error(L: *mut lua_State) -> ! {
|
||||
lua_error_(L);
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
//
|
||||
// Some useful macros (implemented as Rust functions)
|
||||
//
|
||||
@@ -407,6 +417,14 @@ pub unsafe fn lua_pushglobaltable(L: *mut lua_State) {
|
||||
lua_rawgeti_(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS as _)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tolightuserdata(L: *mut lua_State, idx: c_int) -> *mut c_void {
|
||||
if lua_islightuserdata(L, idx) != 0 {
|
||||
return lua_touserdata(L, idx);
|
||||
}
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
lua_tolstring(L, i, ptr::null_mut())
|
||||
@@ -453,7 +471,12 @@ extern "C-unwind" {
|
||||
pub fn lua_upvalueid(L: *mut lua_State, fidx: c_int, n: c_int) -> *mut c_void;
|
||||
pub fn lua_upvaluejoin(L: *mut lua_State, fidx1: c_int, n1: c_int, fidx2: c_int, n2: c_int);
|
||||
|
||||
pub fn lua_sethook(L: *mut lua_State, func: Option<lua_Hook>, mask: c_int, count: c_int);
|
||||
pub fn lua_sethook(
|
||||
L: *mut lua_State,
|
||||
func: Option<lua_Hook>,
|
||||
mask: c_int,
|
||||
count: c_int,
|
||||
) -> c_int;
|
||||
pub fn lua_gethook(L: *mut lua_State) -> Option<lua_Hook>;
|
||||
pub fn lua_gethookmask(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_gethookcount(L: *mut lua_State) -> c_int;
|
||||
|
||||
@@ -20,7 +20,7 @@ pub struct luaL_Reg {
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: usize);
|
||||
|
||||
@@ -51,7 +51,7 @@ extern "C-unwind" {
|
||||
pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
|
||||
|
||||
pub fn luaL_where(L: *mut lua_State, lvl: c_int);
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> c_int;
|
||||
|
||||
pub fn luaL_checkoption(
|
||||
L: *mut lua_State,
|
||||
|
||||
@@ -314,7 +314,8 @@ extern "C-unwind" {
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
pub fn lua_error(L: *mut lua_State) -> !;
|
||||
#[link_name = "lua_error"]
|
||||
fn lua_error_(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||
pub fn lua_len(L: *mut lua_State, idx: c_int);
|
||||
@@ -323,6 +324,15 @@ extern "C-unwind" {
|
||||
pub fn lua_setallocf(L: *mut lua_State, f: lua_Alloc, ud: *mut c_void);
|
||||
}
|
||||
|
||||
// lua_error does not return but is declared to return int, and Rust translates
|
||||
// ! to void which can cause link-time errors if the platform linker is aware
|
||||
// of return types and requires they match (for example: wasm does this).
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_error(L: *mut lua_State) -> ! {
|
||||
lua_error_(L);
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
//
|
||||
// Some useful macros (implemented as Rust functions)
|
||||
//
|
||||
@@ -414,6 +424,14 @@ pub unsafe fn lua_pushglobaltable(L: *mut lua_State) -> c_int {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tolightuserdata(L: *mut lua_State, idx: c_int) -> *mut c_void {
|
||||
if lua_islightuserdata(L, idx) != 0 {
|
||||
return lua_touserdata(L, idx);
|
||||
}
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
lua_tolstring(L, i, ptr::null_mut())
|
||||
|
||||
@@ -50,7 +50,7 @@ extern "C-unwind" {
|
||||
pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
|
||||
|
||||
pub fn luaL_where(L: *mut lua_State, lvl: c_int);
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> c_int;
|
||||
|
||||
pub fn luaL_checkoption(
|
||||
L: *mut lua_State,
|
||||
|
||||
@@ -149,13 +149,21 @@ extern "C-unwind" {
|
||||
pub fn lua_tointegerx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Integer;
|
||||
pub fn lua_toboolean(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char;
|
||||
pub fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize;
|
||||
#[link_name = "lua_rawlen"]
|
||||
fn lua_rawlen_(L: *mut lua_State, idx: c_int) -> lua_Unsigned;
|
||||
pub fn lua_tocfunction(L: *mut lua_State, idx: c_int) -> Option<lua_CFunction>;
|
||||
pub fn lua_touserdata(L: *mut lua_State, idx: c_int) -> *mut c_void;
|
||||
pub fn lua_tothread(L: *mut lua_State, idx: c_int) -> *mut lua_State;
|
||||
pub fn lua_topointer(L: *mut lua_State, idx: c_int) -> *const c_void;
|
||||
}
|
||||
|
||||
// lua_rawlen's return type changed from size_t to lua_Unsigned int in Lua 5.4.
|
||||
// This adapts the crate API to the new Lua ABI.
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize {
|
||||
lua_rawlen_(L, idx) as usize
|
||||
}
|
||||
|
||||
//
|
||||
// Comparison and arithmetic functions
|
||||
//
|
||||
@@ -336,7 +344,8 @@ extern "C-unwind" {
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
pub fn lua_error(L: *mut lua_State) -> !;
|
||||
#[link_name = "lua_error"]
|
||||
fn lua_error_(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||
pub fn lua_len(L: *mut lua_State, idx: c_int);
|
||||
@@ -348,6 +357,15 @@ extern "C-unwind" {
|
||||
pub fn lua_closeslot(L: *mut lua_State, idx: c_int);
|
||||
}
|
||||
|
||||
// lua_error does not return but is declared to return int, and Rust translates
|
||||
// ! to void which can cause link-time errors if the platform linker is aware
|
||||
// of return types and requires they match (for example: wasm does this).
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_error(L: *mut lua_State) -> ! {
|
||||
lua_error_(L);
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
//
|
||||
// Some useful macros (implemented as Rust functions)
|
||||
//
|
||||
@@ -439,6 +457,14 @@ pub unsafe fn lua_pushglobaltable(L: *mut lua_State) -> c_int {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tolightuserdata(L: *mut lua_State, idx: c_int) -> *mut c_void {
|
||||
if lua_islightuserdata(L, idx) != 0 {
|
||||
return lua_touserdata(L, idx);
|
||||
}
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
lua_tolstring(L, i, ptr::null_mut())
|
||||
|
||||
@@ -8,7 +8,13 @@ use std::{mem, ptr};
|
||||
pub const LUA_MULTRET: c_int = -1;
|
||||
|
||||
// Max number of Lua stack slots
|
||||
const LUAI_MAXCSTACK: c_int = 100000;
|
||||
const LUAI_MAXCSTACK: c_int = 1000000;
|
||||
|
||||
// Number of valid Lua userdata tags
|
||||
const LUA_UTAG_LIMIT: c_int = 128;
|
||||
|
||||
// Number of valid Lua lightuserdata tags
|
||||
const LUA_LUTAG_LIMIT: c_int = 128;
|
||||
|
||||
//
|
||||
// Pseudo-indices
|
||||
@@ -144,9 +150,11 @@ extern "C-unwind" {
|
||||
pub fn lua_objlen(L: *mut lua_State, idx: c_int) -> usize;
|
||||
pub fn lua_tocfunction(L: *mut lua_State, idx: c_int) -> Option<lua_CFunction>;
|
||||
pub fn lua_tolightuserdata(L: *mut lua_State, idx: c_int) -> *mut c_void;
|
||||
pub fn lua_tolightuserdatatagged(L: *mut lua_State, idx: c_int, tag: c_int) -> *mut c_void;
|
||||
pub fn lua_touserdata(L: *mut lua_State, idx: c_int) -> *mut c_void;
|
||||
pub fn lua_touserdatatagged(L: *mut lua_State, idx: c_int, tag: c_int) -> *mut c_void;
|
||||
pub fn lua_userdatatag(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_lightuserdatatag(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_tothread(L: *mut lua_State, idx: c_int) -> *mut lua_State;
|
||||
pub fn lua_tobuffer(L: *mut lua_State, idx: c_int, len: *mut usize) -> *mut c_void;
|
||||
pub fn lua_topointer(L: *mut lua_State, idx: c_int) -> *const c_void;
|
||||
@@ -179,7 +187,7 @@ extern "C-unwind" {
|
||||
pub fn lua_pushboolean(L: *mut lua_State, b: c_int);
|
||||
pub fn lua_pushthread(L: *mut lua_State) -> c_int;
|
||||
|
||||
pub fn lua_pushlightuserdata(L: *mut lua_State, p: *mut c_void);
|
||||
pub fn lua_pushlightuserdatatagged(L: *mut lua_State, p: *mut c_void, tag: c_int);
|
||||
pub fn lua_newuserdatatagged(L: *mut lua_State, sz: usize, tag: c_int) -> *mut c_void;
|
||||
pub fn lua_newuserdatadtor(L: *mut lua_State, sz: usize, dtor: lua_Udestructor) -> *mut c_void;
|
||||
|
||||
@@ -280,6 +288,8 @@ extern "C-unwind" {
|
||||
pub fn lua_setuserdatatag(L: *mut lua_State, idx: c_int, tag: c_int);
|
||||
pub fn lua_setuserdatadtor(L: *mut lua_State, tag: c_int, dtor: Option<lua_Destructor>);
|
||||
pub fn lua_getuserdatadtor(L: *mut lua_State, tag: c_int) -> Option<lua_Destructor>;
|
||||
pub fn lua_setlightuserdataname(L: *mut lua_State, tag: c_int, name: *const c_char);
|
||||
pub fn lua_getlightuserdataname(L: *mut lua_State, tag: c_int) -> *const c_char;
|
||||
pub fn lua_clonefunction(L: *mut lua_State, idx: c_int);
|
||||
pub fn lua_cleartable(L: *mut lua_State, idx: c_int);
|
||||
pub fn lua_getallocf(L: *mut lua_State, ud: *mut *mut c_void) -> lua_Alloc;
|
||||
@@ -398,18 +408,22 @@ pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &'static str) {
|
||||
lua_pushlstring_(L, c_str.as_ptr(), c_str.as_bytes().len())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) {
|
||||
lua_pushcclosurek(L, f, ptr::null(), 0, None)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushcfunctiond(L: *mut lua_State, f: lua_CFunction, debugname: *const c_char) {
|
||||
lua_pushcclosurek(L, f, debugname, 0, None)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushcclosure(L: *mut lua_State, f: lua_CFunction, nup: c_int) {
|
||||
lua_pushcclosurek(L, f, ptr::null(), nup, None)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushcclosured(
|
||||
L: *mut lua_State,
|
||||
f: lua_CFunction,
|
||||
@@ -419,6 +433,11 @@ pub unsafe fn lua_pushcclosured(
|
||||
lua_pushcclosurek(L, f, debugname, nup, None)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushlightuserdata(L: *mut lua_State, p: *mut c_void) {
|
||||
lua_pushlightuserdatatagged(L, p, 0)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_setglobal(L: *mut lua_State, var: *const c_char) {
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, var)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua_derive"
|
||||
version = "0.9.0"
|
||||
version = "0.9.2"
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>"]
|
||||
edition = "2021"
|
||||
description = "Procedural macros for the mlua crate."
|
||||
@@ -19,6 +19,6 @@ quote = "1.0"
|
||||
proc-macro2 = { version = "1.0", features = ["span-locations"] }
|
||||
proc-macro-error = { version = "1.0", optional = true }
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
itertools = { version = "0.11", optional = true }
|
||||
itertools = { version = "0.12", optional = true }
|
||||
regex = { version = "1.4", optional = true }
|
||||
once_cell = { version = "1.0", optional = true }
|
||||
|
||||
@@ -7,16 +7,17 @@ pub fn from_lua(input: TokenStream) -> TokenStream {
|
||||
ident, generics, ..
|
||||
} = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let ident_str = ident.to_string();
|
||||
let (impl_generics, ty_generics, _) = generics.split_for_impl();
|
||||
let where_clause = match &generics.where_clause {
|
||||
Some(where_clause) => quote! { #where_clause, Self: 'static + Clone },
|
||||
None => quote! { where Self: 'static + Clone },
|
||||
};
|
||||
let ident_str = ident.to_string();
|
||||
|
||||
quote! {
|
||||
impl #generics ::mlua::FromLua<'_> for #ident #generics #where_clause {
|
||||
impl #impl_generics ::mlua::FromLua<'_> for #ident #ty_generics #where_clause {
|
||||
#[inline]
|
||||
fn from_lua(value: ::mlua::Value<'_>, lua: &'_ ::mlua::Lua) -> ::mlua::Result<Self> {
|
||||
fn from_lua(value: ::mlua::Value<'_>, _: &'_ ::mlua::Lua) -> ::mlua::Result<Self> {
|
||||
match value {
|
||||
::mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||
_ => Err(::mlua::Error::FromLuaConversionError {
|
||||
|
||||
@@ -51,7 +51,11 @@ pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let func_name = &func.sig.ident;
|
||||
let module_name = args.name.unwrap_or_else(|| func_name.clone());
|
||||
let ext_entrypoint_name = Ident::new(&format!("luaopen_{module_name}"), Span::call_site());
|
||||
let skip_memory_check = args.skip_memory_check;
|
||||
let skip_memory_check = if args.skip_memory_check {
|
||||
quote! { lua.skip_memory_check(true); }
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
let wrapped = quote! {
|
||||
::mlua::require_module_feature!();
|
||||
@@ -61,8 +65,8 @@ pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
#[no_mangle]
|
||||
unsafe extern "C-unwind" fn #ext_entrypoint_name(state: *mut ::mlua::lua_State) -> ::std::os::raw::c_int {
|
||||
let lua = ::mlua::Lua::init_from_ptr(state);
|
||||
lua.skip_memory_check(#skip_memory_check);
|
||||
lua.entrypoint1(#func_name)
|
||||
#skip_memory_check
|
||||
lua.entrypoint1(state, #func_name)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+191
-2
@@ -16,12 +16,15 @@ use crate::lua::Lua;
|
||||
use crate::string::String;
|
||||
use crate::table::Table;
|
||||
use crate::thread::Thread;
|
||||
use crate::types::{LightUserData, MaybeSend};
|
||||
use crate::types::{LightUserData, MaybeSend, RegistryKey};
|
||||
use crate::userdata::{AnyUserData, UserData, UserDataRef, UserDataRefMut};
|
||||
use crate::value::{FromLua, IntoLua, Nil, Value};
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
use crate::{function::OwnedFunction, table::OwnedTable, userdata::OwnedAnyUserData};
|
||||
use crate::{
|
||||
function::OwnedFunction, string::OwnedString, table::OwnedTable, thread::OwnedThread,
|
||||
userdata::OwnedAnyUserData,
|
||||
};
|
||||
|
||||
impl<'lua> IntoLua<'lua> for Value<'lua> {
|
||||
#[inline]
|
||||
@@ -44,6 +47,18 @@ impl<'lua> IntoLua<'lua> for String<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for &String<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::String(self.clone()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for String<'lua> {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<String<'lua>> {
|
||||
@@ -57,6 +72,38 @@ impl<'lua> FromLua<'lua> for String<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> IntoLua<'lua> for OwnedString {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::String(String(lua.adopt_owned_ref(self.0))))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> IntoLua<'lua> for &OwnedString {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
OwnedString::into_lua(self.clone(), lua)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_owned_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> FromLua<'lua> for OwnedString {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedString> {
|
||||
String::from_lua(value, lua).map(|s| s.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for Table<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
@@ -64,6 +111,18 @@ impl<'lua> IntoLua<'lua> for Table<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for &Table<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::Table(self.clone()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for Table<'lua> {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Table<'lua>> {
|
||||
@@ -87,6 +146,20 @@ impl<'lua> IntoLua<'lua> for OwnedTable {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> IntoLua<'lua> for &OwnedTable {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
OwnedTable::into_lua(self.clone(), lua)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_owned_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> FromLua<'lua> for OwnedTable {
|
||||
@@ -103,6 +176,18 @@ impl<'lua> IntoLua<'lua> for Function<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for &Function<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::Function(self.clone()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for Function<'lua> {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Function<'lua>> {
|
||||
@@ -126,6 +211,20 @@ impl<'lua> IntoLua<'lua> for OwnedFunction {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> IntoLua<'lua> for &OwnedFunction {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
OwnedFunction::into_lua(self.clone(), lua)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_owned_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> FromLua<'lua> for OwnedFunction {
|
||||
@@ -142,6 +241,18 @@ impl<'lua> IntoLua<'lua> for Thread<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for &Thread<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::Thread(self.clone()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for Thread<'lua> {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Thread<'lua>> {
|
||||
@@ -156,6 +267,38 @@ impl<'lua> FromLua<'lua> for Thread<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> IntoLua<'lua> for OwnedThread {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::Thread(Thread(lua.adopt_owned_ref(self.0), self.1)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> IntoLua<'lua> for &OwnedThread {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
OwnedThread::into_lua(self.clone(), lua)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_owned_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> FromLua<'lua> for OwnedThread {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedThread> {
|
||||
Thread::from_lua(value, lua).map(|s| s.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for AnyUserData<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
@@ -163,6 +306,18 @@ impl<'lua> IntoLua<'lua> for AnyUserData<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for &AnyUserData<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::UserData(self.clone()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for AnyUserData<'lua> {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<AnyUserData<'lua>> {
|
||||
@@ -189,6 +344,20 @@ impl<'lua> IntoLua<'lua> for OwnedAnyUserData {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> IntoLua<'lua> for &OwnedAnyUserData {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
OwnedAnyUserData::into_lua(self.clone(), lua)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
Ok(lua.push_owned_ref(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
|
||||
impl<'lua> FromLua<'lua> for OwnedAnyUserData {
|
||||
@@ -240,6 +409,26 @@ impl<'lua> FromLua<'lua> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for &RegistryKey {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
lua.registry_value(self)
|
||||
}
|
||||
|
||||
unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
|
||||
if !lua.owns_registry_value(self) {
|
||||
return Err(Error::MismatchedRegistryKey);
|
||||
}
|
||||
|
||||
if self.is_nil() {
|
||||
ffi::lua_pushnil(lua.state());
|
||||
} else {
|
||||
ffi::lua_rawgeti(lua.state(), ffi::LUA_REGISTRYINDEX, self.registry_id as _);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for bool {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
|
||||
+3
-4
@@ -6,12 +6,11 @@ use std::slice;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::lua::Lua;
|
||||
use crate::memory::MemoryState;
|
||||
use crate::table::Table;
|
||||
use crate::types::{Callback, LuaRef, MaybeSend};
|
||||
use crate::util::{
|
||||
assert_stack, check_stack, error_traceback, linenumber_to_usize, pop_error, ptr_to_lossy_str,
|
||||
ptr_to_str, StackGuard,
|
||||
assert_stack, check_stack, linenumber_to_usize, pop_error, ptr_to_lossy_str, ptr_to_str,
|
||||
StackGuard,
|
||||
};
|
||||
use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti, Value};
|
||||
|
||||
@@ -131,7 +130,7 @@ impl<'lua> Function<'lua> {
|
||||
check_stack(state, 2)?;
|
||||
|
||||
// Push error handler
|
||||
MemoryState::relax_limit_with(state, || ffi::lua_pushcfunction(state, error_traceback));
|
||||
lua.push_error_traceback();
|
||||
let stack_start = ffi::lua_gettop(state);
|
||||
// Push function and the arguments
|
||||
lua.push_ref(&self.0);
|
||||
|
||||
+62
-20
@@ -31,10 +31,10 @@ use crate::types::{
|
||||
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataCell};
|
||||
use crate::userdata_impl::{UserDataProxy, UserDataRegistry};
|
||||
use crate::util::{
|
||||
self, assert_stack, check_stack, get_destructed_userdata_metatable, get_gc_metatable,
|
||||
get_gc_userdata, get_main_state, get_userdata, init_error_registry, init_gc_metatable,
|
||||
init_userdata_metatable, pop_error, push_gc_userdata, push_string, push_table, rawset_field,
|
||||
safe_pcall, safe_xpcall, short_type_name, StackGuard, WrappedFailure,
|
||||
self, assert_stack, check_stack, error_traceback, get_destructed_userdata_metatable,
|
||||
get_gc_metatable, get_gc_userdata, get_main_state, get_userdata, init_error_registry,
|
||||
init_gc_metatable, init_userdata_metatable, pop_error, push_gc_userdata, push_string,
|
||||
push_table, rawset_field, safe_pcall, safe_xpcall, short_type_name, StackGuard, WrappedFailure,
|
||||
};
|
||||
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil, Value};
|
||||
|
||||
@@ -499,6 +499,13 @@ impl Lua {
|
||||
ptr
|
||||
};
|
||||
|
||||
// Store `error_traceback` function on the ref stack
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushcfunction(ref_thread, error_traceback);
|
||||
assert_eq!(ffi::lua_gettop(ref_thread), ExtraData::ERROR_TRACEBACK_IDX);
|
||||
}
|
||||
|
||||
// Create ExtraData
|
||||
let extra = Arc::new(UnsafeCell::new(ExtraData {
|
||||
inner: MaybeUninit::uninit(),
|
||||
@@ -701,18 +708,20 @@ impl Lua {
|
||||
// The returned value then pushed onto the stack.
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
pub unsafe fn entrypoint<'lua, A, R, F>(self, func: F) -> c_int
|
||||
pub unsafe fn entrypoint<'lua, A, R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
|
||||
where
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLua<'lua>,
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
{
|
||||
let (state, extra) = (self.state(), self.extra.get());
|
||||
// It must be safe to drop `self` as in the module mode we keep strong reference to `Lua` in the registry
|
||||
let extra = self.extra.get();
|
||||
// `self` is no longer needed and must be dropped at this point to avoid possible memory leak
|
||||
// in case of possible longjmp (lua_error) below
|
||||
drop(self);
|
||||
|
||||
callback_error_ext(state, extra, move |nargs| {
|
||||
let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
|
||||
let _guard = StateGuard::new(&lua.0, state);
|
||||
let args = A::from_stack_args(nargs, 1, None, lua)?;
|
||||
func(lua, args)?.push_into_stack(lua)?;
|
||||
Ok(1)
|
||||
@@ -722,12 +731,12 @@ impl Lua {
|
||||
// A simple module entrypoint without arguments
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
pub unsafe fn entrypoint1<'lua, R, F>(self, func: F) -> c_int
|
||||
pub unsafe fn entrypoint1<'lua, R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
|
||||
where
|
||||
R: IntoLua<'lua>,
|
||||
F: Fn(&'lua Lua) -> Result<R> + MaybeSend + 'static,
|
||||
{
|
||||
self.entrypoint(move |lua, _: ()| func(lua))
|
||||
self.entrypoint(state, move |lua, _: ()| func(lua))
|
||||
}
|
||||
|
||||
/// Skips memory checks for some operations.
|
||||
@@ -2549,6 +2558,15 @@ impl Lua {
|
||||
ffi::lua_xpush(self.ref_thread(), self.state(), lref.index);
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
pub(crate) unsafe fn push_owned_ref(&self, loref: &crate::types::LuaOwnedRef) {
|
||||
assert!(
|
||||
Arc::ptr_eq(&loref.inner, &self.0),
|
||||
"Lua instance passed Value created from a different main Lua state"
|
||||
);
|
||||
ffi::lua_xpush(self.ref_thread(), self.state(), loref.index);
|
||||
}
|
||||
|
||||
// Pops the topmost element of the stack and stores a reference to it. This pins the object,
|
||||
// preventing garbage collection until the returned `LuaRef` is dropped.
|
||||
//
|
||||
@@ -2601,6 +2619,16 @@ impl Lua {
|
||||
LuaRef::new(self, index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn push_error_traceback(&self) {
|
||||
let state = self.state();
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
ffi::lua_xpush(self.ref_thread(), state, ExtraData::ERROR_TRACEBACK_IDX);
|
||||
// Lua 5.2+ support light C functions that does not require extra allocations
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
ffi::lua_pushcfunction(state, error_traceback);
|
||||
}
|
||||
|
||||
unsafe fn register_userdata_metatable<'lua, T: 'static>(
|
||||
&'lua self,
|
||||
mut registry: UserDataRegistry<'lua, T>,
|
||||
@@ -2944,11 +2972,14 @@ impl Lua {
|
||||
let fut = &mut (*upvalue).data;
|
||||
let mut ctx = Context::from_waker(lua.waker());
|
||||
match fut.as_mut().poll(&mut ctx) {
|
||||
Poll::Pending => Ok(0),
|
||||
Poll::Pending => {
|
||||
ffi::lua_pushnil(state);
|
||||
ffi::lua_pushlightuserdata(state, Lua::poll_pending().0);
|
||||
Ok(2)
|
||||
}
|
||||
Poll::Ready(nresults) => {
|
||||
let nresults = nresults?;
|
||||
match nresults {
|
||||
0..=2 => {
|
||||
match nresults? {
|
||||
nresults @ 0..=2 => {
|
||||
// Fast path for up to 2 results without creating a table
|
||||
ffi::lua_pushinteger(state, nresults as _);
|
||||
if nresults > 0 {
|
||||
@@ -2956,7 +2987,7 @@ impl Lua {
|
||||
}
|
||||
Ok(nresults + 1)
|
||||
}
|
||||
_ => {
|
||||
nresults => {
|
||||
let results = MultiValue::from_stack_multi(nresults, lua)?;
|
||||
ffi::lua_pushinteger(state, nresults as _);
|
||||
lua.push_value(Value::Table(lua.create_sequence_from(results)?))?;
|
||||
@@ -3000,20 +3031,17 @@ impl Lua {
|
||||
|
||||
let coroutine = self.globals().get::<_, Table>("coroutine")?;
|
||||
|
||||
let env = self.create_table_with_capacity(0, 4)?;
|
||||
let env = self.create_table_with_capacity(0, 3)?;
|
||||
env.set("get_poll", get_poll)?;
|
||||
// Cache `yield` function
|
||||
env.set("yield", coroutine.get::<_, Function>("yield")?)?;
|
||||
unsafe {
|
||||
env.set("unpack", self.create_c_function(unpack)?)?;
|
||||
}
|
||||
env.set("pending", {
|
||||
LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut c_void)
|
||||
})?;
|
||||
|
||||
self.load(
|
||||
r#"
|
||||
local poll = get_poll(...)
|
||||
local pending, yield, unpack = pending, yield, unpack
|
||||
while true do
|
||||
local nres, res, res2 = poll()
|
||||
if nres ~= nil then
|
||||
@@ -3027,7 +3055,7 @@ impl Lua {
|
||||
return unpack(res, nres)
|
||||
end
|
||||
end
|
||||
yield(pending)
|
||||
yield(res) -- `res` is a "pending" value
|
||||
end
|
||||
"#,
|
||||
)
|
||||
@@ -3049,6 +3077,14 @@ impl Lua {
|
||||
mem::replace(&mut (*self.extra.get()).waker, waker)
|
||||
}
|
||||
|
||||
/// Returns internal `Poll::Pending` constant used for executing async callbacks.
|
||||
#[cfg(feature = "async")]
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn poll_pending() -> LightUserData {
|
||||
LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut c_void)
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn make_userdata<T>(&self, data: UserDataCell<T>) -> Result<AnyUserData>
|
||||
where
|
||||
T: UserData + 'static,
|
||||
@@ -3211,6 +3247,12 @@ impl LuaInner {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtraData {
|
||||
// Index of `error_traceback` function in auxiliary thread stack
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
const ERROR_TRACEBACK_IDX: c_int = 1;
|
||||
}
|
||||
|
||||
struct StateGuard<'a>(&'a LuaInner, *mut ffi::lua_State);
|
||||
|
||||
impl<'a> StateGuard<'a> {
|
||||
|
||||
+3
-8
@@ -15,7 +15,7 @@ use crate::{
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
use {
|
||||
crate::{lua::ASYNC_POLL_PENDING, value::MultiValue},
|
||||
crate::value::MultiValue,
|
||||
futures_util::stream::Stream,
|
||||
std::{
|
||||
future::Future,
|
||||
@@ -239,7 +239,7 @@ impl<'lua> Thread<'lua> {
|
||||
///
|
||||
/// [Lua 5.4]: https://www.lua.org/manual/5.4/manual.html#lua_closethread
|
||||
#[cfg(any(feature = "lua54", feature = "luau"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "lua54", feature = "luau"))))]
|
||||
pub fn reset(&self, func: crate::function::Function<'lua>) -> Result<()> {
|
||||
let lua = self.0.lua;
|
||||
let thread_state = self.state();
|
||||
@@ -530,12 +530,7 @@ where
|
||||
#[cfg(feature = "async")]
|
||||
#[inline(always)]
|
||||
unsafe fn is_poll_pending(state: *mut ffi::lua_State) -> bool {
|
||||
if ffi::lua_islightuserdata(state, -1) != 0 {
|
||||
let stack_ptr = ffi::lua_touserdata(state, -1) as *const u8;
|
||||
let pending_ptr = &ASYNC_POLL_PENDING as *const u8;
|
||||
return std::ptr::eq(stack_ptr, pending_ptr);
|
||||
}
|
||||
false
|
||||
ffi::lua_tolightuserdata(state, -1) == Lua::poll_pending().0
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
|
||||
+2
-2
@@ -580,12 +580,12 @@ pub trait UserDataFields<'lua, T> {
|
||||
/// # use mlua::{Lua, Result, UserData};
|
||||
/// # fn main() -> Result<()> {
|
||||
/// # let lua = Lua::new();
|
||||
/// struct MyUserData(i32);
|
||||
/// struct MyUserData;
|
||||
///
|
||||
/// impl UserData for MyUserData {}
|
||||
///
|
||||
/// // `MyUserData` now implements `IntoLua`:
|
||||
/// lua.globals().set("myobject", MyUserData(123))?;
|
||||
/// lua.globals().set("myobject", MyUserData)?;
|
||||
///
|
||||
/// lua.load("assert(type(myobject) == 'userdata')").exec()?;
|
||||
/// # Ok(())
|
||||
|
||||
@@ -218,7 +218,7 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = get_function_name::<T>(name);
|
||||
let name = Arc::new(get_function_name::<T>(name));
|
||||
let method = Arc::new(method);
|
||||
|
||||
Box::new(move |lua, mut args| unsafe {
|
||||
@@ -312,7 +312,7 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = get_function_name::<T>(name);
|
||||
let name = Arc::new(get_function_name::<T>(name));
|
||||
let method = Arc::new(method);
|
||||
|
||||
Box::new(move |lua, mut args| unsafe {
|
||||
|
||||
+8
-1
@@ -10,10 +10,17 @@ use mlua::{
|
||||
UserData, UserDataMethods, Value,
|
||||
};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
async fn sleep_ms(ms: u64) {
|
||||
tokio::time::sleep(Duration::from_millis(ms)).await;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
async fn sleep_ms(_ms: u64) {
|
||||
// I was unable to make sleep() work in wasm32-emscripten target
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_function() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
@@ -436,7 +443,7 @@ async fn test_async_userdata() -> Result<()> {
|
||||
let globals = lua.globals();
|
||||
|
||||
let userdata = lua.create_userdata(MyUserData(11))?;
|
||||
globals.set("userdata", userdata.clone())?;
|
||||
globals.set("userdata", &userdata)?;
|
||||
|
||||
lua.load(
|
||||
r#"
|
||||
|
||||
@@ -7,6 +7,12 @@ use mlua::{Lua, Result};
|
||||
fn test_chunk_path() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
// TODO: figure out why emscripten fails on file operations
|
||||
// Also see https://github.com/rust-lang/rust/issues/119250
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
fs::write(
|
||||
temp_dir.path().join("module.lua"),
|
||||
|
||||
@@ -4,7 +4,7 @@ error: lifetime may not live long enough
|
||||
9 | reg.add_async_method("t", |_, this: &String, ()| async {
|
||||
| ___________________________________----------------------_^
|
||||
| | | |
|
||||
| | | return type of closure `[async block@$DIR/tests/compile/async_any_userdata_method.rs:9:58: 12:10]` contains a lifetime `'2`
|
||||
| | | return type of closure `{async block@$DIR/tests/compile/async_any_userdata_method.rs:9:58: 12:10}` contains a lifetime `'2`
|
||||
| | lifetime `'1` represents this closure's body
|
||||
10 | | s = this;
|
||||
11 | | Ok(())
|
||||
@@ -27,6 +27,8 @@ error[E0596]: cannot borrow `s` as mutable, as it is a captured variable in a `F
|
||||
error[E0597]: `s` does not live long enough
|
||||
--> tests/compile/async_any_userdata_method.rs:8:21
|
||||
|
|
||||
7 | let s = String::new();
|
||||
| - binding `s` declared here
|
||||
8 | let mut s = &s;
|
||||
| ^^ borrowed value does not live long enough
|
||||
9 | / reg.add_async_method("t", |_, this: &String, ()| async {
|
||||
|
||||
@@ -7,14 +7,46 @@ error[E0277]: the type `UnsafeCell<mlua::lua::ExtraData>` may contain interior m
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: within `Lua`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<mlua::lua::ExtraData>`
|
||||
= note: required because it appears within the type `ArcInner<UnsafeCell<ExtraData>>`
|
||||
= note: required because it appears within the type `PhantomData<ArcInner<UnsafeCell<ExtraData>>>`
|
||||
= note: required because it appears within the type `Arc<UnsafeCell<ExtraData>>`
|
||||
= note: required because it appears within the type `LuaInner`
|
||||
= note: required because it appears within the type `ArcInner<LuaInner>`
|
||||
= note: required because it appears within the type `PhantomData<ArcInner<LuaInner>>`
|
||||
= note: required because it appears within the type `Arc<LuaInner>`
|
||||
= note: required because it appears within the type `Lua`
|
||||
note: required because it appears within the type `ArcInner<UnsafeCell<ExtraData>>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| struct ArcInner<T: ?Sized> {
|
||||
| ^^^^^^^^
|
||||
note: required because it appears within the type `PhantomData<ArcInner<UnsafeCell<ExtraData>>>`
|
||||
--> $RUST/core/src/marker.rs
|
||||
|
|
||||
| pub struct PhantomData<T: ?Sized>;
|
||||
| ^^^^^^^^^^^
|
||||
note: required because it appears within the type `Arc<UnsafeCell<ExtraData>>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| pub struct Arc<
|
||||
| ^^^
|
||||
note: required because it appears within the type `LuaInner`
|
||||
--> src/lua.rs
|
||||
|
|
||||
| pub struct LuaInner {
|
||||
| ^^^^^^^^
|
||||
note: required because it appears within the type `ArcInner<LuaInner>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| struct ArcInner<T: ?Sized> {
|
||||
| ^^^^^^^^
|
||||
note: required because it appears within the type `PhantomData<ArcInner<LuaInner>>`
|
||||
--> $RUST/core/src/marker.rs
|
||||
|
|
||||
| pub struct PhantomData<T: ?Sized>;
|
||||
| ^^^^^^^^^^^
|
||||
note: required because it appears within the type `Arc<LuaInner>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| pub struct Arc<
|
||||
| ^^^
|
||||
note: required because it appears within the type `Lua`
|
||||
--> src/lua.rs
|
||||
|
|
||||
| pub struct Lua(Arc<LuaInner>);
|
||||
| ^^^
|
||||
= note: required for `&Lua` to implement `UnwindSafe`
|
||||
note: required because it's used within this closure
|
||||
--> tests/compile/lua_norefunwindsafe.rs:7:18
|
||||
|
||||
@@ -4,22 +4,25 @@ error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
|
||||
11 | lua.create_function(move |_, ()| {
|
||||
| --------------- ^-----------
|
||||
| | |
|
||||
| _________|_______________within this `[closure@$DIR/tests/compile/non_send.rs:11:25: 11:37]`
|
||||
| _________|_______________within this `{closure@$DIR/tests/compile/non_send.rs:11:25: 11:37}`
|
||||
| | |
|
||||
| | required by a bound introduced by this call
|
||||
12 | | Ok(data.get())
|
||||
13 | | })?
|
||||
| |_____^ `Rc<Cell<i32>>` cannot be sent between threads safely
|
||||
|
|
||||
= help: within `[closure@$DIR/tests/compile/non_send.rs:11:25: 11:37]`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
|
||||
= help: within `{closure@$DIR/tests/compile/non_send.rs:11:25: 11:37}`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
|
||||
note: required because it's used within this closure
|
||||
--> tests/compile/non_send.rs:11:25
|
||||
|
|
||||
11 | lua.create_function(move |_, ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
= note: required for `[closure@$DIR/tests/compile/non_send.rs:11:25: 11:37]` to implement `mlua::types::MaybeSend`
|
||||
= note: required for `{closure@$DIR/tests/compile/non_send.rs:11:25: 11:37}` to implement `mlua::types::MaybeSend`
|
||||
note: required by a bound in `Lua::create_function`
|
||||
--> src/lua.rs
|
||||
|
|
||||
| pub fn create_function<'lua, A, R, F>(&'lua self, func: F) -> Result<Function<'lua>>
|
||||
| --------------- required by a bound in this associated function
|
||||
...
|
||||
| F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
| ^^^^^^^^^ required by this bound in `Lua::create_function`
|
||||
|
||||
@@ -7,17 +7,57 @@ error[E0277]: the type `UnsafeCell<mlua::lua::ExtraData>` may contain interior m
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: within `Lua`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<mlua::lua::ExtraData>`
|
||||
= note: required because it appears within the type `ArcInner<UnsafeCell<ExtraData>>`
|
||||
= note: required because it appears within the type `PhantomData<ArcInner<UnsafeCell<ExtraData>>>`
|
||||
= note: required because it appears within the type `Arc<UnsafeCell<ExtraData>>`
|
||||
= note: required because it appears within the type `LuaInner`
|
||||
= note: required because it appears within the type `ArcInner<LuaInner>`
|
||||
= note: required because it appears within the type `PhantomData<ArcInner<LuaInner>>`
|
||||
= note: required because it appears within the type `Arc<LuaInner>`
|
||||
= note: required because it appears within the type `Lua`
|
||||
note: required because it appears within the type `ArcInner<UnsafeCell<ExtraData>>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| struct ArcInner<T: ?Sized> {
|
||||
| ^^^^^^^^
|
||||
note: required because it appears within the type `PhantomData<ArcInner<UnsafeCell<ExtraData>>>`
|
||||
--> $RUST/core/src/marker.rs
|
||||
|
|
||||
| pub struct PhantomData<T: ?Sized>;
|
||||
| ^^^^^^^^^^^
|
||||
note: required because it appears within the type `Arc<UnsafeCell<ExtraData>>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| pub struct Arc<
|
||||
| ^^^
|
||||
note: required because it appears within the type `LuaInner`
|
||||
--> src/lua.rs
|
||||
|
|
||||
| pub struct LuaInner {
|
||||
| ^^^^^^^^
|
||||
note: required because it appears within the type `ArcInner<LuaInner>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| struct ArcInner<T: ?Sized> {
|
||||
| ^^^^^^^^
|
||||
note: required because it appears within the type `PhantomData<ArcInner<LuaInner>>`
|
||||
--> $RUST/core/src/marker.rs
|
||||
|
|
||||
| pub struct PhantomData<T: ?Sized>;
|
||||
| ^^^^^^^^^^^
|
||||
note: required because it appears within the type `Arc<LuaInner>`
|
||||
--> $RUST/alloc/src/sync.rs
|
||||
|
|
||||
| pub struct Arc<
|
||||
| ^^^
|
||||
note: required because it appears within the type `Lua`
|
||||
--> src/lua.rs
|
||||
|
|
||||
| pub struct Lua(Arc<LuaInner>);
|
||||
| ^^^
|
||||
= note: required for `&Lua` to implement `UnwindSafe`
|
||||
= note: required because it appears within the type `LuaRef<'_>`
|
||||
= note: required because it appears within the type `Table<'_>`
|
||||
note: required because it appears within the type `LuaRef<'_>`
|
||||
--> src/types.rs
|
||||
|
|
||||
| pub(crate) struct LuaRef<'lua> {
|
||||
| ^^^^^^
|
||||
note: required because it appears within the type `Table<'_>`
|
||||
--> src/table.rs
|
||||
|
|
||||
| pub struct Table<'lua>(pub(crate) LuaRef<'lua>);
|
||||
| ^^^^^
|
||||
note: required because it's used within this closure
|
||||
--> tests/compile/ref_nounwindsafe.rs:8:18
|
||||
|
|
||||
|
||||
@@ -4,6 +4,8 @@ error[E0597]: `ibad` does not live long enough
|
||||
11 | lua.scope(|scope| {
|
||||
| ----- has type `&mlua::Scope<'_, '1>`
|
||||
...
|
||||
14 | let ibad = 42;
|
||||
| ---- binding `ibad` declared here
|
||||
15 | scope.create_nonstatic_userdata(MyUserData(&ibad)).unwrap();
|
||||
| -------------------------------------------^^^^^--
|
||||
| | |
|
||||
|
||||
@@ -1,35 +1,31 @@
|
||||
error[E0597]: `lua` does not live long enough
|
||||
--> tests/compile/static_callback_args.rs:12:5
|
||||
|
|
||||
10 | let lua = Lua::new();
|
||||
| --- binding `lua` declared here
|
||||
10 | let lua = Lua::new();
|
||||
| --- binding `lua` declared here
|
||||
11 |
|
||||
12 | / lua.create_function(|_, table: Table| {
|
||||
13 | |/ BAD_TIME.with(|bt| {
|
||||
14 | || *bt.borrow_mut() = Some(table);
|
||||
15 | || });
|
||||
| ||__________- argument requires that `lua` is borrowed for `'static`
|
||||
16 | | Ok(())
|
||||
17 | | })?
|
||||
| |_______^ borrowed value does not live long enough
|
||||
12 | lua.create_function(|_, table: Table| {
|
||||
| ^^^ borrowed value does not live long enough
|
||||
13 | / BAD_TIME.with(|bt| {
|
||||
14 | | *bt.borrow_mut() = Some(table);
|
||||
15 | | });
|
||||
| |__________- argument requires that `lua` is borrowed for `'static`
|
||||
...
|
||||
32 | }
|
||||
| - `lua` dropped here while still borrowed
|
||||
32 | }
|
||||
| - `lua` dropped here while still borrowed
|
||||
|
||||
error[E0505]: cannot move out of `lua` because it is borrowed
|
||||
--> tests/compile/static_callback_args.rs:22:10
|
||||
|
|
||||
10 | let lua = Lua::new();
|
||||
| --- binding `lua` declared here
|
||||
10 | let lua = Lua::new();
|
||||
| --- binding `lua` declared here
|
||||
11 |
|
||||
12 | / lua.create_function(|_, table: Table| {
|
||||
13 | |/ BAD_TIME.with(|bt| {
|
||||
14 | || *bt.borrow_mut() = Some(table);
|
||||
15 | || });
|
||||
| ||__________- argument requires that `lua` is borrowed for `'static`
|
||||
16 | | Ok(())
|
||||
17 | | })?
|
||||
| |_______- borrow of `lua` occurs here
|
||||
12 | lua.create_function(|_, table: Table| {
|
||||
| --- borrow of `lua` occurs here
|
||||
13 | / BAD_TIME.with(|bt| {
|
||||
14 | | *bt.borrow_mut() = Some(table);
|
||||
15 | | });
|
||||
| |__________- argument requires that `lua` is borrowed for `'static`
|
||||
...
|
||||
22 | drop(lua);
|
||||
| ^^^ move out of `lua` occurs here
|
||||
22 | drop(lua);
|
||||
| ^^^ move out of `lua` occurs here
|
||||
|
||||
+233
-1
@@ -3,7 +3,239 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use maplit::{btreemap, btreeset, hashmap, hashset};
|
||||
use mlua::{Error, Lua, Result};
|
||||
use mlua::{AnyUserData, Error, Function, IntoLua, Lua, Result, Table, Thread, UserDataRef, Value};
|
||||
|
||||
#[test]
|
||||
fn test_string_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let s = lua.create_string("hello, world!")?;
|
||||
let s2 = (&s).into_lua(&lua)?;
|
||||
assert_eq!(s, s2.as_string().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("s", &s)?;
|
||||
assert_eq!(s, table.get::<_, String>("s")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
#[test]
|
||||
fn test_owned_string_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let s = lua.create_string("hello, world")?.into_owned();
|
||||
let s2 = (&s).into_lua(&lua)?;
|
||||
assert_eq!(s.to_ref(), *s2.as_string().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("s", &s)?;
|
||||
assert_eq!(s.to_ref(), table.get::<_, String>("s")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
#[test]
|
||||
fn test_owned_string_from_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let s = lua.unpack::<mlua::OwnedString>(lua.pack("hello, world")?)?;
|
||||
assert_eq!(s.to_ref(), "hello, world");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let t = lua.create_table()?;
|
||||
let t2 = (&t).into_lua(&lua)?;
|
||||
assert_eq!(&t, t2.as_table().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let f = lua.create_function(|_, (t, s): (Table, String)| t.set("s", s))?;
|
||||
f.call((&t, "hello"))?;
|
||||
assert_eq!("hello", t.get::<_, String>("s")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
#[test]
|
||||
fn test_owned_table_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let t = lua.create_table()?.into_owned();
|
||||
let t2 = (&t).into_lua(&lua)?;
|
||||
assert_eq!(t.to_ref(), *t2.as_table().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let f = lua.create_function(|_, (t, s): (Table, String)| t.set("s", s))?;
|
||||
f.call((&t, "hello"))?;
|
||||
assert_eq!("hello", t.to_ref().get::<_, String>("s")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_function_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let f = lua.create_function(|_, ()| Ok::<_, Error>(()))?;
|
||||
let f2 = (&f).into_lua(&lua)?;
|
||||
assert_eq!(&f, f2.as_function().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("f", &f)?;
|
||||
assert_eq!(f, table.get::<_, Function>("f")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
#[test]
|
||||
fn test_owned_function_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let f = lua
|
||||
.create_function(|_, ()| Ok::<_, Error>(()))?
|
||||
.into_owned();
|
||||
let f2 = (&f).into_lua(&lua)?;
|
||||
assert_eq!(f.to_ref(), *f2.as_function().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("f", &f)?;
|
||||
assert_eq!(f.to_ref(), table.get::<_, Function>("f")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_thread_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let f = lua.create_function(|_, ()| Ok::<_, Error>(()))?;
|
||||
let th = lua.create_thread(f)?;
|
||||
let th2 = (&th).into_lua(&lua)?;
|
||||
assert_eq!(&th, th2.as_thread().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("th", &th)?;
|
||||
assert_eq!(th, table.get::<_, Thread>("th")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
#[test]
|
||||
fn test_owned_thread_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let f = lua.create_function(|_, ()| Ok::<_, Error>(()))?;
|
||||
let th = lua.create_thread(f)?.into_owned();
|
||||
let th2 = (&th).into_lua(&lua)?;
|
||||
assert_eq!(&th.to_ref(), th2.as_thread().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("th", &th)?;
|
||||
assert_eq!(th.to_ref(), table.get::<_, Thread>("th")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
#[test]
|
||||
fn test_owned_thread_from_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let th = lua.unpack::<mlua::OwnedThread>(Value::Thread(lua.current_thread()))?;
|
||||
assert_eq!(th.to_ref(), lua.current_thread());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anyuserdata_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let ud = lua.create_any_userdata(String::from("hello"))?;
|
||||
let ud2 = (&ud).into_lua(&lua)?;
|
||||
assert_eq!(&ud, ud2.as_userdata().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("ud", &ud)?;
|
||||
assert_eq!(ud, table.get::<_, AnyUserData>("ud")?);
|
||||
assert_eq!("hello", *table.get::<_, UserDataRef<String>>("ud")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "send")))]
|
||||
#[test]
|
||||
fn test_owned_anyuserdata_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Direct conversion
|
||||
let ud = lua.create_any_userdata(String::from("hello"))?.into_owned();
|
||||
let ud2 = (&ud).into_lua(&lua)?;
|
||||
assert_eq!(ud.to_ref(), *ud2.as_userdata().unwrap());
|
||||
|
||||
// Push into stack
|
||||
let table = lua.create_table()?;
|
||||
table.set("ud", &ud)?;
|
||||
assert_eq!(ud.to_ref(), table.get::<_, AnyUserData>("ud")?);
|
||||
assert_eq!("hello", *table.get::<_, UserDataRef<String>>("ud")?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_registry_value_into_lua() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let t = lua.create_table()?;
|
||||
let r = lua.create_registry_value(t)?;
|
||||
let f = lua.create_function(|_, t: Table| t.raw_set("hello", "world"))?;
|
||||
|
||||
f.call(&r)?;
|
||||
let v = r.into_lua(&lua)?;
|
||||
let t = v.as_table().unwrap();
|
||||
assert_eq!(t.get::<_, String>("hello")?, "world");
|
||||
|
||||
// Try to set nil registry key
|
||||
let r_nil = lua.create_registry_value(Value::Nil)?;
|
||||
t.set("hello", &r_nil)?;
|
||||
assert_eq!(t.get::<_, Value>("hello")?, Value::Nil);
|
||||
|
||||
// Check non-owned registry key
|
||||
let lua2 = Lua::new();
|
||||
let r2 = lua2.create_registry_value("abc")?;
|
||||
assert!(matches!(
|
||||
f.call::<_, ()>(&r2),
|
||||
Err(Error::MismatchedRegistryKey)
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_conv_vec() -> Result<()> {
|
||||
|
||||
@@ -28,6 +28,12 @@ fn test_require() -> Result<()> {
|
||||
assert!(lua.globals().get::<_, Option<Value>>("require")?.is_none());
|
||||
assert!(lua.globals().get::<_, Option<Value>>("package")?.is_none());
|
||||
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
// TODO: figure out why emscripten fails on file operations
|
||||
// Also see https://github.com/rust-lang/rust/issues/119250
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
lua = Lua::new();
|
||||
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
@@ -59,7 +59,8 @@ fn test_module_from_thread() -> Result<()> {
|
||||
assert(mod.sum(a, b) == a + b)
|
||||
end)
|
||||
|
||||
coroutine.resume(co, 3, 5)
|
||||
local ok, err = coroutine.resume(co, 3, 5)
|
||||
assert(ok, err)
|
||||
collectgarbage()
|
||||
|
||||
assert(mod.used_memory() > 0)
|
||||
@@ -68,6 +69,29 @@ fn test_module_from_thread() -> Result<()> {
|
||||
.exec()
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "lua51"
|
||||
))]
|
||||
#[test]
|
||||
fn test_module_multi_from_thread() -> Result<()> {
|
||||
let lua = make_lua()?;
|
||||
lua.load(
|
||||
r#"
|
||||
local mod = require("test_module")
|
||||
local co = coroutine.create(function()
|
||||
local mod2 = require("test_module.second")
|
||||
assert(mod2.userdata ~= nil)
|
||||
end)
|
||||
local ok, err = coroutine.resume(co)
|
||||
assert(ok, err)
|
||||
"#,
|
||||
)
|
||||
.exec()
|
||||
}
|
||||
|
||||
fn make_lua() -> Result<Lua> {
|
||||
let (dylib_path, dylib_ext, separator);
|
||||
if cfg!(target_os = "macos") {
|
||||
|
||||
+1
-1
@@ -598,7 +598,7 @@ fn test_from_value_with_options() -> Result<(), Box<dyn StdError>> {
|
||||
|
||||
// Check recursion when using `Serialize` impl
|
||||
let t = lua.create_table()?;
|
||||
t.set("t", t.clone())?;
|
||||
t.set("t", &t)?;
|
||||
assert!(serde_json::to_string(&t).is_err());
|
||||
|
||||
// Serialize Lua globals table
|
||||
|
||||
+11
-2
@@ -73,13 +73,22 @@ fn test_static_lua_coroutine() -> Result<()> {
|
||||
async fn test_static_async() -> Result<()> {
|
||||
let lua = Lua::new().into_static();
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
async fn sleep_ms(ms: u64) {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(ms)).await;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
async fn sleep_ms(_ms: u64) {
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
|
||||
let timer =
|
||||
lua.create_async_function(|_, (i, n, f): (u64, u64, mlua::Function)| async move {
|
||||
tokio::task::spawn_local(async move {
|
||||
let dur = std::time::Duration::from_millis(i);
|
||||
for _ in 0..n {
|
||||
tokio::task::spawn_local(f.call_async::<(), ()>(()));
|
||||
tokio::time::sleep(dur).await;
|
||||
sleep_ms(i).await;
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
|
||||
+23
-11
@@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use std::iter::FromIterator;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::string::String as StdString;
|
||||
@@ -312,30 +313,29 @@ fn test_error() -> Result<()> {
|
||||
globals.set("rust_error_function", rust_error_function)?;
|
||||
|
||||
let no_error = globals.get::<_, Function>("no_error")?;
|
||||
let lua_error = globals.get::<_, Function>("lua_error")?;
|
||||
let rust_error = globals.get::<_, Function>("rust_error")?;
|
||||
let return_error = globals.get::<_, Function>("return_error")?;
|
||||
let return_string_error = globals.get::<_, Function>("return_string_error")?;
|
||||
let test_pcall = globals.get::<_, Function>("test_pcall")?;
|
||||
let understand_recursion = globals.get::<_, Function>("understand_recursion")?;
|
||||
|
||||
assert!(no_error.call::<_, ()>(()).is_ok());
|
||||
|
||||
let lua_error = globals.get::<_, Function>("lua_error")?;
|
||||
match lua_error.call::<_, ()>(()) {
|
||||
Err(Error::RuntimeError(_)) => {}
|
||||
Err(e) => panic!("error is not RuntimeError kind, got {:?}", e),
|
||||
_ => panic!("error not returned"),
|
||||
}
|
||||
|
||||
let rust_error = globals.get::<_, Function>("rust_error")?;
|
||||
match rust_error.call::<_, ()>(()) {
|
||||
Err(Error::CallbackError { .. }) => {}
|
||||
Err(e) => panic!("error is not CallbackError kind, got {:?}", e),
|
||||
_ => panic!("error not returned"),
|
||||
}
|
||||
|
||||
let return_error = globals.get::<_, Function>("return_error")?;
|
||||
match return_error.call::<_, Value>(()) {
|
||||
Ok(Value::Error(_)) => {}
|
||||
_ => panic!("Value::Error not returned"),
|
||||
}
|
||||
|
||||
let return_string_error = globals.get::<_, Function>("return_string_error")?;
|
||||
assert!(return_string_error.call::<_, Error>(()).is_ok());
|
||||
|
||||
match lua
|
||||
@@ -358,9 +358,14 @@ fn test_error() -> Result<()> {
|
||||
_ => panic!("error not returned"),
|
||||
}
|
||||
|
||||
let test_pcall = globals.get::<_, Function>("test_pcall")?;
|
||||
test_pcall.call::<_, ()>(())?;
|
||||
|
||||
assert!(understand_recursion.call::<_, ()>(()).is_err());
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
let understand_recursion = globals.get::<_, Function>("understand_recursion")?;
|
||||
assert!(understand_recursion.call::<_, ()>(()).is_err());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -947,6 +952,7 @@ fn test_application_data() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn test_recursion() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
@@ -959,21 +965,23 @@ fn test_recursion() -> Result<()> {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
lua.globals().set("f", f.clone())?;
|
||||
lua.globals().set("f", &f)?;
|
||||
f.call::<_, ()>(1)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn test_too_many_returns() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
let f = lua.create_function(|_, ()| Ok(Variadic::from_iter(1..1000000)))?;
|
||||
assert!(f.call::<_, Vec<u32>>(()).is_err());
|
||||
assert!(f.call::<_, Variadic<u32>>(()).is_err());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn test_too_many_arguments() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
lua.load("function test(...) end").exec()?;
|
||||
@@ -988,19 +996,21 @@ fn test_too_many_arguments() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "luajit"))]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn test_too_many_recursions() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let f = lua
|
||||
.create_function(move |lua, ()| lua.globals().get::<_, Function>("f")?.call::<_, ()>(()))?;
|
||||
|
||||
lua.globals().set("f", f.clone())?;
|
||||
lua.globals().set("f", &f)?;
|
||||
assert!(f.call::<_, ()>(()).is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn test_too_many_binds() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
@@ -1022,6 +1032,7 @@ fn test_too_many_binds() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn test_ref_stack_exhaustion() {
|
||||
match catch_unwind(AssertUnwindSafe(|| -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
@@ -1351,6 +1362,7 @@ fn test_luajit_cdata() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "send")]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn test_send() {
|
||||
let lua = Lua::new();
|
||||
std::thread::spawn(move || {
|
||||
|
||||
+1
-1
@@ -182,7 +182,7 @@ fn test_coroutine_panic() {
|
||||
let thrd_main = lua.create_function(|_, ()| -> Result<()> {
|
||||
panic!("test_panic");
|
||||
})?;
|
||||
lua.globals().set("main", thrd_main.clone())?;
|
||||
lua.globals().set("main", &thrd_main)?;
|
||||
let thrd: Thread = lua.create_thread(thrd_main)?;
|
||||
thrd.resume(())
|
||||
}) {
|
||||
|
||||
+5
-5
@@ -58,7 +58,7 @@ fn test_methods() -> Result<()> {
|
||||
|
||||
fn check_methods(lua: &Lua, userdata: AnyUserData) -> Result<()> {
|
||||
let globals = lua.globals();
|
||||
globals.set("userdata", userdata.clone())?;
|
||||
globals.set("userdata", &userdata)?;
|
||||
lua.load(
|
||||
r#"
|
||||
function get_it()
|
||||
@@ -342,7 +342,7 @@ fn test_userdata_take() -> Result<()> {
|
||||
}
|
||||
|
||||
fn check_userdata_take(lua: &Lua, userdata: AnyUserData, rc: Arc<i64>) -> Result<()> {
|
||||
lua.globals().set("userdata", userdata.clone())?;
|
||||
lua.globals().set("userdata", &userdata)?;
|
||||
assert_eq!(Arc::strong_count(&rc), 3);
|
||||
{
|
||||
let _value = userdata.borrow::<MyUserdata>()?;
|
||||
@@ -474,7 +474,7 @@ fn test_functions() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
let userdata = lua.create_userdata(MyUserData(42))?;
|
||||
globals.set("userdata", userdata.clone())?;
|
||||
globals.set("userdata", &userdata)?;
|
||||
lua.load(
|
||||
r#"
|
||||
function get_it()
|
||||
@@ -991,9 +991,9 @@ fn test_userdata_derive() -> Result<()> {
|
||||
// More complex struct where generics and where clause
|
||||
|
||||
#[derive(Clone, Copy, mlua::FromLua)]
|
||||
struct MyUserData2<'a, T>(&'a T)
|
||||
struct MyUserData2<'a, T: ?Sized>(&'a T)
|
||||
where
|
||||
T: ?Sized;
|
||||
T: Copy;
|
||||
|
||||
lua.register_userdata_type::<MyUserData2<'static, i32>>(|reg| {
|
||||
reg.add_function("val", |_, this: MyUserData2<'static, i32>| Ok(*this.0));
|
||||
|
||||
Reference in New Issue
Block a user