Add frontend file structure docs and some related cleanup

This commit is contained in:
Keavon Chambers 2022-05-23 19:13:51 -07:00
parent e4e37cca7b
commit d5b43ef2da
21 changed files with 168 additions and 145 deletions

View file

@ -19,23 +19,39 @@ use serde_wasm_bindgen::{self, from_value};
use std::sync::atomic::Ordering;
use wasm_bindgen::prelude::*;
/// Set the random seed used by the editor by calling this from JS upon initialization.
/// This is necessary because WASM doesn't have a random number generator.
#[wasm_bindgen]
pub fn set_random_seed(seed: u64) {
editor::communication::set_uuid_seed(seed);
}
/// Access a handle to WASM memory
#[wasm_bindgen]
pub fn wasm_memory() -> JsValue {
wasm_bindgen::memory()
}
// To avoid wasm-bindgen from checking mutable reference issues using WasmRefCell we must make all methods take a non mutable reference to self.
// Not doing this creates an issue when rust calls into JS which calls back to rust in the same call stack.
#[wasm_bindgen]
#[derive(Clone)]
pub struct JsEditorHandle {
editor_id: u64,
handle_response: js_sys::Function,
frontend_message_handler_callback: js_sys::Function,
}
#[wasm_bindgen]
#[allow(clippy::too_many_arguments)]
impl JsEditorHandle {
#[wasm_bindgen(constructor)]
pub fn new(handle_response: js_sys::Function) -> Self {
pub fn new(frontend_message_handler_callback: js_sys::Function) -> Self {
let editor_id = generate_uuid();
let editor = Editor::new();
let editor_handle = JsEditorHandle { editor_id, handle_response };
let editor_handle = JsEditorHandle {
editor_id,
frontend_message_handler_callback,
};
EDITOR_INSTANCES.with(|instances| instances.borrow_mut().insert(editor_id, editor));
JS_EDITOR_HANDLES.with(|instances| instances.borrow_mut().insert(editor_id, editor_handle.clone()));
editor_handle
@ -48,27 +64,27 @@ impl JsEditorHandle {
return;
}
let responses = EDITOR_INSTANCES.with(|instances| {
let frontend_messages = EDITOR_INSTANCES.with(|instances| {
instances
.borrow_mut()
.get_mut(&self.editor_id)
.expect("EDITOR_INSTANCES does not contain the current editor_id")
.handle_message(message.into())
});
for response in responses.into_iter() {
for message in frontend_messages.into_iter() {
// Send each FrontendMessage to the JavaScript frontend
self.handle_response(response);
self.send_frontend_message_to_js(message);
}
}
// Sends a FrontendMessage to JavaScript
fn handle_response(&self, message: FrontendMessage) {
fn send_frontend_message_to_js(&self, message: FrontendMessage) {
let message_type = message.to_discriminant().local_name();
let serializer = serde_wasm_bindgen::Serializer::new().serialize_large_number_types_as_bigints(true);
let message_data = message.serialize(&serializer).expect("Failed to serialize FrontendMessage");
let js_return_value = self.handle_response.call2(&JsValue::null(), &JsValue::from(message_type), &message_data);
let js_return_value = self.frontend_message_handler_callback.call2(&JsValue::null(), &JsValue::from(message_type), &message_data);
if let Err(error) = js_return_value {
log::error!(
@ -111,6 +127,30 @@ impl JsEditorHandle {
EDITOR_HAS_CRASHED.load(Ordering::SeqCst)
}
/// Get the constant `FILE_SAVE_SUFFIX`
#[wasm_bindgen]
pub fn file_save_suffix(&self) -> String {
FILE_SAVE_SUFFIX.into()
}
/// Get the constant `GRAPHITE_DOCUMENT_VERSION`
#[wasm_bindgen]
pub fn graphite_document_version(&self) -> String {
GRAPHITE_DOCUMENT_VERSION.to_string()
}
/// Get the constant `i32::MAX`
#[wasm_bindgen]
pub fn i32_max(&self) -> i32 {
i32::MAX
}
/// Get the constant `i32::MIN`
#[wasm_bindgen]
pub fn i32_min(&self) -> i32 {
i32::MIN
}
/// Request that the Node Graph panel be shown or hidden by toggling the visibility state
pub fn toggle_node_graph_visibility(&self) {
self.dispatch(WorkspaceMessage::NodeGraphToggleVisibility);
@ -491,8 +531,8 @@ impl JsEditorHandle {
// Needed to make JsEditorHandle functions pub to Rust.
// The reason is not fully clear but it has to do with the #[wasm_bindgen] procedural macro.
impl JsEditorHandle {
pub fn handle_response_rust_proxy(&self, message: FrontendMessage) {
self.handle_response(message);
pub fn send_frontend_message_to_js_rust_proxy(&self, message: FrontendMessage) {
self.send_frontend_message_to_js(message);
}
}
@ -501,40 +541,3 @@ impl Drop for JsEditorHandle {
EDITOR_INSTANCES.with(|instances| instances.borrow_mut().remove(&self.editor_id));
}
}
/// Set the random seed used by the editor by calling this from JS upon initialization.
/// This is necessary because WASM doesn't have a random number generator.
#[wasm_bindgen]
pub fn set_random_seed(seed: u64) {
editor::communication::set_uuid_seed(seed)
}
/// Access a handle to WASM memory
#[wasm_bindgen]
pub fn wasm_memory() -> JsValue {
wasm_bindgen::memory()
}
/// Get the constant `FILE_SAVE_SUFFIX`
#[wasm_bindgen]
pub fn file_save_suffix() -> String {
FILE_SAVE_SUFFIX.into()
}
/// Get the constant `GRAPHITE_DOCUMENT_VERSION`
#[wasm_bindgen]
pub fn graphite_version() -> String {
GRAPHITE_DOCUMENT_VERSION.to_string()
}
/// Get the constant `i32::MAX`
#[wasm_bindgen]
pub fn i32_max() -> i32 {
i32::MAX
}
/// Get the constant `i32::MIN`
#[wasm_bindgen]
pub fn i32_min() -> i32 {
i32::MIN
}

View file

@ -13,7 +13,7 @@ pub fn panic_hook(info: &panic::PanicInfo) {
log::error!("{}", info);
JS_EDITOR_HANDLES.with(|instances| {
instances.borrow_mut().values_mut().for_each(|instance| {
instance.handle_response_rust_proxy(FrontendMessage::DisplayDialogPanic {
instance.send_frontend_message_to_js_rust_proxy(FrontendMessage::DisplayDialogPanic {
panic_info: panic_info.clone(),
title: title.clone(),
description: description.clone(),

View file

@ -1,7 +1,8 @@
pub mod api;
pub mod editor_api;
pub mod helpers;
use helpers::{panic_hook, WasmLog};
use std::cell::RefCell;
use std::collections::HashMap;
use std::panic;
@ -13,7 +14,7 @@ pub static EDITOR_HAS_CRASHED: AtomicBool = AtomicBool::new(false);
pub static LOGGER: WasmLog = WasmLog;
thread_local! {
pub static EDITOR_INSTANCES: RefCell<HashMap<u64, editor::Editor>> = RefCell::new(HashMap::new());
pub static JS_EDITOR_HANDLES: RefCell<HashMap<u64, api::JsEditorHandle>> = RefCell::new(HashMap::new());
pub static JS_EDITOR_HANDLES: RefCell<HashMap<u64, editor_api::JsEditorHandle>> = RefCell::new(HashMap::new());
}
/// Initialize the backend