Require environment to be a Table instead of Value in Chunks.

In addition to that, `AsChunk::env()` renamed to `AsChunk::environment()`.
This commit is contained in:
Alex Orlenko 2023-06-02 23:59:16 +01:00
parent c905a34b1d
commit 9785722d61
No known key found for this signature in database
GPG Key ID: 4C150C250863B96D
3 changed files with 26 additions and 22 deletions

View File

@ -84,26 +84,26 @@ pub fn chunk(input: TokenStream) -> TokenStream {
}); });
let wrapped_code = quote! {{ let wrapped_code = quote! {{
use ::mlua::{AsChunk, ChunkMode, Lua, Result, Value}; use ::mlua::{AsChunk, ChunkMode, Lua, Result, Table};
use ::std::borrow::Cow; use ::std::borrow::Cow;
use ::std::io::Result as IoResult; use ::std::io::Result as IoResult;
use ::std::sync::Mutex; use ::std::sync::Mutex;
struct InnerChunk<F: for <'a> FnOnce(&'a Lua) -> Result<Value<'a>>>(Mutex<Option<F>>); struct InnerChunk<F: for <'a> FnOnce(&'a Lua) -> Result<Table<'a>>>(Mutex<Option<F>>);
impl<F> AsChunk<'static> for InnerChunk<F> impl<F> AsChunk<'static> for InnerChunk<F>
where where
F: for <'a> FnOnce(&'a Lua) -> Result<Value<'a>>, F: for <'a> FnOnce(&'a Lua) -> Result<Table<'a>>,
{ {
fn env<'lua>(&self, lua: &'lua Lua) -> Result<Value<'lua>> { fn environment<'lua>(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
if #caps_len > 0 { if #caps_len > 0 {
if let Ok(mut make_env) = self.0.lock() { if let Ok(mut make_env) = self.0.lock() {
if let Some(make_env) = make_env.take() { 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<ChunkMode> { fn mode(&self) -> Option<ChunkMode> {
@ -115,9 +115,9 @@ pub fn chunk(input: TokenStream) -> TokenStream {
} }
} }
fn annotate<F: for<'a> FnOnce(&'a Lua) -> Result<Value<'a>>>(f: F) -> F { f } fn annotate<F: for<'a> FnOnce(&'a Lua) -> Result<Table<'a>>>(f: F) -> F { f }
let make_env = annotate(move |lua: &Lua| -> Result<Value> { let make_env = annotate(move |lua: &Lua| -> Result<Table> {
let globals = lua.globals(); let globals = lua.globals();
let env = lua.create_table()?; let env = lua.create_table()?;
let meta = lua.create_table()?; let meta = lua.create_table()?;
@ -128,7 +128,7 @@ pub fn chunk(input: TokenStream) -> TokenStream {
#(#caps)* #(#caps)*
env.set_metatable(Some(meta)); env.set_metatable(Some(meta));
Ok(Value::Table(env)) Ok(env)
}); });
InnerChunk(Mutex::new(Some(make_env))) InnerChunk(Mutex::new(Some(make_env)))

View File

@ -5,10 +5,11 @@ use std::io::Result as IoResult;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::string::String as StdString; use std::string::String as StdString;
use crate::error::{Error, Result}; use crate::error::{Error, ErrorContext, Result};
use crate::function::Function; use crate::function::Function;
use crate::lua::Lua; use crate::lua::Lua;
use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti, Value}; use crate::table::Table;
use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti};
#[cfg(feature = "async")] #[cfg(feature = "async")]
use futures_util::future::{self, LocalBoxFuture}; use futures_util::future::{self, LocalBoxFuture};
@ -26,9 +27,9 @@ pub trait AsChunk<'a> {
/// Returns optional chunk [environment] /// Returns optional chunk [environment]
/// ///
/// [environment]: https://www.lua.org/manual/5.4/manual.html#2.2 /// [environment]: https://www.lua.org/manual/5.4/manual.html#2.2
fn env<'lua>(&self, lua: &'lua Lua) -> Result<Value<'lua>> { fn environment<'lua>(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
let _lua = lua; // suppress warning let _lua = lua; // suppress warning
Ok(Value::Nil) Ok(None)
} }
/// Returns optional chunk mode (text or binary) /// Returns optional chunk mode (text or binary)
@ -103,7 +104,7 @@ impl AsChunk<'static> for PathBuf {
pub struct Chunk<'lua, 'a> { pub struct Chunk<'lua, 'a> {
pub(crate) lua: &'lua Lua, pub(crate) lua: &'lua Lua,
pub(crate) name: StdString, pub(crate) name: StdString,
pub(crate) env: Result<Value<'lua>>, pub(crate) env: Result<Option<Table<'lua>>>,
pub(crate) mode: Option<ChunkMode>, pub(crate) mode: Option<ChunkMode>,
pub(crate) source: IoResult<Cow<'a, [u8]>>, pub(crate) source: IoResult<Cow<'a, [u8]>>,
#[cfg(feature = "luau")] #[cfg(feature = "luau")]
@ -254,9 +255,9 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
self 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. /// 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 /// 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 /// necessary to populate the environment in order for scripts using custom environments to be
/// useful. /// useful.
pub fn set_environment<V: IntoLua<'lua>>(mut self, env: V) -> Self { pub fn set_environment<V: IntoLua<'lua>>(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 self
} }
@ -414,7 +418,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
self.mode = Some(ChunkMode::Binary); self.mode = Some(ChunkMode::Binary);
} }
#[cfg(not(feature = "luau"))] #[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); let data = func.dump(false);
self.source = Ok(Cow::Owned(data)); self.source = Ok(Cow::Owned(data));
self.mode = Some(ChunkMode::Binary); self.mode = Some(ChunkMode::Binary);

View File

@ -1319,7 +1319,7 @@ impl Lua {
Chunk { Chunk {
lua: self, lua: self,
name: chunk.name().unwrap_or_else(|| caller.to_string()), name: chunk.name().unwrap_or_else(|| caller.to_string()),
env: chunk.env(self), env: chunk.environment(self),
mode: chunk.mode(), mode: chunk.mode(),
source: chunk.source(), source: chunk.source(),
#[cfg(feature = "luau")] #[cfg(feature = "luau")]
@ -1330,7 +1330,7 @@ impl Lua {
pub(crate) fn load_chunk<'lua>( pub(crate) fn load_chunk<'lua>(
&'lua self, &'lua self,
name: Option<&CStr>, name: Option<&CStr>,
env: Value<'lua>, env: Option<Table>,
mode: Option<ChunkMode>, mode: Option<ChunkMode>,
source: &[u8], source: &[u8],
) -> Result<Function<'lua>> { ) -> Result<Function<'lua>> {
@ -1353,8 +1353,8 @@ impl Lua {
mode_str, mode_str,
) { ) {
ffi::LUA_OK => { ffi::LUA_OK => {
if env != Value::Nil { if let Some(env) = env {
self.push_value(env)?; self.push_ref(&env.0);
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
ffi::lua_setupvalue(state, -2, 1); ffi::lua_setupvalue(state, -2, 1);
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]