Compare commits
4 commits
642ced45f8
...
043a3ee183
| Author | SHA1 | Date | |
|---|---|---|---|
| 043a3ee183 | |||
| e32643486d | |||
| d79b891b7b | |||
| a850c3cc58 |
9 changed files with 272 additions and 50 deletions
99
Cargo.lock
generated
99
Cargo.lock
generated
|
|
@ -434,6 +434,25 @@ dependencies = [
|
||||||
"cfg-if",
|
"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]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
@ -554,6 +573,18 @@ dependencies = [
|
||||||
"simd-adler32",
|
"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]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.26"
|
version = "1.0.26"
|
||||||
|
|
@ -627,6 +658,15 @@ dependencies = [
|
||||||
"syn 2.0.18",
|
"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]]
|
[[package]]
|
||||||
name = "generator"
|
name = "generator"
|
||||||
version = "0.7.5"
|
version = "0.7.5"
|
||||||
|
|
@ -828,6 +868,26 @@ dependencies = [
|
||||||
"hashbrown",
|
"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]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
|
|
@ -917,6 +977,26 @@ dependencies = [
|
||||||
"pkg-config",
|
"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]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
|
@ -1247,6 +1327,24 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"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]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
|
|
@ -1393,6 +1491,7 @@ dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"image",
|
"image",
|
||||||
"log",
|
"log",
|
||||||
|
"notify",
|
||||||
"oden-js",
|
"oden-js",
|
||||||
"pollster",
|
"pollster",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ bytemuck = { version = "1.13", features = ["derive"] }
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
image = { version = "0.24", default-features = false, features = ["png"] }
|
image = { version = "0.24", default-features = false, features = ["png"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
notify = "6"
|
||||||
oden-js = { path = "oden-js" }
|
oden-js = { path = "oden-js" }
|
||||||
pollster = "0.3"
|
pollster = "0.3"
|
||||||
swc_common = "0.31.16"
|
swc_common = "0.31.16"
|
||||||
|
|
|
||||||
14
game/main.ts
14
game/main.ts
|
|
@ -49,6 +49,20 @@ export function init() {
|
||||||
load_assets();
|
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;
|
const friction = 0.6;
|
||||||
let robo_vel = new_v2(0);
|
let robo_vel = new_v2(0);
|
||||||
let robo_pos = new_v2(10);
|
let robo_pos = new_v2(10);
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,9 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
bitflags = "1"
|
bitflags = "1"
|
||||||
thiserror = "1"
|
|
||||||
oden-js-sys = {path = "../oden-js-sys"}
|
oden-js-sys = {path = "../oden-js-sys"}
|
||||||
|
thiserror = "1"
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_matches = "1.5.0"
|
assert_matches = "1.5.0"
|
||||||
|
|
|
||||||
|
|
@ -396,6 +396,23 @@ impl ContextRef {
|
||||||
pub fn process_all_jobs(&self) -> Result<()> {
|
pub fn process_all_jobs(&self) -> Result<()> {
|
||||||
self.get_runtime().process_all_jobs()
|
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<Value> {
|
||||||
|
self.check_exception(unsafe {
|
||||||
|
sys::JS_ReadObject(
|
||||||
|
self.ctx,
|
||||||
|
data.as_ptr(),
|
||||||
|
data.len(),
|
||||||
|
sys::JS_READ_OBJ_REFERENCE as i32,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
||||||
|
|
@ -337,6 +337,42 @@ 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<Vec<u8>> {
|
||||||
|
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 {
|
impl fmt::Debug for ValueRef {
|
||||||
|
|
|
||||||
25
src/lib.rs
25
src/lib.rs
|
|
@ -1,7 +1,7 @@
|
||||||
use bytemuck;
|
use bytemuck;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::{channel, Receiver};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use tracy_client::{frame_mark, set_thread_name, span};
|
use tracy_client::{frame_mark, set_thread_name, span};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
@ -765,8 +765,11 @@ struct UIEvent {
|
||||||
|
|
||||||
fn main_thread(event_loop: EventLoopProxy<OdenEvent>, state: State, reciever: Receiver<UIEvent>) {
|
fn main_thread(event_loop: EventLoopProxy<OdenEvent>, state: State, reciever: Receiver<UIEvent>) {
|
||||||
let mut state = state;
|
let mut state = state;
|
||||||
let mut script = script::ScriptContext::new();
|
|
||||||
script.init();
|
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");
|
||||||
|
|
||||||
const SPF: f64 = 1.0 / 60.0;
|
const SPF: f64 = 1.0 / 60.0;
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -811,6 +814,22 @@ fn main_thread(event_loop: EventLoopProxy<OdenEvent>, 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");
|
let _span = span!("update");
|
||||||
script.update();
|
script.update();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
use oden_js::{
|
use oden_js::{
|
||||||
module::loader::{ModuleLoader, ModuleSource},
|
module::loader::{ModuleLoader, ModuleSource},
|
||||||
Context, ContextRef, Result, Runtime, Value,
|
Context, ContextRef, Result, Runtime, Value,
|
||||||
};
|
};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::sync::mpsc::{channel, Receiver};
|
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use tracy_client::span;
|
use tracy_client::span;
|
||||||
use winit::event::*;
|
use winit::event::*;
|
||||||
|
|
@ -18,11 +20,19 @@ use graphics::GraphicsCommand;
|
||||||
mod typescript;
|
mod typescript;
|
||||||
use typescript::transpile_to_javascript;
|
use typescript::transpile_to_javascript;
|
||||||
|
|
||||||
struct Loader {}
|
struct Loader {
|
||||||
|
watcher: Arc<Mutex<RecommendedWatcher>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Loader {
|
impl Loader {
|
||||||
pub fn new() -> Loader {
|
pub fn new(reload_trigger: Sender<()>) -> Loader {
|
||||||
Loader {}
|
let watcher = Arc::new(Mutex::new(
|
||||||
|
notify::recommended_watcher(move |_| {
|
||||||
|
let _ = reload_trigger.send(());
|
||||||
|
})
|
||||||
|
.expect("Unable to create watcher"),
|
||||||
|
));
|
||||||
|
Loader { watcher }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,15 +47,17 @@ impl ModuleLoader for Loader {
|
||||||
contents
|
contents
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut watcher = self.watcher.lock().unwrap();
|
||||||
|
let _ = watcher.watch(&path, RecursiveMode::NonRecursive);
|
||||||
Ok(ModuleSource::JavaScript(contents))
|
Ok(ModuleSource::JavaScript(contents))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ScriptContext {
|
pub struct ScriptContext {
|
||||||
context: Context,
|
context: Context,
|
||||||
init: Value,
|
|
||||||
update: Value,
|
update: Value,
|
||||||
draw: Value,
|
draw: Value,
|
||||||
|
suspend: Value,
|
||||||
|
|
||||||
state: Value,
|
state: Value,
|
||||||
|
|
||||||
|
|
@ -57,9 +69,9 @@ pub struct ScriptContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScriptContext {
|
impl ScriptContext {
|
||||||
pub fn new() -> Self {
|
pub fn new(suspend_state: Option<Vec<u8>>, reload_trigger: Sender<()>) -> Result<Self> {
|
||||||
let mut runtime = Runtime::new();
|
let mut runtime = Runtime::new();
|
||||||
runtime.set_module_loader(Loader::new());
|
runtime.set_module_loader(Loader::new(reload_trigger));
|
||||||
|
|
||||||
let mut context = Context::new(runtime);
|
let mut context = Context::new(runtime);
|
||||||
context.add_intrinsic_bigfloat();
|
context.add_intrinsic_bigfloat();
|
||||||
|
|
@ -68,33 +80,31 @@ impl ScriptContext {
|
||||||
|
|
||||||
let (gfx_send, gfx_receive) = channel();
|
let (gfx_send, gfx_receive) = channel();
|
||||||
|
|
||||||
let gfx = graphics::GraphicsAPI::define(&context, gfx_send.clone())
|
let gfx = graphics::GraphicsAPI::define(&context, gfx_send.clone())?;
|
||||||
.expect("Graphics module should load without error");
|
let _io = io::IoAPI::define(&context)?;
|
||||||
let _io = io::IoAPI::define(&context).expect("IO module should load without error");
|
let time = time::TimeAPI::define(&context)?;
|
||||||
let time = time::TimeAPI::define(&context).expect("Time module should load without error");
|
let input = input::InputAPI::define(&context)?;
|
||||||
let input =
|
|
||||||
input::InputAPI::define(&context).expect("Input module should load without error");
|
|
||||||
|
|
||||||
let module = context
|
let module = context.import_module("./main.ts", "")?;
|
||||||
.import_module("./main.ts", "")
|
|
||||||
.expect("Unable to load main");
|
|
||||||
|
|
||||||
let init = module
|
let init = module.get_export(&context, "init")?;
|
||||||
.get_export(&context, "init")
|
let suspend = module.get_export(&context, "suspend")?;
|
||||||
.expect("Unable to fetch init");
|
let resume = module.get_export(&context, "resume")?;
|
||||||
let update = module
|
let update = module.get_export(&context, "update")?;
|
||||||
.get_export(&context, "update")
|
let draw = module.get_export(&context, "draw")?;
|
||||||
.expect("Unable to fetch update");
|
|
||||||
let draw = module
|
|
||||||
.get_export(&context, "draw")
|
|
||||||
.expect("Unable to fetch draw");
|
|
||||||
|
|
||||||
let state = context.undefined();
|
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])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScriptContext {
|
Ok(ScriptContext {
|
||||||
context,
|
context,
|
||||||
|
|
||||||
init,
|
suspend,
|
||||||
update,
|
update,
|
||||||
draw,
|
draw,
|
||||||
|
|
||||||
|
|
@ -105,6 +115,25 @@ impl ScriptContext {
|
||||||
|
|
||||||
time,
|
time,
|
||||||
input,
|
input,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allow the script to save its state before we destroy it and re-create
|
||||||
|
/// it.
|
||||||
|
pub fn suspend(&self) -> Option<Vec<u8>> {
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,15 +141,6 @@ impl ScriptContext {
|
||||||
// We would want a bi-directional gate for frames to not let the
|
// 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.
|
// 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 {
|
pub fn input(&mut self, event: &WindowEvent) -> bool {
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::KeyboardInput { input, .. } => self.input.handle_keyboard_input(input),
|
WindowEvent::KeyboardInput { input, .. } => self.input.handle_keyboard_input(input),
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,20 @@ fn format_swc_diagnostic(source_map: &SourceMap, diagnostic: &Diagnostic) -> Str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn diagnostics_to_parse_error<'a>(
|
||||||
|
name: &str,
|
||||||
|
source_map: &SourceMap,
|
||||||
|
diagnostics: impl Iterator<Item = &'a Diagnostic>,
|
||||||
|
) -> Error {
|
||||||
|
Error::ParseError(
|
||||||
|
name.into(),
|
||||||
|
diagnostics
|
||||||
|
.map(|d| format_swc_diagnostic(source_map, d))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n\n"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn ensure_no_fatal_swc_diagnostics<'a>(
|
fn ensure_no_fatal_swc_diagnostics<'a>(
|
||||||
name: &str,
|
name: &str,
|
||||||
source_map: &SourceMap,
|
source_map: &SourceMap,
|
||||||
|
|
@ -66,13 +80,10 @@ fn ensure_no_fatal_swc_diagnostics<'a>(
|
||||||
.filter(|d| is_fatal_swc_diagnostic(d))
|
.filter(|d| is_fatal_swc_diagnostic(d))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if !fatal_diagnostics.is_empty() {
|
if !fatal_diagnostics.is_empty() {
|
||||||
Err(Error::ParseError(
|
Err(diagnostics_to_parse_error(
|
||||||
name.into(),
|
name,
|
||||||
fatal_diagnostics
|
source_map,
|
||||||
.iter()
|
fatal_diagnostics.into_iter(),
|
||||||
.map(|d| format_swc_diagnostic(source_map, d))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\n\n"),
|
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -109,8 +120,12 @@ pub fn transpile_to_javascript(path: &str, input: String) -> Result<String> {
|
||||||
|
|
||||||
let module = parser
|
let module = parser
|
||||||
.parse_module()
|
.parse_module()
|
||||||
.map_err(|e| e.into_diagnostic(&handler).emit())
|
.map_err(|e| e.into_diagnostic(&handler))
|
||||||
.expect("failed to parse module.");
|
.map_err(|mut e| {
|
||||||
|
e.emit();
|
||||||
|
let diagnostics = diagnostics_cell.borrow();
|
||||||
|
diagnostics_to_parse_error(path, &cm, diagnostics.iter())
|
||||||
|
})?;
|
||||||
|
|
||||||
let globals = Globals::default();
|
let globals = Globals::default();
|
||||||
GLOBALS.set(&globals, || {
|
GLOBALS.set(&globals, || {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue