Merge pull request #219 from jquesada2016/leptos_dom_stable

Stable support for `leptos_dom`
This commit is contained in:
Greg Johnston 2023-01-02 12:09:48 -05:00 committed by GitHub
commit 60187961a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 115 additions and 79 deletions

View file

@ -9,6 +9,7 @@ description = "DOM operations for the Leptos web framework."
[dependencies]
cfg-if = "1"
drain_filter_polyfill = "0.1"
educe = "0.4"
futures = "0.3"
gloo = "0.8"
@ -17,6 +18,7 @@ indexmap = "1.9"
itertools = "0.10"
js-sys = "0.3"
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.1.0-alpha" }
once_cell = "1"
pad-adapter = "0.1"
paste = "1"
rustc-hash = "1.1.0"

View file

@ -13,9 +13,11 @@ pub use dyn_child::*;
pub use each::*;
pub use fragment::*;
use leptos_reactive::Scope;
use std::{borrow::Cow, fmt};
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use std::{cell::OnceCell, rc::Rc};
use once_cell::unsync::OnceCell;
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use std::rc::Rc;
use std::{borrow::Cow, fmt};
pub use unit::*;
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use wasm_bindgen::JsCast;

View file

@ -3,11 +3,12 @@ use cfg_if::cfg_if;
cfg_if! {
if #[cfg(all(target_arch = "wasm32", feature = "web"))] {
use crate::{mount_child, prepare_to_move, MountKind, Mountable, RANGE};
use std::cell::OnceCell;
use once_cell::unsync::OnceCell;
use leptos_reactive::create_effect;
use rustc_hash::FxHasher;
use std::hash::BuildHasherDefault;
use wasm_bindgen::JsCast;
use drain_filter_polyfill::VecExt as VecDrainFilterExt;
type FxIndexSet<T> = indexmap::IndexSet<T, BuildHasherDefault<FxHasher>>;
@ -573,7 +574,7 @@ fn apply_cmds<T, EF, N>(
EF: Fn(T) -> N,
N: IntoView,
{
let range = &RANGE;
let range = RANGE.with(|range| (*range).clone());
// Resize children if needed
if cmds.added.len().checked_sub(cmds.removed.len()).is_some() {

View file

@ -12,7 +12,7 @@ cfg_if! {
};
use crate::{mount_child, MountKind};
use leptos_reactive::create_render_effect;
use std::cell::LazyCell;
use once_cell::unsync::Lazy as LazyCell;
use wasm_bindgen::JsCast;
/// Trait alias for the trait bounts on [`ElementDescriptor`].
@ -671,13 +671,14 @@ macro_rules! generate_html_tags {
paste::paste! {
$(
#[cfg(all(target_arch = "wasm32", feature = "web"))]
#[thread_local]
static [<$tag:upper>]: LazyCell<web_sys::HtmlElement> = LazyCell::new(|| {
crate::document()
.create_element(stringify!($tag))
.unwrap()
.unchecked_into()
});
thread_local! {
static [<$tag:upper>]: LazyCell<web_sys::HtmlElement> = LazyCell::new(|| {
crate::document()
.create_element(stringify!($tag))
.unwrap()
.unchecked_into()
});
}
#[derive(Clone, Debug)]
#[$meta]
@ -735,10 +736,20 @@ macro_rules! generate_html_tags {
"not found, ignoring it for hydration"
);
[<$tag:upper>].clone_node().unwrap().unchecked_into()
[<$tag:upper>]
.with(|el|
el.clone_node()
.unwrap()
.unchecked_into()
)
}
} else {
[<$tag:upper>].clone_node().unwrap().unchecked_into()
[<$tag:upper>]
.with(|el|
el.clone_node()
.unwrap()
.unchecked_into()
)
};
Self {

View file

@ -7,7 +7,7 @@ use leptos_reactive::Scope;
use std::borrow::Cow;
cfg_if! {
if #[cfg(all(target_arch = "wasm32", feature = "web"))] {
use std::cell::LazyCell;
use once_cell::unsync::Lazy as LazyCell;
use wasm_bindgen::JsCast;
} else {
use super::{HydrationKey, HTML_ELEMENT_DEREF_UNIMPLEMENTED_MSG};
@ -25,24 +25,25 @@ macro_rules! generate_math_tags {
paste::paste! {
$(
#[cfg(all(target_arch = "wasm32", feature = "web"))]
#[thread_local]
static [<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]: LazyCell<web_sys::HtmlElement> = LazyCell::new(|| {
crate::document()
.create_element_ns(
Some(wasm_bindgen::intern("http://www.w3.org/1998/Math/MathML")),
concat![
stringify!($tag),
$(
"-", stringify!($second),
thread_local! {
static [<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]: LazyCell<web_sys::HtmlElement> = LazyCell::new(|| {
crate::document()
.create_element_ns(
Some(wasm_bindgen::intern("http://www.w3.org/1998/Math/MathML")),
concat![
stringify!($tag),
$(
"-", stringify!($third)
"-", stringify!($second),
$(
"-", stringify!($third)
)?
)?
)?
],
)
.unwrap()
.unchecked_into()
});
],
)
.unwrap()
.unchecked_into()
});
}
#[derive(Clone, Debug)]
#[$meta]
@ -100,10 +101,20 @@ macro_rules! generate_math_tags {
"not found, ignoring it for hydration"
);
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>].clone_node().unwrap().unchecked_into()
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]
.with(|el|
el.clone_node()
.unwrap()
.unchecked_into()
)
}
} else {
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>].clone_node().unwrap().unchecked_into()
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]
.with(|el|
el.clone_node()
.unwrap()
.unchecked_into()
)
};
Self {

View file

@ -5,9 +5,9 @@ use super::{ElementDescriptor, HtmlElement};
use super::{HydrationKey, HTML_ELEMENT_DEREF_UNIMPLEMENTED_MSG};
use crate::HydrationCtx;
use leptos_reactive::Scope;
use std::borrow::Cow;
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use std::cell::LazyCell;
use once_cell::unsync::Lazy as LazyCell;
use std::borrow::Cow;
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use wasm_bindgen::JsCast;
@ -22,24 +22,25 @@ macro_rules! generate_svg_tags {
paste::paste! {
$(
#[cfg(all(target_arch = "wasm32", feature = "web"))]
#[thread_local]
static [<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]: LazyCell<web_sys::HtmlElement> = LazyCell::new(|| {
crate::document()
.create_element_ns(
Some(wasm_bindgen::intern("http://www.w3.org/2000/svg")),
concat![
stringify!($tag),
$(
"-", stringify!($second),
thread_local! {
static [<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]: LazyCell<web_sys::HtmlElement> = LazyCell::new(|| {
crate::document()
.create_element_ns(
Some(wasm_bindgen::intern("http://www.w3.org/2000/svg")),
concat![
stringify!($tag),
$(
"-", stringify!($third)
"-", stringify!($second),
$(
"-", stringify!($third)
)?
)?
)?
],
)
.unwrap()
.unchecked_into()
});
],
)
.unwrap()
.unchecked_into()
});
}
#[derive(Clone, Debug)]
#[$meta]
@ -97,10 +98,20 @@ macro_rules! generate_svg_tags {
"not found, ignoring it for hydration"
);
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>].clone_node().unwrap().unchecked_into()
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]
.with(|el|
el.clone_node()
.unwrap()
.unchecked_into()
)
}
} else {
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>].clone_node().unwrap().unchecked_into()
[<$tag:upper $(_ $second:upper $(_ $third:upper)?)?>]
.with(|el|
el.clone_node()
.unwrap()
.unchecked_into()
)
};
Self {

View file

@ -1,21 +1,22 @@
use std::{cell::RefCell, fmt::Display};
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use std::cell::LazyCell;
use once_cell::unsync::Lazy as LazyCell;
/// We can tell if we start in hydration mode by checking to see if the
/// id "_0" is present in the DOM. If it is, we know we are hydrating from
/// the server, if not, we are starting off in CSR
#[cfg(all(target_arch = "wasm32", feature = "web"))]
#[thread_local]
static mut IS_HYDRATING: LazyCell<bool> = LazyCell::new(|| {
#[cfg(debug_assertions)]
return crate::document().get_element_by_id("_0-0-0").is_some()
|| crate::document().get_element_by_id("_0-0-0o").is_some();
thread_local! {
static IS_HYDRATING: RefCell<LazyCell<bool>> = RefCell::new(LazyCell::new(|| {
#[cfg(debug_assertions)]
return crate::document().get_element_by_id("_0-0-0").is_some()
|| crate::document().get_element_by_id("_0-0-0o").is_some();
#[cfg(not(debug_assertions))]
return crate::document().get_element_by_id("_0-0-0").is_some();
});
#[cfg(not(debug_assertions))]
return crate::document().get_element_by_id("_0-0-0").is_some();
}));
}
/// A stable identifer within the server-rendering or hydration process.
#[derive(Clone, Debug, PartialEq, Eq)]
@ -86,14 +87,14 @@ impl HydrationCtx {
#[cfg(all(target_arch = "wasm32", feature = "web"))]
pub(crate) fn stop_hydrating() {
unsafe {
std::mem::take(&mut IS_HYDRATING);
}
IS_HYDRATING.with(|is_hydrating| {
std::mem::take(&mut *is_hydrating.borrow_mut());
})
}
#[cfg(all(target_arch = "wasm32", feature = "web"))]
pub(crate) fn is_hydrating() -> bool {
unsafe { *IS_HYDRATING }
IS_HYDRATING.with(|is_hydrating| **is_hydrating.borrow())
}
pub(crate) fn to_string(id: &HydrationKey, closing: bool) -> String {

View file

@ -1,5 +1,4 @@
#![deny(missing_docs)]
#![feature(once_cell, iter_intersperse, drain_filter, thread_local)]
#![cfg_attr(not(feature = "stable"), feature(fn_traits))]
#![cfg_attr(not(feature = "stable"), feature(unboxed_closures))]
@ -32,16 +31,15 @@ use leptos_reactive::Scope;
pub use logging::*;
pub use macro_helpers::{IntoAttribute, IntoClass, IntoProperty};
pub use node_ref::*;
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use once_cell::unsync::Lazy as LazyCell;
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
use smallvec::SmallVec;
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
pub use ssr::*;
use std::{borrow::Cow, fmt};
#[cfg(all(target_arch = "wasm32", feature = "web"))]
use std::{
cell::{LazyCell, RefCell},
rc::Rc,
};
use std::{cell::RefCell, rc::Rc};
pub use transparent::*;
pub use wasm_bindgen;
#[cfg(all(target_arch = "wasm32", feature = "web"))]
@ -50,13 +48,12 @@ use wasm_bindgen::UnwrapThrowExt;
pub use web_sys;
#[cfg(all(target_arch = "wasm32", feature = "web"))]
#[thread_local]
static COMMENT: LazyCell<web_sys::Node> =
LazyCell::new(|| document().create_comment("").unchecked_into());
#[cfg(all(target_arch = "wasm32", feature = "web"))]
#[thread_local]
static RANGE: LazyCell<web_sys::Range> =
LazyCell::new(|| web_sys::Range::new().unwrap());
thread_local! {
static COMMENT: LazyCell<web_sys::Node> =
LazyCell::new(|| document().create_comment("").unchecked_into());
static RANGE: LazyCell<web_sys::Range> =
LazyCell::new(|| web_sys::Range::new().unwrap());
}
/// Converts the value into a [`View`].
pub trait IntoView {
@ -289,7 +286,7 @@ impl Comment {
}
#[cfg(all(target_arch = "wasm32", feature = "web"))]
let node = COMMENT.clone_node().unwrap();
let node = COMMENT.with(|comment| comment.clone_node().unwrap());
#[cfg(all(debug_assertions, target_arch = "wasm32", feature = "web"))]
node.set_text_content(Some(&format!(" {content} ")));