Fix undefined behavior in the editor wasm bridge (#414)

* removed possible undifined behavior

* changed naming of Editor -> JsEditorHandle

* fix rust formatting

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mfish33 2021-12-20 17:55:31 -05:00 committed by Keavon Chambers
parent 6701437433
commit 53a1f19af0
3 changed files with 32 additions and 15 deletions

View file

@ -2,37 +2,40 @@
// It serves as a thin wrapper over the editor backend API that relies
// on the dispatcher messaging system and more complex Rust data types.
use std::cell::{Cell, UnsafeCell};
use std::cell::Cell;
use crate::helpers::Error;
use crate::type_translators::{translate_blend_mode, translate_key, translate_tool_type};
use crate::EDITOR_HAS_CRASHED;
use crate::{EDITOR_HAS_CRASHED, EDITOR_INSTANCES};
use editor::consts::FILE_SAVE_SUFFIX;
use editor::input::input_preprocessor::ModifierKeys;
use editor::input::mouse::{EditorMouseState, ScrollDelta, ViewportBounds};
use editor::message_prelude::*;
use editor::misc::EditorError;
use editor::tool::{tool_options::ToolOptions, tools, ToolType};
use editor::Color;
use editor::LayerId;
use editor::{message_prelude::*, Editor};
use wasm_bindgen::prelude::*;
// 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]
pub struct Editor {
editor: UnsafeCell<editor::Editor>,
pub struct JsEditorHandle {
editor_id: u64,
instance_received_crashed: Cell<bool>,
handle_response: js_sys::Function,
}
#[wasm_bindgen]
impl Editor {
impl JsEditorHandle {
#[wasm_bindgen(constructor)]
pub fn new(handle_response: js_sys::Function) -> Editor {
Editor {
editor: UnsafeCell::new(editor::Editor::new()),
pub fn new(handle_response: js_sys::Function) -> JsEditorHandle {
let editor_id = generate_uuid();
let editor = Editor::new();
EDITOR_INSTANCES.with(|instances| instances.borrow_mut().insert(editor_id, editor));
JsEditorHandle {
editor_id,
instance_received_crashed: Cell::new(false),
handle_response,
}
@ -50,9 +53,13 @@ impl Editor {
return;
}
let editor = unsafe { self.editor.get().as_mut().unwrap() };
// Dispatch the message and receive a vector of FrontendMessage responses
let responses = editor.handle_message(message.into());
let responses = 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() {
// Send each FrontendMessage to the JavaScript frontend
self.handle_response(response);
@ -432,6 +439,12 @@ impl Editor {
}
}
impl Drop for JsEditorHandle {
fn drop(&mut self) {
EDITOR_INSTANCES.with(|instances| instances.borrow_mut().remove(&self.editor_id));
}
}
/// Access a handle to WASM memory
#[wasm_bindgen]
pub fn wasm_memory() -> JsValue {

View file

@ -6,12 +6,16 @@ pub mod type_translators;
use editor::message_prelude::FrontendMessage;
use logging::WasmLog;
use std::cell::RefCell;
use std::collections::HashMap;
use std::panic;
use wasm_bindgen::prelude::*;
// Set up the persistent editor backend state
static LOGGER: WasmLog = WasmLog;
thread_local! { pub static EDITOR_HAS_CRASHED: RefCell<Option<FrontendMessage>> = RefCell::new(None); }
thread_local! {
pub static EDITOR_HAS_CRASHED: RefCell<Option<FrontendMessage>> = RefCell::new(None);
pub static EDITOR_INSTANCES: RefCell<HashMap<u64, editor::Editor>> = RefCell::new(HashMap::new());
}
// Initialize the backend
#[wasm_bindgen(start)]