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

Leptos v0.6 (NOT the rewrite) #2158

Merged
merged 100 commits into from
Jan 20, 2024
Merged

Leptos v0.6 (NOT the rewrite) #2158

merged 100 commits into from
Jan 20, 2024

Conversation

gbj
Copy link
Collaborator

@gbj gbj commented Jan 4, 2024

In the spirit of releasing incremental wins rather than waiting for one huge release, we've decided to release a 0.6.

This is not the larger rendering rewrite I've mentioned in the roadmap and elsewhere.

It contains two features:

TODO

@rakshith-ravi
Copy link
Contributor

rakshith-ravi commented Jan 12, 2024

Tested the server fn with serde-lite and got this error. Not sure why the view macro is expecting serde instead of serde-lite.

/var/folders/z9/1_txvfkx67g0v8ltmzb0ll_c0000gn/T/fsio_uG9oOEzOBS.sh: line 3: pidof: command not found
   Compiling todo_app_sqlite_axum v0.1.0 (/leptos/examples/todo_app_sqlite_axum)
error[E0277]: the trait bound `Todo: server_fn::serde::Serialize` is not satisfied
   --> src/todo.rs:115:17
    |
115 |     let todos = create_resource(
    |                 ^^^^^^^^^^^^^^^ the trait `server_fn::serde::Serialize` is not implemented for `Todo`
    |
    = help: the following other types implement trait `server_fn::serde::Serialize`:
              bool
              char
              isize
              i8
              i16
              i32
              i64
              i128
            and 164 others
    = note: required for `Vec<Todo>` to implement `server_fn::serde::Serialize`
    = note: 1 redundant requirement hidden
    = note: required for `Result<Vec<Todo>, leptos::ServerFnError>` to implement `server_fn::serde::Serialize`
    = note: required for `Result<Vec<Todo>, leptos::ServerFnError>` to implement `Serializable`
note: required by a bound in `leptos::create_resource`
   --> /leptos/leptos_reactive/src/resource.rs:103:8
    |
97  | pub fn create_resource<S, T, Fu>(
    |        --------------- required by a bound in this function
...
103 |     T: Serializable + 'static,
    |        ^^^^^^^^^^^^ required by this bound in `create_resource`

error[E0277]: the trait bound `Todo: server_fn::serde::Deserialize<'_>` is not satisfied
   --> src/todo.rs:115:17
    |
115 |     let todos = create_resource(
    |                 ^^^^^^^^^^^^^^^ the trait `server_fn::serde::Deserialize<'_>` is not implemented for `Todo`
    |
    = help: the following other types implement trait `server_fn::serde::Deserialize<'de>`:
              <bool as server_fn::serde::Deserialize<'de>>
              <char as server_fn::serde::Deserialize<'de>>
              <isize as server_fn::serde::Deserialize<'de>>
              <i8 as server_fn::serde::Deserialize<'de>>
              <i16 as server_fn::serde::Deserialize<'de>>
              <i32 as server_fn::serde::Deserialize<'de>>
              <i64 as server_fn::serde::Deserialize<'de>>
              <i128 as server_fn::serde::Deserialize<'de>>
            and 164 others
    = note: required for `Vec<Todo>` to implement `server_fn::serde::Deserialize<'_>`
    = note: 1 redundant requirement hidden
    = note: required for `Result<Vec<Todo>, leptos::ServerFnError>` to implement `for<'de> server_fn::serde::Deserialize<'de>`
    = note: required for `Result<Vec<Todo>, leptos::ServerFnError>` to implement `DeserializeOwned`
    = note: required for `Result<Vec<Todo>, leptos::ServerFnError>` to implement `Serializable`
note: required by a bound in `leptos::create_resource`
   --> /leptos/leptos_reactive/src/resource.rs:103:8
    |
97  | pub fn create_resource<S, T, Fu>(
    |        --------------- required by a bound in this function
...
103 |     T: Serializable + 'static,
    |        ^^^^^^^^^^^^ required by this bound in `create_resource`

error[E0277]: the trait bound `for<'de> AddTodo: server_fn::serde::Deserialize<'de>` is not satisfied
   --> src/todo.rs:122:30
    |
122 |             <MultiActionForm action=add_todo>
    |                              ^^^^^^ the trait `for<'de> server_fn::serde::Deserialize<'de>` is not implemented for `AddTodo`
    |
    = help: the following other types implement trait `server_fn::serde::Deserialize<'de>`:
              <bool as server_fn::serde::Deserialize<'de>>
              <char as server_fn::serde::Deserialize<'de>>
              <isize as server_fn::serde::Deserialize<'de>>
              <i8 as server_fn::serde::Deserialize<'de>>
              <i16 as server_fn::serde::Deserialize<'de>>
              <i32 as server_fn::serde::Deserialize<'de>>
              <i64 as server_fn::serde::Deserialize<'de>>
              <i128 as server_fn::serde::Deserialize<'de>>
            and 164 others
    = note: required for `AddTodo` to implement `DeserializeOwned`
note: required by a bound in `MultiActionFormPropsBuilder::<ServFn, ((), __class, __error, __node_ref, __attributes, __children)>::action`
   --> /leptos/router/src/components/form.rs:537:17
    |
519 |     action: MultiAction<ServFn, Result<ServFn::Output, ServerFnError>>,
    |     ------ required by a bound in this associated function
...
537 |         Clone + DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
    |                 ^^^^^^^^^^^^^^^^ required by this bound in `MultiActionFormPropsBuilder::<ServFn, ((), __class, __error, __node_ref, __attributes, __children)>::action`

error[E0277]: the trait bound `for<'de> AddTodo: server_fn::serde::Deserialize<'de>` is not satisfied
   --> src/todo.rs:122:14
    |
122 |             <MultiActionForm action=add_todo>
    |              ^^^^^^^^^^^^^^^ the trait `for<'de> server_fn::serde::Deserialize<'de>` is not implemented for `AddTodo`
    |
    = help: the following other types implement trait `server_fn::serde::Deserialize<'de>`:
              <bool as server_fn::serde::Deserialize<'de>>
              <char as server_fn::serde::Deserialize<'de>>
              <isize as server_fn::serde::Deserialize<'de>>
              <i8 as server_fn::serde::Deserialize<'de>>
              <i16 as server_fn::serde::Deserialize<'de>>
              <i32 as server_fn::serde::Deserialize<'de>>
              <i64 as server_fn::serde::Deserialize<'de>>
              <i128 as server_fn::serde::Deserialize<'de>>
            and 164 others
    = note: required for `AddTodo` to implement `DeserializeOwned`
note: required by a bound in `leptos_router::MultiActionForm`
   --> /leptos/router/src/components/form.rs:537:17
    |
515 | pub fn MultiActionForm<ServFn>(
    |        --------------- required by a bound in this function
...
537 |         Clone + DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
    |                 ^^^^^^^^^^^^^^^^ required by this bound in `MultiActionForm`

error[E0271]: type mismatch resolving `<AddTodo as ServerFn>::InputEncoding == PostUrl`
   --> src/todo.rs:120:5
    |
120 | /     view! {
121 | |         <div>
122 | |             <MultiActionForm action=add_todo>
123 | |                 <label>
...   |
190 | |         </div>
191 | |     }
    | |_____^ expected `PostUrl`, found `SerdeLite`
    |
    = note: required for `MultiActionFormProps<AddTodo>` to implement `leptos::Props`
    = note: required for `fn(MultiActionFormProps<AddTodo>) -> impl leptos::IntoView {leptos_router::MultiActionForm::<AddTodo>}` to implement `leptos::Component<MultiActionFormProps<AddTodo>>`
note: required by a bound in `component_props_builder`
   --> /leptos/leptos/src/lib.rs:319:15
    |
318 | pub fn component_props_builder<P: PropsOrNoPropsBuilder>(
    |        ----------------------- required by a bound in this function
319 |     _f: &impl Component<P>,
    |               ^^^^^^^^^^^^ required by this bound in `component_props_builder`
    = note: this error originates in the macro `view` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: the method `children` exists for struct `MultiActionFormPropsBuilder<AddTodo, ((MultiAction<AddTodo, Result<(), ServerFnError>>,), (), (), (), (), ())>`, but its trait bounds were not satisfied
   --> src/todo.rs:120:5
    |
58  |   #[server(output = SerdeLite, input = SerdeLite)]
    |   ------------------------------------------------
    |   |
    |   doesn't satisfy `<AddTodo as ServerFn>::InputEncoding = PostUrl`
    |   doesn't satisfy `AddTodo: DeserializeOwned`
    |   doesn't satisfy `AddTodo: server_fn::serde::Deserialize<'de>`
...
120 |       view! {
    |  _____^
121 | |         <div>
122 | |             <MultiActionForm action=add_todo>
123 | |                 <label>
...   |
190 | |         </div>
191 | |     }
    | |_____^ method cannot be called due to unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
            `<AddTodo as ServerFn>::InputEncoding = PostUrl`
            `AddTodo: DeserializeOwned`
            `AddTodo: server_fn::serde::Deserialize<'de>`
            which is required by `AddTodo: DeserializeOwned`
note: the trait `DeserializeOwned` must be implemented
   --> /.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.195/src/de/mod.rs:607:1
    |
607 | pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `view` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `for<'de> DeleteTodo: server_fn::serde::Deserialize<'de>` is not satisfied
   --> src/todo.rs:150:77
    |
150 | ...                   <ActionForm action=delete_todo>
    |                                   ^^^^^^ the trait `for<'de> server_fn::serde::Deserialize<'de>` is not implemented for `DeleteTodo`
    |
    = help: the following other types implement trait `server_fn::serde::Deserialize<'de>`:
              <bool as server_fn::serde::Deserialize<'de>>
              <char as server_fn::serde::Deserialize<'de>>
              <isize as server_fn::serde::Deserialize<'de>>
              <i8 as server_fn::serde::Deserialize<'de>>
              <i16 as server_fn::serde::Deserialize<'de>>
              <i32 as server_fn::serde::Deserialize<'de>>
              <i64 as server_fn::serde::Deserialize<'de>>
              <i128 as server_fn::serde::Deserialize<'de>>
            and 164 others
    = note: required for `DeleteTodo` to implement `DeserializeOwned`
note: required by a bound in `ActionFormPropsBuilder::<ServFn, ((), __class, __node_ref, __attributes, __children)>::action`
   --> /leptos/router/src/components/form.rs:443:13
    |
426 |     action: Action<
    |     ------ required by a bound in this associated function
...
443 |     ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
    |             ^^^^^^^^^^^^^^^^ required by this bound in `ActionFormPropsBuilder::<ServFn, ((), __class, __node_ref, __attributes, __children)>::action`

error[E0277]: the trait bound `for<'de> DeleteTodo: server_fn::serde::Deserialize<'de>` is not satisfied
   --> src/todo.rs:150:66
    |
150 | ...                   <ActionForm action=delete_todo>
    |                        ^^^^^^^^^^ the trait `for<'de> server_fn::serde::Deserialize<'de>` is not implemented for `DeleteTodo`
    |
    = help: the following other types implement trait `server_fn::serde::Deserialize<'de>`:
              <bool as server_fn::serde::Deserialize<'de>>
              <char as server_fn::serde::Deserialize<'de>>
              <isize as server_fn::serde::Deserialize<'de>>
              <i8 as server_fn::serde::Deserialize<'de>>
              <i16 as server_fn::serde::Deserialize<'de>>
              <i32 as server_fn::serde::Deserialize<'de>>
              <i64 as server_fn::serde::Deserialize<'de>>
              <i128 as server_fn::serde::Deserialize<'de>>
            and 164 others
    = note: required for `DeleteTodo` to implement `DeserializeOwned`
note: required by a bound in `leptos_router::ActionForm`
   --> /leptos/router/src/components/form.rs:443:13
    |
422 | pub fn ActionForm<ServFn>(
    |        ---------- required by a bound in this function
...
443 |     ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
    |             ^^^^^^^^^^^^^^^^ required by this bound in `ActionForm`

error[E0271]: type mismatch resolving `<DeleteTodo as ServerFn>::InputEncoding == PostUrl`
   --> src/todo.rs:146:57
    |
146 | / ...                   view! {
147 | | ...
148 | | ...                       <li>
149 | | ...                           {todo.title}
...   |
154 | | ...                       </li>
155 | | ...                   }
    | |_______________________^ expected `PostUrl`, found `SerdeLite`
    |
    = note: required for `ActionFormProps<DeleteTodo>` to implement `leptos::Props`
    = note: required for `fn(ActionFormProps<DeleteTodo>) -> impl leptos::IntoView {leptos_router::ActionForm::<DeleteTodo>}` to implement `leptos::Component<ActionFormProps<DeleteTodo>>`
note: required by a bound in `component_props_builder`
   --> /leptos/leptos/src/lib.rs:319:15
    |
318 | pub fn component_props_builder<P: PropsOrNoPropsBuilder>(
    |        ----------------------- required by a bound in this function
319 |     _f: &impl Component<P>,
    |               ^^^^^^^^^^^^ required by this bound in `component_props_builder`
    = note: this error originates in the macro `view` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: the method `children` exists for struct `ActionFormPropsBuilder<DeleteTodo, ((Action<DeleteTodo, Result<(), ServerFnError>>,), (), (), (), ())>`, but its trait bounds were not satisfied
   --> src/todo.rs:146:57
    |
76  |   #[server(output = SerdeLite, input = SerdeLite)]
    |   ------------------------------------------------
    |   |
    |   doesn't satisfy `<DeleteTodo as ServerFn>::InputEncoding = PostUrl`
    |   doesn't satisfy `DeleteTodo: DeserializeOwned`
    |   doesn't satisfy `DeleteTodo: server_fn::serde::Deserialize<'de>`
...
146 |                                                           view! {
    |  _________________________________________________________^
147 | |
148 | |                                                             <li>
149 | |                                                                 {todo.title}
...   |
154 | |                                                             </li>
155 | |                                                         }
    | |_________________________________________________________^ method cannot be called due to unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
            `<DeleteTodo as ServerFn>::InputEncoding = PostUrl`
            `DeleteTodo: DeserializeOwned`
            `DeleteTodo: server_fn::serde::Deserialize<'de>`
            which is required by `DeleteTodo: DeserializeOwned`
note: the trait `DeserializeOwned` must be implemented
   --> /.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.195/src/de/mod.rs:607:1
    |
607 | pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `view` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `for<'de> AddTodo: server_fn::serde::Deserialize<'de>` is not satisfied
   --> src/todo.rs:120:5
    |
120 | /     view! {
121 | |         <div>
122 | |             <MultiActionForm action=add_todo>
123 | |                 <label>
...   |
190 | |         </div>
191 | |     }
    | |_____^ the trait `for<'de> server_fn::serde::Deserialize<'de>` is not implemented for `AddTodo`
    |
    = help: the following other types implement trait `server_fn::serde::Deserialize<'de>`:
              <bool as server_fn::serde::Deserialize<'de>>
              <char as server_fn::serde::Deserialize<'de>>
              <isize as server_fn::serde::Deserialize<'de>>
              <i8 as server_fn::serde::Deserialize<'de>>
              <i16 as server_fn::serde::Deserialize<'de>>
              <i32 as server_fn::serde::Deserialize<'de>>
              <i64 as server_fn::serde::Deserialize<'de>>
              <i128 as server_fn::serde::Deserialize<'de>>
            and 164 others
    = note: required for `AddTodo` to implement `DeserializeOwned`
    = note: required for `MultiActionFormProps<AddTodo>` to implement `leptos::Props`
    = note: this error originates in the macro `view` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `for<'de> DeleteTodo: server_fn::serde::Deserialize<'de>` is not satisfied
   --> src/todo.rs:146:57
    |
146 | / ...                   view! {
147 | | ...
148 | | ...                       <li>
149 | | ...                           {todo.title}
...   |
154 | | ...                       </li>
155 | | ...                   }
    | |_______________________^ the trait `for<'de> server_fn::serde::Deserialize<'de>` is not implemented for `DeleteTodo`
    |
    = help: the following other types implement trait `server_fn::serde::Deserialize<'de>`:
              <bool as server_fn::serde::Deserialize<'de>>
              <char as server_fn::serde::Deserialize<'de>>
              <isize as server_fn::serde::Deserialize<'de>>
              <i8 as server_fn::serde::Deserialize<'de>>
              <i16 as server_fn::serde::Deserialize<'de>>
              <i32 as server_fn::serde::Deserialize<'de>>
              <i64 as server_fn::serde::Deserialize<'de>>
              <i128 as server_fn::serde::Deserialize<'de>>
            and 164 others
    = note: required for `DeleteTodo` to implement `DeserializeOwned`
    = note: required for `ActionFormProps<DeleteTodo>` to implement `leptos::Props`
    = note: this error originates in the macro `view` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0271, E0277, E0599.
For more information about an error, try `rustc --explain E0271`.
error: could not compile `todo_app_sqlite_axum` (lib) due to 12 previous errors

Edit: this was with the todo_app_sqlite_axum example

@gbj
Copy link
Collaborator Author

gbj commented Jan 13, 2024

@rakshith-ravi I'm seeing two different categories of error

  1. I think your PR to add serde-lite enables it with the serde-lite feature on leptos. These features were/are poorly designed by me — serde-lite actually switches all resources to use serde-lite rather than serde by default. (Planning to change this in an upcoming version). So it's probably best to enable serde-lite server fns by enabling the serde-lite feature on server_fn directly as a depedency. Or I guess we could add additional features to leptos like server-fn-serde-lite but that seems like a lot of duplication to keep them in sync.
  2. ActionForm is set up only to accept server fns that use PostUrl as the input encoding. This is so that, if there's no JS/WASM, it can directly post the form data and succeed. It looks like you tried to use SerdeLite as the input encoding for a server function that's then used in an ActionForm and the compiler (correctly) rejects it.

I think SerdeLite should work as the output encoding in that case, or for other server functions not used with ActionForm.

@gbj gbj marked this pull request as ready for review January 17, 2024 12:29
@sebadob
Copy link
Contributor

sebadob commented Jan 17, 2024

I just wanted to test the new 0.6 beta release and I am not able to compile server_fn with this release.
I probably just messed something up, but I get a few errors with the ServerFnError and the try_into_ fn's not being Send.
The compile errors are coming up when cargo-leptos compiles the wasm binary.

  • All my leptos dependencies are using 0.6.0-beta.
  • Backend is axum
  • server_fn with the following features:
    server_fn = { workspace = true, features = ["axum", "reqwest", "rustls", "ssr"] }

I checked the example diff's and I guess I am just missing something, maybe you can give me a hint.
I guess all of these errors come up for the same reason, here is a small example:

Error Output

error: future cannot be sent between threads safely
  --> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:8:5
   |
8  |     async fn try_into_string(self) -> Result> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `try_into_string` is not `Send`
   |
   = help: within `impl futures::Future>>`, the trait `std::marker::Send` is not implemented for `*mut u8`
note: captured value is not `Send`
  --> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:8:30
   |
8  |     async fn try_into_string(self) -> Result> {
   |                              ^^^^ has type `reqwest::Response` which is not `Send`
note: required by a bound in `ClientRes::{opaque#0}`
  --> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/mod.rs:56:73
   |
56 |     ) -> impl Future>> + Send;
   |                                                                         ^^^^ required by this bound in `ClientRes::{opaque#0}`

error[E0277]: Rc<RefCell<wasm_bindgen_futures::Inner>> cannot be sent between threads safely
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:8:5
|
8 | async fn try_into_string(self) -> Result<String, ServerFnError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| Rc<RefCell<wasm_bindgen_futures::Inner>> cannot be sent between threads safely
| within this impl futures::Future<Output = std::result::Result<std::string::String, ServerFnError<CustErr>>>
|
= help: within impl futures::Future<Output = std::result::Result<std::string::String, ServerFnError<CustErr>>>, the trait std::marker::Send is not implemented for Rc<RefCell<wasm_bindgen_futures::Inner>>
note: required because it appears within the type JsFuture
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-bindgen-futures-0.4.40/src/lib.rs:101:12
|
101 | pub struct JsFuture {
| ^^^^^^^^
= note: required because it captures the following types: wasm_bindgen_futures::JsFuture
note: required because it's used within this async fn body
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.11.23/src/wasm/mod.rs:20:1
|
20 | / {
21 | | use wasm_bindgen_futures::JsFuture;
22 | |
23 | | let js_val = JsFuture::from(promise).await.map_err(crate::error::wasm)?;
... |
27 | | .map_err(|js_val| "promise resolved to unexpected type".into())
28 | | }
| |
^
= note: required because it captures the following types: reqwest::Response, impl futures::Future<Output = std::result::Result<JsValue, Box<(dyn StdError + std::marker::Send + Sync + 'static)>>>
note: required because it's used within this async fn body
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.11.23/src/wasm/response.rs:99:54
|
99 | pub async fn text(self) -> crate::Result {
| _________________________________________________^
100 | | let p = self
101 | | .http
102 | | .body()
... |
113 | | }
114 | | }
| |
^
= note: required because it captures the following types: impl futures::Future<Output = std::result::Result<std::string::String, reqwest::Error>>
note: required because it's used within this async fn body
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:8:78
|
8 | async fn try_into_string(self) -> Result<String, ServerFnError> {
| _________________________________________________________________________^
9 | | self.text()
10 | | .await
11 | | .map_err(|e| ServerFnError::Deserialization(e.to_string()))
12 | | }
| |
^
note: required by a bound in ClientRes::{opaque#0}
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/mod.rs:56:73
|
56 | ) -> impl Future<Output = Result<String, ServerFnError>> + Send;
| ^^^^ required by this bound in ClientRes::{opaque#0}

error: future cannot be sent between threads safely
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:14:5
|
14 | async fn try_into_bytes(self) -> Result<Bytes, ServerFnError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by try_into_bytes is not Send
|
= help: within impl futures::Future<Output = std::result::Result<bytes::Bytes, ServerFnError<CustErr>>>, the trait std::marker::Send is not implemented for *mut u8
note: captured value is not Send
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:14:29
|
14 | async fn try_into_bytes(self) -> Result<Bytes, ServerFnError> {
| ^^^^ has type reqwest::Response which is not Send
note: required by a bound in ClientRes::{opaque#1}
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/mod.rs:61:72
|
61 | ) -> impl Future<Output = Result<Bytes, ServerFnError>> + Send;
| ^^^^ required by this bound in ClientRes::{opaque#1}

error[E0277]: Rc<RefCell<wasm_bindgen_futures::Inner>> cannot be sent between threads safely
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:14:5
|
14 | async fn try_into_bytes(self) -> Result<Bytes, ServerFnError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| Rc<RefCell<wasm_bindgen_futures::Inner>> cannot be sent between threads safely
| within this impl futures::Future<Output = std::result::Result<bytes::Bytes, ServerFnError<CustErr>>>
|
= help: within impl futures::Future<Output = std::result::Result<bytes::Bytes, ServerFnError<CustErr>>>, the trait std::marker::Send is not implemented for Rc<RefCell<wasm_bindgen_futures::Inner>>
note: required because it appears within the type JsFuture
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-bindgen-futures-0.4.40/src/lib.rs:101:12
|
101 | pub struct JsFuture {
| ^^^^^^^^
= note: required because it captures the following types: wasm_bindgen_futures::JsFuture
note: required because it's used within this async fn body
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.11.23/src/wasm/mod.rs:20:1
|
20 | / {
21 | | use wasm_bindgen_futures::JsFuture;
22 | |
23 | | let js_val = JsFuture::from(promise).await.map_err(crate::error::wasm)?;
... |
27 | | .map_err(|js_val| "promise resolved to unexpected type".into())
28 | | }
| |
^
= note: required because it captures the following types: reqwest::Response, impl futures::Future<Output = std::result::Result<JsValue, Box<(dyn StdError + std::marker::Send + Sync + 'static)>>>
note: required because it's used within this async fn body
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.11.23/src/wasm/response.rs:117:54
|
117 | pub async fn bytes(self) -> crate::Result {
| ____________________________________________^
118 | | let p = self
119 | | .http
120 | | .body()
... |
132 | | Ok(bytes.into())
133 | | }
| |
^
= note: required because it captures the following types: impl futures::Future<Output = std::result::Result<bytes::Bytes, reqwest::Error>>
note: required because it's used within this async fn body
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/reqwest.rs:14:76
|
14 | async fn try_into_bytes(self) -> Result<Bytes, ServerFnError> {
| ____________________________________________________________________________^
15 | | self.bytes()
16 | | .await
17 | | .map_err(|e| ServerFnError::Deserialization(e.to_string()))
18 | | }
| |
^
note: required by a bound in ClientRes::{opaque#1}
--> /home/sd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/server_fn-0.6.0-beta/src/response/mod.rs:61:72
|
61 | ) -> impl Future<Output = Result<Bytes, ServerFnError>> + Send;
| ^^^^ required by this bound in ClientRes::{opaque#1}

edit:

I was using leptos_axum with the 0.6-alpha already, which means everything was running fine with axum 0.7.

Copy link
Contributor

@fundon fundon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently implementing leptos_viz. Need some support from upstream.

server_fn/src/lib.rs Show resolved Hide resolved
server_fn/src/lib.rs Outdated Show resolved Hide resolved
@gbj
Copy link
Collaborator Author

gbj commented Jan 17, 2024

@sebadob Are you trying to use reqwest as a browser/WASM client here? Reqwest is supported as a client for desktop use but the default one for browser use should be the browser client.

reqwest::Response is Send but the errors show it's in a WASM environment here. Remove the reqwest feature and we should find a way to document the above.

@sebadob
Copy link
Contributor

sebadob commented Jan 17, 2024

@gbj I digged a bit deeper and found the problem:

I had rustls as a feature for leptos in the workspace root. This was not a problem before.
Now, when rustls is added globally for leptos, during wasm compilation we would get as dependencies:

leptos -> leptos_dom -> server_fn -> reqwest

...which caused the errors.

The solution is dead simple. I just removed rustls globally and only added it in the server crate as a feature.
I don't now if this error would be expected in that case, its just a difference from v0.5.

Now I can go on adopting my extractors in my server functions.

Edit:

btw I only added reqwest as a feature for server_fn because I saw this error and wanted to check, if adding it would fix the issue. server_fn adds reqwest as soon as rustls is present.

@sebadob
Copy link
Contributor

sebadob commented Jan 18, 2024

Just to give you some feedback on the binary size.
I tested this on a real application.

v0.5

The WASM uncompressed was 2.6MB, with brotli 612kB.

v0.6

Just with the migration to v0.6 and without using any of the more efficient encodings, the WASM size uncompressed went down to 2.2MB and with brotli to 537kB.

This is a really nice improvement. Great work!

@gbj
Copy link
Collaborator Author

gbj commented Jan 19, 2024

Just with the migration to v0.6 and without using any of the more efficient encodings, the WASM size uncompressed went down to 2.2MB and with brotli to 537kB.

That's really good news and exactly the sort of thing we were hoping to unlock with this change from an enum-based to a trait-based approach.

It's the same conceptual shift I'm planning to bring to reactivity and rendering in upcoming versions so it's good to see it works out well with server functions in a real app.

Thanks for sharing those results.

@gbj
Copy link
Collaborator Author

gbj commented Jan 19, 2024

@gbj I digged a bit deeper and found the problem:

...

btw I only added reqwest as a feature for server_fn because I saw this error and wanted to check, if adding it would fix the issue. server_fn adds reqwest as soon as rustls is present.

Thanks as always @sebadob. TIL about "weak dependency features" in cargo: rather than rustls = ["reqwest/rustls"] we want rustls = ["reqwest?/rustls"] so it activates the feature on reqwest if reqwest has been enabled, but doesn't enable rustls by itself. Should be fixed now.

@sebadob
Copy link
Contributor

sebadob commented Jan 19, 2024

I didn't know that something like weak dependencies exist
This is really good to know, thanks!

@gbj gbj mentioned this pull request Jan 19, 2024
dgsantana and others added 14 commits January 19, 2024 14:13
* chore: update to axum 0.7

Removed http, since it's included in axum, and replaced hyper by http-body-util, which is a smaller.

* chore: update samples to work with nre axum

Missing sessions_axum_auth, pending PR merge.

* chore: all dependencies update to axum 0.7

* chore: cargo fmt

* chore: fix doctests

* chore: Fix example that in reality doesn't use axum.

Fixed anyway.

* chore: more examples support for axum 0.7

* Small tweak
@gbj gbj merged commit c84c6ee into main Jan 20, 2024
59 checks passed
@gbj
Copy link
Collaborator Author

gbj commented Jan 20, 2024

I have merged this branch into main for my sanity. Feel free to continue opening issues or PRs to the main branch for any changes that need to happen before release. I'll release an rc1 in the next few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants