Enum lignin::Node [−][src]
pub enum Node<'a, S: ThreadSafety> { Comment { comment: &'a str, dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&Comment>)>>, }, HtmlElement { element: &'a Element<'a, S>, dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&HtmlElement>)>>, }, MathMlElement { element: &'a Element<'a, S>, dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&Element>)>>, }, SvgElement { element: &'a Element<'a, S>, dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&SvgElement>)>>, }, Memoized { state_key: u64, content: &'a Node<'a, S>, }, Multi(&'a [Node<'a, S>]), Keyed(&'a [ReorderableFragment<'a, S>]), Text { text: &'a str, dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&Text>)>>, }, RemnantSite(&'a RemnantSite), }
Vdom
A single generic VDOM node.
This should be relatively small:
if size_of::<usize>() == 8 { assert!(size_of::<Node<ThreadSafe>>() <= 24); } // e.g. current Wasm if size_of::<usize>() == 4 { assert!(size_of::<Node<ThreadSafe>>() <= 16); }
Variants
Represents a Comment node.
Fields of Comment
comment: &'a str
The comment’s body, as unescaped plaintext.
Renderers shouldn’t insert padding whitespace around it, except as required by e.g. pretty-printing.
Implementation Contract
This is not a soundness contract. Code using this crate must not rely on it for soundness. However, it is free to panic when encountering an incorrect implementation.
Security
This field may contain arbitrary character sequences, some of which are illegal in Comments at least when serialized as HTML. See https://html.spec.whatwg.org/multipage/syntax.html#comments for more information.
Renderers must either refuse or replace illegal-for-target comments with ones that are inert.
Not doing so opens the door for XSS and/or format confusion vulnerabilities.
dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&Comment>)>>
Represents a single HTMLElement.
Fields of HtmlElement
element: &'a Element<'a, S>
The Element
to render.
dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&HtmlElement>)>>
Registers for HTMLElement reference updates.
See DomRef
for more information.
Represents a single MathMLElement.
Note that distinct browser support for these is really quite bad and correct styling isn’t much more available.
However, MathML is part of the HTML standard, so browsers should at least parse it correctly, and styling can be polyfilled.
Fields of MathMlElement
Represents a single SVGElement.
Note that even outermost <SVG>
elements are SVGElements!
Fields of SvgElement
element: &'a Element<'a, S>
The Element
to render.
dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&SvgElement>)>>
Registers for SVGElement reference updates.
See DomRef
for more information.
DOM-transparent. This variant uses shallow comparison and hashes based on its state_key
only.
A (good enough) content
hash makes for a good state_key
, but this isn’t the only possible scheme and may not be the optimal one for your use case.
Implementation Contract (reminder)
Even if state_key
is unchanged between two VDOM iterations, the full contents must still be present in the second.
When skipping the memoized
content
, a renderer may still require this information to, for example, advance its DOM cursor.
Note that when diffing a non-Memoized
Node
into a Node::Memoized
(and vice-versa), renderers must still behave as if the DOM tree was recreated, which means cycling all Node reference bindings even if they match.
However, this often happens with matching or near-matching fragments during hydration of a web app.
If you already have a function to strip subscriptions (e.g. Node reference bindings) from a DOM and VDOM tree, or even just one to strip all callbacks (but this is less efficient), it’s likely more efficient to do so and then recurse.
Make sure the trees are actually somewhat compatible first, or you may end up processing the old VDOM twice for nothing.
Fields of Memoized
state_key: u64
A value that’s (very likely to be) distinct between VDOM graphs where the path of two Node::Memoized
instances matches but their Node::Memoized::content
is distinct.
Consider using a (good enough) hash of content
for this purpose.
content: &'a Node<'a, S>
The VDOM tree memoized by this Node
.
DOM-transparent. Represents a sequence of VDOM nodes.
Used to hint diffs in case of additions and removals.
Keyed(&'a [ReorderableFragment<'a, S>])
A sequence of VDOM nodes that’s transparent at rest, but encodes information on how to reuse and reorder elements when diffing.
List indices are bad ReorderableFragment::dom_key
values unless reordered along with the items!
Use the Multi
variant instead if you don’t track component identity.
Implementation Contract
This is not a soundness contract. Code using this crate must not rely on it for soundness. However, it is free to panic when encountering an incorrect implementation.
The ReorderableFragment::dom_key
values must be unique within a slice referenced by a Node::Keyed
instance.
If a dom_key
value appears both in the initial and target slice of a ReorderableFragment::dom_key
diff,
those ReorderableFragment
instances are considered path-matching and any respective Node(s!) must
be moved to their new location without being recreated.
These rules do not apply between distinct
ReorderableFragment
slices, even if they overlap in memory or one is reachable from the other.
The recursive diff otherwise proceeds as normal. There are no rules on whether it happens before or after the reordering.
Represents a Text node.
Fields of Text
text: &'a str
The Text
’s Node.textContent.
Implementation Contract
This is not a soundness contract. Code using this crate must not rely on it for soundness. However, it is free to panic when encountering an incorrect implementation.
Security
This field contains unescaped plaintext. Renderers must escape all control characters and sequences.
Not doing so opens the door for XSS vulnerabilities.
In order to support e.g. formatting instructions, apps should (carefully) parse user-generated content and translate it into a matching VDOM graph.
Live components also have the option of using for example Node::HtmlElement::dom_binding
to set Element.innerHTML,
but this is not recommended due to the difficulty of implementing allow-listing with such an approach.
dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&Text>)>>
Currently unused.
The plan here is to allow fragments to linger in the DOM after being diffed out, which seems like the most economical way to enable e.g. fade-out animations.
Implementations
impl<'a, S: ThreadSafety> Node<'a, S>
[src]
#[must_use]pub fn deanonymize(self) -> Self
[src]
Call of .deanonymize()
on named type.
When called on an opaque type, deanonymizes it into the underlying named type.
Both AutoSafe
and Deanonymize
must be in scope and the method must be called without qualification for this to work.
Calling this method on a named type returns the value and type unchanged and produces a deprecation warning.
impl<'a> Node<'a, ThreadSafe>
[src]
#[must_use]pub fn prefer_thread_safe(self) -> Self
[src]
Gently nudges the compiler to choose the ThreadSafe
version of a value if both are possible.
This method is by value, so it will resolve with higher priority than the by-reference method on the ThreadBound
type.
Note that not all tooling will show the correct overload here, but the compiler knows which to pick.
#[must_use]pub fn prefer_thread_safe_ref(&self) -> &Self
[src]
Gently nudges the compiler to choose the ThreadSafe
version of a reference if both are possible.
This method is once by single reference, so it will resolve with higher priority than the twice-by-reference method on the ThreadBound
type.
Note that not all tooling will show the correct overload here, but the compiler knows which to pick.
impl<'a> Node<'a, ThreadBound>
[src]
#[must_use]pub fn prefer_thread_safe(&self) -> Self
[src]
Gently nudges the compiler to choose the ThreadSafe
version of a value if both are is possible.
This method is by reference, so it will resolve with lower priority than the by-value method on the ThreadSafe
type.
Note that not all tooling will show the correct overload here, but the compiler knows which to pick.
#[must_use]pub fn prefer_thread_safe_ref<'b>(self: &&'b Self) -> &'b Self
[src]
Gently nudges the compiler to choose the ThreadSafe
version of a reference if both are is possible.
This method is twice by reference, so it will resolve with lower priority than the once-by-reference method on the ThreadSafe
type.
Note that not all tooling will show the correct overload here, but the compiler knows which to pick.
impl<'a, S: ThreadSafety> Node<'a, S>
[src]
#[must_use]pub fn dom_len(&self) -> usize
[src]
Calculates the aggregate surface level length of this Node
in Nodes.
This operation is recursive across for example Node::Multi
and Node::Keyed
, which sum up their contents in this regard.
#[must_use]pub fn dom_empty(&self) -> bool
[src]
Determines whether this Node
represents no Nodes at all.
This operation is recursive across for example Node::Multi
and Node::Keyed
, which sum up their contents in this regard.
Trait Implementations
impl<'a, S1, S2> Align<Node<'a, S2>> for Node<'a, S1> where
S1: ThreadSafety + Into<S2>,
S2: ThreadSafety,
[src]
S1: ThreadSafety + Into<S2>,
S2: ThreadSafety,
Not derived from the Into
constraints on $Name
directly since those are too broad.
impl<'a, S> Clone for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
fn clone(&self) -> Self
[src]
pub fn clone_from(&mut self, source: &Self)
1.0.0[src]
impl<'a, S> Copy for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
impl<'a, V> Deanonymize<Node<'a, ThreadSafe>> for V where
V: Send + Sync + AutoSafe<Node<'a, ThreadBound>>,
[src]
V: Send + Sync + AutoSafe<Node<'a, ThreadBound>>,
#[must_use]fn deanonymize(self) -> SafeVariant
[src]
impl<'a, S> Debug for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
impl<'a, S> Eq for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
impl<'a, S1, S2> From<&'a [Node<'a, S1>]> for Node<'a, S2> where
S1: ThreadSafety + Into<S2>,
S2: ThreadSafety,
[src]
S1: ThreadSafety + Into<S2>,
S2: ThreadSafety,
impl<'a, S1, S2> From<&'a mut [Node<'a, S1>]> for Node<'a, S2> where
S1: ThreadSafety + Into<S2>,
S2: ThreadSafety,
[src]
S1: ThreadSafety + Into<S2>,
S2: ThreadSafety,
impl<'a, S> From<&'a mut str> for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
impl<'a, S> From<&'a str> for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
impl<'a> From<Node<'a, ThreadSafe>> for Node<'a, ThreadBound>
[src]
fn from(thread_safe: Node<'a, ThreadSafe>) -> Self
[src]
impl<'a, S> Hash for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
fn hash<H: Hasher>(&self, state: &mut H)
[src]
pub fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
1.3.0[src]
H: Hasher,
impl<'a, S> Ord for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
fn cmp(&self, other: &Self) -> Ordering
[src]
#[must_use]pub fn max(self, other: Self) -> Self
1.21.0[src]
#[must_use]pub fn min(self, other: Self) -> Self
1.21.0[src]
#[must_use]pub fn clamp(self, min: Self, max: Self) -> Self
1.50.0[src]
impl<'a, S1, S2> PartialEq<Node<'a, S2>> for Node<'a, S1> where
S1: ThreadSafety,
S2: ThreadSafety,
[src]
S1: ThreadSafety,
S2: ThreadSafety,
fn eq(&self, other: &Node<'a, S2>) -> bool
[src]
#[must_use]pub fn ne(&self, other: &Rhs) -> bool
1.0.0[src]
impl<'a, S1, S2> PartialOrd<Node<'a, S2>> for Node<'a, S1> where
S1: ThreadSafety,
S2: ThreadSafety,
[src]
S1: ThreadSafety,
S2: ThreadSafety,
fn partial_cmp(&self, other: &Node<'a, S2>) -> Option<Ordering>
[src]
#[must_use]pub fn lt(&self, other: &Rhs) -> bool
1.0.0[src]
#[must_use]pub fn le(&self, other: &Rhs) -> bool
1.0.0[src]
#[must_use]pub fn gt(&self, other: &Rhs) -> bool
1.0.0[src]
#[must_use]pub fn ge(&self, other: &Rhs) -> bool
1.0.0[src]
impl<'a, S> Vdom for Node<'a, S> where
S: ThreadSafety,
[src]
S: ThreadSafety,
type ThreadSafety = S
The ThreadSafety
of the Vdom
type, either ThreadSafe
or ThreadBound
. Read more
Auto Trait Implementations
impl<'a, S> RefUnwindSafe for Node<'a, S> where
S: RefUnwindSafe,
S: RefUnwindSafe,
impl<'a, S> Send for Node<'a, S> where
S: Send + Sync,
S: Send + Sync,
impl<'a, S> Sync for Node<'a, S> where
S: Sync,
S: Sync,
impl<'a, S> Unpin for Node<'a, S> where
S: Unpin,
S: Unpin,
impl<'a, S> UnwindSafe for Node<'a, S> where
S: RefUnwindSafe + UnwindSafe,
S: RefUnwindSafe + UnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<'a, S, T> AutoSafe<T> for S where
S: Vdom + Align<T>,
T: Vdom<ThreadSafety = ThreadBound>,
[src]
S: Vdom + Align<T>,
T: Vdom<ThreadSafety = ThreadBound>,
#[must_use]fn deanonymize(&self) -> BoundVariant
[src]
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<'a, V> Deanonymize<Node<'a, ThreadSafe>> for V where
V: Send + Sync + AutoSafe<Node<'a, ThreadBound>>,
[src]
V: Send + Sync + AutoSafe<Node<'a, ThreadBound>>,
#[must_use]fn deanonymize(self) -> SafeVariant
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,