diff --git a/.github/workflows/main-checks.yml b/.github/workflows/main-checks.yml
index 434d9047ee8..e4b3445e237 100644
--- a/.github/workflows/main-checks.yml
+++ b/.github/workflows/main-checks.yml
@@ -25,7 +25,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
- args: --all-targets --all-features -- -D warnings
+ args: --all-targets --features "csr,ssr,hydration" -- -D warnings
- name: Lint feature soundness
run: |
@@ -33,7 +33,7 @@ jobs:
cargo clippy --features=ssr -- --deny=warnings
cargo clippy --features=csr -- --deny=warnings
cargo clippy --features=hydration -- --deny=warnings
- cargo clippy --all-features --all-targets -- --deny=warnings
+ cargo clippy --features "csr,ssr,hydration,tokio" --all-targets -- --deny=warnings
working-directory: packages/yew
@@ -55,7 +55,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
- args: --all-targets --all-features --release -- -D warnings
+ args: --all-targets --features "csr,ssr,hydration" --release -- -D warnings
- name: Lint feature soundness
run: |
@@ -63,7 +63,7 @@ jobs:
cargo clippy --release --features=ssr -- --deny=warnings
cargo clippy --release --features=csr -- --deny=warnings
cargo clippy --release --features=hydration -- --deny=warnings
- cargo clippy --release --all-features --all-targets -- --deny=warnings
+ cargo clippy --release --features "csr,ssr,hydration,tokio" --all-targets -- --deny=warnings
working-directory: packages/yew
spell_check:
diff --git a/examples/simple_ssr/src/lib.rs b/examples/simple_ssr/src/lib.rs
index dd291b644a8..1204af904ec 100644
--- a/examples/simple_ssr/src/lib.rs
+++ b/examples/simple_ssr/src/lib.rs
@@ -18,7 +18,7 @@ async fn fetch_uuid() -> Uuid {
#[function_component]
fn Content() -> HtmlResult {
- let uuid = use_prepared_state!(async |_| -> Uuid { fetch_uuid().await }, ())?.unwrap();
+ let uuid = use_prepared_state!(async move |_| -> Uuid { fetch_uuid().await }, ())?.unwrap();
Ok(html! {
{"Random UUID: "}{uuid}
diff --git a/packages/yew-macro/Cargo.toml b/packages/yew-macro/Cargo.toml
index ae17548fbb0..5cd5679ad2a 100644
--- a/packages/yew-macro/Cargo.toml
+++ b/packages/yew-macro/Cargo.toml
@@ -35,3 +35,4 @@ yew = { path = "../yew" }
[features]
lints = []
+nightly = []
diff --git a/packages/yew-macro/src/html_tree/html_element.rs b/packages/yew-macro/src/html_tree/html_element.rs
index a6e9e9e179a..8b981a10d1c 100644
--- a/packages/yew-macro/src/html_tree/html_element.rs
+++ b/packages/yew-macro/src/html_tree/html_element.rs
@@ -387,6 +387,18 @@ impl ToTokens for HtmlElement {
}}
});
+ #[cfg(feature = "nightly")]
+ let invalid_void_tag_msg_start = {
+ let span = vtag.span().unwrap();
+ let source_file = span.source_file().path();
+ let source_file = source_file.display();
+ let start = span.start();
+ format!("[{}:{}:{}] ", source_file, start.line, start.column)
+ };
+
+ #[cfg(not(feature = "nightly"))]
+ let invalid_void_tag_msg_start = "";
+
// this way we get a nice error message (with the correct span) when the expression
// doesn't return a valid value
quote_spanned! {expr.span()=> {
@@ -442,10 +454,6 @@ impl ToTokens for HtmlElement {
// These are the runtime-checks exclusive to dynamic tags.
// For literal tags this is already done at compile-time.
//
- // When Span::source_file Span::start get stabilised or yew-macro introduces a
- // nightly feature flag we should expand the panic message to contain the exact
- // location of the dynamic tag.
- //
// check void element
if !#vtag.children().is_empty() {
::std::debug_assert!(
@@ -453,7 +461,7 @@ impl ToTokens for HtmlElement {
"area" | "base" | "br" | "col" | "embed" | "hr" | "img" | "input"
| "link" | "meta" | "param" | "source" | "track" | "wbr"
),
- "a dynamic tag tried to create a `<{0}>` tag with children. `<{0}>` is a void element which can't have any children.",
+ concat!(#invalid_void_tag_msg_start, "a dynamic tag tried to create a `<{0}>` tag with children. `<{0}>` is a void element which can't have any children."),
#vtag.tag(),
);
}
diff --git a/packages/yew-macro/src/lib.rs b/packages/yew-macro/src/lib.rs
index e5a50ab2250..5822f0325ff 100644
--- a/packages/yew-macro/src/lib.rs
+++ b/packages/yew-macro/src/lib.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
+
//! This crate provides Yew's procedural macro `html!` which allows using JSX-like syntax
//! for generating html and the `Properties` derive macro for deriving the `Properties` trait
//! for components.
diff --git a/packages/yew-macro/src/use_prepared_state.rs b/packages/yew-macro/src/use_prepared_state.rs
index c94240aab1c..e860277a9f8 100644
--- a/packages/yew-macro/src/use_prepared_state.rs
+++ b/packages/yew-macro/src/use_prepared_state.rs
@@ -1,7 +1,7 @@
use proc_macro2::TokenStream;
use quote::quote;
use syn::parse::{Parse, ParseStream};
-use syn::{parse_quote, Expr, ExprClosure, ReturnType, Token, Type};
+use syn::{Expr, ExprClosure, ReturnType, Token, Type};
#[derive(Debug)]
pub struct PreparedState {
@@ -58,8 +58,11 @@ impl Parse for PreparedState {
}
impl PreparedState {
- // Async closure is not stable, so we rewrite it to clsoure + async block
+ // Async closure is not stable, so we rewrite it to closure + async block
+ #[cfg(not(feature = "nightly"))]
pub fn rewrite_to_closure_with_async_block(&self) -> ExprClosure {
+ use syn::parse_quote;
+
let async_token = match &self.closure.asyncness {
Some(m) => m,
None => return self.closure.clone(),
@@ -87,6 +90,11 @@ impl PreparedState {
closure
}
+ #[cfg(feature = "nightly")]
+ pub fn rewrite_to_closure_with_async_block(&self) -> ExprClosure {
+ self.closure.clone()
+ }
+
pub fn to_token_stream_with_closure(&self) -> TokenStream {
let deps = &self.deps;
let rt = &self.return_type;
diff --git a/packages/yew/Cargo.toml b/packages/yew/Cargo.toml
index 74d8234090f..a6e6f650d53 100644
--- a/packages/yew/Cargo.toml
+++ b/packages/yew/Cargo.toml
@@ -96,6 +96,7 @@ features = [
ssr = ["futures", "html-escape", "base64ct", "bincode"] # dep:html-escape
csr = []
hydration = ["csr", "bincode"]
+nightly = ["yew-macro/nightly"]
default = []
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs
index 4f05f6d0abc..417273a015b 100644
--- a/packages/yew/src/functional/hooks/use_force_update.rs
+++ b/packages/yew/src/functional/hooks/use_force_update.rs
@@ -6,29 +6,47 @@ use crate::functional::ReRender;
/// A handle which can be used to force a re-render of the associated
/// function component.
#[derive(Clone)]
-pub struct UseForceUpdate {
+pub struct UseForceUpdateHandle {
trigger: ReRender,
}
-impl fmt::Debug for UseForceUpdate {
+impl fmt::Debug for UseForceUpdateHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("UseForceUpdate").finish()
}
}
-impl UseForceUpdate {
+impl UseForceUpdateHandle {
/// Trigger an unconditional re-render of the associated function component
pub fn force_update(&self) {
(self.trigger)()
}
}
-// #![feature(fn_traits)] // required nightly feature to make UseForceUpdate callable directly
-// impl Fn<()> for UseForceUpdate {
-// extern "rust-call" fn call(&self, _args: ()) {
-// self.force_update()
-// }
-// }
+#[cfg(feature = "nightly")]
+mod feat_nightly {
+ use super::*;
+
+ impl FnOnce<()> for UseForceUpdateHandle {
+ type Output = ();
+
+ extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
+ self.force_update()
+ }
+ }
+
+ impl FnMut<()> for UseForceUpdateHandle {
+ extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
+ self.force_update()
+ }
+ }
+
+ impl Fn<()> for UseForceUpdateHandle {
+ extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
+ self.force_update()
+ }
+ }
+}
/// This hook is used to manually force a function component to re-render.
///
@@ -78,14 +96,14 @@ impl UseForceUpdate {
///
/// [`use_state`]: super::use_state()
/// [`use_reducer`]: super::use_reducer()
-pub fn use_force_update() -> impl Hook