intendednull / yewdux

Ergonomic state management for Yew applications
https://intendednull.github.io/yewdux/
Apache License 2.0
322 stars 31 forks source link

Panic with BorrowMutError in yewdux::mrc::Mrc #36

Closed ma1ko closed 2 years ago

ma1ko commented 2 years ago

I managed to narrow this down to a minimal example:

use yew::prelude::*;
use yewdux::prelude::*;
fn main() {
    wasm_logger::init(wasm_logger::Config::default());
    yew::start_app::<Model>();
}
#[function_component(Model)]
fn test() -> html {
    let (points, dispatch) = use_store::<Points>();
    let cb = dispatch.reduce_callback(|points| Points {
        points: points.points + 1,
    });
    let html = (0..points.points)
        .map(|_| {
            html! { <div>
                <Listener/>
            </div>}
        })
        .collect::<Vec<_>>();
    html! {
        <div>
            <button onclick={cb}>{"Click me"}</button>
            {html}
        </div>
    }
}
#[function_component(Listener)]
fn listener() -> html {
    let (points, _) = use_store::<Points>();
    html! { {points.points}}
}
#[derive(Store, PartialEq, Eq, Default, Clone)]
struct Points {
    points: usize,
}

This panics with a BorrowMutError when clicking the button. Stacktrace:


  | imports.wbg.__wbg_error_09919627ac0992f5 | @ | yewdux_test-b5ad39e837318030.js:298
