mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
Incremental performance improvements to element creation (#3169)
* enable interning * intern tag names * intern attribute keys and event listener types * intern attribute values * cache and clone elements * clean up the node cloning version a bit * use HashMap instead of Vec for element cache * Revert "intern attribute values" This reverts commit 28653c4660dcf1942fab3b0ad7d4c840b96e0f2a. * add `enable-interning` feature to Yew that activates the same in wasm-bindgen * remove interning feature
This commit is contained in:
parent
8086a73a21
commit
bdf5712d96
@ -75,7 +75,7 @@ features = [
|
|||||||
"WheelEvent",
|
"WheelEvent",
|
||||||
"Window",
|
"Window",
|
||||||
"HtmlScriptElement",
|
"HtmlScriptElement",
|
||||||
"SubmitEvent"
|
"SubmitEvent",
|
||||||
]
|
]
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||||
@ -89,11 +89,7 @@ trybuild = "1"
|
|||||||
|
|
||||||
[dev-dependencies.web-sys]
|
[dev-dependencies.web-sys]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
features = [
|
features = ["ShadowRootInit", "ShadowRootMode", "HtmlButtonElement"]
|
||||||
"ShadowRootInit",
|
|
||||||
"ShadowRootMode",
|
|
||||||
"HtmlButtonElement"
|
|
||||||
]
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
ssr = ["dep:html-escape", "dep:base64ct", "dep:bincode"]
|
ssr = ["dep:html-escape", "dep:base64ct", "dep:bincode"]
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::{intern, JsValue};
|
||||||
use web_sys::{Element, HtmlInputElement as InputElement, HtmlTextAreaElement as TextAreaElement};
|
use web_sys::{Element, HtmlInputElement as InputElement, HtmlTextAreaElement as TextAreaElement};
|
||||||
use yew::AttrValue;
|
use yew::AttrValue;
|
||||||
|
|
||||||
@ -163,9 +163,9 @@ impl Attributes {
|
|||||||
|
|
||||||
fn set(el: &Element, key: &str, value: &str, apply_as: ApplyAttributeAs) {
|
fn set(el: &Element, key: &str, value: &str, apply_as: ApplyAttributeAs) {
|
||||||
match apply_as {
|
match apply_as {
|
||||||
ApplyAttributeAs::Attribute => {
|
ApplyAttributeAs::Attribute => el
|
||||||
el.set_attribute(key, value).expect("invalid attribute key")
|
.set_attribute(intern(key), value)
|
||||||
}
|
.expect("invalid attribute key"),
|
||||||
ApplyAttributeAs::Property => {
|
ApplyAttributeAs::Property => {
|
||||||
let key = JsValue::from_str(key);
|
let key = JsValue::from_str(key);
|
||||||
let value = JsValue::from_str(value);
|
let value = JsValue::from_str(value);
|
||||||
@ -177,7 +177,7 @@ impl Attributes {
|
|||||||
fn remove(el: &Element, key: &str, apply_as: ApplyAttributeAs) {
|
fn remove(el: &Element, key: &str, apply_as: ApplyAttributeAs) {
|
||||||
match apply_as {
|
match apply_as {
|
||||||
ApplyAttributeAs::Attribute => el
|
ApplyAttributeAs::Attribute => el
|
||||||
.remove_attribute(key)
|
.remove_attribute(intern(key))
|
||||||
.expect("could not remove attribute"),
|
.expect("could not remove attribute"),
|
||||||
ApplyAttributeAs::Property => {
|
ApplyAttributeAs::Property => {
|
||||||
let key = JsValue::from_str(key);
|
let key = JsValue::from_str(key);
|
||||||
|
|||||||
@ -4,6 +4,8 @@ mod attributes;
|
|||||||
mod listeners;
|
mod listeners;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::hint::unreachable_unchecked;
|
use std::hint::unreachable_unchecked;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
@ -252,9 +254,31 @@ impl VTag {
|
|||||||
.create_element_ns(namespace, tag)
|
.create_element_ns(namespace, tag)
|
||||||
.expect("can't create namespaced element for vtag")
|
.expect("can't create namespaced element for vtag")
|
||||||
} else {
|
} else {
|
||||||
document()
|
thread_local! {
|
||||||
.create_element(tag)
|
static CACHED_ELEMENTS: RefCell<HashMap<String, Element>> = RefCell::new(HashMap::with_capacity(32));
|
||||||
.expect("can't create element for vtag")
|
}
|
||||||
|
|
||||||
|
CACHED_ELEMENTS.with(|cache| {
|
||||||
|
let mut cache = cache.borrow_mut();
|
||||||
|
let cached = cache.get(tag).map(|el| {
|
||||||
|
el.clone_node()
|
||||||
|
.expect("couldn't clone cached element")
|
||||||
|
.unchecked_into::<Element>()
|
||||||
|
});
|
||||||
|
cached.unwrap_or_else(|| {
|
||||||
|
let to_be_cached = document()
|
||||||
|
.create_element(tag)
|
||||||
|
.expect("can't create element for vtag");
|
||||||
|
cache.insert(
|
||||||
|
tag.to_string(),
|
||||||
|
to_be_cached
|
||||||
|
.clone_node()
|
||||||
|
.expect("couldn't clone node to be cached")
|
||||||
|
.unchecked_into(),
|
||||||
|
);
|
||||||
|
to_be_cached
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use std::rc::{Rc, Weak};
|
|||||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||||
|
|
||||||
use wasm_bindgen::prelude::{wasm_bindgen, Closure};
|
use wasm_bindgen::prelude::{wasm_bindgen, Closure};
|
||||||
use wasm_bindgen::{JsCast, UnwrapThrowExt};
|
use wasm_bindgen::{intern, JsCast, UnwrapThrowExt};
|
||||||
use web_sys::{
|
use web_sys::{
|
||||||
AddEventListenerOptions, Element, Event, EventTarget as HtmlEventTarget, ShadowRoot,
|
AddEventListenerOptions, Element, Event, EventTarget as HtmlEventTarget, ShadowRoot,
|
||||||
};
|
};
|
||||||
@ -157,7 +157,7 @@ impl EventListener {
|
|||||||
|
|
||||||
target
|
target
|
||||||
.add_event_listener_with_callback_and_add_event_listener_options(
|
.add_event_listener_with_callback_and_add_event_listener_options(
|
||||||
&event_type,
|
intern(&event_type),
|
||||||
callback.as_ref().unchecked_ref(),
|
callback.as_ref().unchecked_ref(),
|
||||||
&options,
|
&options,
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user