Make Runtime::run Return Lua Values (#178)

This commit is contained in:
Erica Marigold 2024-10-16 20:35:23 +01:00 committed by GitHub
parent eaac9ff53a
commit df4fb9be91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 39 additions and 39 deletions

View file

@ -27,11 +27,13 @@ pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(methods: &mut M)
} }
fn get_or_create_material_colors(instance: &Instance) -> MaterialColors { fn get_or_create_material_colors(instance: &Instance) -> MaterialColors {
if let Some(Variant::MaterialColors(material_colors)) = instance.get_property("MaterialColors") if let Variant::MaterialColors(inner) = instance
.get_property("MaterialColors")
.unwrap_or(Variant::MaterialColors(MaterialColors::default()))
{ {
material_colors inner
} else { } else {
MaterialColors::default() unreachable!()
} }
} }

View file

@ -7,9 +7,8 @@ use tokio::{
io::{stdin, AsyncReadExt as _}, io::{stdin, AsyncReadExt as _},
}; };
use lune::Runtime;
use super::utils::files::{discover_script_path_including_lune_dirs, strip_shebang}; use super::utils::files::{discover_script_path_including_lune_dirs, strip_shebang};
use lune::Runtime;
/// Run a script /// Run a script
#[derive(Debug, Clone, Parser)] #[derive(Debug, Clone, Parser)]
@ -41,8 +40,8 @@ impl RunCommand {
}; };
// Create a new lune object with all globals & run the script // Create a new lune object with all globals & run the script
let result = Runtime::new() let mut runtime = Runtime::new().with_args(self.script_args);
.with_args(self.script_args) let result = runtime
.run(&script_display_name, strip_shebang(script_contents)) .run(&script_display_name, strip_shebang(script_contents))
.await; .await;
Ok(match result { Ok(match result {
@ -50,7 +49,7 @@ impl RunCommand {
eprintln!("{err}"); eprintln!("{err}");
ExitCode::FAILURE ExitCode::FAILURE
} }
Ok(code) => code, Ok((code, _)) => ExitCode::from(code),
}) })
} }
} }

View file

@ -1,7 +1,6 @@
#![allow(clippy::missing_panics_doc)] #![allow(clippy::missing_panics_doc)]
use std::{ use std::{
process::ExitCode,
rc::Rc, rc::Rc,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
@ -144,7 +143,8 @@ impl Runtime {
&mut self, &mut self,
script_name: impl AsRef<str>, script_name: impl AsRef<str>,
script_contents: impl AsRef<[u8]>, script_contents: impl AsRef<[u8]>,
) -> RuntimeResult<ExitCode> { ) -> RuntimeResult<(u8, Vec<LuaValue>)> {
// Create a new scheduler for this run
let lua = self.inner.lua(); let lua = self.inner.lua();
let sched = self.inner.scheduler(); let sched = self.inner.scheduler();
@ -162,18 +162,20 @@ impl Runtime {
.set_name(script_name.as_ref()); .set_name(script_name.as_ref());
// Run it on our scheduler until it and any other spawned threads complete // Run it on our scheduler until it and any other spawned threads complete
sched.push_thread_back(main, ())?; let main_thread_id = sched.push_thread_back(main, ())?;
sched.run().await; sched.run().await;
// Return the exit code - default to FAILURE if we got any errors let thread_res = match sched.get_thread_result(main_thread_id) {
let exit_code = sched.get_exit_code().unwrap_or({ Some(res) => res,
if got_any_error.load(Ordering::SeqCst) { None => LuaValue::Nil.into_lua_multi(lua),
ExitCode::FAILURE }?
} else { .into_vec();
ExitCode::SUCCESS
}
});
Ok(exit_code) Ok((
sched
.get_exit_code()
.unwrap_or(u8::from(got_any_error.load(Ordering::SeqCst))),
thread_res,
))
} }
} }

View file

@ -29,16 +29,14 @@ pub async fn run(patched_bin: impl AsRef<[u8]>) -> Result<ExitCode> {
let args = env::args().skip(1).collect::<Vec<_>>(); let args = env::args().skip(1).collect::<Vec<_>>();
let meta = Metadata::from_bytes(patched_bin).expect("must be a standalone binary"); let meta = Metadata::from_bytes(patched_bin).expect("must be a standalone binary");
let result = Runtime::new() let mut rt = Runtime::new().with_args(args);
.with_args(args) let result = rt.run("STANDALONE", meta.bytecode).await;
.run("STANDALONE", meta.bytecode)
.await;
Ok(match result { Ok(match result {
Err(err) => { Err(err) => {
eprintln!("{err}"); eprintln!("{err}");
ExitCode::FAILURE ExitCode::FAILURE
} }
Ok(code) => code, Ok((code, _)) => ExitCode::from(code),
}) })
} }

