Răsfoiți Sursa

add more internal documentation about tasks

Evan Almloff 1 an în urmă
părinte
comite
b42992bad1

+ 35 - 0
packages/core/src/dirty_scope.rs

@@ -1,3 +1,32 @@
+//! Dioxus resolves scopes in a specific order to avoid unexpected behavior. All tasks are resolved in the order of height. Scopes that are higher up in the tree are resolved first.
+//! When a scope that is higher up in the tree is rerendered, it may drop scopes lower in the tree along with their tasks.
+//!
+//! ```rust
+//! use dioxus::prelude::*;
+//!
+//! fn app() -> Element {
+//!     let vec = use_signal(|| vec![0; 10]);
+//!     rsx! {
+//!         // If the length of the vec shrinks we need to make sure that the children are dropped along with their tasks the new state of the vec is read
+//!         for idx in 0..vec.len() {
+//!             Child { idx, vec }
+//!         }
+//!     }
+//! }
+//!
+//! #[component]
+//! fn Child(vec: Signal<Vec<usize>>, idx: usize) -> Element {
+//!     use_hook(|| {
+//!         spawn(async {
+//!             // If we let this task run after the child is dropped, it will panic.
+//!             println!("Task {}", vec.read()[idx]);
+//!         });
+//!     });
+//!
+//!     rsx! {}
+//! }
+//! ```
+
 use crate::ScopeId;
 use crate::Task;
 use std::borrow::Borrow;
@@ -49,6 +78,7 @@ pub struct DirtyScopes {
 }
 
 impl DirtyScopes {
+    /// Queue a task to be polled
     pub fn queue_task(&mut self, task: Task, order: ScopeOrder) {
         match self.tasks.get(&order) {
             Some(scope) => scope.queue_task(task),
@@ -60,22 +90,27 @@ impl DirtyScopes {
         }
     }
 
+    /// Queue a scope to be rerendered
     pub fn queue_scope(&mut self, order: ScopeOrder) {
         self.scopes.insert(order);
     }
 
+    /// Check if there are any dirty scopes
     pub fn has_dirty_scopes(&self) -> bool {
         !self.scopes.is_empty()
     }
 
+    /// Take any tasks from the highest scope
     pub fn pop_task(&mut self) -> Option<DirtyTasks> {
         self.tasks.pop_first()
     }
 
+    /// Take the highest scope that needs to be rerendered
     pub fn pop_scope(&mut self) -> Option<ScopeOrder> {
         self.scopes.pop_first()
     }
 
+    /// Take any work from the highest scope. This may include rerunning the scope and/or running tasks
     pub fn pop_work(&mut self) -> Option<Work> {
         let dirty_scope = self.scopes.first();
         let dirty_task = self.tasks.first();

+ 2 - 0
packages/core/src/render_signal.rs

@@ -1,3 +1,5 @@
+//! In dioxus, effects are run using normal async functions after a render. [RenderSignalFuture] is a future that resolves after a render has passed.
+
 use std::cell::RefCell;
 use std::future::Future;
 use std::pin::Pin;

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

@@ -439,7 +439,7 @@ impl VirtualDom {
         self.poll_tasks().await;
     }
 
-    ///
+    /// Poll the scheduler for any work
     async fn poll_tasks(&mut self) {
         loop {
             // Process all events - Scopes are marked dirty, etc
@@ -454,6 +454,7 @@ impl VirtualDom {
             // Make sure we set the runtime since we're running user code
             let _runtime = RuntimeGuard::new(self.runtime.clone());
 
+            /// There isn't any more work we can do synchronously. Wait for any new work to be ready
             match self.rx.next().await.expect("channel should never close") {
                 SchedulerMsg::Immediate(id) => self.mark_dirty(id),
                 SchedulerMsg::TaskNotified(id) => {