Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepared States dependency should be Reference Counted #2769

Merged
merged 9 commits into from Jul 19, 2022
7 changes: 6 additions & 1 deletion packages/yew-macro/src/use_prepared_state.rs
Expand Up @@ -61,14 +61,19 @@ impl PreparedState {
// 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 proc_macro2::Span;
use syn::parse_quote;

let async_token = match &self.closure.asyncness {
Some(m) => m,
None => return self.closure.clone(),
};

let move_token = &self.closure.capture;
// The async block always need to be move so input can be moved into it.
let move_token = self
.closure
.capture
.unwrap_or_else(|| Token![move](Span::call_site()));
let body = &self.closure.body;

let inner = parse_quote! {
Expand Down
8 changes: 0 additions & 8 deletions packages/yew/src/functional/hooks/mod.rs
Expand Up @@ -3,29 +3,21 @@ mod use_context;
mod use_effect;
mod use_force_update;
mod use_memo;
#[cfg_attr(documenting, doc(cfg(any(target_arch = "wasm32", feature = "tokio"))))]
futursolo marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(any(target_arch = "wasm32", feature = "tokio"))]
mod use_prepared_state;
mod use_reducer;
mod use_ref;
mod use_state;
#[cfg_attr(documenting, doc(cfg(any(target_arch = "wasm32", feature = "tokio"))))]
#[cfg(any(target_arch = "wasm32", feature = "tokio"))]
mod use_transitive_state;

pub use use_callback::*;
pub use use_context::*;
pub use use_effect::*;
pub use use_force_update::*;
pub use use_memo::*;
#[cfg_attr(documenting, doc(cfg(any(target_arch = "wasm32", feature = "tokio"))))]
#[cfg(any(target_arch = "wasm32", feature = "tokio"))]
pub use use_prepared_state::*;
pub use use_reducer::*;
pub use use_ref::*;
pub use use_state::*;
#[cfg_attr(documenting, doc(cfg(any(target_arch = "wasm32", feature = "tokio"))))]
#[cfg(any(target_arch = "wasm32", feature = "tokio"))]
pub use use_transitive_state::*;

use crate::functional::HookContext;
Expand Down
Expand Up @@ -19,13 +19,13 @@ pub fn use_prepared_state<T, D, F>(
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> T,
F: FnOnce(Rc<D>) -> T,
{
struct HookProvider<T, D, F>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> T,
F: FnOnce(Rc<D>) -> T,
{
deps: D,
f: F,
Expand All @@ -35,7 +35,7 @@ where
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> T,
F: FnOnce(Rc<D>) -> T,
{
type Output = SuspensionResult<Option<Rc<T>>>;

Expand All @@ -58,14 +58,14 @@ pub fn use_prepared_state_with_suspension<T, D, F, U>(
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> U,
F: FnOnce(Rc<D>) -> U,
U: 'static + Future<Output = T>,
{
struct HookProvider<T, D, F, U>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> U,
F: FnOnce(Rc<D>) -> U,
U: 'static + Future<Output = T>,
{
deps: D,
Expand All @@ -76,7 +76,7 @@ where
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> U,
F: FnOnce(Rc<D>) -> U,
U: 'static + Future<Output = T>,
{
type Output = SuspensionResult<Option<Rc<T>>>;
Expand Down
16 changes: 8 additions & 8 deletions packages/yew/src/functional/hooks/use_prepared_state/feat_ssr.rs
Expand Up @@ -20,13 +20,13 @@ pub fn use_prepared_state<T, D, F>(
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> T,
F: FnOnce(Rc<D>) -> T,
{
struct HookProvider<T, D, F>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> T,
F: FnOnce(Rc<D>) -> T,
{
deps: D,
f: F,
Expand All @@ -36,7 +36,7 @@ where
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> T,
F: FnOnce(Rc<D>) -> T,
{
type Output = SuspensionResult<Option<Rc<T>>>;

Expand All @@ -46,7 +46,7 @@ where

let state = {
let deps = deps.clone();
use_memo(move |_| f(&deps), ()).run(ctx)
use_memo(move |_| f(deps), ()).run(ctx)
};

let state = PreparedStateBase {
Expand Down Expand Up @@ -75,14 +75,14 @@ pub fn use_prepared_state_with_suspension<T, D, F, U>(
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> U,
F: FnOnce(Rc<D>) -> U,
U: 'static + Future<Output = T>,
{
struct HookProvider<T, D, F, U>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> U,
F: FnOnce(Rc<D>) -> U,
U: 'static + Future<Output = T>,
{
deps: D,
Expand All @@ -93,7 +93,7 @@ where
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: FnOnce(&D) -> U,
F: FnOnce(Rc<D>) -> U,
U: 'static + Future<Output = T>,
{
type Output = SuspensionResult<Option<Rc<T>>>;
Expand All @@ -112,7 +112,7 @@ where
let deps = deps.clone();
let result = result.clone();
use_state(move || {
let state_f = f(&deps);
let state_f = f(deps.clone());

spawn_local(async move {
let state = state_f.await;
Expand Down
5 changes: 2 additions & 3 deletions packages/yew/src/functional/hooks/use_prepared_state/mod.rs
Expand Up @@ -43,7 +43,7 @@ pub use feat_ssr::*;
/// where
/// D: Serialize + DeserializeOwned + PartialEq + 'static,
/// T: Serialize + DeserializeOwned + 'static,
/// F: FnOnce(&D) -> T,
/// F: FnOnce(Rc<D>) -> T,
/// # { todo!() }
/// ```
///
Expand All @@ -69,7 +69,7 @@ pub use feat_ssr::*;
/// where
/// D: Serialize + DeserializeOwned + PartialEq + 'static,
/// T: Serialize + DeserializeOwned + 'static,
/// F: FnOnce(&D) -> U,
/// F: FnOnce(Rc<D>) -> U,
/// U: 'static + Future<Output = T>,
/// # { todo!() }
/// ```
Expand All @@ -89,7 +89,6 @@ pub use feat_ssr::*;
/// Whilst async closure is an unstable feature, the procedural macro will rewrite this to a
/// closure that returns an async block automatically. You can use this hook with async closure
/// in stable Rust.
#[cfg_attr(documenting, doc(cfg(any(target_arch = "wasm32", feature = "tokio"))))]
pub use use_prepared_state_macro as use_prepared_state;
// With SSR.
#[doc(hidden)]
Expand Down
Expand Up @@ -18,13 +18,13 @@ pub fn use_transitive_state<T, D, F>(
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
struct HookProvider<T, D, F>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
deps: D,
f: F,
Expand All @@ -34,7 +34,7 @@ where
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
type Output = SuspensionResult<Option<Rc<T>>>;

Expand Down
20 changes: 10 additions & 10 deletions packages/yew/src/functional/hooks/use_transitive_state/feat_ssr.rs
Expand Up @@ -14,24 +14,24 @@ pub(super) struct TransitiveStateBase<T, D, F>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
pub state_fn: RefCell<Option<F>>,
pub deps: D,
pub deps: Rc<D>,
}

impl<T, D, F> PreparedState for TransitiveStateBase<T, D, F>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
fn prepare(&self) -> String {
let f = self.state_fn.borrow_mut().take().unwrap();
let state = f(&self.deps);
let state = f(self.deps.clone());

let state =
bincode::serialize(&(Some(&state), Some(&self.deps))).expect("failed to prepare state");
let state = bincode::serialize(&(Some(&state), Some(&*self.deps)))
.expect("failed to prepare state");

Base64::encode_string(&state)
}
Expand All @@ -45,13 +45,13 @@ pub fn use_transitive_state<T, D, F>(
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
struct HookProvider<T, D, F>
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
deps: D,
f: F,
Expand All @@ -61,7 +61,7 @@ where
where
D: Serialize + DeserializeOwned + PartialEq + 'static,
T: Serialize + DeserializeOwned + 'static,
F: 'static + FnOnce(&D) -> T,
F: 'static + FnOnce(Rc<D>) -> T,
{
type Output = SuspensionResult<Option<Rc<T>>>;

Expand All @@ -71,7 +71,7 @@ where
ctx.next_prepared_state(move |_re_render, _| -> TransitiveStateBase<T, D, F> {
TransitiveStateBase {
state_fn: Some(f).into(),
deps: self.deps,
deps: self.deps.into(),
}
});

Expand Down
Expand Up @@ -43,7 +43,7 @@ pub use feat_ssr::*;
/// where
/// D: Serialize + DeserializeOwned + PartialEq + 'static,
/// T: Serialize + DeserializeOwned + 'static,
/// F: 'static + FnOnce(&D) -> T,
/// F: 'static + FnOnce(Rc<D>) -> T,
/// # { todo!() }
/// ```
///
Expand All @@ -55,7 +55,6 @@ pub use feat_ssr::*;
/// You MUST denote the return type of the closure with `|deps| -> ReturnType { ... }`. This
/// type is used during client side rendering to deserialize the state prepared on the server
/// side.
#[cfg_attr(documenting, doc(cfg(any(target_arch = "wasm32", feature = "tokio"))))]
pub use use_transitive_state_macro as use_transitive_state;
// With SSR.
#[doc(hidden)]
Expand Down