View file

@ -42,8 +42,8 @@ macro_rules! create_tests {
.trim_end_matches(".luau") .trim_end_matches(".luau")
.trim_end_matches(".lua") .trim_end_matches(".lua")
.to_string(); .to_string();
let exit_code = lune.run(&script_name, &script).await?; let (exit_code, _) = lune.run(&script_name, &script).await?;
Ok(exit_code) Ok(ExitCode::from(exit_code))
} }
)* } )* }
} }

View file

@ -32,7 +32,7 @@ pub fn main() -> LuaResult<()> {
// Verify that we got a correct exit code // Verify that we got a correct exit code
let code = sched.get_exit_code().unwrap_or_default(); let code = sched.get_exit_code().unwrap_or_default();
assert!(format!("{code:?}").contains("(1)")); assert_eq!(code, 1);
Ok(()) Ok(())
} }

View file

@ -1,10 +1,10 @@
use std::{cell::Cell, process::ExitCode, rc::Rc}; use std::{cell::Cell, rc::Rc};
use event_listener::Event; use event_listener::Event;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct Exit { pub(crate) struct Exit {
code: Rc<Cell<Option<ExitCode>>>, code: Rc<Cell<Option<u8>>>,
event: Rc<Event>, event: Rc<Event>,
} }
@ -16,12 +16,12 @@ impl Exit {
} }
} }
pub fn set(&self, code: ExitCode) { pub fn set(&self, code: u8) {
self.code.set(Some(code)); self.code.set(Some(code));
self.event.notify(usize::MAX); self.event.notify(usize::MAX);
} }
pub fn get(&self) -> Option<ExitCode> { pub fn get(&self) -> Option<u8> {
self.code.get() self.code.get()
} }

View file

@ -1,7 +1,7 @@
#![allow(unused_imports)] #![allow(unused_imports)]
#![allow(clippy::too_many_lines)] #![allow(clippy::too_many_lines)]
use std::process::ExitCode; use std::process::{ExitCode, ExitStatus};
use mlua::prelude::*; use mlua::prelude::*;
@ -232,7 +232,7 @@ impl<'lua> Functions<'lua> {
"exit", "exit",
lua.create_function(|lua, code: Option<u8>| { lua.create_function(|lua, code: Option<u8>| {
let _span = tracing::trace_span!("Scheduler::fn_exit").entered(); let _span = tracing::trace_span!("Scheduler::fn_exit").entered();
let code = code.map(ExitCode::from).unwrap_or_default(); let code = code.unwrap_or_default();
lua.set_exit_code(code); lua.set_exit_code(code);
Ok(()) Ok(())
})?, })?,

View file

@ -2,7 +2,6 @@
use std::{ use std::{
cell::Cell, cell::Cell,
process::ExitCode,
rc::{Rc, Weak as WeakRc}, rc::{Rc, Weak as WeakRc},
sync::{Arc, Weak as WeakArc}, sync::{Arc, Weak as WeakArc},
thread::panicking, thread::panicking,
@ -168,7 +167,7 @@ impl<'lua> Scheduler<'lua> {
Gets the exit code for this scheduler, if one has been set. Gets the exit code for this scheduler, if one has been set.
*/ */
#[must_use] #[must_use]
pub fn get_exit_code(&self) -> Option<ExitCode> { pub fn get_exit_code(&self) -> Option<u8> {
self.exit.get() self.exit.get()
} }
@ -177,7 +176,7 @@ impl<'lua> Scheduler<'lua> {
This will cause [`Scheduler::run`] to exit immediately. This will cause [`Scheduler::run`] to exit immediately.
*/ */
pub fn set_exit_code(&self, code: ExitCode) { pub fn set_exit_code(&self, code: u8) {
self.exit.set(code); self.exit.set(code);
} }

View file

@ -82,7 +82,7 @@ pub trait LuaSchedulerExt<'lua> {
Panics if called outside of a running [`Scheduler`]. Panics if called outside of a running [`Scheduler`].
*/ */
fn set_exit_code(&self, code: ExitCode); fn set_exit_code(&self, code: u8);
/** /**
Pushes (spawns) a lua thread to the **front** of the current scheduler. Pushes (spawns) a lua thread to the **front** of the current scheduler.
@ -283,7 +283,7 @@ pub trait LuaSpawnExt<'lua> {
} }
impl<'lua> LuaSchedulerExt<'lua> for Lua { impl<'lua> LuaSchedulerExt<'lua> for Lua {
fn set_exit_code(&self, code: ExitCode) { fn set_exit_code(&self, code: u8) {
let exit = self let exit = self
.app_data_ref::<Exit>() .app_data_ref::<Exit>()
.expect("exit code can only be set from within an active scheduler"); .expect("exit code can only be set from within an active scheduler");