lib.rs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. use dioxus_core::internal::HotReloadedTemplate;
  2. use dioxus_core::{ScopeId, VirtualDom};
  3. use dioxus_signals::{GlobalKey, Signal, Writable};
  4. pub use dioxus_devtools_types::*;
  5. pub use subsecond;
  6. use subsecond::PatchError;
  7. /// Applies template and literal changes to the VirtualDom
  8. ///
  9. /// Assets need to be handled by the renderer.
  10. pub fn apply_changes(dom: &VirtualDom, msg: &HotReloadMsg) {
  11. try_apply_changes(dom, msg).unwrap()
  12. }
  13. /// Applies template and literal changes to the VirtualDom, but doesn't panic if patching fails.
  14. ///
  15. /// Assets need to be handled by the renderer.
  16. pub fn try_apply_changes(dom: &VirtualDom, msg: &HotReloadMsg) -> Result<(), PatchError> {
  17. dom.runtime().on_scope(ScopeId::ROOT, || {
  18. // 1. Update signals...
  19. let ctx = dioxus_signals::get_global_context();
  20. for template in &msg.templates {
  21. let value = template.template.clone();
  22. let key = GlobalKey::File {
  23. file: template.key.file.as_str(),
  24. line: template.key.line as _,
  25. column: template.key.column as _,
  26. index: template.key.index as _,
  27. };
  28. if let Some(mut signal) = ctx.get_signal_with_key(key.clone()) {
  29. signal.set(Some(value));
  30. }
  31. }
  32. // 2. Attempt to hotpatch
  33. if let Some(jump_table) = msg.jump_table.as_ref().cloned() {
  34. if msg.for_build_id == Some(dioxus_cli_config::build_id()) {
  35. unsafe { subsecond::apply_patch(jump_table) }?;
  36. dioxus_core::prelude::force_all_dirty();
  37. ctx.clear::<Signal<Option<HotReloadedTemplate>>>();
  38. }
  39. }
  40. Ok(())
  41. })
  42. }
  43. /// Connect to the devserver and handle its messages with a callback.
  44. ///
  45. /// This doesn't use any form of security or protocol, so it's not safe to expose to the internet.
  46. #[cfg(not(target_arch = "wasm32"))]
  47. pub fn connect(endpoint: String, mut callback: impl FnMut(DevserverMsg) + Send + 'static) {
  48. std::thread::spawn(move || {
  49. let uri = format!(
  50. "{endpoint}?aslr_reference={}&build_id={}",
  51. subsecond::__aslr_reference(),
  52. dioxus_cli_config::build_id()
  53. );
  54. let (mut websocket, _req) = match tungstenite::connect(uri) {
  55. Ok((websocket, req)) => (websocket, req),
  56. Err(_) => return,
  57. };
  58. while let Ok(msg) = websocket.read() {
  59. if let tungstenite::Message::Text(text) = msg {
  60. if let Ok(msg) = serde_json::from_str(&text) {
  61. callback(msg);
  62. }
  63. }
  64. }
  65. });
  66. }