mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3516f4c6ca | |||
| ca73583714 | |||
| 36560435f7 | |||
| 763c2b2564 | |||
| bafdb6138c | |||
| c9d6a610e1 | |||
| bd63f63bc9 | |||
| c035c23a15 | |||
| cb153a52b2 | |||
| b1c69d3005 | |||
| 841bd332e4 | |||
| 815d1bd7c9 |
@@ -1,3 +1,10 @@
|
||||
## v0.11.2 (Aug 10, 2025)
|
||||
|
||||
- Faster stack push for `Variadic<T>`
|
||||
- Fix handling Windows paths with drive letter in Luau require (#623)
|
||||
- Make Luau registered aliases ascii case-insensitive (#620)
|
||||
- Fix deserializing negative zeros `-0.0` (#618)
|
||||
|
||||
## v0.11.1 (Jul 15, 2025)
|
||||
|
||||
- Fixed bug exhausting Lua auxiliary stack and leaving it without reserve (#615)
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua"
|
||||
version = "0.11.1" # remember to update mlua_derive
|
||||
version = "0.11.2" # remember to update mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@kyju.org>"]
|
||||
rust-version = "1.79.0"
|
||||
edition = "2021"
|
||||
@@ -62,7 +62,7 @@ parking_lot = { version = "0.12", features = ["arc_lock"] }
|
||||
anyhow = { version = "1.0", optional = true }
|
||||
rustversion = "1.0"
|
||||
|
||||
ffi = { package = "mlua-sys", version = "0.8.0", path = "mlua-sys" }
|
||||
ffi = { package = "mlua-sys", version = "0.8.3", path = "mlua-sys" }
|
||||
|
||||
[dev-dependencies]
|
||||
trybuild = "1.0"
|
||||
@@ -78,8 +78,8 @@ tempfile = "3"
|
||||
static_assertions = "1.0"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||
criterion = { version = "0.6", features = ["async_tokio"] }
|
||||
rustyline = "16.0"
|
||||
criterion = { version = "0.7", features = ["async_tokio"] }
|
||||
rustyline = "17.0"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
|
||||
[lints.rust]
|
||||
|
||||
+10
-8
@@ -20,14 +20,16 @@ fn main() {
|
||||
match lua.load(&line).eval::<MultiValue>() {
|
||||
Ok(values) => {
|
||||
editor.add_history_entry(line).unwrap();
|
||||
println!(
|
||||
"{}",
|
||||
values
|
||||
.iter()
|
||||
.map(|value| format!("{:#?}", value))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\t")
|
||||
);
|
||||
if values.len() > 0 {
|
||||
println!(
|
||||
"{}",
|
||||
values
|
||||
.iter()
|
||||
.map(|value| format!("{:#?}", value))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\t")
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Err(Error::SyntaxError {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua-sys"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>"]
|
||||
rust-version = "1.71"
|
||||
edition = "2021"
|
||||
|
||||
@@ -186,7 +186,8 @@ pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int {
|
||||
if lua_type(L, idx) == LUA_TNUMBER {
|
||||
let n = lua_tonumber(L, idx);
|
||||
let i = lua_tointeger(L, idx);
|
||||
if (n - i as lua_Number).abs() < lua_Number::EPSILON {
|
||||
// Lua 5.3+ returns "false" for `-0.0`
|
||||
if n.to_bits() == (i as lua_Number).to_bits() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int {
|
||||
if lua_type(L, idx) == LUA_TNUMBER {
|
||||
let n = lua_tonumber(L, idx);
|
||||
let i = lua_tointeger(L, idx);
|
||||
if (n - i as lua_Number).abs() < lua_Number::EPSILON {
|
||||
// Lua 5.3+ returns "false" for `-0.0`
|
||||
if n.to_bits() == (i as lua_Number).to_bits() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,8 @@ pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int {
|
||||
if lua_type(L, idx) == LUA_TNUMBER {
|
||||
let n = lua_tonumber(L, idx);
|
||||
let i = lua_tointeger(L, idx);
|
||||
if (n - i as lua_Number).abs() < lua_Number::EPSILON {
|
||||
// Lua 5.3+ returns "false" for `-0.0`
|
||||
if n.to_bits() == (i as lua_Number).to_bits() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
+21
-4
@@ -129,7 +129,7 @@ impl TextRequirer {
|
||||
}
|
||||
|
||||
fn normalize_chunk_name(chunk_name: &str) -> &str {
|
||||
if let Some((path, line)) = chunk_name.split_once(':') {
|
||||
if let Some((path, line)) = chunk_name.rsplit_once(':') {
|
||||
if line.parse::<u32>().is_ok() {
|
||||
return path;
|
||||
}
|
||||
@@ -567,10 +567,26 @@ pub(super) fn create_require_function<R: Require + MaybeSend + 'static>(
|
||||
1
|
||||
}
|
||||
|
||||
let (error, r#type) = unsafe {
|
||||
lua.exec_raw::<(Function, Function)>((), move |state| {
|
||||
unsafe extern "C-unwind" fn to_lowercase(state: *mut ffi::lua_State) -> c_int {
|
||||
let s = ffi::luaL_checkstring(state, 1);
|
||||
let s = CStr::from_ptr(s);
|
||||
if !s.to_bytes().iter().any(|&c| c.is_ascii_uppercase()) {
|
||||
// If the string does not contain any uppercase ASCII letters, return it as is
|
||||
return 1;
|
||||
}
|
||||
callback_error_ext(state, ptr::null_mut(), true, |extra, _| {
|
||||
let s = (s.to_bytes().iter())
|
||||
.map(|&c| c.to_ascii_lowercase())
|
||||
.collect::<bstr::BString>();
|
||||
(*extra).raw_lua().push(s).map(|_| 1)
|
||||
})
|
||||
}
|
||||
|
||||
let (error, r#type, to_lowercase) = unsafe {
|
||||
lua.exec_raw::<(Function, Function, Function)>((), move |state| {
|
||||
ffi::lua_pushcfunctiond(state, error, cstr!("error"));
|
||||
ffi::lua_pushcfunctiond(state, r#type, cstr!("type"));
|
||||
ffi::lua_pushcfunctiond(state, to_lowercase, cstr!("to_lowercase"));
|
||||
})
|
||||
}?;
|
||||
|
||||
@@ -583,6 +599,7 @@ pub(super) fn create_require_function<R: Require + MaybeSend + 'static>(
|
||||
env.raw_set("LOADER_CACHE", loader_cache)?;
|
||||
env.raw_set("error", error)?;
|
||||
env.raw_set("type", r#type)?;
|
||||
env.raw_set("to_lowercase", to_lowercase)?;
|
||||
|
||||
lua.load(
|
||||
r#"
|
||||
@@ -592,7 +609,7 @@ pub(super) fn create_require_function<R: Require + MaybeSend + 'static>(
|
||||
end
|
||||
|
||||
-- Check if the module (path) is explicitly registered
|
||||
local maybe_result = REGISTERED_MODULES[path]
|
||||
local maybe_result = REGISTERED_MODULES[to_lowercase(path)]
|
||||
if maybe_result ~= nil then
|
||||
return maybe_result
|
||||
end
|
||||
|
||||
@@ -297,6 +297,15 @@ impl<T: IntoLua> IntoLuaMulti for Variadic<T> {
|
||||
fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
|
||||
MultiValue::from_lua_iter(lua, self)
|
||||
}
|
||||
|
||||
unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
|
||||
let nresults = self.len() as i32;
|
||||
check_stack(lua.state(), nresults + 1)?;
|
||||
for value in self.0 {
|
||||
value.push_into_stack(lua)?;
|
||||
}
|
||||
Ok(nresults)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FromLua> FromLuaMulti for Variadic<T> {
|
||||
|
||||
@@ -358,6 +358,8 @@ impl Lua {
|
||||
if cfg!(feature = "luau") && !modname.starts_with('@') {
|
||||
return Err(Error::runtime("module name must begin with '@'"));
|
||||
}
|
||||
#[cfg(feature = "luau")]
|
||||
let modname = modname.to_ascii_lowercase();
|
||||
unsafe {
|
||||
self.exec_raw::<()>(value, |state| {
|
||||
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, LOADED_MODULES_KEY);
|
||||
|
||||
+1
-1
@@ -728,7 +728,7 @@ impl RawLua {
|
||||
|
||||
let n = ffi::lua_tonumber(state, idx);
|
||||
match num_traits::cast(n) {
|
||||
Some(i) if (n - (i as Number)).abs() < Number::EPSILON => Value::Integer(i),
|
||||
Some(i) if n.to_bits() == (i as Number).to_bits() => Value::Integer(i),
|
||||
_ => Value::Number(n),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,11 @@ fn test_require_with_config() {
|
||||
let res = run_require(&lua, "./tests/luau/require/with_config/src/alias_requirer").unwrap();
|
||||
assert_eq!("result from dependency", get_str(&res, 1));
|
||||
|
||||
// RequirePathWithAlias (case-insensitive)
|
||||
let res2 = run_require(&lua, "./tests/luau/require/with_config/src/alias_requirer_uc").unwrap();
|
||||
assert_eq!("result from dependency", get_str(&res2, 1));
|
||||
assert_eq!(res.to_pointer(), res2.to_pointer());
|
||||
|
||||
// RequirePathWithParentAlias
|
||||
let res = run_require(&lua, "./tests/luau/require/with_config/src/parent_alias_requirer").unwrap();
|
||||
assert_eq!("result from other_dependency", get_str(&res, 1));
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
return require("@DeP")
|
||||
@@ -602,6 +602,21 @@ fn test_num_conversion() -> Result<()> {
|
||||
|
||||
assert_eq!(lua.unpack::<i128>(lua.pack(1i128 << 64)?)?, 1i128 << 64);
|
||||
|
||||
// Negative zero
|
||||
let negative_zero = lua.load("-0.0").eval::<f64>()?;
|
||||
assert_eq!(negative_zero, 0.0);
|
||||
// LuaJIT treats -0.0 as a positive zero
|
||||
#[cfg(not(feature = "luajit"))]
|
||||
assert!(negative_zero.is_sign_negative());
|
||||
|
||||
// In Lua <5.3 all numbers are floats
|
||||
#[cfg(not(any(feature = "lua54", feature = "lua53", feature = "luajit")))]
|
||||
{
|
||||
let negative_zero = lua.load("-0").eval::<f64>()?;
|
||||
assert_eq!(negative_zero, 0.0);
|
||||
assert!(negative_zero.is_sign_negative());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1227,6 +1242,17 @@ fn test_register_module() -> Result<()> {
|
||||
res.unwrap_err().to_string(),
|
||||
"runtime error: module name must begin with '@'"
|
||||
);
|
||||
|
||||
// Luau registered modules (aliases) are case-insensitive
|
||||
let res = lua.register_module("@My_Module", &t);
|
||||
assert!(res.is_ok());
|
||||
lua.load(
|
||||
r#"
|
||||
local my_module = require("@MY_MODule")
|
||||
assert(my_module.name == "my_module")
|
||||
"#,
|
||||
)
|
||||
.exec()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user