-- | -- | -- | --
  | $console_error_panic_hook::error::h1bf004dd5dd797d3 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x89e18
  | $console_error_panic_hook::hook_impl::h2f812b50a8f0b4ee | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x46af3
  | $console_error_panic_hook::hook::h87dfebef834b97cb | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xdd092
  | $core::ops::function::Fn::call::hb5125e048d9483c1 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xcfcbf
  | $std::panicking::rust_panic_with_hook::h8888bbc201384d7b | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x70d70
  | $std::panicking::begin_panic_handler::{{closure}}::hea311ea2bd92a293 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x97390
  | $std::sys_common::backtrace::__rust_end_short_backtrace::h7df6c1a4b8949645 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xe4948
  | $rust_begin_unwind | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xd981d
  | $core::panicking::panic_fmt::h18b15be283411c65 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xda52a
  | $core::result::unwrap_failed::he84b58f6b44a7df4 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xa16bc
  | $core::result::Result<T,E>::expect::h3be6d4948a308f88 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x8a44a
  | $core::cell::RefCell<T>::borrow_mut::h6ea2ee2c4c616321 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x957c7
  | $yewdux::mrc::Mrc<T>::borrow_mut::h142978717a104ae5 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x8fd45
  | $yewdux::subscriber::<impl yewdux::mrc::Mrc<yewdux::subscriber::Subscribers<S>>>::subscribe::hd5e737e518c8a197 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x4db1c
  | $yewdux::dispatch::subscribe_silent::h5d904aff3a057541 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x52084
  | $yewdux::dispatch::Dispatch<S>::subscribe_silent::h5fc3187de10b37d9 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x60b52
  | $yewdux::functional::use_store::{{closure}}::h6b1cc4bf1f406180 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xacb20
  | $yew::functional::hooks::use_state::use_state::{{closure}}::h9e7fd398f9da59d5 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x92529
  | $yew::functional::hooks::use_reducer::use_reducer_base::{{closure}}::hb062d1a9b3d25667 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x78081
  | $yew::functional::hooks::use_hook::{{closure}}::h48bf44ea4b54c8a0 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x280fc
  | $scoped_tls_hkt::ScopedKeyMut<T>::with::{{closure}}::hffe18d03ef49d574 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x82a5a
  | $scoped_tls_hkt::ScopedKeyMut<T>::replace::he6ba7b33de1346a1 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x6209c
  | $scoped_tls_hkt::ScopedKeyMut<T>::with::h348c7ce78b7032ba | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x8e683
  | $yew::functional::hooks::use_hook::h298c206310724745 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x2f590
  | $yew::functional::hooks::use_reducer::use_reducer_base::hd9240f079f2ddf4e | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xad395
  | $yew::functional::hooks::use_reducer::use_reducer::hb388a6c61784b344 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xad32e
  | $yew::functional::hooks::use_state::use_state::h7ca065e0df553d47 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x64ebe
  | $yewdux::functional::use_store::hfbbf76e937f2ac8e | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x4ba9a
  | $<yewdux_test::listener as yew::functional::FunctionProvider>::run::h586cf77fdf950556 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x68ba4
  | $<yew::functional::FunctionComponent<T> as yew::html::component::Component>::view::{{closure}}::hf25fd87fb7ff370a | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xce049
  | $scoped_tls_hkt::ScopedKeyMut<T>::set::{{closure}}::h3edcc5e30a510a39 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xd51d0
  | $scoped_tls_hkt::ScopedKeyMut<T>::replace::h7207ef6fcd16b62f | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x7d3c4
  | $scoped_tls_hkt::ScopedKeyMut<T>::set::hb0d3513ad957a88c | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xb257d
  | $yew::functional::FunctionComponent<T>::with_hook_state::he9f5ec900265b1c7 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x7d6e5
  | $<yew::functional::FunctionComponent<T> as yew::html::component::Component>::view::hc9f8f79bb6a459d8 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xb6ef1
  | $<yew::html::component::lifecycle::RenderRunner<COMP> as yew::scheduler::Runnable>::run::h62d62b05cad1f717 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x16939
  | $yew::scheduler::start::{{closure}}::hff3797e886ac8179 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x285a5
  | $std::thread::local::LocalKey<T>::try_with::h9e78c40b52aa8483 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x70038
  | $std::thread::local::LocalKey<T>::with::h52c5a0213964e7ea | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xb18f7
  | $yew::scheduler::start::h1da8427f37f92d11 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xe4a24
  | $yew::html::component::scope::Scope<COMP>::push_update::h5347c5c0d2d61c28 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x7033e
  | $yew::html::component::scope::Scope<COMP>::send_message::hb359b9baaa4b7636 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x95fcd
  | $<yew::functional::FunctionComponent<T> as yew::html::component::Component>::create::{{closure}}::ha626eacd102907e7 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xa55d6
  | $yew::functional::HookUpdater::callback::h963690d127ca2972 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x3ca90
  | $yew::functional::hooks::use_reducer::use_reducer_base::{{closure}}::{{closure}}::h0d479cf880ffa1dc | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xa652d
  | $yew::functional::hooks::use_reducer::UseReducerHandle<T>::dispatch::hd800521261ec9dac | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x84b35
  | $yew::functional::hooks::use_state::UseStateHandle<T>::set::h4872376548d49de2 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xd524a
  | $yewdux::functional::use_store::{{closure}}::{{closure}}::h1d1991e0a6c1b94d | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xd5119
  | $<F as yewdux::subscriber::Callable<S>>::call::hcbeeaa73d29bc53c | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xc7e0d
  | $yewdux::subscriber::<impl yewdux::mrc::Mrc<yewdux::subscriber::Subscribers<S>>>::notify::h8b1c40e7ec48f1ff | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x4696f
  | $yewdux::dispatch::notify_subscribers::h75bed5ed2a6abf5d | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x6cc6d
  | $yewdux::dispatch::reduce::h26152b03e40f2580 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x57f10
  | $yewdux::dispatch::Dispatch<S>::reduce_callback::{{closure}}::hf079313223315938 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xc199c
  | $yew::callback::Callback<IN>::emit::h70402f57b2567734 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x44ec9
  | $<yew::html::listener::events::onclick::Wrapper as yew::virtual_dom::listeners::Listener>::handle::h5ec2809813994f2b | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xcede2
  | $yew::virtual_dom::listeners::Registry::run_handlers::{{closure}}::h7181ab016b56a6fc | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x1bf82
  | $yew::virtual_dom::listeners::Registry::run_handlers::hfa834aba393fdf4d | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x395ba
  | $yew::virtual_dom::listeners::Registry::handle::h0acf85ab015152be | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x62718
  | $yew::virtual_dom::listeners::GlobalHandlers::ensure_handled::{{closure}}::{{closure}}::h0378e231be9d3fee | @ | yewdux_test-b5ad39e8…030_bg.wasm:0xbb83a
  | $<dyn core::ops::function::Fn<(A,)>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::h5974d5da5247ef08 | @ | yewdux_test-b5ad39e8…030_bg.wasm:0x7e9f0
  | __wbg_adapter_18 | @ | yewdux_test-b5ad39e837318030.js:214
  | real

As far as I understand it, if you increase the amount of state listeners while using the state, it panics. Is there any way to fix this?

intendednull commented 2 years ago

This looks correct, and I was able to run it without any issue. Sometimes this error pops up if your app has already crashed before you press a button. Is there another error message in the console besides this one?

intendednull commented 2 years ago

The only part I didn't include in my test was the wasm logger, maybe that's panicking for some reason?

ma1ko commented 2 years ago

Thanks for looking into this!

If removed the wasm-logger and it didn't change anything, so it's not the cause. There's actually two errors coming up in the developer console: the first is the one I posted already, the second has the exact same stacktrace but error message Uncaught RuntimeError: unreachable, not sure what the difference is of those two. Both errors appear only when pressing the button.

The pasted code should actually show a counter when clicking the button, does this work for you?

I tried understanding the issue from the stacktrace:

Does that make sense?

intendednull commented 2 years ago

Looks like this is a bug with 0.8, can you confirm it is not present on the master branch?

intendednull commented 2 years ago

Seems to be a problem with use_store, because of how Yew 0.19 handles hooks. Will start working on a patch

intendednull commented 2 years ago

Okay 0.8.2 has been publish with the fix!

ma1ko commented 2 years ago

Thanks a lot! I just tried the fix and everything seems to be working!