From d8aff0c4a26be215c2dc69fbfd040a22627ae0da Mon Sep 17 00:00:00 2001 From: Luke Chu <37006668+lukechu10@users.noreply.github.com> Date: Wed, 30 Jun 2021 14:41:33 -0700 Subject: [PATCH] Get NodeId for DomNode lazily (only when getting Hash for DomNode) (#136) * NodeId start at 1 * Get node id lazily --- .../sycamore/src/generic_node/dom_node.rs | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/packages/sycamore/src/generic_node/dom_node.rs b/packages/sycamore/src/generic_node/dom_node.rs index 30066cd6c..31071f292 100644 --- a/packages/sycamore/src/generic_node/dom_node.rs +++ b/packages/sycamore/src/generic_node/dom_node.rs @@ -17,10 +17,10 @@ use crate::template::Template; // TODO: remove js snippet #[wasm_bindgen(inline_js = "\ export function set_node_id(node, id) {\ - node.__sycamoreNodeId = id\ + node.$$$nodeId = id\ }\ export function get_node_id(node) {\ - return node.__sycamoreNodeId\ + return node.$$$nodeId\ }\ ")] extern "C" { @@ -29,12 +29,18 @@ extern "C" { } /// An unique id for every node. -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] struct NodeId(usize); +impl Default for NodeId { + fn default() -> Self { + Self(0) + } +} + impl NodeId { fn new_with_node(node: &Node) -> Self { - thread_local!(static NODE_ID_COUNTER: Cell = Cell::new(0)); + thread_local!(static NODE_ID_COUNTER: Cell = Cell::new(1)); // 0 is reserved for default value. let id = NODE_ID_COUNTER.with(|x| { let tmp = x.get(); @@ -51,7 +57,7 @@ impl NodeId { /// _This API requires the following crate features to be activated: `dom`_ #[derive(Clone)] pub struct DomNode { - id: NodeId, + id: Cell, node: Rc, } @@ -63,11 +69,23 @@ impl DomNode { pub fn unchecked_into(self) -> T { (*self.node).clone().unchecked_into() } + + fn get_node_id(&self) -> NodeId { + if self.id.get().0 == 0 { + // self.id not yet initialized. + if let Some(id) = get_node_id(&self.node) { + self.id.set(NodeId(id)); + } else { + self.id.set(NodeId::new_with_node(&self.node)); + } + } + self.id.get() + } } impl PartialEq for DomNode { fn eq(&self, other: &Self) -> bool { - self.id == other.id + self.node == other.node } } @@ -75,7 +93,7 @@ impl Eq for DomNode {} impl Hash for DomNode { fn hash(&self, state: &mut H) { - self.id.hash(state); + self.get_node_id().hash(state); } } @@ -121,7 +139,7 @@ impl GenericNode for DomNode { .unwrap(), ); DomNode { - id: NodeId::new_with_node(&node), + id: Default::default(), node, } } @@ -129,7 +147,7 @@ impl GenericNode for DomNode { fn text_node(text: &str) -> Self { let node = Rc::new(document().create_text_node(text).into()); DomNode { - id: NodeId::new_with_node(&node), + id: Default::default(), node, } } @@ -137,7 +155,7 @@ impl GenericNode for DomNode { fn marker() -> Self { let node = Rc::new(document().create_comment("").into()); DomNode { - id: NodeId::new_with_node(&node), + id: Default::default(), node, } } @@ -180,14 +198,14 @@ impl GenericNode for DomNode { fn parent_node(&self) -> Option { self.node.parent_node().map(|node| Self { - id: NodeId(get_node_id(&node).unwrap()), + id: Default::default(), node: Rc::new(node), }) } fn next_sibling(&self) -> Option { self.node.next_sibling().map(|node| Self { - id: NodeId(get_node_id(&node).unwrap()), + id: Default::default(), node: Rc::new(node), }) } @@ -231,7 +249,7 @@ pub fn render_to(template: impl FnOnce() -> Template, parent: &Node) { let scope = create_root(|| { insert( &DomNode { - id: NodeId::new_with_node(parent), + id: Default::default(), node: Rc::new(parent.clone()), }, template(), @@ -296,7 +314,7 @@ pub fn hydrate_to(template: impl FnOnce() -> Template, parent: &Node) { let scope = create_root(|| { insert( &DomNode { - id: NodeId::new_with_node(&parent), + id: Default::default(), node: Rc::new(parent.clone()), }, template(),