Refactor Mutations and simplify Templates (#578)
* update mutations to be path based rather than renderer integrated
This commit is contained in:
1 parent
020c4bf0f8
commit
3b7b503333
44 files changed
+2643
-3134
No files matched your search
@@ -1,8 +1,78 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use dioxus_core::ElementId;
|
||||
|
||||
pub mod layout_attributes;
|
||||
pub mod node_ref;
|
||||
pub mod real_dom;
|
||||
pub mod state;
|
||||
pub mod template;
|
||||
#[doc(hidden)]
|
||||
pub mod traversable;
|
||||
pub mod utils;
|
||||
|
||||
/// A id for a node that lives in the real dom.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum RealNodeId {
|
||||
ElementId(ElementId),
|
||||
UnaccessableId(usize),
|
||||
}
|
||||
|
||||
impl RealNodeId {
|
||||
pub fn as_element_id(&self) -> ElementId {
|
||||
match self {
|
||||
RealNodeId::ElementId(id) => *id,
|
||||
RealNodeId::UnaccessableId(_) => panic!("Expected element id"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_unaccessable_id(&self) -> usize {
|
||||
match self {
|
||||
RealNodeId::ElementId(_) => panic!("Expected unaccessable id"),
|
||||
RealNodeId::UnaccessableId(id) => *id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for RealNodeId {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for RealNodeId {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(Self::ElementId(a), Self::ElementId(b)) => a.0.partial_cmp(&b.0),
|
||||
(Self::UnaccessableId(a), Self::UnaccessableId(b)) => a.partial_cmp(b),
|
||||
(Self::ElementId(_), Self::UnaccessableId(_)) => Some(Ordering::Greater),
|
||||
(Self::UnaccessableId(_), Self::ElementId(_)) => Some(Ordering::Less),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used in derived state macros
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[doc(hidden)]
|
||||
pub struct HeightOrdering {
|
||||
pub height: u16,
|
||||
pub id: RealNodeId,
|
||||
}
|
||||
|
||||
impl HeightOrdering {
|
||||
pub fn new(height: u16, id: RealNodeId) -> Self {
|
||||
HeightOrdering { height, id }
|
||||
}
|
||||
}
|
||||
|
||||
// not the ordering after height is just for deduplication it can be any ordering as long as it is consistent
|
||||
impl Ord for HeightOrdering {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.height.cmp(&other.height).then(self.id.cmp(&other.id))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for HeightOrdering {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
use dioxus_core::*;
|
||||
|
||||
use crate::{
|
||||
real_dom::{NodeData, NodeType, OwnedAttributeView},
|
||||
state::union_ordered_iter,
|
||||
RealNodeId,
|
||||
};
|
||||
|
||||
/// A view into a [VNode] with limited access.
|
||||
@@ -22,8 +21,8 @@ impl<'a> NodeView<'a> {
|
||||
}
|
||||
|
||||
/// Get the id of the node
|
||||
pub fn id(&self) -> GlobalNodeId {
|
||||
self.inner.id
|
||||
pub fn id(&self) -> RealNodeId {
|
||||
self.inner.id.unwrap()
|
||||
}
|
||||
|
||||
/// Get the tag of the node if the tag is enabled in the mask
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,12 +1,11 @@
|
||||
use std::{cmp::Ordering, fmt::Debug};
|
||||
|
||||
use anymap::AnyMap;
|
||||
use dioxus_core::GlobalNodeId;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::node_ref::{NodeMask, NodeView};
|
||||
use crate::real_dom::NodeData;
|
||||
use crate::traversable::Traversable;
|
||||
use crate::RealNodeId;
|
||||
use anymap::AnyMap;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
/// Join two sorted iterators
|
||||
pub(crate) fn union_ordered_iter<T: Ord + Debug>(
|
||||
@@ -209,14 +208,14 @@ pub trait State: Default + Clone {
|
||||
#[doc(hidden)]
|
||||
fn update<
|
||||
'a,
|
||||
T: Traversable<Node = Self, Id = GlobalNodeId>,
|
||||
T2: Traversable<Node = NodeData, Id = GlobalNodeId>,
|
||||
T: Traversable<Node = Self, Id = RealNodeId>,
|
||||
T2: Traversable<Node = NodeData, Id = RealNodeId>,
|
||||
>(
|
||||
dirty: &[(GlobalNodeId, NodeMask)],
|
||||
dirty: &[(RealNodeId, NodeMask)],
|
||||
state_tree: &'a mut T,
|
||||
rdom: &'a T2,
|
||||
ctx: &AnyMap,
|
||||
) -> FxHashSet<GlobalNodeId>;
|
||||
) -> FxHashSet<RealNodeId>;
|
||||
}
|
||||
|
||||
impl ChildDepState for () {
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
use dioxus_core::{GlobalNodeId, TemplateNodeId};
|
||||
|
||||
use crate::{real_dom::Node, state::State};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NativeTemplate<S: State> {
|
||||
pub(crate) nodes: Vec<Option<Box<Node<S>>>>,
|
||||
pub(crate) roots: Vec<usize>,
|
||||
}
|
||||
|
||||
impl<S: State> NativeTemplate<S> {
|
||||
pub fn insert(&mut self, node: Node<S>) {
|
||||
let id = node.node_data.id;
|
||||
match id {
|
||||
GlobalNodeId::TemplateId {
|
||||
template_node_id: TemplateNodeId(id),
|
||||
..
|
||||
} => {
|
||||
self.nodes.resize(id + 1, None);
|
||||
self.nodes[id] = Some(Box::new(node));
|
||||
}
|
||||
GlobalNodeId::VNodeId(_) => panic!("Cannot insert a VNode into a template"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum TemplateRefOrNode<S: State> {
|
||||
Ref {
|
||||
nodes: Vec<Option<Box<Node<S>>>>,
|
||||
roots: Vec<GlobalNodeId>,
|
||||
parent: Option<GlobalNodeId>,
|
||||
},
|
||||
Node(Node<S>),
|
||||
}
|
||||
|
||||
impl<S: State> TemplateRefOrNode<S> {
|
||||
pub fn parent(&self) -> Option<GlobalNodeId> {
|
||||
match self {
|
||||
TemplateRefOrNode::Ref { parent, .. } => *parent,
|
||||
TemplateRefOrNode::Node(node) => node.node_data.parent,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
use crate::{
|
||||
real_dom::{NodeType, RealDom},
|
||||
state::State,
|
||||
RealNodeId,
|
||||
};
|
||||
use dioxus_core::{DomEdit, ElementId, GlobalNodeId, Mutations};
|
||||
use dioxus_core::{DomEdit, ElementId, Mutations};
|
||||
|
||||
pub enum ElementProduced {
|
||||
/// The iterator produced an element by progressing to the next node in a depth first order.
|
||||
Progressed(GlobalNodeId),
|
||||
Progressed(RealNodeId),
|
||||
/// The iterator reached the end of the tree and looped back to the root
|
||||
Looped(GlobalNodeId),
|
||||
Looped(RealNodeId),
|
||||
}
|
||||
impl ElementProduced {
|
||||
pub fn id(&self) -> GlobalNodeId {
|
||||
pub fn id(&self) -> RealNodeId {
|
||||
match self {
|
||||
ElementProduced::Progressed(id) => *id,
|
||||
ElementProduced::Looped(id) => *id,
|
||||
@@ -50,16 +51,13 @@ impl NodePosition {
|
||||
/// The iterator loops around when it reaches the end or the beginning.
|
||||
pub struct PersistantElementIter {
|
||||
// stack of elements and fragments
|
||||
stack: smallvec::SmallVec<[(GlobalNodeId, NodePosition); 5]>,
|
||||
stack: smallvec::SmallVec<[(RealNodeId, NodePosition); 5]>,
|
||||
}
|
||||
|
||||
impl Default for PersistantElementIter {
|
||||
fn default() -> Self {
|
||||
PersistantElementIter {
|
||||
stack: smallvec::smallvec![(
|
||||
GlobalNodeId::VNodeId(dioxus_core::ElementId(0)),
|
||||
NodePosition::AtNode
|
||||
)],
|
||||
stack: smallvec::smallvec![(RealNodeId::ElementId(ElementId(0)), NodePosition::AtNode)],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,7 +77,7 @@ impl PersistantElementIter {
|
||||
.filter_map(|e| {
|
||||
// nodes within templates will never be removed
|
||||
if let DomEdit::Remove { root } = e {
|
||||
let id = rdom.decode_id(*root);
|
||||
let id = rdom.resolve_maybe_id(*root);
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
@@ -102,21 +100,23 @@ impl PersistantElementIter {
|
||||
for m in &mutations.edits {
|
||||
match m {
|
||||
DomEdit::Remove { root } => {
|
||||
let id = rdom.decode_id(*root);
|
||||
let id = rdom.resolve_maybe_id(*root);
|
||||
if children.iter().take(*child_idx + 1).any(|c| *c == id) {
|
||||
*child_idx -= 1;
|
||||
}
|
||||
}
|
||||
DomEdit::InsertBefore { root, n } => {
|
||||
let id = rdom.decode_id(*root);
|
||||
DomEdit::InsertBefore { root, nodes } => {
|
||||
let id = rdom.resolve_maybe_id(*root);
|
||||
let n = nodes.len();
|
||||
if children.iter().take(*child_idx + 1).any(|c| *c == id) {
|
||||
*child_idx += *n as usize;
|
||||
*child_idx += n as usize;
|
||||
}
|
||||
}
|
||||
DomEdit::InsertAfter { root, n } => {
|
||||
let id = rdom.decode_id(*root);
|
||||
DomEdit::InsertAfter { root, nodes } => {
|
||||
let id = rdom.resolve_maybe_id(*root);
|
||||
let n = nodes.len();
|
||||
if children.iter().take(*child_idx).any(|c| *c == id) {
|
||||
*child_idx += *n as usize;
|
||||
*child_idx += n as usize;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
@@ -131,7 +131,7 @@ impl PersistantElementIter {
|
||||
/// get the next element
|
||||
pub fn next<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
|
||||
if self.stack.is_empty() {
|
||||
let id = GlobalNodeId::VNodeId(ElementId(0));
|
||||
let id = RealNodeId::ElementId(ElementId(0));
|
||||
let new = (id, NodePosition::AtNode);
|
||||
self.stack.push(new);
|
||||
ElementProduced::Looped(id)
|
||||
@@ -167,10 +167,10 @@ impl PersistantElementIter {
|
||||
pub fn prev<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
|
||||
// recursively add the last child element to the stack
|
||||
fn push_back<S: State>(
|
||||
stack: &mut smallvec::SmallVec<[(GlobalNodeId, NodePosition); 5]>,
|
||||
new_node: GlobalNodeId,
|
||||
stack: &mut smallvec::SmallVec<[(RealNodeId, NodePosition); 5]>,
|
||||
new_node: RealNodeId,
|
||||
rdom: &RealDom<S>,
|
||||
) -> GlobalNodeId {
|
||||
) -> RealNodeId {
|
||||
match &rdom[new_node].node_data.node_type {
|
||||
NodeType::Element { children, .. } => {
|
||||
if children.is_empty() {
|
||||
@@ -184,7 +184,7 @@ impl PersistantElementIter {
|
||||
}
|
||||
}
|
||||
if self.stack.is_empty() {
|
||||
let new_node = GlobalNodeId::VNodeId(ElementId(0));
|
||||
let new_node = RealNodeId::ElementId(ElementId(0));
|
||||
ElementProduced::Looped(push_back(&mut self.stack, new_node, rdom))
|
||||
} else {
|
||||
let (last, o_child_idx) = self.stack.last_mut().unwrap();
|
||||
@@ -223,7 +223,7 @@ impl PersistantElementIter {
|
||||
}
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> GlobalNodeId {
|
||||
fn pop(&mut self) -> RealNodeId {
|
||||
self.stack.pop().unwrap().0
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user