Merge pull request #2262 from leptos-rs/2261
fix: guarantee execution order of effects (closes #2261)
This commit is contained in:
commit
e4b89ba243
|
@ -281,7 +281,7 @@ cfg_if! {
|
|||
/// When `El` has a corresponding [`web_sys::HtmlElement`] -> `El` will implement [`std::ops::Deref`] for it.
|
||||
/// For instance [`leptos::HtmlElement<Div>`] implements [`std::ops::Deref`] for [`web_sys::HtmlDivElement`]
|
||||
/// Because of [Deref Coercion](https://doc.rust-lang.org/std/ops/trait.Deref.html#deref-coercion) you can call applicable [`web_sys::HtmlElement`] methods on `HtmlElement<El>` as if it were that type.
|
||||
/// If both `HtmlElement<El>` and one of its derefs have a method with the same name, the dot syntax will call the method on the inherent impl (i.e. `HtmlElement<El>` or it's [`std::ops::Deref`] Target).
|
||||
/// If both `HtmlElement<El>` and one of its derefs have a method with the same name, the dot syntax will call the method on the inherent impl (i.e. `HtmlElement<El>` or it's [`std::ops::Deref`] Target).
|
||||
/// You may need to manually deref to access other methods, for example, `(*el).style()` to get the `CssStyleDeclaration` instead of calling [`leptos::HtmlElement::style`].
|
||||
|
||||
#[must_use = "You are creating an HtmlElement<_> but not using it. An unused view can \
|
||||
|
|
|
@ -308,7 +308,18 @@ impl Runtime {
|
|||
let subs = self.node_subscribers.borrow();
|
||||
for source in sources.borrow().iter() {
|
||||
if let Some(source) = subs.get(*source) {
|
||||
source.borrow_mut().swap_remove(&node_id);
|
||||
// Using `.shift_remove()` here guarantees that dependencies
|
||||
// of a signal are always triggered in the same order.
|
||||
// This is important for cases in which, for example, the first effect
|
||||
// conditionally checks that the signal value is `Some(_)`, and the
|
||||
// second one unwraps its value; if they maintain this order, then the check
|
||||
// will always run first, and will cancel the unwrap if it is None. But if the
|
||||
// order can be inverted (by using .swap_remove() here), the unwrap will
|
||||
// run first on a subsequent run.
|
||||
//
|
||||
// Maintaining execution order is the intention of using an IndexSet here anyway,
|
||||
// but using .swap_remove() would undermine that goal.
|
||||
source.borrow_mut().shift_remove(&node_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
//! ## Example
|
||||
//!
|
||||
//! ```rust
|
||||
//!
|
||||
//!
|
||||
//! use leptos::*;
|
||||
//! use leptos_router::*;
|
||||
//!
|
||||
|
|
|
@ -59,14 +59,15 @@ pub fn server_macro_impl(
|
|||
.inputs
|
||||
.iter_mut()
|
||||
.map(|f| {
|
||||
let typed_arg =
|
||||
match f {
|
||||
FnArg::Receiver(_) => return Err(syn::Error::new(
|
||||
let typed_arg = match f {
|
||||
FnArg::Receiver(_) => {
|
||||
return Err(syn::Error::new(
|
||||
f.span(),
|
||||
"cannot use receiver types in server function macro",
|
||||
)),
|
||||
FnArg::Typed(t) => t,
|
||||
};
|
||||
))
|
||||
}
|
||||
FnArg::Typed(t) => t,
|
||||
};
|
||||
|
||||
// strip `mut`, which is allowed in fn args but not in struct fields
|
||||
if let Pat::Ident(ident) = &mut *typed_arg.pat {
|
||||
|
|
Loading…
Reference in New Issue