dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

Using recv in js inside an eval on desktop blocks all js if it doesnt have any data to fetch

Open elias098 opened this issue 10 months ago • 2 comments

Problem

Currently when you do eval("await dioxus.recv();") on desktop and dont send a message it blocks all js from running, including devtool console and events.

Steps To Reproduce

Heres the code i used to test it

#![allow(non_snake_case)]

use dioxus::{desktop::use_window, prelude::*};
use log::LevelFilter;

fn main() {
    // Init debug
    dioxus_logger::init(LevelFilter::Info).expect("failed to init logger");

    dioxus::launch(App);
}

#[component]
fn App() -> Element {
    // Build cool things ✌️
    let windows = use_window();
    use_hook(|| windows.devtool());
    let mut signal = use_signal(|| false);
    use_effect(move || {
        if signal() {
            eval(
                r#"
                    window.alert("1"); 
                    await dioxus.recv(); 
                    window.alert("2");
                "#,
            );
        }
    });

    let onclick = move |_| signal.with_mut(|v| *v = !*v);
    rsx! {
        button {
            onclick,
            "locks js"
        }
        {format!("{}", signal())}
    }
}

Environment:

  • Dioxus version: 0.5.1
  • Rust version: 1.76.0
  • OS info: MacOS
  • App platform: desktop

Questionnaire

  • [ ] I'm interested in fixing this myself but don't know where to start
  • [ ] I would like to fix and I have a solution
  • [ ] I don't have time to fix this right now, but maybe later

elias098 avatar Apr 11 '24 18:04 elias098

as far as i understand it the offending code is the infinite loop in the timeout here in query.rs

recv: function () {
        return new Promise((resolve, _reject) => {
            // Ever 50 ms check for new data
            let timeout = setTimeout(() => {
                let __msg = null;
                while (true) {
                    let __data = _message_queue.shift();
                    if (__data) {
                        __msg = __data;
                        break;
                    }
                }
                clearTimeout(timeout);
                resolve(__msg);
            }, 50);
        });
    },

the above timeout should likely be changed to an interval without the inner loop instead

elias098 avatar Apr 11 '24 18:04 elias098

not directly related but it should probably be cleaned up when dropping UseEval as well

elias098 avatar Apr 11 '24 19:04 elias098