Refactor the TypeScript data flow for full type safety and auto-generation of Rust types (#3865)

* Migrate Specta to Tsify to auto-generate messages.ts, working except colors and widgets

* Adopt the generated FillColor/Color/GradientStops

* Fix widget typing

* Separate WidgetGroup enum variants into wrapper structs

* Small rename

* Simplify widgets further

* Clean up message type references

* Switch type imports to the auto-generated file

* Remove lowercase serde rename

* Fix FillChoice deserialization

* Fix small regression from #3837

* Improve type safety

* Make WidgetSpan type-safe

* More cleanup and type safety

* More type safety

* More type safety

* Get the rest to type-check without errors; improve widget builder macro to have optional icons; improve Svelte 5 configs

* Cargo fmt

* Fix imports

* Update outdated readme info

* Fix lint command rename references

* Fix typos

* One more typos fix

* Remove unnecessary dep: prefix from the edited Cargo.toml files

* Remove excess parts from Cargo.toml

* Fix compiling on desktop

* Revert "Remove excess parts from Cargo.toml"

This reverts commit 6b711117b3a5d5d8a3ee20f36a43bc74930b7c82.

* Update dev docs with simpler, more accurate instructions
This commit is contained in:
Keavon Chambers
2026-03-09 16:35:04 -07:00
parent fbd2658148
commit 52d2b38a82
199 changed files with 2265 additions and 2811 deletions
+11 -8
View File
@@ -1,14 +1,17 @@
# Overview of `/frontend/wasm/`
## WASM wrapper API: `src/editor_api.rs`
Provides bindings for JS to call functions defined in this file, and for FrontendMessages to be sent from Rust back to JS in the form of a callback to the subscription router. This WASM wrapper crate, since it's written in Rust, is able to call into the Editor crate's codebase and send FrontendMessages back to JS.
## Wasm wrapper API: `src/editor_api.rs`
Provides bindings for JS to call functions defined in this file, and for `FrontendMessage`s to be sent from Rust back to JS in the form of a callback to the subscription router. This Wasm wrapper crate, since it's written in Rust, is able to call into the Editor crate's codebase and send `FrontendMessage`s back to JS.
## WASM wrapper helper code: `src/helpers.rs`
Assorted function and struct definitions used in the WASM wrapper.
## Wasm wrapper helper code: `src/helpers.rs`
## WASM wrapper initialization: `src/lib.rs`
Entry point for the Rust entire codebase in the WASM environment. Initializes the WASM module and persistent storage for editor and WASM wrapper instances.
Assorted function and struct definitions used in the Wasm wrapper.
## WASM wrapper tests: `tests/`
We currently have no WASM wrapper tests, but this is where they would go.
## Native communication: `src/native_communication.rs`
Handles receiving serialized `FrontendMessage`s from the native desktop app via an `ArrayBuffer` and forwarding them to JS through the editor handle.
## Wasm wrapper initialization: `src/lib.rs`
Entry point for the Rust codebase in the Wasm environment. Sets up panic hooks and logging, and defines thread-local storage for the editor instance, editor handle, message buffer, and panic dialog callback.
+5 -10
View File
@@ -69,7 +69,7 @@ pub fn is_platform_native() -> bool {
#[wasm_bindgen]
#[derive(Clone)]
pub struct EditorHandle {
/// This callback is called by the editor's dispatcher when directing FrontendMessages from Rust to JS
/// This callback is called by the editor's dispatcher when directing `FrontendMessage`s from Rust to JS
frontend_message_handler_callback: js_sys::Function,
}
@@ -154,7 +154,7 @@ impl EditorHandle {
log::error!("Failed to serialize message");
return;
};
crate::native_communcation::send_message_to_cef(serialized_message)
crate::native_communication::send_message_to_cef(serialized_message)
}
// Sends a FrontendMessage to JavaScript
@@ -190,7 +190,7 @@ impl EditorHandle {
#[wasm_bindgen(js_name = initAfterFrontendReady)]
pub fn init_after_frontend_ready(&self) {
#[cfg(feature = "native")]
crate::native_communcation::initialize_native_communication();
crate::native_communication::initialize_native_communication();
self.dispatch(PortfolioMessage::Init);
@@ -955,16 +955,11 @@ pub fn sample_interpolated_gradient(position: Vec<f64>, midpoint: Vec<f64>, colo
}
#[wasm_bindgen(js_name = evaluateGradientAtPosition)]
pub fn evaluate_gradient_at_position(t: f64, position: Vec<f64>, midpoint: Vec<f64>, color: Vec<JsValue>) -> Object {
pub fn evaluate_gradient_at_position(t: f64, position: Vec<f64>, midpoint: Vec<f64>, color: Vec<JsValue>) -> JsValue {
let color = color.into_iter().filter_map(|c| serde_wasm_bindgen::from_value(c).ok()).collect();
let color = GradientStops { position, midpoint, color }.evaluate(t);
let obj = Object::new();
Reflect::set(&obj, &JsValue::from_str("red"), &JsValue::from_f64(color.r() as f64)).unwrap();
Reflect::set(&obj, &JsValue::from_str("green"), &JsValue::from_f64(color.g() as f64)).unwrap();
Reflect::set(&obj, &JsValue::from_str("blue"), &JsValue::from_f64(color.b() as f64)).unwrap();
Reflect::set(&obj, &JsValue::from_str("alpha"), &JsValue::from_f64(color.a() as f64)).unwrap();
obj
serde_wasm_bindgen::to_value(&color).unwrap()
}
/// Helper function for calling JS's `requestAnimationFrame` with the given closure
+1 -1
View File
@@ -6,7 +6,7 @@ extern crate log;
pub mod editor_api;
pub mod helpers;
pub mod native_communcation;
pub mod native_communication;
use editor::messages::prelude::*;
use std::panic;