Ver código fonte

Merge branch 'master' into router-typesafe

Evan Almloff 2 anos atrás
pai
commit
495fd22bfd

+ 2 - 9
.github/workflows/macos.yml

@@ -30,14 +30,7 @@ jobs:
     name: Test Suite
     name: Test Suite
     runs-on: macos-latest
     runs-on: macos-latest
     steps:
     steps:
-      - uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: stable
-          override: true
+      - uses: dtolnay/rust-toolchain@stable
       - uses: Swatinem/rust-cache@v2
       - uses: Swatinem/rust-cache@v2
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
-      - uses: actions-rs/cargo@v1
-        with:
-          command: test
-          args: --all --tests
+      - run: cargo test --all --tests

+ 8 - 36
.github/workflows/main.yml

@@ -32,30 +32,19 @@ jobs:
     name: Check
     name: Check
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-      - uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: stable
-          override: true
+      - uses: dtolnay/rust-toolchain@stable
       - uses: Swatinem/rust-cache@v2
       - uses: Swatinem/rust-cache@v2
       - run: sudo apt-get update
       - run: sudo apt-get update
       - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev
       - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
-      - uses: actions-rs/cargo@v1
-        with:
-          command: check
-          args: --all --examples --tests
+      - run: cargo check --all --examples --tests
 
 
   test:
   test:
     if: github.event.pull_request.draft == false
     if: github.event.pull_request.draft == false
     name: Test Suite
     name: Test Suite
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-      - uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: stable
-          override: true
+      - uses: dtolnay/rust-toolchain@stable
       - uses: Swatinem/rust-cache@v2
       - uses: Swatinem/rust-cache@v2
       - run: sudo apt-get update
       - run: sudo apt-get update
       - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev
       - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev
@@ -63,48 +52,31 @@ jobs:
       - uses: browser-actions/setup-firefox@latest
       - uses: browser-actions/setup-firefox@latest
       - uses: jetli/wasm-pack-action@v0.4.0
       - uses: jetli/wasm-pack-action@v0.4.0
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
-      - uses: actions-rs/cargo@v1
-        with:
-          command: make
-          args: tests
+      - run: cargo make tests
 
 
   fmt:
   fmt:
     if: github.event.pull_request.draft == false
     if: github.event.pull_request.draft == false
     name: Rustfmt
     name: Rustfmt
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-      - uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: stable
-          override: true
+      - uses: dtolnay/rust-toolchain@stable
       - uses: Swatinem/rust-cache@v2
       - uses: Swatinem/rust-cache@v2
       - run: rustup component add rustfmt
       - run: rustup component add rustfmt
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
-      - uses: actions-rs/cargo@v1
-        with:
-          command: fmt
-          args: --all -- --check
+      - run: cargo fmt --all -- --check
 
 
   clippy:
   clippy:
     if: github.event.pull_request.draft == false
     if: github.event.pull_request.draft == false
     name: Clippy
     name: Clippy
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-      - uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: stable
-          override: true
+      - uses: dtolnay/rust-toolchain@stable
       - uses: Swatinem/rust-cache@v2
       - uses: Swatinem/rust-cache@v2
       - run: sudo apt-get update
       - run: sudo apt-get update
       - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev
       - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev
       - run: rustup component add clippy
       - run: rustup component add clippy
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
-      - uses: actions-rs/cargo@v1
-        with:
-          command: clippy
-          args: --workspace --examples --tests -- -D warnings
+      - run: cargo clippy --workspace --examples --tests -- -D warnings
 
 
   # Coverage is disabled until we can fix it
   # Coverage is disabled until we can fix it
   # coverage:
   # coverage:

+ 1 - 1
README.md

@@ -64,7 +64,7 @@ fn app(cx: Scope) -> Element {
 }
 }
 ```
 ```
 
 
-Dioxus can be used to deliver webapps, desktop apps, static sites, mobile apps, TUI apps, liveview apps, and more. Dioxus is entirely renderer agnostic and can be used as platform for any renderer.
+Dioxus can be used to deliver webapps, desktop apps, static sites, mobile apps, TUI apps, liveview apps, and more. Dioxus is entirely renderer agnostic and can be used as a platform for any renderer.
 
 
 If you know React, then you already know Dioxus.
 If you know React, then you already know Dioxus.
 
 

+ 0 - 3
docs/guide/examples/server_context.rs

