diff --git a/mlua_derive/src/lib.rs b/mlua_derive/src/lib.rs index 31d3b52..8f057dc 100644 --- a/mlua_derive/src/lib.rs +++ b/mlua_derive/src/lib.rs @@ -84,26 +84,26 @@ pub fn chunk(input: TokenStream) -> TokenStream { }); let wrapped_code = quote! {{ - use ::mlua::{AsChunk, ChunkMode, Lua, Result, Value}; + use ::mlua::{AsChunk, ChunkMode, Lua, Result, Table}; use ::std::borrow::Cow; use ::std::io::Result as IoResult; use ::std::sync::Mutex; - struct InnerChunk FnOnce(&'a Lua) -> Result>>(Mutex>); + struct InnerChunk FnOnce(&'a Lua) -> Result>>(Mutex>); impl AsChunk<'static> for InnerChunk where - F: for <'a> FnOnce(&'a Lua) -> Result>, + F: for <'a> FnOnce(&'a Lua) -> Result>, { - fn env<'lua>(&self, lua: &'lua Lua) -> Result> { + fn environment<'lua>(&self, lua: &'lua Lua) -> Result>> { if #caps_len > 0 { if let Ok(mut make_env) = self.0.lock() { if let Some(make_env) = make_env.take() { - return make_env(lua); + return make_env(lua).map(Some); } } } - Ok(Value::Nil) + Ok(None) } fn mode(&self) -> Option { @@ -115,9 +115,9 @@ pub fn chunk(input: TokenStream) -> TokenStream { } } - fn annotate FnOnce(&'a Lua) -> Result>>(f: F) -> F { f } + fn annotate FnOnce(&'a Lua) -> Result>>(f: F) -> F { f } - let make_env = annotate(move |lua: &Lua| -> Result { + let make_env = annotate(move |lua: &Lua| -> Result { let globals = lua.globals(); let env = lua.create_table()?; let meta = lua.create_table()?; @@ -128,7 +128,7 @@ pub fn chunk(input: TokenStream) -> TokenStream { #(#caps)* env.set_metatable(Some(meta)); - Ok(Value::Table(env)) + Ok(env) }); InnerChunk(Mutex::new(Some(make_env))) diff --git a/src/chunk.rs b/src/chunk.rs index 5dcb2fa..b3b3cb5 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -5,10 +5,11 @@ use std::io::Result as IoResult; use std::path::{Path, PathBuf}; use std::string::String as StdString; -use crate::error::{Error, Result}; +use crate::error::{Error, ErrorContext, Result}; use crate::function::Function; use crate::lua::Lua; -use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti, Value}; +use crate::table::Table; +use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti}; #[cfg(feature = "async")] use futures_util::future::{self, LocalBoxFuture}; @@ -26,9 +27,9 @@ pub trait AsChunk<'a> { /// Returns optional chunk [environment] /// /// [environment]: https://www.lua.org/manual/5.4/manual.html#2.2 - fn env<'lua>(&self, lua: &'lua Lua) -> Result> { + fn environment<'lua>(&self, lua: &'lua Lua) -> Result>> { let _lua = lua; // suppress warning - Ok(Value::Nil) + Ok(None) } /// Returns optional chunk mode (text or binary) @@ -103,7 +104,7 @@ impl AsChunk<'static> for PathBuf { pub struct Chunk<'lua, 'a> { pub(crate) lua: &'lua Lua, pub(crate) name: StdString, - pub(crate) env: Result>, + pub(crate) env: Result>>, pub(crate) mode: Option, pub(crate) source: IoResult>, #[cfg(feature = "luau")] @@ -254,9 +255,9 @@ impl<'lua, 'a> Chunk<'lua, 'a> { self } - /// Sets the first upvalue (`_ENV`) of the loaded chunk to the given value. + /// Sets the environment of the loaded chunk to the given value. /// - /// Lua main chunks always have exactly one upvalue, and this upvalue is used as the `_ENV` + /// In Lua >=5.2 main chunks always have exactly one upvalue, and this upvalue is used as the `_ENV` /// variable inside the chunk. By default this value is set to the global environment. /// /// Calling this method changes the `_ENV` upvalue to the value provided, and variables inside @@ -266,7 +267,10 @@ impl<'lua, 'a> Chunk<'lua, 'a> { /// necessary to populate the environment in order for scripts using custom environments to be /// useful. pub fn set_environment>(mut self, env: V) -> Self { - self.env = env.into_lua(self.lua); + self.env = env + .into_lua(self.lua) + .and_then(|val| self.lua.unpack(val)) + .context("bad environment value"); self } @@ -414,7 +418,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> { self.mode = Some(ChunkMode::Binary); } #[cfg(not(feature = "luau"))] - if let Ok(func) = self.lua.load_chunk(None, Value::Nil, None, source.as_ref()) { + if let Ok(func) = self.lua.load_chunk(None, None, None, source.as_ref()) { let data = func.dump(false); self.source = Ok(Cow::Owned(data)); self.mode = Some(ChunkMode::Binary); diff --git a/src/lua.rs b/src/lua.rs index 4fe89e2..d8bb215 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -1319,7 +1319,7 @@ impl Lua { Chunk { lua: self, name: chunk.name().unwrap_or_else(|| caller.to_string()), - env: chunk.env(self), + env: chunk.environment(self), mode: chunk.mode(), source: chunk.source(), #[cfg(feature = "luau")] @@ -1330,7 +1330,7 @@ impl Lua { pub(crate) fn load_chunk<'lua>( &'lua self, name: Option<&CStr>, - env: Value<'lua>, + env: Option
, mode: Option, source: &[u8], ) -> Result> { @@ -1353,8 +1353,8 @@ impl Lua { mode_str, ) { ffi::LUA_OK => { - if env != Value::Nil { - self.push_value(env)?; + if let Some(env) = env { + self.push_ref(&env.0); #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] ffi::lua_setupvalue(state, -2, 1); #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]