This commit is contained in:
Evan Almloff 2022-05-27 18:26:31 -05:00
commit 4b1ea5879d
11 changed files with 28 additions and 29 deletions

View file

@ -1,26 +1,26 @@
#![warn(clippy::pedantic)]
#![allow(clippy::cast_possible_truncation)]
//! This module contains the stateful [`DiffState`] and all methods to diff [`VNodes`], their properties, and their children.
//! This module contains the stateful [`DiffState`] and all methods to diff [`VNode`]s, their properties, and their children.
//!
//! The [`DiffState`] calculates the diffs between the old and new frames, updates the new nodes, and generates a set
//! of mutations for the [`RealDom`] to apply.
//! of mutations for the renderer to apply.
//!
//! ## Notice:
//!
//! The inspiration and code for this module was originally taken from Dodrio (@fitzgen) and then modified to support
//! Components, Fragments, Suspense, [`SubTree`] memoization, incremental diffing, cancellation, [`NodeRefs`], pausing, priority
//! Components, Fragments, Suspense, `SubTree` memoization, incremental diffing, cancellation, pausing, priority
//! scheduling, and additional batching operations.
//!
//! ## Implementation Details:
//!
//! ### IDs for elements
//! --------------------
//! All nodes are addressed by their IDs. The [`RealDom`] provides an imperative interface for making changes to these nodes.
//! All nodes are addressed by their IDs.
//! We don't necessarily require that DOM changes happen instantly during the diffing process, so the implementor may choose
//! to batch nodes if it is more performant for their application. The element IDs are indices into the internal element
//! array. The expectation is that implementors will use the ID as an index into a Vec of real nodes, allowing for passive
//! garbage collection as the [`VirtualDOM`] replaces old nodes.
//! garbage collection as the [`crate::VirtualDom`] replaces old nodes.
//!
//! When new vnodes are created through `cx.render`, they won't know which real node they correspond to. During diffing,
//! we always make sure to copy over the ID. If we don't do this properly, the [`ElementId`] will be populated incorrectly
@ -30,7 +30,7 @@
//! --------------------
//! Fragments (nodes without a parent) are supported through a combination of "replace with" and anchor vnodes. Fragments
//! can be particularly challenging when they are empty, so the anchor node lets us "reserve" a spot for the empty
//! fragment to be replaced with when it is no longer empty. This is guaranteed by logic in the [`NodeFactory`] - it is
//! fragment to be replaced with when it is no longer empty. This is guaranteed by logic in the [`crate::innerlude::NodeFactory`] - it is
//! impossible to craft a fragment with 0 elements - they must always have at least a single placeholder element. Adding
//! "dummy" nodes _is_ inefficient, but it makes our diffing algorithm faster and the implementation is completely up to
//! the platform.
@ -44,13 +44,13 @@
//! into a promise-like value. React will then work on the next "ready" fiber, checking back on the previous fiber once
//! it has finished its new work. In Dioxus, we use a similar approach, but try to completely render the tree before
//! switching sub-fibers. Instead, each future is submitted into a futures-queue and the node is manually loaded later on.
//! Due to the frequent calls to [`yield_now`] we can get the pure "fetch-as-you-render" behavior of React Fiber.
//! Due to the frequent calls to [`crate::virtual_dom::VirtualDom::work_with_deadline`] we can get the pure "fetch-as-you-render" behavior of React Fiber.
//!
//! We're able to use this approach because we use placeholder nodes - futures that aren't ready still get submitted to
//! DOM, but as a placeholder.
//!
//! Right now, the "suspense" queue is intertwined with hooks. In the future, we should allow any future to drive attributes
//! and contents, without the need for the [`use_suspense`] hook. In the interim, this is the quickest way to get Suspense working.
//! and contents, without the need for a `use_suspense` hook. In the interim, this is the quickest way to get Suspense working.
//!
//! ## Subtree Memoization
//! -----------------------

View file