@@ -16,9 +16,6 @@ fn main() {
         use axum::extract::State;
         use axum::extract::State;
         use axum::routing::get;
         use axum::routing::get;
 
 
-        // Register the server function before starting the server
-        DoubleServer::register().unwrap();
-
         tokio::runtime::Runtime::new()
         tokio::runtime::Runtime::new()
             .unwrap()
             .unwrap()
             .block_on(async move {
             .block_on(async move {

+ 0 - 3
docs/guide/examples/server_context_state.rs

@@ -25,9 +25,6 @@ fn main() {
         use axum::routing::get;
         use axum::routing::get;
         use std::sync::Arc;
         use std::sync::Arc;
 
 
-        // Register the server function before starting the server
-        DoubleServer::register().unwrap();
-
         tokio::runtime::Runtime::new()
         tokio::runtime::Runtime::new()
             .unwrap()
             .unwrap()
             .block_on(async move {
             .block_on(async move {

+ 0 - 3
docs/guide/examples/server_function.rs

@@ -16,9 +16,6 @@ fn main() {
         use axum::extract::State;
         use axum::extract::State;
         use axum::routing::get;
         use axum::routing::get;
 
 
-        // Register the server function before starting the server
-        DoubleServer::register().unwrap();
-
         tokio::runtime::Runtime::new()
         tokio::runtime::Runtime::new()
             .unwrap()
             .unwrap()
             .block_on(async move {
             .block_on(async move {

+ 1 - 1
docs/guide/src/en/interactivity/event_handlers.md

@@ -29,7 +29,7 @@ To learn what the different event types for HTML provide, read the [events modul
 
 
 Some events will trigger first on the element the event originated at upward. For example, a click event on a `button` inside a `div` would first trigger the button's event listener and then the div's event listener.
 Some events will trigger first on the element the event originated at upward. For example, a click event on a `button` inside a `div` would first trigger the button's event listener and then the div's event listener.
 
 
-> For more information about event propigation see [the mdn docs on event bubling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
+> For more information about event propagation see [the mdn docs on event bubbling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
 
 
 If you want to prevent this behavior, you can call `stop_propagation()` on the event:
 If you want to prevent this behavior, you can call `stop_propagation()` on the event:
 
 

+ 1 - 1
packages/core/src/virtual_dom.rs

@@ -426,7 +426,7 @@ impl VirtualDom {
                         }
                         }
                     }
                     }
 
 
-                    parent_path = dbg!(template.parent).and_then(|id| self.elements.get(id.0));
+                    parent_path = template.parent.and_then(|id| self.elements.get(id.0));
                 } else {
                 } else {
                     break;
                     break;
                 }
                 }

+ 1 - 1
packages/desktop/src/query.rs

@@ -22,7 +22,7 @@ pub(crate) struct QueryEngine {
 
 
 impl Default for QueryEngine {
 impl Default for QueryEngine {
     fn default() -> Self {
     fn default() -> Self {
-        let (sender, _) = tokio::sync::broadcast::channel(8);
+        let (sender, _) = tokio::sync::broadcast::channel(1000);
         Self {
         Self {
             sender: Rc::new(sender),
             sender: Rc::new(sender),
             active_requests: SharedSlab::default(),
             active_requests: SharedSlab::default(),

+ 1 - 1
packages/fullstack/Cargo.toml

@@ -13,7 +13,7 @@ keywords = ["dom", "ui", "gui", "react", "ssr", "fullstack"]
 
 
 [dependencies]
 [dependencies]
 # server functions
 # server functions
-server_fn = { git = "https://github.com/leptos-rs/leptos", rev = "671b1e4a8fff7a2e05bb621ef08e87be2b18ccae", default-features = false, features = ["stable"] }
+server_fn = { git = "https://github.com/leptos-rs/leptos", rev = "15a4e54435eb5a539afb75891292bcccd2cc8e85", default-features = false, features = ["stable"] }
 dioxus_server_macro = { path = "server-macro" }
 dioxus_server_macro = { path = "server-macro" }
 
 
 # warp
 # warp

+ 0 - 1
packages/fullstack/README.md

@@ -46,7 +46,6 @@ fn main() {
     );
     );
     #[cfg(feature = "ssr")]
     #[cfg(feature = "ssr")]
     {
     {
-        GetMeaning::register().unwrap();
         tokio::runtime::Runtime::new()
         tokio::runtime::Runtime::new()
             .unwrap()
             .unwrap()
             .block_on(async move {
             .block_on(async move {

+ 0 - 3
packages/fullstack/examples/axum-desktop/src/server.rs

@@ -8,9 +8,6 @@ use dioxus_fullstack::prelude::*;
 
 
 #[tokio::main]
 #[tokio::main]
 async fn main() {
 async fn main() {
-    PostServerData::register().unwrap();
-    GetServerData::register().unwrap();
-
     let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080));
     let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080));
     axum::Server::bind(&addr)
     axum::Server::bind(&addr)
         .serve(
         .serve(

+ 0 - 2
packages/fullstack/examples/axum-hello-world/src/main.rs

@@ -32,8 +32,6 @@ fn main() {
             true
             true
         }));
         }));
 
 
-        PostServerData::register().unwrap();
-        GetServerData::register().unwrap();
         tokio::runtime::Runtime::new()
         tokio::runtime::Runtime::new()
             .unwrap()
             .unwrap()
             .block_on(async move {
             .block_on(async move {

+ 0 - 2
packages/fullstack/examples/salvo-hello-world/src/main.rs

@@ -33,8 +33,6 @@ fn main() {
         }));
         }));
 
 
         use salvo::prelude::*;
         use salvo::prelude::*;
-        PostServerData::register().unwrap();
-        GetServerData::register().unwrap();
         tokio::runtime::Runtime::new()
         tokio::runtime::Runtime::new()
             .unwrap()
             .unwrap()
             .block_on(async move {
             .block_on(async move {

+ 0 - 2
packages/fullstack/examples/warp-hello-world/src/main.rs

@@ -32,8 +32,6 @@ fn main() {
             true
             true
         }));
         }));
 
 
-        PostServerData::register().unwrap();
-        GetServerData::register().unwrap();
         tokio::runtime::Runtime::new()
         tokio::runtime::Runtime::new()
             .unwrap()
             .unwrap()
             .block_on(async move {
             .block_on(async move {

+ 2 - 2
packages/fullstack/server-macro/Cargo.toml

@@ -7,8 +7,8 @@ edition = "2021"
 
 
 [dependencies]
 [dependencies]
 quote = "1.0.26"
 quote = "1.0.26"
-server_fn_macro = { git = "https://github.com/leptos-rs/leptos", rev = "671b1e4a8fff7a2e05bb621ef08e87be2b18ccae", features = ["stable"] }
-syn = { version = "1", features = ["full"] }
+server_fn_macro = { git = "https://github.com/leptos-rs/leptos", rev = "15a4e54435eb5a539afb75891292bcccd2cc8e85", features = ["stable"] }
+syn = { version = "2", features = ["full"] }
 
 
 [lib]
 [lib]
 proc-macro = true
 proc-macro = true

+ 1 - 1
packages/fullstack/server-macro/src/lib.rs

@@ -35,7 +35,6 @@ use server_fn_macro::*;
 /// ```
 /// ```
 ///
 ///
 /// Note the following:
 /// Note the following:
-/// - You must **register** the server function by calling `T::register()` somewhere in your main function.
 /// - **Server functions must be `async`.** Even if the work being done inside the function body
 /// - **Server functions must be `async`.** Even if the work being done inside the function body
 ///   can run synchronously on the server, from the client’s perspective it involves an asynchronous
 ///   can run synchronously on the server, from the client’s perspective it involves an asynchronous
 ///   function call.
 ///   function call.
@@ -62,6 +61,7 @@ pub fn server(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
     match server_macro_impl(
     match server_macro_impl(
         args.into(),
         args.into(),
         s.into(),
         s.into(),
+        syn::parse_quote!(::dioxus_fullstack::prelude::ServerFnTraitObj),
         Some(context),
         Some(context),
         Some(syn::parse_quote!(::dioxus_fullstack::prelude::server_fn)),
         Some(syn::parse_quote!(::dioxus_fullstack::prelude::server_fn)),
     ) {
     ) {

+ 7 - 8
packages/fullstack/src/adapters/axum_adapter.rs

@@ -12,7 +12,6 @@
 //!     dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
 //!     dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
 //!     #[cfg(feature = "ssr")]
 //!     #[cfg(feature = "ssr")]
 //!     {
 //!     {
-//!         GetServerData::register().unwrap();
 //!         tokio::runtime::Runtime::new()
 //!         tokio::runtime::Runtime::new()
 //!             .unwrap()
 //!             .unwrap()
 //!             .block_on(async move {
 //!             .block_on(async move {
@@ -107,7 +106,7 @@ pub trait DioxusRouterExt<S> {
     fn register_server_fns_with_handler<H, T>(
     fn register_server_fns_with_handler<H, T>(
         self,
         self,
         server_fn_route: &'static str,
         server_fn_route: &'static str,
-        handler: impl Fn(ServerFunction) -> H,
+        handler: impl FnMut(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
     ) -> Self
     ) -> Self
     where
     where
         H: Handler<T, S>,
         H: Handler<T, S>,
@@ -232,7 +231,7 @@ where
     fn register_server_fns_with_handler<H, T>(
     fn register_server_fns_with_handler<H, T>(
         self,
         self,
         server_fn_route: &'static str,
         server_fn_route: &'static str,
-        mut handler: impl FnMut(ServerFunction) -> H,
+        mut handler: impl FnMut(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
     ) -> Self
     ) -> Self
     where
     where
         H: Handler<T, S, Body>,
         H: Handler<T, S, Body>,
@@ -243,7 +242,7 @@ where
         for server_fn_path in DioxusServerFnRegistry::paths_registered() {
         for server_fn_path in DioxusServerFnRegistry::paths_registered() {
             let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
             let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
             let full_route = format!("{server_fn_route}/{server_fn_path}");
             let full_route = format!("{server_fn_route}/{server_fn_path}");
-            match func.encoding {
+            match func.encoding() {
                 Encoding::Url | Encoding::Cbor => {
                 Encoding::Url | Encoding::Cbor => {
                     router = router.route(&full_route, post(handler(func)));
                     router = router.route(&full_route, post(handler(func)));
                 }
                 }
@@ -314,7 +313,7 @@ where
         let cfg = cfg.into();
         let cfg = cfg.into();
 
 
         // Add server functions and render index.html
         // Add server functions and render index.html
-        self.serve_static_assets(&cfg.assets_path)
+        self.serve_static_assets(cfg.assets_path)
             .route(
             .route(
                 "/",
                 "/",
                 get(render_handler).with_state((cfg, SSRState::default())),
                 get(render_handler).with_state((cfg, SSRState::default())),
@@ -371,7 +370,7 @@ async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>(
 /// A default handler for server functions. It will deserialize the request, call the server function, and serialize the response.
 /// A default handler for server functions. It will deserialize the request, call the server function, and serialize the response.
 pub async fn server_fn_handler(
 pub async fn server_fn_handler(
     server_context: DioxusServerContext,
     server_context: DioxusServerContext,
-    function: ServerFunction,
+    function: server_fn::ServerFnTraitObj<DioxusServerContext>,
     parts: Arc<RequestParts>,
     parts: Arc<RequestParts>,
     body: Body,
     body: Body,
 ) -> impl IntoResponse {
 ) -> impl IntoResponse {
@@ -389,11 +388,11 @@ pub async fn server_fn_handler(
                 .expect("couldn't spawn runtime")
                 .expect("couldn't spawn runtime")
                 .block_on(async {
                 .block_on(async {
                     let query = &query_string.into();
                     let query = &query_string.into();
-                    let data = match &function.encoding {
+                    let data = match &function.encoding() {
                         Encoding::Url | Encoding::Cbor => &body,
                         Encoding::Url | Encoding::Cbor => &body,
                         Encoding::GetJSON | Encoding::GetCBOR => query,
                         Encoding::GetJSON | Encoding::GetCBOR => query,
                     };
                     };
-                    let resp = match (function.trait_obj)(server_context.clone(), &data).await {
+                    let resp = match function.call(server_context.clone(), data).await {
                         Ok(serialized) => {
                         Ok(serialized) => {
                             // if this is Accept: application/json then send a serialized JSON response
                             // if this is Accept: application/json then send a serialized JSON response
                             let accept_header = parts
                             let accept_header = parts

+ 14 - 12
packages/fullstack/src/adapters/salvo_adapter.rs

@@ -12,7 +12,6 @@
 //!     #[cfg(feature = "ssr")]
 //!     #[cfg(feature = "ssr")]
 //!     {
 //!     {
 //!         use salvo::prelude::*;
 //!         use salvo::prelude::*;
-//!         GetServerData::register().unwrap();
 //!         tokio::runtime::Runtime::new()
 //!         tokio::runtime::Runtime::new()
 //!             .unwrap()
 //!             .unwrap()
 //!             .block_on(async move {
 //!             .block_on(async move {
@@ -77,7 +76,7 @@ pub trait DioxusRouterExt {
     /// use dioxus_fullstack::prelude::*;
     /// use dioxus_fullstack::prelude::*;
     ///
     ///
     /// struct ServerFunctionHandler {
     /// struct ServerFunctionHandler {
-    ///     server_fn: ServerFunction,
+    ///     server_fn: server_fn::ServerFnTraitObj<DioxusServerContext>,
     /// }
     /// }
     ///
     ///
     /// #[handler]
     /// #[handler]
@@ -110,7 +109,7 @@ pub trait DioxusRouterExt {
     fn register_server_fns_with_handler<H>(
     fn register_server_fns_with_handler<H>(
         self,
         self,
         server_fn_route: &'static str,
         server_fn_route: &'static str,
-        handler: impl Fn(ServerFunction) -> H,
+        handler: impl Fn(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
     ) -> Self
     ) -> Self
     where
     where
         H: Handler + 'static;
         H: Handler + 'static;
@@ -204,7 +203,7 @@ impl DioxusRouterExt for Router {
     fn register_server_fns_with_handler<H>(
     fn register_server_fns_with_handler<H>(
         self,
         self,
         server_fn_route: &'static str,
         server_fn_route: &'static str,
-        mut handler: impl FnMut(ServerFunction) -> H,
+        mut handler: impl FnMut(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
     ) -> Self
     ) -> Self
     where
     where
         H: Handler + 'static,
         H: Handler + 'static,
@@ -213,7 +212,7 @@ impl DioxusRouterExt for Router {
         for server_fn_path in DioxusServerFnRegistry::paths_registered() {
         for server_fn_path in DioxusServerFnRegistry::paths_registered() {
             let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
             let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
             let full_route = format!("{server_fn_route}/{server_fn_path}");
             let full_route = format!("{server_fn_route}/{server_fn_path}");
-            match func.encoding {
+            match func.encoding() {
                 Encoding::Url | Encoding::Cbor => {
                 Encoding::Url | Encoding::Cbor => {
                     router = router.push(Router::with_path(&full_route).post(handler(func)));
                     router = router.push(Router::with_path(&full_route).post(handler(func)));
                 }
                 }
@@ -280,7 +279,7 @@ impl DioxusRouterExt for Router {
     ) -> Self {
     ) -> Self {
         let cfg = cfg.into();
         let cfg = cfg.into();
 
 
-        self.serve_static_assets(&cfg.assets_path)
+        self.serve_static_assets(cfg.assets_path)
             .connect_hot_reload()
             .connect_hot_reload()
             .register_server_fns(server_fn_path)
             .register_server_fns(server_fn_path)
             .push(Router::with_path("/").get(SSRHandler { cfg }))
             .push(Router::with_path("/").get(SSRHandler { cfg }))
@@ -288,8 +287,8 @@ impl DioxusRouterExt for Router {
 
 
     fn connect_hot_reload(self) -> Self {
     fn connect_hot_reload(self) -> Self {
         let mut _dioxus_router = Router::with_path("_dioxus");
         let mut _dioxus_router = Router::with_path("_dioxus");
-        _dioxus_router = _dioxus_router
-            .push(Router::with_path("hot_reload").handle(HotReloadHandler::default()));
+        _dioxus_router =
+            _dioxus_router.push(Router::with_path("hot_reload").handle(HotReloadHandler));
         #[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
         #[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
         {
         {
             _dioxus_router = _dioxus_router.push(Router::with_path("disconnect").handle(ignore_ws));
             _dioxus_router = _dioxus_router.push(Router::with_path("disconnect").handle(ignore_ws));
@@ -346,12 +345,15 @@ impl<P: Clone + serde::Serialize + Send + Sync + 'static> Handler for SSRHandler
 /// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
 /// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
 pub struct ServerFnHandler {
 pub struct ServerFnHandler {
     server_context: DioxusServerContext,
     server_context: DioxusServerContext,
-    function: ServerFunction,
+    function: server_fn::ServerFnTraitObj<DioxusServerContext>,
 }
 }
 
 
 impl ServerFnHandler {
 impl ServerFnHandler {
     /// Create a new server function handler with the given server context and server function.
     /// Create a new server function handler with the given server context and server function.
-    pub fn new(server_context: impl Into<DioxusServerContext>, function: ServerFunction) -> Self {
+    pub fn new(
+        server_context: impl Into<DioxusServerContext>,
+        function: server_fn::ServerFnTraitObj<DioxusServerContext>,
+    ) -> Self {
         let server_context = server_context.into();
         let server_context = server_context.into();
         Self {
         Self {
             server_context,
             server_context,
@@ -395,11 +397,11 @@ impl ServerFnHandler {
                 tokio::runtime::Runtime::new()
                 tokio::runtime::Runtime::new()
                     .expect("couldn't spawn runtime")
                     .expect("couldn't spawn runtime")
                     .block_on(async move {
                     .block_on(async move {
-                        let data = match &function.encoding {
+                        let data = match function.encoding() {
                             Encoding::Url | Encoding::Cbor => &body,
                             Encoding::Url | Encoding::Cbor => &body,
                             Encoding::GetJSON | Encoding::GetCBOR => &query,
                             Encoding::GetJSON | Encoding::GetCBOR => &query,
                         };
                         };
-                        let resp = (function.trait_obj)(server_context, data).await;
+                        let resp = function.call(server_context, data).await;
 
 
                         resp_tx.send(resp).unwrap();
                         resp_tx.send(resp).unwrap();
                     })
                     })

+ 8 - 9
packages/fullstack/src/adapters/warp_adapter.rs

@@ -11,7 +11,6 @@
 //!     dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
 //!     dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
 //!     #[cfg(feature = "ssr")]
 //!     #[cfg(feature = "ssr")]
 //!     {
 //!     {
-//!         GetServerData::register().unwrap();
 //!         tokio::runtime::Runtime::new()
 //!         tokio::runtime::Runtime::new()
 //!             .unwrap()
 //!             .unwrap()
 //!             .block_on(async move {
 //!             .block_on(async move {
@@ -93,7 +92,7 @@ pub fn register_server_fns_with_handler<H, F, R>(
     mut handler: H,
     mut handler: H,
 ) -> BoxedFilter<(R,)>
 ) -> BoxedFilter<(R,)>
 where
 where
-    H: FnMut(String, ServerFunction) -> F,
+    H: FnMut(String, server_fn::ServerFnTraitObj<DioxusServerContext>) -> F,
     F: Filter<Extract = (R,), Error = warp::Rejection> + Send + Sync + 'static,
     F: Filter<Extract = (R,), Error = warp::Rejection> + Send + Sync + 'static,
     F::Extract: Send,
     F::Extract: Send,
     R: Reply + 'static,
     R: Reply + 'static,
@@ -104,7 +103,7 @@ where
         let full_route = format!("{server_fn_route}/{server_fn_path}")
         let full_route = format!("{server_fn_route}/{server_fn_path}")
             .trim_start_matches('/')
             .trim_start_matches('/')
             .to_string();
             .to_string();
-        let route = handler(full_route, func.clone()).boxed();
+        let route = handler(full_route, func).boxed();
         if let Some(boxed_filter) = filter.take() {
         if let Some(boxed_filter) = filter.take() {
             filter = Some(boxed_filter.or(route).unify().boxed());
             filter = Some(boxed_filter.or(route).unify().boxed());
         } else {
         } else {
@@ -128,7 +127,7 @@ where
 /// ```
 /// ```
 pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl Reply,)> {
 pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl Reply,)> {
     register_server_fns_with_handler(server_fn_route, |full_route, func| {
     register_server_fns_with_handler(server_fn_route, |full_route, func| {
-        path(full_route.clone())
+        path(full_route)
             .and(warp::post().or(warp::get()).unify())
             .and(warp::post().or(warp::get()).unify())
             .and(request_parts())
             .and(request_parts())
             .and(warp::body::bytes())
             .and(warp::body::bytes())
@@ -250,7 +249,7 @@ impl warp::reject::Reject for RecieveFailed {}
 /// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
 /// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
 pub async fn server_fn_handler(
 pub async fn server_fn_handler(
     server_context: impl Into<DioxusServerContext>,
     server_context: impl Into<DioxusServerContext>,
-    function: ServerFunction,
+    function: server_fn::ServerFnTraitObj<DioxusServerContext>,
     parts: RequestParts,
     parts: RequestParts,
     body: Bytes,
     body: Bytes,
 ) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
 ) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
@@ -274,11 +273,11 @@ pub async fn server_fn_handler(
                         .as_bytes()
                         .as_bytes()
                         .to_vec()
                         .to_vec()
                         .into();
                         .into();
-                    let data = match &function.encoding {
+                    let data = match function.encoding() {
                         Encoding::Url | Encoding::Cbor => &body,
                         Encoding::Url | Encoding::Cbor => &body,
                         Encoding::GetJSON | Encoding::GetCBOR => &query,
                         Encoding::GetJSON | Encoding::GetCBOR => &query,
                     };
                     };
-                    let resp = match (function.trait_obj)(server_context.clone(), data).await {
+                    let resp = match function.call(server_context.clone(), data).await {
                         Ok(serialized) => {
                         Ok(serialized) => {
                             // if this is Accept: application/json then send a serialized JSON response
                             // if this is Accept: application/json then send a serialized JSON response
                             let accept_header = parts
                             let accept_header = parts
@@ -373,7 +372,7 @@ pub fn connect_hot_reload() -> impl Filter<Extract = (impl Reply,), Error = warp
         use warp::ws::Message;
         use warp::ws::Message;
 
 
         let hot_reload = warp::path!("_dioxus" / "hot_reload")
         let hot_reload = warp::path!("_dioxus" / "hot_reload")
-            .and(warp::any().then(|| crate::hot_reload::spawn_hot_reload()))
+            .and(warp::any().then(crate::hot_reload::spawn_hot_reload))
             .and(warp::ws())
             .and(warp::ws())
             .map(move |state: &'static HotReloadState, ws: warp::ws::Ws| {
             .map(move |state: &'static HotReloadState, ws: warp::ws::Ws| {
                 #[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
                 #[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
@@ -425,7 +424,7 @@ pub fn connect_hot_reload() -> impl Filter<Extract = (impl Reply,), Error = warp
                         struct DisconnectOnDrop(Option<warp::ws::WebSocket>);
                         struct DisconnectOnDrop(Option<warp::ws::WebSocket>);
                         impl Drop for DisconnectOnDrop {
                         impl Drop for DisconnectOnDrop {
                             fn drop(&mut self) {
                             fn drop(&mut self) {
-                                let _ = self.0.take().unwrap().close();
+                                std::mem::drop(self.0.take().unwrap().close());
                             }
                             }
                         }
                         }
 
 

+ 1 - 1
packages/fullstack/src/lib.rs

@@ -36,7 +36,7 @@ pub mod prelude {
     #[cfg(feature = "ssr")]
     #[cfg(feature = "ssr")]
     pub use crate::server_context::RequestParts;
     pub use crate::server_context::RequestParts;
     pub use crate::server_context::{DioxusServerContext, HasServerContext};
     pub use crate::server_context::{DioxusServerContext, HasServerContext};
-    pub use crate::server_fn::ServerFn;
+    pub use crate::server_fn::DioxusServerFn;
     #[cfg(feature = "ssr")]
     #[cfg(feature = "ssr")]
     pub use crate::server_fn::{ServerFnTraitObj, ServerFunction};
     pub use crate::server_fn::{ServerFnTraitObj, ServerFunction};
     pub use dioxus_server_macro::*;
     pub use dioxus_server_macro::*;

+ 71 - 23
packages/fullstack/src/server_fn.rs

@@ -1,18 +1,63 @@
 use crate::server_context::DioxusServerContext;
 use crate::server_context::DioxusServerContext;
 
 
 #[cfg(any(feature = "ssr", doc))]
 #[cfg(any(feature = "ssr", doc))]
+#[derive(Clone)]
 /// A trait object for a function that be called on serializable arguments and returns a serializable result.
 /// A trait object for a function that be called on serializable arguments and returns a serializable result.
-pub type ServerFnTraitObj = server_fn::ServerFnTraitObj<DioxusServerContext>;
+pub struct ServerFnTraitObj(server_fn::ServerFnTraitObj<DioxusServerContext>);
+
+#[cfg(any(feature = "ssr", doc))]
+impl std::ops::Deref for ServerFnTraitObj {
+    type Target = server_fn::ServerFnTraitObj<DioxusServerContext>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+#[cfg(any(feature = "ssr", doc))]
+impl std::ops::DerefMut for ServerFnTraitObj {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+#[cfg(any(feature = "ssr", doc))]
+impl ServerFnTraitObj {
+    fn new(
+        prefix: &'static str,
+        url: &'static str,
+        encoding: server_fn::Encoding,
+        run: ServerFunction,
+    ) -> Self {
+        Self(server_fn::ServerFnTraitObj::new(prefix, url, encoding, run))
+    }
+
+    /// Create a new `ServerFnTraitObj` from a `server_fn::ServerFnTraitObj`.
+    pub const fn from_generic_server_fn(
+        server_fn: server_fn::ServerFnTraitObj<DioxusServerContext>,
+    ) -> Self {
+        Self(server_fn)
+    }
+}
+
+#[cfg(any(feature = "ssr", doc))]
+server_fn::inventory::collect!(ServerFnTraitObj);
 
 
 #[cfg(any(feature = "ssr", doc))]
 #[cfg(any(feature = "ssr", doc))]
 /// A server function that can be called on serializable arguments and returns a serializable result.
 /// A server function that can be called on serializable arguments and returns a serializable result.
-pub type ServerFunction = server_fn::ServerFunction<DioxusServerContext>;
+pub type ServerFunction = server_fn::SerializedFnTraitObj<DioxusServerContext>;
 
 
 #[cfg(any(feature = "ssr", doc))]
 #[cfg(any(feature = "ssr", doc))]
 #[allow(clippy::type_complexity)]
 #[allow(clippy::type_complexity)]
 static REGISTERED_SERVER_FUNCTIONS: once_cell::sync::Lazy<
 static REGISTERED_SERVER_FUNCTIONS: once_cell::sync::Lazy<
-    std::sync::Arc<std::sync::RwLock<std::collections::HashMap<&'static str, ServerFunction>>>,
-> = once_cell::sync::Lazy::new(Default::default);
+    std::sync::Arc<std::sync::RwLock<std::collections::HashMap<&'static str, ServerFnTraitObj>>>,
+> = once_cell::sync::Lazy::new(|| {
+    let mut map = std::collections::HashMap::new();
+    for server_fn in server_fn::inventory::iter::<ServerFnTraitObj> {
+        map.insert(server_fn.0.url(), server_fn.clone());
+    }
+    std::sync::Arc::new(std::sync::RwLock::new(map))
+});
 
 
 #[cfg(any(feature = "ssr", doc))]
 #[cfg(any(feature = "ssr", doc))]
 /// The registry of all Dioxus server functions.
 /// The registry of all Dioxus server functions.
@@ -22,9 +67,10 @@ pub struct DioxusServerFnRegistry;
 impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRegistry {
 impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRegistry {
     type Error = ServerRegistrationFnError;
     type Error = ServerRegistrationFnError;
 
 
-    fn register(
+    fn register_explicit(
+        prefix: &'static str,
         url: &'static str,
         url: &'static str,
-        server_function: std::sync::Arc<ServerFnTraitObj>,
+        server_function: ServerFunction,
         encoding: server_fn::Encoding,
         encoding: server_fn::Encoding,
     ) -> Result<(), Self::Error> {
     ) -> Result<(), Self::Error> {
         // store it in the hashmap
         // store it in the hashmap
@@ -33,10 +79,7 @@ impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRe
             .map_err(|e| ServerRegistrationFnError::Poisoned(e.to_string()))?;
             .map_err(|e| ServerRegistrationFnError::Poisoned(e.to_string()))?;
         let prev = write.insert(
         let prev = write.insert(
             url,
             url,
-            ServerFunction {
-                trait_obj: server_function,
-                encoding,
-            },
+            ServerFnTraitObj::new(prefix, url, encoding, server_function),
         );
         );
 
 
         // if there was already a server function with this key,
         // if there was already a server function with this key,
@@ -53,27 +96,32 @@ impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRe
         }
         }
     }
     }
 
 
+    fn register(
+        url: &'static str,
+        server_function: ServerFunction,
+        encoding: server_fn::Encoding,
+    ) -> Result<(), Self::Error> {
+        Self::register_explicit("", url, server_function, encoding)
+    }
+
     /// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
     /// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
-    fn get(url: &str) -> Option<ServerFunction> {
+    fn get(url: &str) -> Option<server_fn::ServerFnTraitObj<DioxusServerContext>> {
         REGISTERED_SERVER_FUNCTIONS
         REGISTERED_SERVER_FUNCTIONS
             .read()
             .read()
             .ok()
             .ok()
-            .and_then(|fns| fns.get(url).cloned())
+            .and_then(|fns| fns.get(url).map(|inner| inner.0.clone()))
     }
     }
 
 
     /// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
     /// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
-    fn get_trait_obj(url: &str) -> Option<std::sync::Arc<ServerFnTraitObj>> {
-        REGISTERED_SERVER_FUNCTIONS
-            .read()
-            .ok()
-            .and_then(|fns| fns.get(url).map(|f| f.trait_obj.clone()))
+    fn get_trait_obj(url: &str) -> Option<server_fn::ServerFnTraitObj<DioxusServerContext>> {
+        Self::get(url)
     }
     }
 
 
     fn get_encoding(url: &str) -> Option<server_fn::Encoding> {
     fn get_encoding(url: &str) -> Option<server_fn::Encoding> {
         REGISTERED_SERVER_FUNCTIONS
         REGISTERED_SERVER_FUNCTIONS
             .read()
             .read()
             .ok()
             .ok()
-            .and_then(|fns| fns.get(url).map(|f| f.encoding.clone()))
+            .and_then(|fns| fns.get(url).map(|f| f.encoding()))
     }
     }
 
 
     /// Returns a list of all registered server functions.
     /// Returns a list of all registered server functions.
@@ -103,16 +151,16 @@ pub enum ServerRegistrationFnError {
 ///
 ///
 /// Server functions are created using the `server` macro.
 /// Server functions are created using the `server` macro.
 ///
 ///
-/// The function should be registered by calling `ServerFn::register()`. The set of server functions
+/// The set of server functions
 /// can be queried on the server for routing purposes by calling [server_fn::ServerFunctionRegistry::get].
 /// can be queried on the server for routing purposes by calling [server_fn::ServerFunctionRegistry::get].
 ///
 ///
 /// Technically, the trait is implemented on a type that describes the server function's arguments, not the function itself.
 /// Technically, the trait is implemented on a type that describes the server function's arguments, not the function itself.
-pub trait ServerFn: server_fn::ServerFn<DioxusServerContext> {
+pub trait DioxusServerFn: server_fn::ServerFn<DioxusServerContext> {
     /// Registers the server function, allowing the client to query it by URL.
     /// Registers the server function, allowing the client to query it by URL.
     #[cfg(any(feature = "ssr", doc))]
     #[cfg(any(feature = "ssr", doc))]
-    fn register() -> Result<(), server_fn::ServerFnError> {
-        Self::register_in::<DioxusServerFnRegistry>()
+    fn register_explicit() -> Result<(), server_fn::ServerFnError> {
+        Self::register_in_explicit::<DioxusServerFnRegistry>()
     }
     }
 }
 }
 
 
-impl<T> ServerFn for T where T: server_fn::ServerFn<DioxusServerContext> {}
+impl<T> DioxusServerFn for T where T: server_fn::ServerFn<DioxusServerContext> {}

+ 1 - 1
packages/hooks/src/use_shared_state.rs

@@ -71,7 +71,7 @@ impl<T> ProvidedStateInner<T> {
 ///     let current_theme = *theme.read();
 ///     let current_theme = *theme.read();
 ///
 ///
 ///     render! {
 ///     render! {
-///         match &*theme.read() {
+///         match current_theme {
 ///             Theme::Dark => {
 ///             Theme::Dark => {
 ///                 "Dark mode"
 ///                 "Dark mode"
 ///             }
 ///             }

+ 1 - 1
packages/interpreter/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 [package]
 name = "dioxus-interpreter-js"
 name = "dioxus-interpreter-js"
-version = "0.3.2"
+version = "0.3.3"
 edition = "2018"
 edition = "2018"
 authors = ["Jonathan Kelley"]
 authors = ["Jonathan Kelley"]
 description = "JS Intepreter for Dioxus - a concurrent renderer-agnostic Virtual DOM for interactive user experiences"
 description = "JS Intepreter for Dioxus - a concurrent renderer-agnostic Virtual DOM for interactive user experiences"