not-fl3 / miniquad

Cross platform rendering in Rust
Apache License 2.0
1.54k stars 173 forks source link

Use of `&mut Context` from `EventHandler` causes `BorrowedMutError` in wasm #373

Open zbrachinara opened 1 year ago

zbrachinara commented 1 year ago

On wasm, when GraphicsContext::get_clipboard is called from inside either EventHandler::mouse_button_down_event or EventHandler::key_down_event (but likely all event handlers which take a &mut Context), it causes a panic by RefCell BorrowedMutError.

Can be reproduced using this code (master branch of miniquad patched in using cargo patch) with current version of macroquad on crates.io:

use macroquad::miniquad::EventHandler;

struct Handler;

impl EventHandler for Handler {
    fn update(&mut self, _ctx: &mut macroquad::miniquad::Context) {}
    fn draw(&mut self, _ctx: &mut macroquad::miniquad::Context) {}

    fn key_down_event(
        &mut self,
        ctx: &mut macroquad::miniquad::Context,
        _: macroquad::prelude::KeyCode,
        _: macroquad::miniquad::KeyMods,
        _: bool,
    ) {
        ctx.clipboard_get();
    }
}

#[macroquad::main("")]
async fn main() {
    let mut handler = Handler;
    let id = macroquad::input::utils::register_input_subscriber();
    loop {
        macroquad::input::utils::repeat_all_miniquad_input(&mut handler, id);
        macroquad::window::next_frame().await
    }
}

Compiling for wasm, running the program, then pressing a key while focused on the window causes the panic.

Initially discovered in https://github.com/optozorax/egui-macroquad/issues/34

not-fl3 commented 3 months ago

Hmm, I've tried it. Miniquad do not have &mut Context argument for quite a while, I fixed your example to make it run with a latest miniquad:

use macroquad::miniquad::EventHandler;

struct Handler;

impl EventHandler for Handler {
    fn update(&mut self) {}
    fn draw(&mut self) {}

    fn key_down_event(
        &mut self,
        _: macroquad::prelude::KeyCode,
        _: macroquad::miniquad::KeyMods,
        _: bool,
    ) {
        miniquad::window::clipboard_get();
    }
}

#[macroquad::main("")]
async fn main() {
    let mut handler = Handler;
    let id = macroquad::input::utils::register_input_subscriber();
    loop {
        macroquad::input::utils::repeat_all_miniquad_input(&mut handler, id);
        macroquad::window::next_frame().await
    }
}

and it seems to work fine, I do not have any errors on web. Maybe the bug got fixed in more recent miniquad versions?