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

Comment

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>)>>

Registers for Comment reference updates.

See DomRef for more information.

HtmlElement

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.

MathMlElement

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

element: &'a Element<'a, S>

The Element to render.

dom_binding: Option<CallbackRef<S, fn(dom_ref: DomRef<&Element>)>>

Registers for Element reference updates.

See DomRef for more information.

SvgElement

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.

Memoized

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.

Multi(&'a [Node<'a, S>])

DOM-transparent. Represents a sequence of VDOM nodes.

Used to hint diffs in case of additions and removals.

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.

Text

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>)>>

Registers for Text reference updates.

See DomRef for more information.

RemnantSite(&'a RemnantSite)

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]

👎 Deprecated:

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]

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]

impl<'a, S> Copy for Node<'a, S> where
    S: ThreadSafety
[src]

impl<'a, V> Deanonymize<Node<'a, ThreadSafe>> for V where
    V: Send + Sync + AutoSafe<Node<'a, ThreadBound>>, 
[src]

impl<'a, S> Debug for Node<'a, S> where
    S: ThreadSafety
[src]

impl<'a, S> Eq for Node<'a, S> where
    S: ThreadSafety
[src]

impl<'a, S1, S2> From<&'a [Node<'a, S1>]> for Node<'a, S2> where
    S1: ThreadSafety + Into<S2>,
    S2: ThreadSafety
[src]

impl<'a, S1, S2> From<&'a mut [Node<'a, S1>]> for Node<'a, S2> where
    S1: ThreadSafety + Into<S2>,
    S2: ThreadSafety
[src]

impl<'a, S> From<&'a mut str> for Node<'a, S> where
    S: ThreadSafety
[src]

impl<'a, S> From<&'a str> for Node<'a, S> where
    S: ThreadSafety
[src]

impl<'a> From<Node<'a, ThreadSafe>> for Node<'a, ThreadBound>[src]

impl<'a, S> Hash for Node<'a, S> where
    S: ThreadSafety
[src]

impl<'a, S> Ord for Node<'a, S> where
    S: ThreadSafety
[src]

impl<'a, S1, S2> PartialEq<Node<'a, S2>> for Node<'a, S1> where
    S1: ThreadSafety,
    S2: ThreadSafety
[src]

impl<'a, S1, S2> PartialOrd<Node<'a, S2>> for Node<'a, S1> where
    S1: ThreadSafety,
    S2: ThreadSafety
[src]

impl<'a, S> Vdom for Node<'a, S> where
    S: ThreadSafety
[src]

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

impl<'a, S> Send for Node<'a, S> where
    S: Send + Sync

impl<'a, S> Sync for Node<'a, S> where
    S: Sync

impl<'a, S> Unpin for Node<'a, S> where
    S: Unpin

impl<'a, S> UnwindSafe for Node<'a, S> where
    S: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<'a, S, T> AutoSafe<T> for S where
    S: Vdom + Align<T>,
    T: Vdom<ThreadSafety = ThreadBound>, 
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<'a, V> Deanonymize<Node<'a, ThreadSafe>> for V where
    V: Send + Sync + AutoSafe<Node<'a, ThreadBound>>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.