@ -150,7 +150,7 @@ impl AnyEvent {
/// You should prefer to use the name of the event directly, rather than
/// the UiEvent<T> generic type.
///
/// For the HTML crate, this would include [`MouseEvent`], [`FormEvent`] etc.
/// For the HTML crate, this would include MouseEvent, FormEvent etc.
pub struct UiEvent<T> {
/// The internal data of the event
/// This is wrapped in an Arc so that it can be sent across threads

View file

@ -550,7 +550,7 @@ impl<'a> NodeFactory<'a> {
}))
}
/// Create a new [`VNode::VElement`]
/// Create a new [`VNode::Element`]
pub fn element(
&self,
el: impl DioxusElement,
@ -569,7 +569,7 @@ impl<'a> NodeFactory<'a> {
)
}
/// Create a new [`VNode::VElement`] without the trait bound
/// Create a new [`VNode::Element`] without the trait bound
///
/// IE pass in "div" instead of `div`
pub fn raw_element(
@ -637,7 +637,7 @@ impl<'a> NodeFactory<'a> {
}
}
/// Create a new [`VNode::VComponent`]
/// Create a new [`VNode::Component`]
pub fn component<P>(
&self,
component: fn(Scope<'a, P>) -> Element,
@ -684,7 +684,7 @@ impl<'a> NodeFactory<'a> {
}
}
/// Create a new [`VNode::VFragment`] from a root of the rsx! call
/// Create a new [`VNode::Fragment`] from a root of the rsx! call
pub fn fragment_root<'b, 'c>(
self,
node_iter: impl IntoIterator<Item = impl IntoVNode<'a> + 'c> + 'b,
@ -705,7 +705,7 @@ impl<'a> NodeFactory<'a> {
}
}
/// Create a new [`VNode::VFragment`] from any iterator
/// Create a new [`VNode::Fragment`] from any iterator
pub fn fragment_from_iter<'b, 'c>(
self,
node_iter: impl IntoIterator<Item = impl IntoVNode<'a> + 'c> + 'b,

View file

@ -1,7 +1,7 @@
use crate::innerlude::*;
/// An iterator that only yields "real" [`Element`]s. IE only Elements that are
/// not [`VNode::VComponent`] or [`VNode::VFragment`], .
/// not [`VNode::Component`] or [`VNode::Fragment`], .
pub struct ElementIdIterator<'a> {
vdom: &'a VirtualDom,

View file

@ -447,7 +447,7 @@ pub mod on {
/// Get the key code as an enum Variant.
///
/// This is intended for things like arrow keys, escape keys, function keys, and other non-international keys.
/// To match on unicode sequences, use the [`KeyboardEvent::key`] method - this will return a string identifier instead of a limited enum.
/// To match on unicode sequences, use the [`KeyboardData::key`] method - this will return a string identifier instead of a limited enum.
///
///
/// ## Example

View file

@ -15,7 +15,7 @@ use crate::{
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
/// The render state passes from parent to children and or accumulates state from children to parents.
/// To get started implement [PushedDownState] and or [BubbledUpState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
#[derive(Debug)]
pub struct RealDom<S: State> {
root: usize,
@ -712,7 +712,7 @@ impl<S: State> IndexMut<ElementId> for RealDom<S> {
}
}
/// The node is stored client side and stores only basic data about the node. For more complete information about the node see [`domNode::element`].
/// The node is stored client side and stores only basic data about the node.
#[derive(Debug, Clone)]
pub struct Node<S: State> {
/// The id of the node this node was created from.

View file

@ -44,10 +44,10 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
}
/// This state is derived from children. For example a node's size could be derived from the size of children.
/// Called when the current node's node properties are modified, a child's [BubbledUpState] is modified or a child is removed.
/// Called when the current node's node properties are modified, a child's [ChildDepState] is modified or a child is removed.
/// Called at most once per update.
pub trait ChildDepState {
/// The context is passed to the [PushedDownState::reduce] when it is pushed down.
/// The context is passed to the [ChildDepState::reduce] when it is pushed down.
/// This is sometimes nessisary for lifetime purposes.
type Ctx;
/// This must be either a [ChildDepState] or [NodeDepState]
@ -64,10 +64,10 @@ pub trait ChildDepState {
}
/// This state that is passed down to children. For example text properties (`<b>` `<i>` `<u>`) would be passed to children.
/// Called when the current node's node properties are modified or a parrent's [PushedDownState] is modified.
/// Called when the current node's node properties are modified or a parrent's [ParentDepState] is modified.
/// Called at most once per update.
pub trait ParentDepState {
/// The context is passed to the [PushedDownState::reduce] when it is pushed down.
/// The context is passed to the [ParentDepState::reduce] when it is pushed down.
/// This is sometimes nessisary for lifetime purposes.
type Ctx;
/// This must be either a [ParentDepState] or [NodeDepState]
@ -77,7 +77,7 @@ pub trait ParentDepState {
}
/// This state that is upadated lazily. For example any propertys that do not effect other parts of the dom like bg-color.
/// Called when the current node's node properties are modified or a parrent's [PushedDownState] is modified.
/// Called when the current node's node properties are modified or a sibling's [NodeDepState] is modified.
/// Called at most once per update.
pub trait NodeDepState {
type Ctx;

View file

@ -43,9 +43,9 @@
<span> | </span>
<a href="https://github.com/DioxusLabs/example-projects"> Examples </a>
<span> | </span>
<a href="https://dioxuslabs.com/guide"> Guide (0.1.8) </a>
<a href="https://dioxuslabs.com/router"> Guide (Latest) </a>
<span> | </span>
<a href="https://dioxuslabs.com/nightly/guide"> Guide (Master) </a>
<a href="https://dioxuslabs.com/nightly/router"> Guide (Master) </a>
</h3>
</div>

View file

@ -1,7 +1,6 @@
//! Parse components into the VComponent VNode
//! Parse components into the VNode::Component variant
//! ==========================================
//!
//! This parsing path emerges from [`AmbiguousElement`] which supports validation of the vcomponent format.
//! We can be reasonably sure that whatever enters this parsing path is in the right format.
//! This feature must support
//! - [x] Namespaced components

View file

@ -11,7 +11,7 @@ documentation = "https://dioxuslabs.com"
keywords = ["dom", "ui", "gui", "react", "wasm"]
[dependencies]
dioxus-core = { path = "../core", version = "^0.2.1" }
dioxus-core = { path = "../core", version = "^0.2.1", features = ["serialize"] }
dioxus-html = { path = "../html", version = "^0.2.1", features = ["wasm-bind"] }
dioxus-interpreter-js = { path = "../interpreter", version = "^0.2.1", features = [
"web"

View file

@ -26,7 +26,7 @@
// main thread.
//
// React solves this problem by breaking up the rendering process into a "diff" phase and a "render" phase. In Dioxus,
// the diff phase is non-blocking, using "yield_now" to allow the browser to process other events. When the diff phase
// the diff phase is non-blocking, using "work_with_deadline" to allow the browser to process other events. When the diff phase
// is finally complete, the VirtualDOM will return a set of "Mutations" for this crate to apply.
//
// Here, we schedule the "diff" phase during the browser's idle period, achieved by calling RequestIdleCallback and then