Skip to content

Commit

Permalink
Get NodeId for DomNode lazily (only when getting Hash for DomNode) (#136
Browse files Browse the repository at this point in the history
)

* NodeId start at 1

* Get node id lazily
  • Loading branch information
lukechu10 authored Jun 30, 2021
1 parent 844fcc7 commit d8aff0c
Showing 1 changed file with 32 additions and 14 deletions.
46 changes: 32 additions & 14 deletions packages/sycamore/src/generic_node/dom_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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<usize> = Cell::new(0));
thread_local!(static NODE_ID_COUNTER: Cell<usize> = Cell::new(1)); // 0 is reserved for default value.

let id = NODE_ID_COUNTER.with(|x| {
let tmp = x.get();
Expand All @@ -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<NodeId>,
node: Rc<Node>,
}

Expand All @@ -63,19 +69,31 @@ impl DomNode {
pub fn unchecked_into<T: JsCast>(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
}
}

impl Eq for DomNode {}

impl Hash for DomNode {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.get_node_id().hash(state);
}
}

Expand Down Expand Up @@ -121,23 +139,23 @@ impl GenericNode for DomNode {
.unwrap(),
);
DomNode {
id: NodeId::new_with_node(&node),
id: Default::default(),
node,
}
}

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,
}
}

fn marker() -> Self {
let node = Rc::new(document().create_comment("").into());
DomNode {
id: NodeId::new_with_node(&node),
id: Default::default(),
node,
}
}
Expand Down Expand Up @@ -180,14 +198,14 @@ impl GenericNode for DomNode {

fn parent_node(&self) -> Option<Self> {
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> {
self.node.next_sibling().map(|node| Self {
id: NodeId(get_node_id(&node).unwrap()),
id: Default::default(),
node: Rc::new(node),
})
}
Expand Down Expand Up @@ -231,7 +249,7 @@ pub fn render_to(template: impl FnOnce() -> Template<DomNode>, parent: &Node) {
let scope = create_root(|| {
insert(
&DomNode {
id: NodeId::new_with_node(parent),
id: Default::default(),
node: Rc::new(parent.clone()),
},
template(),
Expand Down Expand Up @@ -296,7 +314,7 @@ pub fn hydrate_to(template: impl FnOnce() -> Template<DomNode>, parent: &Node) {
let scope = create_root(|| {
insert(
&DomNode {
id: NodeId::new_with_node(&parent),
id: Default::default(),
node: Rc::new(parent.clone()),
},
template(),
Expand Down

0 comments on commit d8aff0c

Please sign in to comment.