Evan Almloff 1 рік тому
батько
коміт
78b9b157dc

+ 3 - 1
packages/core/src/global_context.rs

@@ -260,7 +260,9 @@ pub fn after_render(f: impl FnMut() + 'static) {
 pub async fn flush_sync() {
     // Wait for the flush lock to be available
     // We release it immediately, so it's impossible for the lock to be held longer than this function
-    Runtime::with(|rt| rt.render_signal.subscribe()).unwrap().await;
+    Runtime::with(|rt| rt.render_signal.subscribe())
+        .unwrap()
+        .await;
 }
 
 /// Use a hook with a cleanup function

+ 1 - 1
packages/core/src/lib.rs

@@ -14,13 +14,13 @@ mod global_context;
 mod mutations;
 mod nodes;
 mod properties;
+mod render_signal;
 mod runtime;
 mod scope_arena;
 mod scope_context;
 mod scopes;
 mod tasks;
 mod virtual_dom;
-mod render_signal;
 
 pub(crate) mod innerlude {
     pub(crate) use crate::any_props::*;

+ 9 - 10
packages/core/src/render_signal.rs

@@ -1,10 +1,10 @@
-use std::rc::Rc;
-use std::task::Waker;
-use std::task::Poll;
-use std::pin::Pin;
+use std::cell::RefCell;
 use std::future::Future;
+use std::pin::Pin;
+use std::rc::Rc;
 use std::task::Context;
-use std::cell::RefCell;
+use std::task::Poll;
+use std::task::Waker;
 
 /// A signal is a message that can be sent to all listening tasks at once
 #[derive(Default)]
@@ -26,15 +26,14 @@ impl RenderSignal {
     }
 
     /// Create a future that resolves when the signal is sent
-    pub fn subscribe(& self) -> RenderSignalFuture {
-        let inner =Rc::new(RefCell::new(RenderSignalFutureInner {
+    pub fn subscribe(&self) -> RenderSignalFuture {
+        let inner = Rc::new(RefCell::new(RenderSignalFutureInner {
             resolved: false,
             waker: None,
         }));
         self.wakers.borrow_mut().push(inner.clone());
-        let waker = RenderSignalFuture {
-            inner
-        };
+        println!("RenderSignalFutureInner");
+        let waker = RenderSignalFuture { inner };
         waker
     }
 }

+ 1 - 1
packages/core/src/runtime.rs

@@ -1,9 +1,9 @@
 use crate::{
     innerlude::{LocalTask, SchedulerMsg},
+    render_signal::RenderSignal,
     scope_context::Scope,
     scopes::ScopeId,
     Task,
-    render_signal::RenderSignal
 };
 use std::{
     cell::{Cell, Ref, RefCell},

+ 1 - 2
packages/core/src/virtual_dom.rs

@@ -478,7 +478,6 @@ impl VirtualDom {
             match self.rx.next().await.expect("channel should never close") {
                 SchedulerMsg::Immediate(id) => self.mark_dirty(id),
                 SchedulerMsg::TaskNotified(id) => {
-                    // _ = self.runtime.handle_task_wakeup(id)
                     // Instead of running the task immediately, we insert it into the runtime's task queue.
                     // The task may be marked dirty at the same time as the scope that owns the task is dropped.
                     self.mark_task_dirty(id);
@@ -631,8 +630,8 @@ impl VirtualDom {
             }
         }
 
-        self.scopes_need_rerun = false;
         self.runtime.render_signal.send();
+        self.scopes_need_rerun = false;
     }
 
     /// [`Self::render_immediate`] to a vector of mutations for testing purposes

+ 21 - 5
packages/core/tests/task.rs

@@ -94,14 +94,22 @@ async fn flushing() {
 
     fn app() -> Element {
         if generation() > 0 {
+            println!("App");
             SEQUENCE.with(|s| s.borrow_mut().push(0));
         }
+        use_hook(|| {
+            spawn(async move {
+                needs_update();
+            });
+        });
         use_hook(|| {
             spawn(async move {
                 for _ in 0..10 {
+                    BROADCAST.with(|b| b.1.resubscribe()).recv().await.unwrap();
+                    println!("Task 1 recved");
                     flush_sync().await;
+                    println!("Task 1");
                     SEQUENCE.with(|s| s.borrow_mut().push(1));
-                    BROADCAST.with(|b| b.1.resubscribe()).recv().await.unwrap();
                 }
             })
         });
@@ -109,9 +117,11 @@ async fn flushing() {
         use_hook(|| {
             spawn(async move {
                 for _ in 0..10 {
+                    BROADCAST.with(|b| b.1.resubscribe()).recv().await.unwrap();
+                    println!("Task 2 recved");
                     flush_sync().await;
+                    println!("Task 2");
                     SEQUENCE.with(|s| s.borrow_mut().push(2));
-                    BROADCAST.with(|b| b.1.resubscribe()).recv().await.unwrap();
                 }
             })
         });
@@ -126,16 +136,22 @@ async fn flushing() {
     let fut = async {
         // Trigger the flush by waiting for work
         for _ in 0..30 {
-            dom.mark_dirty(ScopeId(0));
             BROADCAST.with(|b| b.0.send(()).unwrap());
-            dom.wait_for_work().await;
+            dom.mark_dirty(ScopeId(0));
+            tokio::select! {
+                _ = dom.wait_for_work() => {}
+                _ = tokio::time::sleep(Duration::from_millis(10)) => {}
+            }
             dom.render_immediate(&mut dioxus_core::NoOpMutations);
+            println!("Flushed");
         }
     };
 
     tokio::select! {
         _ = fut => {}
-        _ = tokio::time::sleep(Duration::from_millis(500)) => {}
+        _ = tokio::time::sleep(Duration::from_millis(500)) => {
+            println!("Aborting due to timeout");
+        }
     };
 
     SEQUENCE.with(|s| {

+ 1 - 1
packages/hooks/src/use_effect.rs

@@ -18,7 +18,7 @@ pub fn use_effect(mut callback: impl FnMut() + 'static) {
             loop {
                 // Run the effect
                 rc.run_in(&mut callback);
-                
+
                 // Wait for context to change
                 rc.changed().await;