Fix bug in returning nil-prefixed multi values from async function

This commit is contained in:
Alex Orlenko 2021-03-03 22:32:22 +00:00
parent b93ace0224
commit 7cb9c4f39c
3 changed files with 35 additions and 11 deletions

View File

@ -1741,11 +1741,14 @@ impl Lua {
Ok(2) Ok(2)
} }
Poll::Ready(results) => { Poll::Ready(results) => {
let results = lua.create_sequence_from(results?)?; let results = results?;
check_stack(state, 2)?; let nresults = results.len() as Integer;
let results = lua.create_sequence_from(results)?;
check_stack(state, 3)?;
ffi::lua_pushboolean(state, 1); ffi::lua_pushboolean(state, 1);
lua.push_value(Value::Table(results))?; lua.push_value(Value::Table(results))?;
Ok(2) lua.push_value(Value::Integer(nresults))?;
Ok(3)
} }
} }
}) })
@ -1772,9 +1775,10 @@ impl Lua {
env.set("yield", coroutine.get::<_, Function>("yield")?)?; env.set("yield", coroutine.get::<_, Function>("yield")?)?;
env.set( env.set(
"unpack", "unpack",
self.create_function(|_, tbl: Table| { self.create_function(|_, (tbl, len): (Table, Integer)| {
Ok(MultiValue::from_vec( Ok(MultiValue::from_vec(
tbl.sequence_values().collect::<Result<Vec<Value>>>()?, tbl.raw_sequence_values_by_len(Some(len))
.collect::<Result<Vec<Value>>>()?,
)) ))
})?, })?,
)?; )?;
@ -1785,9 +1789,9 @@ impl Lua {
poll = get_poll(...) poll = get_poll(...)
local poll, yield, unpack = poll, yield, unpack local poll, yield, unpack = poll, yield, unpack
while true do while true do
ready, res = poll() local ready, res, nres = poll()
if ready then if ready then
return unpack(res) return unpack(res, nres)
end end
yield(res) yield(res)
end end

View File

@ -474,9 +474,11 @@ impl<'lua> Table<'lua> {
} }
} }
#[cfg(feature = "serialize")] pub(crate) fn raw_sequence_values_by_len<V: FromLua<'lua>>(
pub(crate) fn raw_sequence_values_by_len<V: FromLua<'lua>>(self) -> TableSequence<'lua, V> { self,
let len = self.raw_len(); len: Option<Integer>,
) -> TableSequence<'lua, V> {
let len = len.unwrap_or_else(|| self.raw_len());
TableSequence { TableSequence {
table: self.0, table: self.0,
index: Some(1), index: Some(1),
@ -641,7 +643,7 @@ impl<'lua> Serialize for Table<'lua> {
let len = self.raw_len() as usize; let len = self.raw_len() as usize;
if len > 0 || self.is_array() { if len > 0 || self.is_array() {
let mut seq = serializer.serialize_seq(Some(len))?; 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)?; let v = v.map_err(serde::ser::Error::custom)?;
seq.serialize_element(&v)?; seq.serialize_element(&v)?;
} }

View File

@ -136,6 +136,24 @@ async fn test_async_handle_yield() -> Result<()> {
Ok(()) 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] #[tokio::test]
async fn test_async_return_async_closure() -> Result<()> { async fn test_async_return_async_closure() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();