Always run toast eval inside the runtime (#3313)

This commit is contained in:
Evan Almloff authored and GitHub committed 2024-12-10 16:47:51 -08:00
1 parent ca70e8660d
commit d89ab3cfad
2 files changed
+23 -7

No files matched your search

+20 -4
View File
@@ -4,9 +4,11 @@
//! We also set up a little recursive timer that will attempt to reconnect if the connection is lost. //! We also set up a little recursive timer that will attempt to reconnect if the connection is lost.
use std::fmt::Display; use std::fmt::Display;
use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use dioxus_core::ScopeId; use dioxus_core::prelude::RuntimeGuard;
use dioxus_core::{Runtime, ScopeId};
use dioxus_devtools::{DevserverMsg, HotReloadMsg}; use dioxus_devtools::{DevserverMsg, HotReloadMsg};
use dioxus_document::eval; use dioxus_document::eval;
use futures_channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}; use futures_channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
@@ -22,17 +24,22 @@ const POLL_INTERVAL_SCALE_FACTOR: i32 = 2;
/// Amount of time that toats should be displayed. /// Amount of time that toats should be displayed.
const TOAST_TIMEOUT: Duration = Duration::from_secs(5); const TOAST_TIMEOUT: Duration = Duration::from_secs(5);
pub(crate) fn init() -> UnboundedReceiver<HotReloadMsg> { pub(crate) fn init(runtime: Rc<Runtime>) -> UnboundedReceiver<HotReloadMsg> {
// Create the tx/rx pair that we'll use for the top-level future in the dioxus loop // Create the tx/rx pair that we'll use for the top-level future in the dioxus loop
let (tx, rx) = unbounded(); let (tx, rx) = unbounded();
// Wire up the websocket to the devserver // Wire up the websocket to the devserver
make_ws(tx, POLL_INTERVAL_MIN, false); make_ws(runtime, tx, POLL_INTERVAL_MIN, false);
rx rx
} }
fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool) { fn make_ws(
runtime: Rc<Runtime>,
tx: UnboundedSender<HotReloadMsg>,
poll_interval: i32,
reload: bool,
) {
// Get the location of the devserver, using the current location plus the /_dioxus path // Get the location of the devserver, using the current location plus the /_dioxus path
// The idea here being that the devserver is always located on the /_dioxus behind a proxy // The idea here being that the devserver is always located on the /_dioxus behind a proxy
let location = web_sys::window().unwrap().location(); let location = web_sys::window().unwrap().location();
@@ -49,6 +56,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
// Set the onmessage handler to bounce messages off to the main dioxus loop // Set the onmessage handler to bounce messages off to the main dioxus loop
let tx_ = tx.clone(); let tx_ = tx.clone();
let runtime_ = runtime.clone();
ws.set_onmessage(Some( ws.set_onmessage(Some(
Closure::<dyn FnMut(MessageEvent)>::new(move |e: MessageEvent| { Closure::<dyn FnMut(MessageEvent)>::new(move |e: MessageEvent| {
let Ok(text) = e.data().dyn_into::<JsString>() else { let Ok(text) = e.data().dyn_into::<JsString>() else {
@@ -72,6 +80,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
// The devserver is telling us that it started a full rebuild. This does not mean that it is ready. // The devserver is telling us that it started a full rebuild. This does not mean that it is ready.
Ok(DevserverMsg::FullReloadStart) => show_toast( Ok(DevserverMsg::FullReloadStart) => show_toast(
runtime_.clone(),
"Your app is being rebuilt.", "Your app is being rebuilt.",
"A non-hot-reloadable change occurred and we must rebuild.", "A non-hot-reloadable change occurred and we must rebuild.",
ToastLevel::Info, ToastLevel::Info,
@@ -80,6 +89,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
), ),
// The devserver is telling us that the full rebuild failed. // The devserver is telling us that the full rebuild failed.
Ok(DevserverMsg::FullReloadFailed) => show_toast( Ok(DevserverMsg::FullReloadFailed) => show_toast(
runtime_.clone(),
"Oops! The build failed.", "Oops! The build failed.",
"We tried to rebuild your app, but something went wrong.", "We tried to rebuild your app, but something went wrong.",
ToastLevel::Error, ToastLevel::Error,
@@ -90,6 +100,7 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
// The devserver is telling us to reload the whole page // The devserver is telling us to reload the whole page
Ok(DevserverMsg::FullReloadCommand) => { Ok(DevserverMsg::FullReloadCommand) => {
show_toast( show_toast(
runtime_.clone(),
"Successfully rebuilt.", "Successfully rebuilt.",
"Your app was rebuilt successfully and without error.", "Your app was rebuilt successfully and without error.",
ToastLevel::Success, ToastLevel::Success,
@@ -121,11 +132,13 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
// set timeout to reload the page in timeout_ms // set timeout to reload the page in timeout_ms
let tx = tx.clone(); let tx = tx.clone();
let runtime = runtime.clone();
web_sys::window() web_sys::window()
.unwrap() .unwrap()
.set_timeout_with_callback_and_timeout_and_arguments_0( .set_timeout_with_callback_and_timeout_and_arguments_0(
Closure::<dyn FnMut()>::new(move || { Closure::<dyn FnMut()>::new(move || {
make_ws( make_ws(
runtime.clone(),
tx.clone(), tx.clone(),
POLL_INTERVAL_MAX.min(poll_interval * POLL_INTERVAL_SCALE_FACTOR), POLL_INTERVAL_MAX.min(poll_interval * POLL_INTERVAL_SCALE_FACTOR),
true, true,
@@ -189,6 +202,7 @@ impl Display for ToastLevel {
/// Displays a toast to the developer. /// Displays a toast to the developer.
fn show_toast( fn show_toast(
runtime: Rc<Runtime>,
header_text: &str, header_text: &str,
message: &str, message: &str,
level: ToastLevel, level: ToastLevel,
@@ -202,6 +216,8 @@ fn show_toast(
false => "showDXToast", false => "showDXToast",
}; };
// Create the guard before running eval which uses the global runtime context
let _guard = RuntimeGuard::new(runtime);
ScopeId::ROOT.in_runtime(|| { ScopeId::ROOT.in_runtime(|| {
eval(&format!( eval(&format!(
r#" r#"
+3 -3
View File
@@ -66,11 +66,11 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! {
#[cfg(feature = "document")] #[cfg(feature = "document")]
virtual_dom.in_runtime(document::init_document); virtual_dom.in_runtime(document::init_document);
#[cfg(all(feature = "devtools", debug_assertions))]
let mut hotreload_rx = devtools::init();
let runtime = virtual_dom.runtime(); let runtime = virtual_dom.runtime();
#[cfg(all(feature = "devtools", debug_assertions))]
let mut hotreload_rx = devtools::init(runtime.clone());
let should_hydrate = web_config.hydrate; let should_hydrate = web_config.hydrate;
let mut websys_dom = WebsysDom::new(web_config, runtime); let mut websys_dom = WebsysDom::new(web_config, runtime);