WIP split element from element ref
This commit is contained in:
1 parent
882c3c9dfb
commit
e337aff0a4
7 files changed
+291
-223
No files matched your search
+42
-44
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user