mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cb1ac28f2a | |||
| 3e7f25670a | |||
| 0d404ce4c3 | |||
| e26cec5db9 | |||
| 0bd36b42e7 | |||
| e0da6ac929 | |||
| 0c7db4916c | |||
| b9589491e4 | |||
| 58cb371f06 | |||
| 8add60b019 | |||
| c363fb9288 | |||
| 3900e23839 | |||
| 726fde7e1f | |||
| 7cb9c4f39c |
@@ -20,4 +20,4 @@ jobs:
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
token: ${{secrets.CODECOV_TOKEN}}
|
||||
fail_ci_if_error: true
|
||||
fail_ci_if_error: false
|
||||
|
||||
@@ -123,7 +123,6 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
- name: Run ${{ matrix.lua }} tests
|
||||
if: ${{ matrix.os != 'macos-latest' || matrix.lua != 'luajit' }}
|
||||
run: |
|
||||
cargo test --release --features "${{ matrix.lua }} vendored"
|
||||
cargo test --release --features "${{ matrix.lua }} vendored async send serialize"
|
||||
@@ -135,27 +134,6 @@ jobs:
|
||||
TRYBUILD=overwrite cargo test --release --features "${{ matrix.lua }} vendored async send serialize" -- --ignored
|
||||
shell: bash
|
||||
|
||||
test_luajit_macos:
|
||||
name: Test LuaJIT on macOS
|
||||
runs-on: macos-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
target: x86_64-apple-darwin
|
||||
override: true
|
||||
- name: Run LuaJIT 2.0.5 tests
|
||||
run: |
|
||||
brew install luajit
|
||||
cargo test --tests --release --features "luajit async send serialize" -- --test-threads=1
|
||||
shell: bash
|
||||
- name: Run LuaJIT vendored tests
|
||||
run: |
|
||||
cargo test --release --features "luajit vendored async send serialize"
|
||||
shell: bash
|
||||
|
||||
test_modules:
|
||||
name: Test modules
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
## v0.5.4
|
||||
|
||||
- Build script improvements
|
||||
- Improvements in panic handling (resume panic on value popping)
|
||||
- Fixed bug serializing 3rd party userdata (causes segfault)
|
||||
- Make error::Error non exhaustive
|
||||
|
||||
## v0.5.3
|
||||
|
||||
- Fixed bug when returning nil-prefixed multi values from async function (+ test)
|
||||
- Performance optimisation for async callbacks (polling)
|
||||
|
||||
## v0.5.2
|
||||
|
||||
- Some performance optimisations (callbacks)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua"
|
||||
version = "0.5.2" # remember to update html_root_url and mlua_derive
|
||||
version = "0.5.4" # remember to update html_root_url and mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@chucklefish.org>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/khvzak/mlua"
|
||||
|
||||
+5
-13
@@ -1,18 +1,7 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio::task;
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
@@ -117,7 +106,10 @@ fn call_sum_callback(c: &mut Criterion) {
|
||||
fn call_async_sum_callback(c: &mut Criterion) {
|
||||
let lua = Lua::new();
|
||||
let callback = lua
|
||||
.create_async_function(|_, (a, b, c): (i64, i64, i64)| async move { Ok(a + b + c) })
|
||||
.create_async_function(|_, (a, b, c): (i64, i64, i64)| async move {
|
||||
task::yield_now().await;
|
||||
Ok(a + b + c)
|
||||
})
|
||||
.unwrap();
|
||||
lua.globals().set("callback", callback).unwrap();
|
||||
|
||||
|
||||
+27
-46
@@ -1,13 +1,19 @@
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Result};
|
||||
use std::ops::Bound;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn get_env_var(name: &str) -> String {
|
||||
match env::var(name) {
|
||||
Ok(val) => val,
|
||||
Err(env::VarError::NotPresent) => String::new(),
|
||||
Err(err) => panic!("cannot get {}: {}", name, err),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn probe_lua() -> PathBuf {
|
||||
let include_dir = env::var_os("LUA_INC").unwrap_or_default();
|
||||
let lib_dir = env::var_os("LUA_LIB").unwrap_or_default();
|
||||
let lua_lib = env::var_os("LUA_LIB_NAME").unwrap_or_default();
|
||||
let include_dir = get_env_var("LUA_INC");
|
||||
let lib_dir = get_env_var("LUA_LIB");
|
||||
let lua_lib = get_env_var("LUA_LIB_NAME");
|
||||
|
||||
println!("cargo:rerun-if-env-changed=LUA_INC");
|
||||
println!("cargo:rerun-if-env-changed=LUA_LIB");
|
||||
@@ -16,11 +22,22 @@ pub fn probe_lua() -> PathBuf {
|
||||
|
||||
let need_lua_lib = cfg!(any(not(feature = "module"), target_os = "windows"));
|
||||
|
||||
if include_dir != "" && (!need_lua_lib || lib_dir != "") {
|
||||
if lua_lib == "" {
|
||||
panic!("LUA_LIB_NAME is not set");
|
||||
if include_dir != "" {
|
||||
if need_lua_lib {
|
||||
if lib_dir == "" {
|
||||
panic!("LUA_LIB is not set");
|
||||
}
|
||||
if lua_lib == "" {
|
||||
panic!("LUA_LIB_NAME is not set");
|
||||
}
|
||||
|
||||
let mut link_lib = "";
|
||||
if get_env_var("LUA_LINK") == "static" {
|
||||
link_lib = "static=";
|
||||
};
|
||||
println!("cargo:rustc-link-search=native={}", lib_dir);
|
||||
println!("cargo:rustc-link-lib={}{}", link_lib, lua_lib);
|
||||
}
|
||||
let _version = use_custom_lua(&include_dir, &lib_dir, &lua_lib).unwrap();
|
||||
return PathBuf::from(include_dir);
|
||||
}
|
||||
|
||||
@@ -100,39 +117,3 @@ pub fn probe_lua() -> PathBuf {
|
||||
lua.unwrap().include_paths[0].clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn use_custom_lua<S: AsRef<Path>>(include_dir: &S, lib_dir: &S, lua_lib: &S) -> Result<String> {
|
||||
let mut version_found = String::new();
|
||||
|
||||
// Find LUA_VERSION_NUM
|
||||
let mut lua_h_path = include_dir.as_ref().to_owned();
|
||||
lua_h_path.push("lua.h");
|
||||
let f = File::open(lua_h_path)?;
|
||||
let reader = BufReader::new(f);
|
||||
for line in reader.lines() {
|
||||
let line = line?;
|
||||
let parts = line.split_whitespace().collect::<Vec<_>>();
|
||||
if parts.len() == 3 && parts[1] == "LUA_VERSION_NUM" {
|
||||
version_found = parts[2].to_string();
|
||||
}
|
||||
}
|
||||
|
||||
let link_lib = match env::var("LUA_LINK") {
|
||||
Ok(s) if s == "static" => "static=",
|
||||
_ => "",
|
||||
};
|
||||
|
||||
if cfg!(any(not(feature = "module"), target_os = "windows")) {
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
lib_dir.as_ref().display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-link-lib={}{}",
|
||||
link_lib,
|
||||
lua_lib.as_ref().display()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(version_found)
|
||||
}
|
||||
|
||||
@@ -236,5 +236,8 @@ fn main() {
|
||||
generate_glue().unwrap();
|
||||
} else {
|
||||
build_glue(&include_dir);
|
||||
println!("cargo:rerun-if-changed=src/ffi/glue/glue.c");
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed=build");
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use std::sync::Arc;
|
||||
|
||||
/// Error type returned by `mlua` methods.
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// Syntax error while parsing Lua source code.
|
||||
SyntaxError {
|
||||
@@ -139,6 +140,11 @@ pub enum Error {
|
||||
/// Original error returned by the Rust code.
|
||||
cause: Arc<Error>,
|
||||
},
|
||||
/// A Rust panic that was previosly resumed, returned again.
|
||||
///
|
||||
/// This error can occur only when a Rust panic resumed previously was recovered
|
||||
/// and returned again.
|
||||
PreviouslyResumedPanic,
|
||||
/// Serialization error.
|
||||
#[cfg(feature = "serialize")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
|
||||
@@ -230,6 +236,9 @@ impl fmt::Display for Error {
|
||||
Error::CallbackError { ref traceback, .. } => {
|
||||
write!(fmt, "callback error: {}", traceback)
|
||||
}
|
||||
Error::PreviouslyResumedPanic => {
|
||||
write!(fmt, "previously resumed panic returned again")
|
||||
}
|
||||
#[cfg(feature = "serialize")]
|
||||
Error::SerializeError(ref err) => {
|
||||
write!(fmt, "serialize error: {}", err)
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@
|
||||
//! [`serde::Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
|
||||
|
||||
// mlua types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/mlua/0.5.2")]
|
||||
#![doc(html_root_url = "https://docs.rs/mlua/0.5.4")]
|
||||
// Deny warnings inside doc tests / examples. When this isn't present, rustdoc doesn't show *any*
|
||||
// warnings at all.
|
||||
#![doc(test(attr(deny(warnings))))]
|
||||
|
||||
+80
-41
@@ -1,9 +1,10 @@
|
||||
use std::any::TypeId;
|
||||
use std::cell::{RefCell, UnsafeCell};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::CString;
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::panic::resume_unwind;
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
use std::{mem, ptr, str};
|
||||
|
||||
@@ -25,7 +26,7 @@ use crate::util::{
|
||||
assert_stack, callback_error, check_stack, get_gc_userdata, get_main_state, get_userdata,
|
||||
get_wrapped_error, init_error_registry, init_gc_metatable_for, init_userdata_metatable,
|
||||
pop_error, protect_lua, protect_lua_closure, push_gc_userdata, push_meta_gc_userdata,
|
||||
push_string, push_userdata, push_wrapped_error, StackGuard,
|
||||
push_string, push_userdata, push_wrapped_error, StackGuard, WrappedPanic,
|
||||
};
|
||||
use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
||||
|
||||
@@ -57,6 +58,7 @@ pub struct Lua {
|
||||
// Data associated with the lua_State.
|
||||
struct ExtraData {
|
||||
registered_userdata: HashMap<TypeId, c_int>,
|
||||
registered_userdata_mt: HashSet<isize>,
|
||||
registry_unref_list: Arc<Mutex<Option<Vec<c_int>>>>,
|
||||
|
||||
libs: StdLib,
|
||||
@@ -321,6 +323,7 @@ impl Lua {
|
||||
|
||||
let extra = Arc::new(Mutex::new(ExtraData {
|
||||
registered_userdata: HashMap::new(),
|
||||
registered_userdata_mt: HashSet::new(),
|
||||
registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))),
|
||||
ref_thread,
|
||||
libs: StdLib::NONE,
|
||||
@@ -1402,32 +1405,33 @@ impl Lua {
|
||||
|
||||
// Uses 2 stack spaces, does not call checkstack
|
||||
pub(crate) unsafe fn pop_value(&self) -> Value {
|
||||
match ffi::lua_type(self.state, -1) {
|
||||
let state = self.state;
|
||||
match ffi::lua_type(state, -1) {
|
||||
ffi::LUA_TNIL => {
|
||||
ffi::lua_pop(self.state, 1);
|
||||
ffi::lua_pop(state, 1);
|
||||
Nil
|
||||
}
|
||||
|
||||
ffi::LUA_TBOOLEAN => {
|
||||
let b = Value::Boolean(ffi::lua_toboolean(self.state, -1) != 0);
|
||||
ffi::lua_pop(self.state, 1);
|
||||
let b = Value::Boolean(ffi::lua_toboolean(state, -1) != 0);
|
||||
ffi::lua_pop(state, 1);
|
||||
b
|
||||
}
|
||||
|
||||
ffi::LUA_TLIGHTUSERDATA => {
|
||||
let ud = Value::LightUserData(LightUserData(ffi::lua_touserdata(self.state, -1)));
|
||||
ffi::lua_pop(self.state, 1);
|
||||
let ud = Value::LightUserData(LightUserData(ffi::lua_touserdata(state, -1)));
|
||||
ffi::lua_pop(state, 1);
|
||||
ud
|
||||
}
|
||||
|
||||
ffi::LUA_TNUMBER => {
|
||||
if ffi::lua_isinteger(self.state, -1) != 0 {
|
||||
let i = Value::Integer(ffi::lua_tointeger(self.state, -1));
|
||||
ffi::lua_pop(self.state, 1);
|
||||
if ffi::lua_isinteger(state, -1) != 0 {
|
||||
let i = Value::Integer(ffi::lua_tointeger(state, -1));
|
||||
ffi::lua_pop(state, 1);
|
||||
i
|
||||
} else {
|
||||
let n = Value::Number(ffi::lua_tonumber(self.state, -1));
|
||||
ffi::lua_pop(self.state, 1);
|
||||
let n = Value::Number(ffi::lua_tonumber(state, -1));
|
||||
ffi::lua_pop(state, 1);
|
||||
n
|
||||
}
|
||||
}
|
||||
@@ -1439,12 +1443,20 @@ impl Lua {
|
||||
ffi::LUA_TFUNCTION => Value::Function(Function(self.pop_ref())),
|
||||
|
||||
ffi::LUA_TUSERDATA => {
|
||||
// It should not be possible to interact with userdata types other than custom
|
||||
// UserData types OR a WrappedError. WrappedPanic should not be here.
|
||||
if let Some(err) = get_wrapped_error(self.state, -1).as_ref() {
|
||||
// We must prevent interaction with userdata types other than UserData OR a WrappedError.
|
||||
// WrappedPanics are automatically resumed.
|
||||
if let Some(err) = get_wrapped_error(state, -1).as_ref() {
|
||||
let err = err.clone();
|
||||
ffi::lua_pop(self.state, 1);
|
||||
ffi::lua_pop(state, 1);
|
||||
Value::Error(err)
|
||||
} else if let Some(panic) = get_gc_userdata::<WrappedPanic>(state, -1).as_mut() {
|
||||
if let Some(panic) = (*panic).0.take() {
|
||||
ffi::lua_pop(state, 1);
|
||||
resume_unwind(panic);
|
||||
}
|
||||
// Previously resumed panic?
|
||||
ffi::lua_pop(state, 1);
|
||||
Nil
|
||||
} else {
|
||||
Value::UserData(AnyUserData(self.pop_ref()))
|
||||
}
|
||||
@@ -1559,34 +1571,52 @@ impl Lua {
|
||||
ffi::lua_pop(self.state, 1);
|
||||
}
|
||||
|
||||
let ptr = ffi::lua_topointer(self.state, -1);
|
||||
let id = protect_lua_closure(self.state, 1, 0, |state| {
|
||||
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
|
||||
})?;
|
||||
|
||||
let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned");
|
||||
extra.registered_userdata.insert(type_id, id);
|
||||
extra.registered_userdata_mt.insert(ptr as isize);
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
// Pushes a LuaRef value onto the stack, checking that it's not destructed
|
||||
pub(crate) fn register_userdata_metatable(&self, id: isize) {
|
||||
let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned");
|
||||
extra.registered_userdata_mt.insert(id);
|
||||
}
|
||||
|
||||
pub(crate) fn deregister_userdata_metatable(&self, id: isize) {
|
||||
let mut extra = mlua_expect!(self.extra.lock(), "extra is poisoned");
|
||||
extra.registered_userdata_mt.remove(&id);
|
||||
}
|
||||
|
||||
// Pushes a LuaRef value onto the stack, checking that it's a registered
|
||||
// and not destructed UserData.
|
||||
// Uses 2 stack spaces, does not call checkstack
|
||||
#[cfg(feature = "serialize")]
|
||||
pub(crate) unsafe fn push_userdata_ref(&self, lref: &LuaRef) -> Result<()> {
|
||||
self.push_ref(lref);
|
||||
if ffi::lua_getmetatable(self.state, -1) == 0 {
|
||||
Err(Error::UserDataTypeMismatch)
|
||||
} else {
|
||||
// Check that userdata is not destructed
|
||||
get_destructed_userdata_metatable(self.state);
|
||||
let eq = ffi::lua_rawequal(self.state, -1, -2) == 1;
|
||||
ffi::lua_pop(self.state, 2);
|
||||
if eq {
|
||||
Err(Error::UserDataDestructed)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
return Err(Error::UserDataTypeMismatch);
|
||||
}
|
||||
// Check that userdata is registered
|
||||
let ptr = ffi::lua_topointer(self.state, -1);
|
||||
let extra = mlua_expect!(self.extra.lock(), "extra is poisoned");
|
||||
if extra.registered_userdata_mt.contains(&(ptr as isize)) {
|
||||
ffi::lua_pop(self.state, 1);
|
||||
return Ok(());
|
||||
}
|
||||
// Maybe userdata was destructed?
|
||||
get_destructed_userdata_metatable(self.state);
|
||||
if ffi::lua_rawequal(self.state, -1, -2) != 0 {
|
||||
ffi::lua_pop(self.state, 2);
|
||||
return Err(Error::UserDataDestructed);
|
||||
}
|
||||
ffi::lua_pop(self.state, 2);
|
||||
Err(Error::UserDataTypeMismatch)
|
||||
}
|
||||
|
||||
// Creates a Function out of a Callback containing a 'static Fn. This is safe ONLY because the
|
||||
@@ -1735,17 +1765,19 @@ impl Lua {
|
||||
|
||||
match (*fut).as_mut().poll(&mut ctx) {
|
||||
Poll::Pending => {
|
||||
check_stack(state, 6)?;
|
||||
check_stack(state, 1)?;
|
||||
ffi::lua_pushboolean(state, 0);
|
||||
push_gc_userdata(state, AsyncPollPending)?;
|
||||
Ok(2)
|
||||
Ok(1)
|
||||
}
|
||||
Poll::Ready(results) => {
|
||||
let results = lua.create_sequence_from(results?)?;
|
||||
check_stack(state, 2)?;
|
||||
let results = results?;
|
||||
let nresults = results.len() as Integer;
|
||||
let results = lua.create_sequence_from(results)?;
|
||||
check_stack(state, 3)?;
|
||||
ffi::lua_pushboolean(state, 1);
|
||||
lua.push_value(Value::Table(results))?;
|
||||
Ok(2)
|
||||
lua.push_value(Value::Integer(nresults))?;
|
||||
Ok(3)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1772,24 +1804,31 @@ impl Lua {
|
||||
env.set("yield", coroutine.get::<_, Function>("yield")?)?;
|
||||
env.set(
|
||||
"unpack",
|
||||
self.create_function(|_, tbl: Table| {
|
||||
self.create_function(|_, (tbl, len): (Table, Integer)| {
|
||||
Ok(MultiValue::from_vec(
|
||||
tbl.sequence_values().collect::<Result<Vec<Value>>>()?,
|
||||
tbl.raw_sequence_values_by_len(Some(len))
|
||||
.collect::<Result<Vec<Value>>>()?,
|
||||
))
|
||||
})?,
|
||||
)?;
|
||||
env.set("pending", unsafe {
|
||||
let _sg = StackGuard::new(self.state);
|
||||
check_stack(self.state, 5)?;
|
||||
push_gc_userdata(self.state, AsyncPollPending)?;
|
||||
self.pop_value()
|
||||
})?;
|
||||
|
||||
// We set `poll` variable in the env table to be able to destroy upvalues
|
||||
self.load(
|
||||
r#"
|
||||
poll = get_poll(...)
|
||||
local poll, yield, unpack = poll, yield, unpack
|
||||
local poll, pending, yield, unpack = poll, pending, yield, unpack
|
||||
while true do
|
||||
ready, res = poll()
|
||||
local ready, res, nres = poll()
|
||||
if ready then
|
||||
return unpack(res)
|
||||
return unpack(res, nres)
|
||||
end
|
||||
yield(res)
|
||||
yield(pending)
|
||||
end
|
||||
"#,
|
||||
)
|
||||
|
||||
+16
-2
@@ -312,7 +312,8 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 6);
|
||||
|
||||
push_userdata(lua.state, ())?;
|
||||
// We need to wrap dummy userdata because their memory can be accessed by serializer
|
||||
push_userdata(lua.state, UserDataCell::new(UserDataWrapped::new(())))?;
|
||||
#[cfg(any(feature = "lua54", feature = "lua53"))]
|
||||
ffi::lua_pushlightuserdata(lua.state, data.as_ptr() as *mut c_void);
|
||||
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
|
||||
@@ -355,9 +356,22 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||
ffi::lua_pop(lua.state, 1);
|
||||
}
|
||||
|
||||
let mt_id = ffi::lua_topointer(lua.state, -1);
|
||||
ffi::lua_setmetatable(lua.state, -2);
|
||||
|
||||
Ok(AnyUserData(lua.pop_ref()))
|
||||
let ud = AnyUserData(lua.pop_ref());
|
||||
lua.register_userdata_metatable(mt_id as isize);
|
||||
self.destructors.borrow_mut().push((ud.0.clone(), |ud| {
|
||||
let state = ud.lua.state;
|
||||
assert_stack(state, 2);
|
||||
ud.lua.push_ref(&ud);
|
||||
ffi::lua_getmetatable(state, -1);
|
||||
let mt_id = ffi::lua_topointer(state, -1);
|
||||
ffi::lua_pop(state, 1);
|
||||
ud.lua.deregister_userdata_metatable(mt_id as isize);
|
||||
vec![Box::new(take_userdata::<UserDataCell<()>>(state))]
|
||||
}));
|
||||
Ok(ud)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -474,9 +474,12 @@ impl<'lua> Table<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
pub(crate) fn raw_sequence_values_by_len<V: FromLua<'lua>>(self) -> TableSequence<'lua, V> {
|
||||
let len = self.raw_len();
|
||||
#[cfg(any(feature = "async", feature = "serialize"))]
|
||||
pub(crate) fn raw_sequence_values_by_len<V: FromLua<'lua>>(
|
||||
self,
|
||||
len: Option<Integer>,
|
||||
) -> TableSequence<'lua, V> {
|
||||
let len = len.unwrap_or_else(|| self.raw_len());
|
||||
TableSequence {
|
||||
table: self.0,
|
||||
index: Some(1),
|
||||
@@ -641,7 +644,7 @@ impl<'lua> Serialize for Table<'lua> {
|
||||
let len = self.raw_len() as usize;
|
||||
if len > 0 || self.is_array() {
|
||||
let mut seq = serializer.serialize_seq(Some(len))?;
|
||||
for v in self.clone().raw_sequence_values_by_len::<Value>() {
|
||||
for v in self.clone().raw_sequence_values_by_len::<Value>(None) {
|
||||
let v = v.map_err(serde::ser::Error::custom)?;
|
||||
seq.serialize_element(&v)?;
|
||||
}
|
||||
|
||||
+11
-16
@@ -186,7 +186,7 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
|
||||
if let Some(p) = (*panic).0.take() {
|
||||
resume_unwind(p);
|
||||
} else {
|
||||
mlua_panic!("error during panic handling, panic was resumed twice")
|
||||
Error::PreviouslyResumedPanic
|
||||
}
|
||||
} else {
|
||||
let err_string = to_string(state, -1).into_owned();
|
||||
@@ -587,27 +587,22 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) {
|
||||
Ok(err_buf)
|
||||
} else if let Some(panic) = get_gc_userdata::<WrappedPanic>(state, -1).as_ref() {
|
||||
if let Some(ref p) = (*panic).0 {
|
||||
ffi::lua_pushlightuserdata(
|
||||
state,
|
||||
&ERROR_PRINT_BUFFER_KEY as *const u8 as *mut c_void,
|
||||
);
|
||||
ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
|
||||
let err_buf_key = &ERROR_PRINT_BUFFER_KEY as *const u8 as *const c_void;
|
||||
ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, err_buf_key);
|
||||
let err_buf = ffi::lua_touserdata(state, -1) as *mut String;
|
||||
(*err_buf).clear();
|
||||
ffi::lua_pop(state, 2);
|
||||
|
||||
let error = if let Some(x) = p.downcast_ref::<&str>() {
|
||||
x.to_string()
|
||||
} else if let Some(x) = p.downcast_ref::<String>() {
|
||||
x.to_string()
|
||||
if let Some(msg) = p.downcast_ref::<&str>() {
|
||||
let _ = write!(&mut (*err_buf), "{}", msg);
|
||||
} else if let Some(msg) = p.downcast_ref::<String>() {
|
||||
let _ = write!(&mut (*err_buf), "{}", msg);
|
||||
} else {
|
||||
"panic".to_string()
|
||||
let _ = write!(&mut (*err_buf), "<panic>");
|
||||
};
|
||||
|
||||
(*err_buf).clear();
|
||||
let _ = write!(&mut (*err_buf), "{}", error);
|
||||
Ok(err_buf)
|
||||
} else {
|
||||
mlua_panic!("error during panic handling, panic was resumed")
|
||||
Err(Error::PreviouslyResumedPanic)
|
||||
}
|
||||
} else {
|
||||
// I'm not sure whether this is possible to trigger without bugs in mlua?
|
||||
@@ -721,7 +716,7 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) {
|
||||
}
|
||||
|
||||
struct WrappedError(pub Error);
|
||||
struct WrappedPanic(pub Option<Box<dyn Any + Send + 'static>>);
|
||||
pub(crate) struct WrappedPanic(pub Option<Box<dyn Any + Send + 'static>>);
|
||||
|
||||
// Converts the given lua value to a string in a reasonable format without causing a Lua error or
|
||||
// panicking.
|
||||
|
||||
+18
-11
@@ -1,15 +1,4 @@
|
||||
#![cfg(feature = "async")]
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
@@ -136,6 +125,24 @@ async fn test_async_handle_yield() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_multi_return_nil() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
lua.globals().set(
|
||||
"func",
|
||||
lua.create_async_function(|_, _: ()| async { Ok((Option::<String>::None, "error")) })?,
|
||||
)?;
|
||||
|
||||
lua.load(
|
||||
r#"
|
||||
local ok, err = func()
|
||||
assert(err == "error")
|
||||
"#,
|
||||
)
|
||||
.exec_async()
|
||||
.await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_return_async_closure() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use bstr::{BStr, BString};
|
||||
use mlua::{Lua, Result};
|
||||
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use mlua::{Function, Lua, Result, String};
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Deref;
|
||||
use std::str;
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use mlua::{Lua, Result, UserData};
|
||||
|
||||
+51
-16
@@ -1,19 +1,9 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use mlua::{Error, Function, Lua, MetaMethod, Result, String, UserData, UserDataMethods};
|
||||
use mlua::{
|
||||
AnyUserData, Error, Function, Lua, MetaMethod, Result, String, UserData, UserDataMethods,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn scope_func() -> Result<()> {
|
||||
@@ -57,17 +47,62 @@ fn scope_drop() -> Result<()> {
|
||||
|
||||
lua.scope(|scope| {
|
||||
lua.globals()
|
||||
.set("test", scope.create_userdata(MyUserdata(rc.clone()))?)?;
|
||||
.set("static_ud", scope.create_userdata(MyUserdata(rc.clone()))?)?;
|
||||
assert_eq!(Rc::strong_count(&rc), 2);
|
||||
Ok(())
|
||||
})?;
|
||||
assert_eq!(Rc::strong_count(&rc), 1);
|
||||
|
||||
match lua.load("test:method()").exec() {
|
||||
Err(Error::CallbackError { .. }) => {}
|
||||
match lua.load("static_ud:method()").exec() {
|
||||
Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() {
|
||||
Error::CallbackDestructed => {}
|
||||
e => panic!("expected CallbackDestructed, got {:?}", e),
|
||||
},
|
||||
r => panic!("improper return for destructed userdata: {:?}", r),
|
||||
};
|
||||
|
||||
let static_ud = lua.globals().get::<_, AnyUserData>("static_ud")?;
|
||||
match static_ud.borrow::<MyUserdata>() {
|
||||
Ok(_) => panic!("borrowed destructed userdata"),
|
||||
Err(Error::UserDataDestructed) => {}
|
||||
Err(e) => panic!("expected UserDataDestructed, got {:?}", e),
|
||||
}
|
||||
|
||||
// Check non-static UserData drop
|
||||
struct MyUserDataRef<'a>(&'a Cell<i64>);
|
||||
|
||||
impl<'a> UserData for MyUserDataRef<'a> {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("inc", |_, data, ()| {
|
||||
data.0.set(data.0.get() + 1);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let i = Cell::new(1);
|
||||
lua.scope(|scope| {
|
||||
lua.globals().set(
|
||||
"nonstatic_ud",
|
||||
scope.create_nonstatic_userdata(MyUserDataRef(&i))?,
|
||||
)
|
||||
})?;
|
||||
|
||||
match lua.load("nonstatic_ud:inc(1)").exec() {
|
||||
Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() {
|
||||
Error::CallbackDestructed => {}
|
||||
e => panic!("expected CallbackDestructed, got {:?}", e),
|
||||
},
|
||||
r => panic!("improper return for destructed userdata: {:?}", r),
|
||||
};
|
||||
|
||||
let nonstatic_ud = lua.globals().get::<_, AnyUserData>("nonstatic_ud")?;
|
||||
match nonstatic_ud.borrow::<MyUserDataRef>() {
|
||||
Ok(_) => panic!("borrowed destructed userdata"),
|
||||
Err(Error::UserDataDestructed) => {}
|
||||
Err(e) => panic!("expected UserDataDestructed, got {:?}", e),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+18
-16
@@ -1,15 +1,4 @@
|
||||
#![cfg(feature = "serialize")]
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use mlua::{Error, Lua, LuaSerdeExt, Result as LuaResult, UserData, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -19,7 +8,7 @@ fn test_serialize() -> Result<(), Box<dyn std::error::Error>> {
|
||||
#[derive(Serialize)]
|
||||
struct MyUserData(i64, String);
|
||||
|
||||
impl UserData for MyUserData {};
|
||||
impl UserData for MyUserData {}
|
||||
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
@@ -81,7 +70,7 @@ fn test_serialize_in_scope() -> LuaResult<()> {
|
||||
#[derive(Serialize, Clone)]
|
||||
struct MyUserData(i64, String);
|
||||
|
||||
impl UserData for MyUserData {};
|
||||
impl UserData for MyUserData {}
|
||||
|
||||
let lua = Lua::new();
|
||||
lua.scope(|scope| {
|
||||
@@ -104,6 +93,19 @@ fn test_serialize_in_scope() -> LuaResult<()> {
|
||||
Err(e) => panic!("expected destructed error, got {}", e),
|
||||
}
|
||||
|
||||
struct MyUserDataRef<'a>(&'a ());
|
||||
|
||||
impl<'a> UserData for MyUserDataRef<'a> {}
|
||||
|
||||
lua.scope(|scope| {
|
||||
let ud = scope.create_nonstatic_userdata(MyUserDataRef(&()))?;
|
||||
match serde_json::to_value(&ud) {
|
||||
Ok(v) => panic!("expected serialization error, got {}", v),
|
||||
Err(serde_json::Error { .. }) => {}
|
||||
};
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -112,7 +114,7 @@ fn test_serialize_failure() -> Result<(), Box<dyn std::error::Error>> {
|
||||
#[derive(Serialize)]
|
||||
struct MyUserData(i64);
|
||||
|
||||
impl UserData for MyUserData {};
|
||||
impl UserData for MyUserData {}
|
||||
|
||||
let lua = Lua::new();
|
||||
|
||||
@@ -148,7 +150,7 @@ fn test_to_value_struct() -> LuaResult<()> {
|
||||
name: String,
|
||||
key: i64,
|
||||
data: Option<bool>,
|
||||
};
|
||||
}
|
||||
|
||||
let test = Test {
|
||||
name: "alex".to_string(),
|
||||
@@ -178,7 +180,7 @@ fn test_to_value_enum() -> LuaResult<()> {
|
||||
name: String,
|
||||
key: i64,
|
||||
data: Option<bool>,
|
||||
};
|
||||
}
|
||||
|
||||
let test = Test {
|
||||
name: "alex".to_string(),
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use mlua::{Lua, Result, String};
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use mlua::{Lua, Nil, Result, Table, TableExt, Value};
|
||||
|
||||
#[test]
|
||||
|
||||
+78
-60
@@ -1,17 +1,5 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::iter::FromIterator;
|
||||
use std::panic::catch_unwind;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::sync::Arc;
|
||||
use std::{error, f32, f64, fmt};
|
||||
|
||||
@@ -384,62 +372,92 @@ fn test_error() -> Result<()> {
|
||||
|
||||
assert!(understand_recursion.call::<_, ()>(()).is_err());
|
||||
|
||||
match catch_unwind(|| -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_panic() -> Result<()> {
|
||||
fn make_lua() -> Result<Lua> {
|
||||
let lua = Lua::new();
|
||||
let rust_panic_function =
|
||||
lua.create_function(|_, ()| -> Result<()> { panic!("rust panic") })?;
|
||||
lua.globals()
|
||||
.set("rust_panic_function", rust_panic_function)?;
|
||||
Ok(lua)
|
||||
}
|
||||
|
||||
// Test triggerting Lua error passing Rust panic (must be resumed)
|
||||
{
|
||||
let lua = make_lua()?;
|
||||
|
||||
match catch_unwind(AssertUnwindSafe(|| -> Result<()> {
|
||||
lua.load(
|
||||
r#"
|
||||
_, err = pcall(rust_panic_function)
|
||||
error(err)
|
||||
"#,
|
||||
)
|
||||
.exec()
|
||||
})) {
|
||||
Ok(Ok(_)) => panic!("no panic was detected"),
|
||||
Ok(Err(e)) => panic!("error during panic test {:?}", e),
|
||||
Err(p) => assert!(*p.downcast::<&str>().unwrap() == "rust panic"),
|
||||
};
|
||||
|
||||
// Trigger same panic again
|
||||
match lua.load("error(err)").exec() {
|
||||
Ok(_) => panic!("no error was detected"),
|
||||
Err(Error::PreviouslyResumedPanic) => {}
|
||||
Err(e) => panic!("expected PreviouslyResumedPanic, got {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
// Test returning Rust panic (must be resumed)
|
||||
{
|
||||
let lua = make_lua()?;
|
||||
match catch_unwind(AssertUnwindSafe(|| -> Result<()> {
|
||||
let _catched_panic = lua
|
||||
.load(
|
||||
r#"
|
||||
-- Set global
|
||||
_, err = pcall(rust_panic_function)
|
||||
return err
|
||||
"#,
|
||||
)
|
||||
.eval::<Value>()?;
|
||||
Ok(())
|
||||
})) {
|
||||
Ok(_) => panic!("no panic was detected"),
|
||||
Err(_) => {}
|
||||
};
|
||||
|
||||
assert!(lua.globals().get::<_, Value>("err")? == Value::Nil);
|
||||
match lua.load("tostring(err)").exec() {
|
||||
Ok(_) => panic!("no error was detected"),
|
||||
Err(Error::CallbackError { ref cause, .. }) => match cause.as_ref() {
|
||||
Error::PreviouslyResumedPanic => {}
|
||||
e => panic!("expected PreviouslyResumedPanic, got {:?}", e),
|
||||
},
|
||||
Err(e) => panic!("expected CallbackError, got {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
// Test representing rust panic as a string
|
||||
match catch_unwind(|| -> Result<()> {
|
||||
let lua = make_lua()?;
|
||||
lua.load(
|
||||
r#"
|
||||
function rust_panic()
|
||||
local _, err = pcall(function () rust_panic_function() end)
|
||||
if err ~= nil then
|
||||
error(err)
|
||||
end
|
||||
end
|
||||
local _, err = pcall(rust_panic_function)
|
||||
error(tostring(err))
|
||||
"#,
|
||||
)
|
||||
.exec()?;
|
||||
let rust_panic_function =
|
||||
lua.create_function(|_, ()| -> Result<()> { panic!("test_panic") })?;
|
||||
globals.set("rust_panic_function", rust_panic_function)?;
|
||||
|
||||
let rust_panic = globals.get::<_, Function>("rust_panic")?;
|
||||
|
||||
rust_panic.call::<_, ()>(())
|
||||
}) {
|
||||
Ok(Ok(_)) => panic!("no panic was detected"),
|
||||
Ok(Err(e)) => panic!("error during panic test {:?}", e),
|
||||
Err(p) => assert!(*p.downcast::<&str>().unwrap() == "test_panic"),
|
||||
};
|
||||
|
||||
match catch_unwind(|| -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
|
||||
lua.load(
|
||||
r#"
|
||||
function rust_panic()
|
||||
local _, err = pcall(function () rust_panic_function() end)
|
||||
if err ~= nil then
|
||||
error(tostring(err))
|
||||
end
|
||||
end
|
||||
"#,
|
||||
)
|
||||
.exec()?;
|
||||
let rust_panic_function =
|
||||
lua.create_function(|_, ()| -> Result<()> { panic!("test_panic") })?;
|
||||
globals.set("rust_panic_function", rust_panic_function)?;
|
||||
|
||||
let rust_panic = globals.get::<_, Function>("rust_panic")?;
|
||||
|
||||
rust_panic.call::<_, ()>(())
|
||||
.exec()
|
||||
}) {
|
||||
Ok(Ok(_)) => panic!("no error was detected"),
|
||||
Ok(Err(Error::RuntimeError(_))) => {}
|
||||
Ok(Err(e)) => panic!("unexpected error during panic test {:?}", e),
|
||||
Ok(Err(e)) => panic!("expected RuntimeError, got {:?}", e),
|
||||
Err(_) => panic!("panic was detected"),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::panic::catch_unwind;
|
||||
|
||||
use mlua::{Error, Function, Lua, Result, Thread, ThreadStatus};
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::os::raw::c_void;
|
||||
|
||||
use mlua::{Function, LightUserData, Lua, Result};
|
||||
|
||||
+2
-14
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
@@ -25,8 +13,8 @@ fn test_user_data() -> Result<()> {
|
||||
struct UserData1(i64);
|
||||
struct UserData2(Box<i64>);
|
||||
|
||||
impl UserData for UserData1 {};
|
||||
impl UserData for UserData2 {};
|
||||
impl UserData for UserData1 {}
|
||||
impl UserData for UserData2 {}
|
||||
|
||||
let lua = Lua::new();
|
||||
let userdata1 = lua.create_userdata(UserData1(1))?;
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#![cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
feature(link_args)
|
||||
)]
|
||||
|
||||
#[cfg_attr(
|
||||
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||
allow(unused_attributes)
|
||||
)]
|
||||
extern "system" {}
|
||||
|
||||
use mlua::{Lua, Result, Value};
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user