Browse Source

Fix: requeue events, process events (#2236)

* Fix: requeue events, process events

* Fix test: wait_for_work shouldn't wait 3 times when one update happens while rendering
Jonathan Kelley 1 year ago
parent
commit
821a650f77
2 changed files with 17 additions and 8 deletions
  1. 14 2
      packages/core/src/virtual_dom.rs
  2. 3 6
      packages/hooks/tests/memo.rs

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

@@ -512,12 +512,17 @@ impl VirtualDom {
         // We choose not to poll the deadline since we complete pretty quickly anyways
         while let Some(task) = self.pop_task() {
             // Then poll any tasks that might be pending
-            let tasks = task.tasks_queued.into_inner();
-            for task in tasks {
+            let mut tasks = task.tasks_queued.into_inner();
+            while let Some(task) = tasks.pop() {
                 let _ = self.runtime.handle_task_wakeup(task);
+
                 // Running that task, may mark a scope higher up as dirty. If it does, return from the function early
                 self.queue_events();
                 if self.has_dirty_scopes() {
+                    // requeue any remaining tasks
+                    for task in tasks {
+                        self.mark_task_dirty(task);
+                    }
                     return;
                 }
             }
@@ -633,10 +638,14 @@ impl VirtualDom {
         while let Some(work) = self.pop_work() {
             {
                 let _runtime = RuntimeGuard::new(self.runtime.clone());
+
                 // Then, poll any tasks that might be pending in the scope
                 for task in work.tasks {
                     let _ = self.runtime.handle_task_wakeup(task);
                 }
+
+                self.queue_events();
+
                 // If the scope is dirty, run the scope and get the mutations
                 if work.rerun_scope {
                     let new_nodes = self.run_scope(work.scope.id);
@@ -718,6 +727,9 @@ impl VirtualDom {
                         let _ = self.runtime.handle_task_wakeup(task);
                     }
                 }
+
+                self.queue_events();
+
                 // If the scope is dirty, run the scope and get the mutations
                 if work.rerun_scope {
                     let new_nodes = self.run_scope(work.scope.id);

+ 3 - 6
packages/hooks/tests/memo.rs

@@ -29,15 +29,13 @@ async fn memo_updates() {
         if generation() < 2 {
             vec.push(len);
         }
+
         // The memo should always be up to date
         assert_eq!(vec.len(), len_memo());
 
         rsx! {
             for i in 0..len {
-                Child {
-                    index: i,
-                    vec,
-                }
+                Child { index: i, vec }
             }
         }
     }
@@ -57,10 +55,9 @@ async fn memo_updates() {
     dom.rebuild_in_place();
     let mut signal = VEC_SIGNAL.with(|cell| (*cell.borrow()).unwrap());
     // Wait for the signal to update
-    for _ in 0..3 {
+    for _ in 0..2 {
         dom.wait_for_work().await;
         dom.render_immediate(&mut dioxus::dioxus_core::NoOpMutations);
-        println!("Signal: {signal:?}");
     }
     assert_eq!(signal(), vec![0, 1, 2, 3, 4, 5]);
     // Remove each element from the vec