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! {{
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<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>
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 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<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 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)))

View File

@ -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<Value<'lua>> {
fn environment<'lua>(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
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<Value<'lua>>,
pub(crate) env: Result<Option<Table<'lua>>>,
pub(crate) mode: Option<ChunkMode>,
pub(crate) source: IoResult<Cow<'a, [u8]>>,
#[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<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
}
@ -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);

View File

@ -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<Table>,
mode: Option<ChunkMode>,
source: &[u8],
) -> Result<Function<'lua>> {
@ -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"))]