diff --git a/Cargo.lock b/Cargo.lock index 0f1a715c..0d190f4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -434,25 +434,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -573,18 +554,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "filetime" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", -] - [[package]] name = "flate2" version = "1.0.26" @@ -658,15 +627,6 @@ dependencies = [ "syn 2.0.18", ] -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - [[package]] name = "generator" version = "0.7.5" @@ -868,26 +828,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - [[package]] name = "instant" version = "0.1.12" @@ -977,26 +917,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -1327,24 +1247,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "notify" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5738a2795d57ea20abec2d6d76c6081186709c0024187cd5977265eda6598b51" -dependencies = [ - "bitflags 1.3.2", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "mio", - "walkdir", - "windows-sys 0.45.0", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1491,7 +1393,6 @@ dependencies = [ "env_logger", "image", "log", - "notify", "oden-js", "pollster", "swc_common", diff --git a/Cargo.toml b/Cargo.toml index 25912249..17dfe5d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ bytemuck = { version = "1.13", features = ["derive"] } env_logger = "0.10" image = { version = "0.24", default-features = false, features = ["png"] } log = "0.4" -notify = "6" oden-js = { path = "oden-js" } pollster = "0.3" swc_common = "0.31.16" diff --git a/game/main.ts b/game/main.ts index 5cbf622c..84282c67 100644 --- a/game/main.ts +++ b/game/main.ts @@ -49,20 +49,6 @@ export function init() { load_assets(); } -export function suspend() { - return { clock }; -} - -export function resume(snapshot) { - if (snapshot) { - print("!Resuming!"); - const { clock: new_clock } = snapshot; - if (new_clock) { - clock = new_clock; - } - } -} - const friction = 0.6; let robo_vel = new_v2(0); let robo_pos = new_v2(10); diff --git a/oden-js/Cargo.toml b/oden-js/Cargo.toml index a0a10e70..c9dcd5c5 100644 --- a/oden-js/Cargo.toml +++ b/oden-js/Cargo.toml @@ -8,9 +8,8 @@ edition = "2021" [dependencies] anyhow = "1" bitflags = "1" -oden-js-sys = {path = "../oden-js-sys"} thiserror = "1" - +oden-js-sys = {path = "../oden-js-sys"} [dev-dependencies] assert_matches = "1.5.0" diff --git a/oden-js/src/context.rs b/oden-js/src/context.rs index 5eb6901a..2004fb65 100644 --- a/oden-js/src/context.rs +++ b/oden-js/src/context.rs @@ -396,23 +396,6 @@ impl ContextRef { pub fn process_all_jobs(&self) -> Result<()> { self.get_runtime().process_all_jobs() } - - /// Deserialize a value from bytes generated by `ValueRef::serialize()`. - /// - /// NOTE: The serialized value is only good for this exact version of - /// QuickJS- do *not* expect to be able to save it to disk and - /// re-load it. This is for more ephemeral usage: passing values - /// between threads, etc. - pub fn deserialize(&self, data: &[u8]) -> Result { - self.check_exception(unsafe { - sys::JS_ReadObject( - self.ctx, - data.as_ptr(), - data.len(), - sys::JS_READ_OBJ_REFERENCE as i32, - ) - }) - } } #[derive(Debug)] diff --git a/oden-js/src/value.rs b/oden-js/src/value.rs index cc73369f..c8a95def 100644 --- a/oden-js/src/value.rs +++ b/oden-js/src/value.rs @@ -337,42 +337,6 @@ impl ValueRef { } } } - - /// Serialize this value into a byte array. Consume the byte array with - /// `ContextRef::deserialize()`. - /// - /// NOTE: The serialized value is only good for this exact version of - /// QuickJS- do *not* expect to be able to save it to disk and - /// re-load it. This is for more ephemeral usage: passing values - /// between threads, etc. - /// - /// NOTE: In theory if we wanted to just serialize a message we could - /// avoid a memory copy; we copy here to avoid keeping the runtime - /// alive, which we would have to do in order to free the buffer - /// correctly. If we were willing to keep the runtime alive... - /// - /// TODO: We do not have support for SharedArrayBuffers here, which would - /// let us use this function to pass large buffers between Runtime - /// instances, like on different threads, without copying. What a - /// pity. - pub fn serialize(&self, ctx: &ContextRef) -> Result> { - unsafe { - let mut size = 0; - let data = sys::JS_WriteObject( - ctx.ctx, - &mut size, - self.val, - sys::JS_WRITE_OBJ_REFERENCE as i32, - ); - if data.is_null() { - Err(ctx.exception_error()) - } else { - let result = std::slice::from_raw_parts(data, size).to_vec(); - sys::js_free(ctx.ctx, data as *mut std::ffi::c_void); - Ok(result) - } - } - } } impl fmt::Debug for ValueRef { diff --git a/src/lib.rs b/src/lib.rs index 4d96e084..1dc698b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use bytemuck; use std::collections::HashMap; use std::rc::Rc; -use std::sync::mpsc::{channel, Receiver}; +use std::sync::mpsc::Receiver; use std::time::Instant; use tracy_client::{frame_mark, set_thread_name, span}; use wgpu::util::DeviceExt; @@ -765,11 +765,8 @@ struct UIEvent { fn main_thread(event_loop: EventLoopProxy, state: State, reciever: Receiver) { let mut state = state; - - let (script_reload_send, script_reload_recv) = channel(); - - let mut script = script::ScriptContext::new(None, script_reload_send.clone()) - .expect("Unable to create initial script context"); + let mut script = script::ScriptContext::new(); + script.init(); const SPF: f64 = 1.0 / 60.0; loop { @@ -814,22 +811,6 @@ fn main_thread(event_loop: EventLoopProxy, state: State, reciever: Re } } - { - let _span = span!("check script reload"); - let mut reload_script = false; - while let Ok(_) = script_reload_recv.try_recv() { - reload_script = true; - } - if reload_script { - eprintln!("RELOADING SCRIPT"); - let suspend_state = script.suspend(); - match script::ScriptContext::new(suspend_state, script_reload_send.clone()) { - Ok(new_script) => script = new_script, - Err(e) => eprintln!("WARNING: Script reload aborted, load failure: {e:?}"), - }; - } - } - { let _span = span!("update"); script.update(); diff --git a/src/script.rs b/src/script.rs index be3abd74..56086f5d 100644 --- a/src/script.rs +++ b/src/script.rs @@ -1,11 +1,9 @@ -use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use oden_js::{ module::loader::{ModuleLoader, ModuleSource}, Context, ContextRef, Result, Runtime, Value, }; use std::ffi::OsStr; -use std::sync::mpsc::{channel, Receiver, Sender}; -use std::sync::{Arc, Mutex}; +use std::sync::mpsc::{channel, Receiver}; use std::time::Instant; use tracy_client::span; use winit::event::*; @@ -20,19 +18,11 @@ use graphics::GraphicsCommand; mod typescript; use typescript::transpile_to_javascript; -struct Loader { - watcher: Arc>, -} +struct Loader {} impl Loader { - pub fn new(reload_trigger: Sender<()>) -> Loader { - let watcher = Arc::new(Mutex::new( - notify::recommended_watcher(move |_| { - let _ = reload_trigger.send(()); - }) - .expect("Unable to create watcher"), - )); - Loader { watcher } + pub fn new() -> Loader { + Loader {} } } @@ -47,17 +37,15 @@ impl ModuleLoader for Loader { contents }; - let mut watcher = self.watcher.lock().unwrap(); - let _ = watcher.watch(&path, RecursiveMode::NonRecursive); Ok(ModuleSource::JavaScript(contents)) } } pub struct ScriptContext { context: Context, + init: Value, update: Value, draw: Value, - suspend: Value, state: Value, @@ -69,9 +57,9 @@ pub struct ScriptContext { } impl ScriptContext { - pub fn new(suspend_state: Option>, reload_trigger: Sender<()>) -> Result { + pub fn new() -> Self { let mut runtime = Runtime::new(); - runtime.set_module_loader(Loader::new(reload_trigger)); + runtime.set_module_loader(Loader::new()); let mut context = Context::new(runtime); context.add_intrinsic_bigfloat(); @@ -80,31 +68,33 @@ impl ScriptContext { let (gfx_send, gfx_receive) = channel(); - let gfx = graphics::GraphicsAPI::define(&context, gfx_send.clone())?; - let _io = io::IoAPI::define(&context)?; - let time = time::TimeAPI::define(&context)?; - let input = input::InputAPI::define(&context)?; + let gfx = graphics::GraphicsAPI::define(&context, gfx_send.clone()) + .expect("Graphics module should load without error"); + let _io = io::IoAPI::define(&context).expect("IO module should load without error"); + let time = time::TimeAPI::define(&context).expect("Time module should load without error"); + let input = + input::InputAPI::define(&context).expect("Input module should load without error"); - let module = context.import_module("./main.ts", "")?; + let module = context + .import_module("./main.ts", "") + .expect("Unable to load main"); - let init = module.get_export(&context, "init")?; - let suspend = module.get_export(&context, "suspend")?; - let resume = module.get_export(&context, "resume")?; - let update = module.get_export(&context, "update")?; - let draw = module.get_export(&context, "draw")?; + let init = module + .get_export(&context, "init") + .expect("Unable to fetch init"); + let update = module + .get_export(&context, "update") + .expect("Unable to fetch update"); + let draw = module + .get_export(&context, "draw") + .expect("Unable to fetch draw"); - let mut state = init.call(&context, &[])?; - if let Some(buffer) = suspend_state { - if !resume.is_undefined() { - let serialized_state = context.deserialize(&buffer)?; - state = resume.call(&context, &[&serialized_state, &state])?; - } - } + let state = context.undefined(); - Ok(ScriptContext { + ScriptContext { context, - suspend, + init, update, draw, @@ -115,25 +105,6 @@ impl ScriptContext { time, input, - }) - } - - /// Allow the script to save its state before we destroy it and re-create - /// it. - pub fn suspend(&self) -> Option> { - let _span = span!("script suspend"); - if !self.suspend.is_undefined() { - let suspend_state = self - .suspend - .call(&self.context, &[&self.state]) - .expect("Exception in suspend"); - Some( - suspend_state - .serialize(&self.context) - .expect("Unable to serialize state"), - ) - } else { - None } } @@ -141,6 +112,15 @@ impl ScriptContext { // We would want a bi-directional gate for frames to not let the // game thread go to fast probably? And to discard whole frames &c. + pub fn init(&mut self) { + let _span = span!("script init"); + + self.state = self + .init + .call(&self.context, &[]) + .expect("Exception in init"); + } + pub fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { input, .. } => self.input.handle_keyboard_input(input), diff --git a/src/script/typescript.rs b/src/script/typescript.rs index dadeba6a..19bfc75b 100644 --- a/src/script/typescript.rs +++ b/src/script/typescript.rs @@ -57,20 +57,6 @@ fn format_swc_diagnostic(source_map: &SourceMap, diagnostic: &Diagnostic) -> Str } } -fn diagnostics_to_parse_error<'a>( - name: &str, - source_map: &SourceMap, - diagnostics: impl Iterator, -) -> Error { - Error::ParseError( - name.into(), - diagnostics - .map(|d| format_swc_diagnostic(source_map, d)) - .collect::>() - .join("\n\n"), - ) -} - fn ensure_no_fatal_swc_diagnostics<'a>( name: &str, source_map: &SourceMap, @@ -80,10 +66,13 @@ fn ensure_no_fatal_swc_diagnostics<'a>( .filter(|d| is_fatal_swc_diagnostic(d)) .collect::>(); if !fatal_diagnostics.is_empty() { - Err(diagnostics_to_parse_error( - name, - source_map, - fatal_diagnostics.into_iter(), + Err(Error::ParseError( + name.into(), + fatal_diagnostics + .iter() + .map(|d| format_swc_diagnostic(source_map, d)) + .collect::>() + .join("\n\n"), )) } else { Ok(()) @@ -120,12 +109,8 @@ pub fn transpile_to_javascript(path: &str, input: String) -> Result { let module = parser .parse_module() - .map_err(|e| e.into_diagnostic(&handler)) - .map_err(|mut e| { - e.emit(); - let diagnostics = diagnostics_cell.borrow(); - diagnostics_to_parse_error(path, &cm, diagnostics.iter()) - })?; + .map_err(|e| e.into_diagnostic(&handler).emit()) + .expect("failed to parse module."); let globals = Globals::default(); GLOBALS.set(&globals, || {