From 0091679779ac281d5c1db60a803c8733303bca26 Mon Sep 17 00:00:00 2001 From: Tim Kurdov Date: Thu, 20 Feb 2025 18:13:07 +0000 Subject: [PATCH] Make ` + + } // make sure that capitalization doesn't matter for the void children check html! { }; diff --git a/packages/yew-macro/tests/html_macro/element-fail.stderr b/packages/yew-macro/tests/html_macro/element-fail.stderr index bec8a082cfe..6fb429a3115 100644 --- a/packages/yew-macro/tests/html_macro/element-fail.stderr +++ b/packages/yew-macro/tests/html_macro/element-fail.stderr @@ -118,28 +118,34 @@ error: the tag `` is a void element and cannot have children (hint: rewri 66 | html! { }; | ^^^^^^^^^^^^^^^^^^^ -error: the tag `` is a void element and cannot have children (hint: rewrite this as ``) +error: the tag ` } + | ^^^^^^^^^^ + +error: the tag `` is a void element and cannot have children (hint: rewrite this as ``) + --> tests/html_macro/element-fail.rs:70:13 + | +70 | html! { }; | ^^^^^^^^^^^^^^^^^^^ error: this dynamic tag is missing an expression block defining its value - --> tests/html_macro/element-fail.rs:71:14 + --> tests/html_macro/element-fail.rs:73:14 | -71 | html! { <@> }; +73 | html! { <@> }; | ^ error: this dynamic tag is missing an expression block defining its value - --> tests/html_macro/element-fail.rs:72:14 + --> tests/html_macro/element-fail.rs:74:14 | -72 | html! { <@/> }; +74 | html! { <@/> }; | ^ error: dynamic closing tags must not have a body (hint: replace it with just ``) - --> tests/html_macro/element-fail.rs:75:27 + --> tests/html_macro/element-fail.rs:77:27 | -75 | html! { <@{"test"}> }; +77 | html! { <@{"test"}> }; | ^^^^^^^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Tuple { @@ -147,9 +153,9 @@ error: the property value must be either a literal or enclosed in braces. Consid paren_token: Paren, elems: [], } - --> tests/html_macro/element-fail.rs:80:24 + --> tests/html_macro/element-fail.rs:82:24 | -80 | html! { }; +82 | html! { }; | ^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Tuple { @@ -157,9 +163,9 @@ error: the property value must be either a literal or enclosed in braces. Consid paren_token: Paren, elems: [], } - --> tests/html_macro/element-fail.rs:81:24 + --> tests/html_macro/element-fail.rs:83:24 | -81 | html! { }; +83 | html! { }; | ^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Call { @@ -173,7 +179,7 @@ error: the property value must be either a literal or enclosed in braces. Consid PathSegment { ident: Ident { ident: "Some", - span: #0 bytes(2482..2486), + span: #0 bytes(2628..2632), }, arguments: PathArguments::None, }, @@ -190,9 +196,9 @@ error: the property value must be either a literal or enclosed in braces. Consid }, ], } - --> tests/html_macro/element-fail.rs:82:28 + --> tests/html_macro/element-fail.rs:84:28 | -82 | html! { }; +84 | html! { }; | ^^^^^^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Path { @@ -204,16 +210,16 @@ error: the property value must be either a literal or enclosed in braces. Consid PathSegment { ident: Ident { ident: "NotToString", - span: #0 bytes(2522..2533), + span: #0 bytes(2668..2679), }, arguments: PathArguments::None, }, ], }, } - --> tests/html_macro/element-fail.rs:83:27 + --> tests/html_macro/element-fail.rs:85:27 | -83 | html! { }; +85 | html! { }; | ^^^^^^^^^^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Call { @@ -227,7 +233,7 @@ error: the property value must be either a literal or enclosed in braces. Consid PathSegment { ident: Ident { ident: "Some", - span: #0 bytes(2561..2565), + span: #0 bytes(2707..2711), }, arguments: PathArguments::None, }, @@ -245,7 +251,7 @@ error: the property value must be either a literal or enclosed in braces. Consid PathSegment { ident: Ident { ident: "NotToString", - span: #0 bytes(2566..2577), + span: #0 bytes(2712..2723), }, arguments: PathArguments::None, }, @@ -254,9 +260,9 @@ error: the property value must be either a literal or enclosed in braces. Consid }, ], } - --> tests/html_macro/element-fail.rs:84:22 + --> tests/html_macro/element-fail.rs:86:22 | -84 | html! { }; +86 | html! { }; | ^^^^^^^^^^^^^^^^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Call { @@ -270,7 +276,7 @@ error: the property value must be either a literal or enclosed in braces. Consid PathSegment { ident: Ident { ident: "Some", - span: #0 bytes(2605..2609), + span: #0 bytes(2751..2755), }, arguments: PathArguments::None, }, @@ -287,9 +293,9 @@ error: the property value must be either a literal or enclosed in braces. Consid }, ], } - --> tests/html_macro/element-fail.rs:85:21 + --> tests/html_macro/element-fail.rs:87:21 | -85 | html! { }; +87 | html! { }; | ^^^^^^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Tuple { @@ -297,9 +303,9 @@ error: the property value must be either a literal or enclosed in braces. Consid paren_token: Paren, elems: [], } - --> tests/html_macro/element-fail.rs:86:25 + --> tests/html_macro/element-fail.rs:88:25 | -86 | html! { }; +88 | html! { }; | ^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Tuple { @@ -307,9 +313,9 @@ error: the property value must be either a literal or enclosed in braces. Consid paren_token: Paren, elems: [], } - --> tests/html_macro/element-fail.rs:87:26 + --> tests/html_macro/element-fail.rs:89:26 | -87 | html! { }; +89 | html! { }; | ^^ error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.: Expr::Path { @@ -321,16 +327,16 @@ error: the property value must be either a literal or enclosed in braces. Consid PathSegment { ident: Ident { ident: "NotToString", - span: #0 bytes(2712..2723), + span: #0 bytes(2858..2869), }, arguments: PathArguments::None, }, ], }, } - --> tests/html_macro/element-fail.rs:88:27 + --> tests/html_macro/element-fail.rs:90:27 | -88 | html! { }; +90 | html! { }; | ^^^^^^^^^^^ error[E0308]: mismatched types @@ -685,9 +691,9 @@ error[E0277]: the trait bound `(): IntoPropValue` is not satisfied = help: for that trait implementation, expected `VNode`, found `yew::NodeRef` error[E0277]: the trait bound `implicit_clone::unsync::string::IString: From<{integer}>` is not satisfied - --> tests/html_macro/element-fail.rs:77:16 + --> tests/html_macro/element-fail.rs:79:16 | -77 | html! { <@{55}> }; +79 | html! { <@{55}> }; | ^^ the trait `From<{integer}>` is not implemented for `implicit_clone::unsync::string::IString` | = help: the following other types implement trait `From`: diff --git a/packages/yew-router/Cargo.toml b/packages/yew-router/Cargo.toml index 056e5633a27..6bc0fb4b2d7 100644 --- a/packages/yew-router/Cargo.toml +++ b/packages/yew-router/Cargo.toml @@ -42,3 +42,6 @@ version = "0.3" features = [ "HtmlHeadElement", ] + +[lints] +workspace = true diff --git a/packages/yew-router/src/utils.rs b/packages/yew-router/src/utils.rs index a1a1067eedb..2b32326c4d1 100644 --- a/packages/yew-router/src/utils.rs +++ b/packages/yew-router/src/utils.rs @@ -66,7 +66,12 @@ pub fn compose_path(pathname: &str, query: &str) -> Option { } } -#[cfg(test)] +// TODO: remove the cfg after wasm-bindgen-test stops emitting the function unconditionally +#[cfg(all( + test, + target_arch = "wasm32", + any(target_os = "unknown", target_os = "none") +))] mod tests { use gloo::utils::document; use wasm_bindgen_test::wasm_bindgen_test as test; diff --git a/packages/yew-router/tests/basename.rs b/packages/yew-router/tests/basename.rs index 15da65412fd..574481bc513 100644 --- a/packages/yew-router/tests/basename.rs +++ b/packages/yew-router/tests/basename.rs @@ -1,4 +1,5 @@ -#![cfg(not(target_os = "wasi"))] +// TODO: remove the cfg after wasm-bindgen-test stops emitting the function unconditionally +#![cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] use std::time::Duration; diff --git a/packages/yew-router/tests/browser_router.rs b/packages/yew-router/tests/browser_router.rs index 2344060080f..6b1ac944b2d 100644 --- a/packages/yew-router/tests/browser_router.rs +++ b/packages/yew-router/tests/browser_router.rs @@ -1,4 +1,5 @@ -#![cfg(not(target_os = "wasi"))] +// TODO: remove the cfg after wasm-bindgen-test stops emitting the function unconditionally +#![cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] use std::time::Duration; diff --git a/packages/yew-router/tests/hash_router.rs b/packages/yew-router/tests/hash_router.rs index 6b11a9bf1d6..b70364a930a 100644 --- a/packages/yew-router/tests/hash_router.rs +++ b/packages/yew-router/tests/hash_router.rs @@ -1,4 +1,5 @@ -#![cfg(not(target_os = "wasi"))] +// TODO: remove the cfg after wasm-bindgen-test stops emitting the function unconditionally +#![cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] use std::time::Duration; diff --git a/packages/yew-router/tests/link.rs b/packages/yew-router/tests/link.rs index 7e195d9246e..24734fba0b6 100644 --- a/packages/yew-router/tests/link.rs +++ b/packages/yew-router/tests/link.rs @@ -1,4 +1,5 @@ -#![cfg(not(target_os = "wasi"))] +// TODO: remove the cfg after wasm-bindgen-test stops emitting the function unconditionally +#![cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] use std::sync::atomic::{AtomicU8, Ordering}; use std::time::Duration; diff --git a/packages/yew-router/tests/router_unit_tests.rs b/packages/yew-router/tests/router_unit_tests.rs index 30ad206d2f9..697842d6844 100644 --- a/packages/yew-router/tests/router_unit_tests.rs +++ b/packages/yew-router/tests/router_unit_tests.rs @@ -1,3 +1,6 @@ +// TODO: remove the cfg after wasm-bindgen-test stops emitting the function unconditionally +#![cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] + use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure}; use yew_router::prelude::*; diff --git a/packages/yew-router/tests/url_encoded_routes.rs b/packages/yew-router/tests/url_encoded_routes.rs index 6d2cf213b74..58ec7bc65d3 100644 --- a/packages/yew-router/tests/url_encoded_routes.rs +++ b/packages/yew-router/tests/url_encoded_routes.rs @@ -1,4 +1,5 @@ -#![cfg(not(target_os = "wasi"))] +// TODO: remove the cfg after wasm-bindgen-test stops emitting the function unconditionally +#![cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] use std::time::Duration; diff --git a/packages/yew/Cargo.toml b/packages/yew/Cargo.toml index fe5449c054f..d0cf8b7f0d6 100644 --- a/packages/yew/Cargo.toml +++ b/packages/yew/Cargo.toml @@ -106,6 +106,5 @@ test = [] all-features = true rustdoc-args = ["--cfg", "documenting"] -[lints.rust] -unexpected_cfgs = { level = "allow", check-cfg = ['cfg(nightly_yew)'] } - +[lints] +workspace = true diff --git a/packages/yew/src/dom_bundle/blist.rs b/packages/yew/src/dom_bundle/blist.rs index fd5bb2a117a..beedfeebb6b 100644 --- a/packages/yew/src/dom_bundle/blist.rs +++ b/packages/yew/src/dom_bundle/blist.rs @@ -69,7 +69,7 @@ impl NodeWriter<'_> { } /// Shift a bundle into place without patching it - fn shift(&self, bundle: &mut BNode) { + fn shift(&self, bundle: &BNode) { bundle.shift(self.parent, self.slot.clone()); } @@ -364,7 +364,7 @@ impl BList { // it should be Ordering::Equal => barrier_idx += 1, // shift the node unconditionally, don't start a run - Ordering::Less => writer.shift(&mut r_bundle), + Ordering::Less => writer.shift(&r_bundle), // start a run Ordering::Greater => { current_run = Some(RunInformation { diff --git a/packages/yew/src/dom_bundle/braw.rs b/packages/yew/src/dom_bundle/braw.rs index 3f089f26913..b579606f3f2 100644 --- a/packages/yew/src/dom_bundle/braw.rs +++ b/packages/yew/src/dom_bundle/braw.rs @@ -74,14 +74,11 @@ impl Reconcilable for VRaw { parent: &Element, slot: DomSlot, ) -> (DomSlot, Self::Bundle) { - let namespace = if parent - .namespace_uri() - .map_or(false, |ns| ns == SVG_NAMESPACE) - { + let namespace = if parent.namespace_uri().is_some_and(|ns| ns == SVG_NAMESPACE) { Some(SVG_NAMESPACE) } else if parent .namespace_uri() - .map_or(false, |ns| ns == MATHML_NAMESPACE) + .is_some_and(|ns| ns == MATHML_NAMESPACE) { Some(MATHML_NAMESPACE) } else { diff --git a/packages/yew/src/dom_bundle/btag/attributes.rs b/packages/yew/src/dom_bundle/btag/attributes.rs index a07a30c7a03..397380076d6 100644 --- a/packages/yew/src/dom_bundle/btag/attributes.rs +++ b/packages/yew/src/dom_bundle/btag/attributes.rs @@ -8,7 +8,7 @@ use yew::AttrValue; use super::Apply; use crate::dom_bundle::BSubtree; -use crate::virtual_dom::vtag::{InputFields, Value}; +use crate::virtual_dom::vtag::{InputFields, TextareaFields, Value}; use crate::virtual_dom::{AttributeOrProperty, Attributes}; impl Apply for Value { @@ -88,6 +88,22 @@ impl Apply for InputFields { } } +impl Apply for TextareaFields { + type Bundle = Value; + type Element = TextAreaElement; + + fn apply(self, root: &BSubtree, el: &Self::Element) -> Self::Bundle { + if let Some(def) = self.defaultvalue { + _ = el.set_default_value(def.as_str()); + } + self.value.apply(root, el) + } + + fn apply_diff(self, root: &BSubtree, el: &Self::Element, bundle: &mut Self::Bundle) { + self.value.apply_diff(root, el, bundle) + } +} + impl Attributes { #[cold] fn apply_diff_index_maps( diff --git a/packages/yew/src/dom_bundle/btag/mod.rs b/packages/yew/src/dom_bundle/btag/mod.rs index 4cf26aa3c42..4ebb4023881 100644 --- a/packages/yew/src/dom_bundle/btag/mod.rs +++ b/packages/yew/src/dom_bundle/btag/mod.rs @@ -16,7 +16,9 @@ use web_sys::{Element, HtmlTextAreaElement as TextAreaElement}; use super::{BNode, BSubtree, DomSlot, Reconcilable, ReconcileTarget}; use crate::html::AnyScope; -use crate::virtual_dom::vtag::{InputFields, VTagInner, Value, MATHML_NAMESPACE, SVG_NAMESPACE}; +use crate::virtual_dom::vtag::{ + InputFields, TextareaFields, VTagInner, Value, MATHML_NAMESPACE, SVG_NAMESPACE, +}; use crate::virtual_dom::{AttrValue, Attributes, Key, VTag}; use crate::NodeRef; @@ -129,8 +131,8 @@ impl Reconcilable for VTag { let f = f.apply(root, el.unchecked_ref()); BTagInner::Input(f) } - VTagInner::Textarea { value } => { - let value = value.apply(root, el.unchecked_ref()); + VTagInner::Textarea(f) => { + let value = f.apply(root, el.unchecked_ref()); BTagInner::Textarea { value } } VTagInner::Other { children, tag } => { @@ -201,7 +203,10 @@ impl Reconcilable for VTag { (VTagInner::Input(new), BTagInner::Input(old)) => { new.apply_diff(root, el.unchecked_ref(), old); } - (VTagInner::Textarea { value: new }, BTagInner::Textarea { value: old }) => { + ( + VTagInner::Textarea(TextareaFields { value: new, .. }), + BTagInner::Textarea { value: old }, + ) => { new.apply_diff(root, el.unchecked_ref(), old); } ( @@ -234,11 +239,7 @@ impl VTag { fn create_element(&self, parent: &Element) -> Element { let tag = self.tag(); - if tag == "svg" - || parent - .namespace_uri() - .map_or(false, |ns| ns == SVG_NAMESPACE) - { + if tag == "svg" || parent.namespace_uri().is_some_and(|ns| ns == SVG_NAMESPACE) { let namespace = Some(SVG_NAMESPACE); document() .create_element_ns(namespace, tag) @@ -246,7 +247,7 @@ impl VTag { } else if tag == "math" || parent .namespace_uri() - .map_or(false, |ns| ns == MATHML_NAMESPACE) + .is_some_and(|ns| ns == MATHML_NAMESPACE) { let namespace = Some(MATHML_NAMESPACE); document() @@ -362,7 +363,7 @@ mod feat_hydration { el.tag_name().to_lowercase(), ); - // We simply registers listeners and updates all attributes. + // We simply register listeners and update all attributes. let attributes = attributes.apply(root, &el); let listeners = listeners.apply(root, &el); @@ -372,8 +373,8 @@ mod feat_hydration { let f = f.apply(root, el.unchecked_ref()); BTagInner::Input(f) } - VTagInner::Textarea { value } => { - let value = value.apply(root, el.unchecked_ref()); + VTagInner::Textarea(f) => { + let value = f.apply(root, el.unchecked_ref()); BTagInner::Textarea { value } } diff --git a/packages/yew/src/virtual_dom/listeners.rs b/packages/yew/src/virtual_dom/listeners.rs index 87774ad3ebb..9bd8359f5e0 100644 --- a/packages/yew/src/virtual_dom/listeners.rs +++ b/packages/yew/src/virtual_dom/listeners.rs @@ -199,7 +199,7 @@ impl PartialEq for Listeners { }) } } - (None, Pending(pending)) | (Pending(pending), None) => pending.len() == 0, + (None, Pending(pending)) | (Pending(pending), None) => pending.is_empty(), } } } diff --git a/packages/yew/src/virtual_dom/vtag.rs b/packages/yew/src/virtual_dom/vtag.rs index 98d17eb5cac..943371fd8d1 100644 --- a/packages/yew/src/virtual_dom/vtag.rs +++ b/packages/yew/src/virtual_dom/vtag.rs @@ -48,7 +48,7 @@ impl Value { /// Set a new value. The caller should take care that the value is valid for the element's /// `value` property - fn set(&mut self, value: Option) { + pub(crate) fn set(&mut self, value: Option) { self.0 = value; } } @@ -93,7 +93,7 @@ impl DerefMut for InputFields { } impl InputFields { - /// Crate new attributes for an [InputElement] element + /// Create new attributes for an [InputElement] element fn new(value: Option, checked: Option) -> Self { Self { value: Value::new(value), @@ -102,6 +102,17 @@ impl InputFields { } } +#[derive(Debug, Clone, Default)] +pub(crate) struct TextareaFields { + /// Contains the value of an + /// [TextAreaElement](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea). + pub(crate) value: Value, + /// Contains the default value of + /// [TextAreaElement](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea). + #[allow(unused)] // unused only if both "csr" and "ssr" features are off + pub(crate) defaultvalue: Option, +} + /// [VTag] fields that are specific to different [VTag] kinds. /// Decreases the memory footprint of [VTag] by avoiding impossible field and value combinations. #[derive(Debug, Clone)] @@ -113,11 +124,7 @@ pub(crate) enum VTagInner { /// Fields specific to /// [TextArea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea) /// [VTag]s - Textarea { - /// Contains a value of an - /// [TextArea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea) - value: Value, - }, + Textarea(TextareaFields), /// Fields for all other kinds of [VTag]s Other { /// A tag of the element. @@ -154,9 +161,7 @@ impl VTag { Self::new_base( match &*tag.to_ascii_lowercase() { "input" => VTagInner::Input(Default::default()), - "textarea" => VTagInner::Textarea { - value: Default::default(), - }, + "textarea" => VTagInner::Textarea(Default::default()), _ => VTagInner::Other { tag, children: Default::default(), @@ -184,7 +189,7 @@ impl VTag { checked: Option, node_ref: NodeRef, key: Option, - // at bottom for more readable macro-expanded coded + // at the bottom for more readable macro-expanded code attributes: Attributes, listeners: Listeners, ) -> Self { @@ -214,16 +219,18 @@ impl VTag { #[allow(clippy::too_many_arguments)] pub fn __new_textarea( value: Option, + defaultvalue: Option, node_ref: NodeRef, key: Option, - // at bottom for more readable macro-expanded coded + // at the bottom for more readable macro-expanded code attributes: Attributes, listeners: Listeners, ) -> Self { VTag::new_base( - VTagInner::Textarea { + VTagInner::Textarea(TextareaFields { value: Value::new(value), - }, + defaultvalue, + }), node_ref, key, attributes, @@ -243,7 +250,7 @@ impl VTag { tag: AttrValue, node_ref: NodeRef, key: Option, - // at bottom for more readable macro-expanded coded + // at the bottom for more readable macro-expanded code attributes: Attributes, listeners: Listeners, children: VNode, @@ -332,7 +339,7 @@ impl VTag { pub fn value(&self) -> Option<&AttrValue> { match &self.inner { VTagInner::Input(f) => f.as_ref(), - VTagInner::Textarea { value } => value.as_ref(), + VTagInner::Textarea(TextareaFields { value, .. }) => value.as_ref(), VTagInner::Other { .. } => None, } } @@ -345,7 +352,7 @@ impl VTag { VTagInner::Input(f) => { f.set(value.into_prop_value()); } - VTagInner::Textarea { value: dst } => { + VTagInner::Textarea(TextareaFields { value: dst, .. }) => { dst.set(value.into_prop_value()); } VTagInner::Other { .. } => (), @@ -447,7 +454,7 @@ impl PartialEq for VTag { (match (&self.inner, &other.inner) { (Input(l), Input(r)) => l == r, - (Textarea { value: value_l }, Textarea { value: value_r }) => value_l == value_r, + (Textarea (TextareaFields{ value: value_l, .. }), Textarea (TextareaFields{ value: value_r, .. })) => value_l == value_r, (Other { tag: tag_l, .. }, Other { tag: tag_r, .. }) => tag_l == tag_r, _ => false, }) && self.listeners.eq(&other.listeners) @@ -471,9 +478,9 @@ mod feat_ssr { use crate::virtual_dom::VText; // Elements that cannot have any child elements. - static VOID_ELEMENTS: &[&str; 14] = &[ + static VOID_ELEMENTS: &[&str; 15] = &[ "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", - "source", "track", "wbr", + "source", "track", "wbr", "textarea", ]; impl VTag { @@ -497,14 +504,14 @@ mod feat_ssr { } }; - if let VTagInner::Input(_) = self.inner { - if let Some(m) = self.value() { - write_attr(w, "value", Some(m)); + if let VTagInner::Input(InputFields { value, checked }) = &self.inner { + if let Some(value) = value.as_deref() { + write_attr(w, "value", Some(value)); } // Setting is as an attribute sets the `defaultChecked` property. Only emit this // if it's explicitly set to checked. - if self.checked() == Some(true) { + if *checked == Some(true) { write_attr(w, "checked", None); } } @@ -515,22 +522,21 @@ mod feat_ssr { let _ = w.write_str(">"); - match self.inner { + match &self.inner { VTagInner::Input(_) => {} - VTagInner::Textarea { .. } => { - if let Some(m) = self.value() { - VText::new(m.to_owned()) + VTagInner::Textarea(TextareaFields { + value, + defaultvalue, + }) => { + if let Some(def) = value.as_ref().or(defaultvalue.as_ref()) { + VText::new(def.clone()) .render_into_stream(w, parent_scope, hydratable, VTagKind::Other) .await; } let _ = w.write_str(""); } - VTagInner::Other { - ref tag, - ref children, - .. - } => { + VTagInner::Other { tag, children } => { if !VOID_ELEMENTS.contains(&tag.as_ref()) { children .render_into_stream(w, parent_scope, hydratable, tag.into()) @@ -644,6 +650,38 @@ mod ssr_tests { assert_eq!(s, r#""#); } + #[cfg_attr(not(target_os = "wasi"), test)] + #[cfg_attr(target_os = "wasi", test(flavor = "current_thread"))] + async fn test_textarea_w_defaultvalue() { + #[function_component] + fn Comp() -> Html { + html! { "#); + } + + #[cfg_attr(not(target_os = "wasi"), test)] + #[cfg_attr(target_os = "wasi", test(flavor = "current_thread"))] + async fn test_value_precedence_over_defaultvalue() { + #[function_component] + fn Comp() -> Html { + html! { "#); + } + #[cfg_attr(not(target_os = "wasi"), test)] #[cfg_attr(target_os = "wasi", test(flavor = "current_thread"))] async fn test_escaping_in_style_tag() { diff --git a/packages/yew/tests/hydration.rs b/packages/yew/tests/hydration.rs index 99d818ec529..ec455036b1f 100644 --- a/packages/yew/tests/hydration.rs +++ b/packages/yew/tests/hydration.rs @@ -364,7 +364,7 @@ async fn hydration_with_suspense_not_suspended_at_start() { Ok(html! {
- + + +``` + +Which would fail to compile, it's customary to write + +```html +