WIP split element from element ref

This commit is contained in:
Evan Almloff committed 2023-08-23 10:48:10 -05:00
1 parent 882c3c9dfb
commit e337aff0a4
7 files changed
+291 -223

No files matched your search

+42 -44
View File
@@ -13,62 +13,52 @@ use crate::{
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct ElementId(pub usize);
pub(crate) struct ElementRef {
/// An Element that can be bubbled to's unique identifier.
///
/// `ElementId` is a `usize` that is unique across the entire VirtualDOM - but not unique across time. If a component is
/// unmounted, then the `ElementId` will be reused for a new component.
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct BubbleId(pub usize);
#[derive(Debug, Clone)]
pub struct ElementRef {
// the pathway of the real element inside the template
pub path: ElementPath,
pub(crate) path: ElementPath,
// The actual template
pub template: Option<NonNull<VNode<'static>>>,
pub(crate) template: NonNull<VNode<'static>>,
// The scope the element belongs to
pub scope: ScopeId,
pub(crate) scope: ScopeId,
}
#[derive(Clone, Copy, Debug)]
pub enum ElementPath {
Deep(&'static [u8]),
Root(usize),
}
impl ElementRef {
pub(crate) fn none() -> Self {
Self {
template: None,
path: ElementPath::Root(0),
scope: ScopeId(0),
}
}
pub struct ElementPath {
path: &'static [u8],
}
impl VirtualDom {
pub(crate) fn next_element(&mut self, template: &VNode, path: &'static [u8]) -> ElementId {
self.next_reference(template, ElementPath::Deep(path))
pub(crate) fn next_element(&mut self) -> ElementId {
ElementId(self.elements.insert(None))
}
pub(crate) fn next_root(&mut self, template: &VNode, path: usize) -> ElementId {
self.next_reference(template, ElementPath::Root(path))
pub(crate) fn next_element_ref(&mut self, template: &VNode, path: &'static [u8]) -> BubbleId {
self.next_reference(template, ElementPath { path })
}
pub(crate) fn next_null(&mut self) -> ElementId {
let entry = self.elements.vacant_entry();
let id = entry.key();
entry.insert(ElementRef::none());
ElementId(id)
}
fn next_reference(&mut self, template: &VNode, path: ElementPath) -> ElementId {
let entry = self.elements.vacant_entry();
fn next_reference(&mut self, template: &VNode, path: ElementPath) -> BubbleId {
let entry = self.element_refs.vacant_entry();
let id = entry.key();
let scope = self.runtime.current_scope_id().unwrap_or(ScopeId(0));
entry.insert(ElementRef {
// We know this is non-null because it comes from a reference
template: Some(unsafe { NonNull::new_unchecked(template as *const _ as *mut _) }),
template: unsafe { NonNull::new_unchecked(template as *const _ as *mut _) },
path,
scope,
});
ElementId(id)
BubbleId(id)
}
pub(crate) fn reclaim(&mut self, el: ElementId) {
@@ -76,7 +66,7 @@ impl VirtualDom {
.unwrap_or_else(|| panic!("cannot reclaim {:?}", el));
}
pub(crate) fn try_reclaim(&mut self, el: ElementId) -> Option<ElementRef> {
pub(crate) fn try_reclaim(&mut self, el: ElementId) -> Option<()> {
if el.0 == 0 {
panic!(
"Cannot reclaim the root element - {:#?}",
@@ -84,12 +74,26 @@ impl VirtualDom {
);
}
self.elements.try_remove(el.0)
self.elements.try_remove(el.0).map(|_| ())
}
pub(crate) fn set_template(&mut self, el: ElementId, node: &VNode, path: &'static [u8]) {
match self.elements[el.0] {
Some(bubble_id) => {
self.element_refs[bubble_id.0].path = ElementPath { path };
self.element_refs[bubble_id.0].template =
unsafe { NonNull::new_unchecked(node as *const _ as *mut _) };
}
None => {
self.elements[el.0] = Some(self.next_reference(node, ElementPath { path }));
}
}
}
pub(crate) fn update_template(&mut self, el: ElementId, node: &VNode) {
let bubble_id = self.elements[el.0].unwrap();
let node: *const VNode = node as *const _;
self.elements[el.0].template = unsafe { std::mem::transmute(node) };
self.element_refs[bubble_id.0].template = unsafe { std::mem::transmute(node) };
}
// Drop a scope and all its children
@@ -182,18 +186,12 @@ impl VirtualDom {
impl ElementPath {
pub(crate) fn is_decendant(&self, small: &&[u8]) -> bool {
match *self {
ElementPath::Deep(big) => small.len() <= big.len() && *small == &big[..small.len()],
ElementPath::Root(r) => small.len() == 1 && small[0] == r as u8,
}
small.len() <= self.path.len() && *small == &self.path[..small.len()]
}
}
impl PartialEq<&[u8]> for ElementPath {
fn eq(&self, other: &&[u8]) -> bool {
match *self {
ElementPath::Deep(deep) => deep.eq(*other),
ElementPath::Root(r) => other.len() == 1 && other[0] == r as u8,
}
self.path.eq(*other)
}
}