From 299acd25f330f6e5ab55a6ac206f658137c8837f Mon Sep 17 00:00:00 2001 From: Greg Johnston Date: Sun, 9 Feb 2025 20:46:41 -0500 Subject: [PATCH] implement `AddAnyAttr` for `AnyView` (#3562) --- Cargo.lock | 493 +++++++-------- examples/counter/tests/web.rs | 14 +- leptos/src/attribute_interceptor.rs | 45 +- leptos/src/error_boundary.rs | 71 +-- leptos/src/into_view.rs | 44 +- leptos/src/mount.rs | 5 +- leptos/src/suspense_component.rs | 83 +-- leptos_server/src/lib.rs | 38 +- meta/src/body.rs | 73 +-- meta/src/html.rs | 77 +-- meta/src/lib.rs | 66 +- meta/src/title.rs | 33 +- router/src/flat_router.rs | 73 +-- router/src/nested_router.rs | 52 +- router/src/reactive.rs | 58 +- tachys/src/html/attribute/any_attribute.rs | 13 +- tachys/src/html/element/element_ext.rs | 2 +- tachys/src/html/element/mod.rs | 115 ++-- tachys/src/html/islands.rs | 77 +-- tachys/src/html/mod.rs | 54 +- tachys/src/oco.rs | 37 +- tachys/src/reactive_graph/class.rs | 14 +- tachys/src/reactive_graph/mod.rs | 165 ++--- tachys/src/reactive_graph/owned.rs | 56 +- tachys/src/reactive_graph/suspense.rs | 51 +- tachys/src/renderer/dom.rs | 16 + tachys/src/ssr/mod.rs | 6 +- tachys/src/view/any_view.rs | 680 ++++++++++----------- tachys/src/view/either.rs | 253 ++++---- tachys/src/view/error_boundary.rs | 85 +-- tachys/src/view/iterators.rs | 160 ++--- tachys/src/view/keyed.rs | 92 ++- tachys/src/view/mod.rs | 108 +--- tachys/src/view/primitives.rs | 25 +- tachys/src/view/static_types.rs | 28 +- tachys/src/view/strings.rs | 143 ++--- tachys/src/view/template.rs | 43 +- tachys/src/view/tuples.rs | 149 ++--- 38 files changed, 1419 insertions(+), 2178 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f1981a874..2a5c72c982 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -205,7 +205,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.15", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -267,7 +267,7 @@ dependencies = [ "async-executor", "futures", "glib", - "thiserror 2.0.11", + "thiserror 2.0.9", "tokio", "tracing", "wasm-bindgen-futures", @@ -275,9 +275,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.95" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "async-executor" @@ -322,7 +322,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -333,13 +333,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.86" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -362,7 +362,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -378,7 +378,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -465,9 +465,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -491,9 +491,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.2" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -501,9 +501,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" @@ -525,7 +525,7 @@ checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -536,9 +536,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "bytestring" @@ -557,9 +557,9 @@ checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" [[package]] name = "cc" -version = "1.2.12" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", @@ -634,7 +634,7 @@ dependencies = [ "serde-lite", "serde-wasm-bindgen", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.9", "wasm-bindgen", ] @@ -752,9 +752,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -782,9 +782,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" @@ -827,20 +827,20 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] name = "derive_more" -version = "0.99.19" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -861,7 +861,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -872,9 +872,9 @@ checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" [[package]] name = "dyn-clone" -version = "1.0.18" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" @@ -935,9 +935,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -1051,9 +1051,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.6.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ "fastrand", "futures-core", @@ -1070,7 +1070,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -1122,22 +1122,10 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets", -] - [[package]] name = "gimli" version = "0.31.1" @@ -1188,7 +1176,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -1203,9 +1191,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gloo-net" @@ -1402,9 +1390,9 @@ checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" [[package]] name = "httparse" -version = "1.10.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1428,9 +1416,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.6.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -1614,7 +1602,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -1640,15 +1628,15 @@ dependencies = [ [[package]] name = "impl-more" -version = "0.1.9" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" +checksum = "aae21c3177a27788957044151cc2800043d127acaa460a47ebb9b84dfa2c6aa0" [[package]] name = "indexmap" -version = "2.7.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1656,14 +1644,13 @@ dependencies = [ [[package]] name = "insta" -version = "1.42.1" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c1b125e30d93896b365e156c33dadfffab45ee8400afcbba4752f59de08a86" +checksum = "7e9ffc4d4892617c50a928c52b2961cb5174b6fc6ebf252b2fac9d21955c48b8" dependencies = [ "console", + "lazy_static", "linked-hash-map", - "once_cell", - "pin-project", "similar", ] @@ -1675,18 +1662,18 @@ checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" [[package]] name = "inventory" -version = "0.3.19" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b12ebb6799019b044deaf431eadfe23245b259bba5a2c0796acec3943a3cdb" +checksum = "e5d80fade88dd420ce0d9ab6f7c58ef2272dde38db874657950f827d4982c817" dependencies = [ "rustversion", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "itertools" @@ -1714,9 +1701,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ "once_cell", "wasm-bindgen", @@ -1728,6 +1715,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "leptos" version = "0.8.0-alpha" @@ -1737,7 +1730,7 @@ dependencies = [ "cfg-if", "either_of", "futures", - "getrandom 0.2.15", + "getrandom", "hydration_context", "leptos-spin-macro", "leptos_config", @@ -1750,7 +1743,7 @@ dependencies = [ "paste", "rand", "reactive_graph", - "rustc-hash 2.1.1", + "rustc-hash 2.1.0", "send_wrapper", "serde", "serde_json", @@ -1758,7 +1751,7 @@ dependencies = [ "server_fn", "slotmap", "tachys", - "thiserror 2.0.11", + "thiserror 2.0.9", "throw_error", "tracing", "typed-builder", @@ -1776,7 +1769,7 @@ dependencies = [ "http 1.2.0", "proc-macro-error", "server_fn_macro 0.6.15", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -1836,7 +1829,7 @@ dependencies = [ "serde", "temp-env", "tempfile", - "thiserror 2.0.11", + "thiserror 2.0.9", "tokio", "typed-builder", ] @@ -1870,7 +1863,7 @@ dependencies = [ "quote", "rstml", "serde", - "syn 2.0.98", + "syn 2.0.90", "walkdir", ] @@ -1909,7 +1902,7 @@ dependencies = [ "serde", "server_fn", "server_fn_macro 0.8.0-alpha", - "syn 2.0.98", + "syn 2.0.90", "tracing", "trybuild", "typed-builder", @@ -1948,7 +1941,7 @@ dependencies = [ "reactive_graph", "send_wrapper", "tachys", - "thiserror 2.0.11", + "thiserror 2.0.9", "tracing", "url", "wasm-bindgen", @@ -1964,7 +1957,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2008,9 +2001,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.15" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" @@ -2047,9 +2040,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.25" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "manyhow" @@ -2060,7 +2053,7 @@ dependencies = [ "manyhow-macros", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2110,7 +2103,7 @@ checksum = "07b7f1340a7f0d2f89755aac4096f1c55352bfcb95cb8f351d6fcefa18df474f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2132,9 +2125,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", ] @@ -2147,7 +2140,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.52.0", ] @@ -2185,14 +2178,14 @@ checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] name = "native-tls" -version = "0.2.13" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ "libc", "log", @@ -2259,20 +2252,20 @@ version = "0.2.0" dependencies = [ "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.9", ] [[package]] name = "once_cell" -version = "1.20.3" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.70" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags", "cfg-if", @@ -2291,20 +2284,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.105" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -2365,22 +2358,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.9" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.9" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2431,12 +2424,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.29" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2491,7 +2484,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2507,9 +2500,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2522,7 +2515,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", "version_check", "yansi", ] @@ -2544,7 +2537,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2557,10 +2550,10 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", + "rustc-hash 2.1.0", "rustls", "socket2", - "thiserror 2.0.11", + "thiserror 2.0.9", "tokio", "tracing", ] @@ -2572,14 +2565,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", - "getrandom 0.2.15", + "getrandom", "rand", "ring", - "rustc-hash 2.1.1", + "rustc-hash 2.1.0", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.11", + "thiserror 2.0.9", "tinyvec", "tracing", "web-time", @@ -2601,9 +2594,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.38" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2627,7 +2620,7 @@ dependencies = [ "proc-macro-utils", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2666,7 +2659,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom", ] [[package]] @@ -2680,11 +2673,11 @@ dependencies = [ "hydration_context", "or_poisoned", "pin-project-lite", - "rustc-hash 2.1.1", + "rustc-hash 2.1.0", "send_wrapper", "serde", "slotmap", - "thiserror 2.0.11", + "thiserror 2.0.9", "tokio", "tokio-test", "tracing", @@ -2703,7 +2696,7 @@ dependencies = [ "paste", "reactive_graph", "reactive_stores_macro", - "rustc-hash 2.1.1", + "rustc-hash 2.1.0", "tokio", "tokio-test", ] @@ -2716,7 +2709,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2774,9 +2767,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.12" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64", "bytes", @@ -2810,7 +2803,6 @@ dependencies = [ "tokio-native-tls", "tokio-rustls", "tokio-util", - "tower", "tower-service", "url", "wasm-bindgen", @@ -2829,7 +2821,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom", "libc", "spin", "untrusted", @@ -2838,9 +2830,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.10" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" +checksum = "b11a153aec4a6ab60795f8ebe2923c597b16b05bb1504377451e705ef1a45323" dependencies = [ "bytecheck", "bytes", @@ -2857,13 +2849,13 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.10" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" +checksum = "beb382a4d9f53bd5c0be86b10d8179c3f8a14c30bf774ff77096ed6581e35981" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -2890,17 +2882,17 @@ dependencies = [ [[package]] name = "rstml" -version = "0.12.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cf4616de7499fc5164570d40ca4e1b24d231c6833a88bff0fe00725080fd56" +checksum = "51187e564f12336ef40cd04f6f4d805d6919188001dcf1e0a021898ea0fe28ce" dependencies = [ "derive-where", "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.98", + "syn 2.0.90", "syn_derive", - "thiserror 2.0.11", + "thiserror 1.0.69", ] [[package]] @@ -2917,9 +2909,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" @@ -2932,9 +2924,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.44" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags", "errno", @@ -2945,9 +2937,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.22" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring", @@ -2968,9 +2960,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" dependencies = [ "web-time", ] @@ -2988,15 +2980,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" -version = "1.0.19" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3037,9 +3029,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -3047,9 +3039,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.25" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "send_wrapper" @@ -3062,9 +3054,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.217" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] @@ -3087,7 +3079,7 @@ checksum = "7ce26a84e3d8d10853301cf6a75c58132b8f5d5e8fee65949ea8dd7758d6760b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3103,20 +3095,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -3198,7 +3190,7 @@ dependencies = [ "serde_json", "serde_qs", "server_fn_macro_default", - "thiserror 2.0.11", + "thiserror 2.0.9", "throw_error", "tower", "tower-layer", @@ -3220,7 +3212,7 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", "xxhash-rust", ] @@ -3232,7 +3224,7 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", "xxhash-rust", ] @@ -3241,7 +3233,7 @@ name = "server_fn_macro_default" version = "0.8.0-alpha" dependencies = [ "server_fn_macro 0.8.0-alpha", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3278,9 +3270,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "similar" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "slab" @@ -3308,7 +3300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33a1b4f13e2bbf2f5b29d09dfebc9de69229ffee245aed80e3b70f9b5fd28c06" dependencies = [ "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3378,9 +3370,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -3389,14 +3381,14 @@ dependencies = [ [[package]] name = "syn_derive" -version = "0.2.0" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb066a04799e45f5d582e8fc6ec8e6d6896040d00898eb4e6a835196815b219" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" dependencies = [ - "proc-macro-error2", + "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3416,7 +3408,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3456,7 +3448,7 @@ dependencies = [ "paste", "reactive_graph", "reactive_stores", - "rustc-hash 2.1.1", + "rustc-hash 2.1.0", "send_wrapper", "sledgehammer_bindgen", "sledgehammer_utils", @@ -3493,13 +3485,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.16.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", - "getrandom 0.3.1", "once_cell", "rustix", "windows-sys 0.59.0", @@ -3525,11 +3516,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.9", ] [[package]] @@ -3540,18 +3531,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3619,9 +3610,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.43.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -3637,13 +3628,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3705,9 +3696,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", @@ -3726,9 +3717,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.23" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -3810,7 +3801,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3830,9 +3821,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.103" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b812699e0c4f813b872b373a4471717d9eb550da14b311058a4d9cf4173cbca6" +checksum = "8dcd332a5496c026f1e14b7f3d2b7bd98e509660c04239c58b0ba38a12daded4" dependencies = [ "glob", "serde", @@ -3860,7 +3851,7 @@ checksum = "560b82d656506509d43abe30e0ba64c56b1953ab3d4fe7ba5902747a7a3cedd5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -3871,15 +3862,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.8.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" @@ -3930,11 +3921,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.13.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ - "getrandom 0.3.1", + "getrandom", ] [[package]] @@ -3986,46 +3977,36 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" -dependencies = [ - "wit-bindgen-rt", -] - [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", - "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", @@ -4036,9 +4017,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4046,25 +4027,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-streams" @@ -4081,9 +4059,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -4101,9 +4079,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.8" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -4231,22 +4209,13 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.1" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" -dependencies = [ - "bitflags", -] - [[package]] name = "write16" version = "1.0.0" @@ -4261,9 +4230,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "xxhash-rust" -version = "0.8.15" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" +checksum = "a08fd76779ae1883bbf1e46c2c46a75a0c4e37c445e68a24b01479d438f26ae6" [[package]] name = "yansi" @@ -4291,7 +4260,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", "synstructure", ] @@ -4313,7 +4282,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] @@ -4333,7 +4302,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", "synstructure", ] @@ -4362,7 +4331,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.90", ] [[package]] diff --git a/examples/counter/tests/web.rs b/examples/counter/tests/web.rs index eb9a2ce2e3..2327be35fa 100644 --- a/examples/counter/tests/web.rs +++ b/examples/counter/tests/web.rs @@ -19,7 +19,7 @@ async fn clear() { // note that we start at the initial value of 10 let _dispose = mount_to( test_wrapper.clone().unchecked_into(), - || view! { }, + || view! { }, ); // now we extract the buttons by iterating over the DOM @@ -59,9 +59,9 @@ async fn clear() { // .into_view() here is just a convenient way of specifying "use the regular DOM renderer" .into_view() // views are lazy -- they describe a DOM tree but don't create it yet - // calling .build(None) will actually build the DOM elements - .build(None) - // .build(None) returned an ElementState, which is a smart pointer for + // calling .build() will actually build the DOM elements + .build() + // .build() returned an ElementState, which is a smart pointer for // a DOM element. So we can still just call .outer_html(), which access the outerHTML on // the actual DOM element .outer_html() @@ -87,7 +87,7 @@ async fn inc() { let _dispose = mount_to( test_wrapper.clone().unchecked_into(), - || view! { }, + || view! { }, ); // You can do testing with vanilla DOM operations @@ -150,7 +150,7 @@ async fn inc() { } } .into_view() - .build(None) + .build() .outer_html() ); @@ -173,7 +173,7 @@ async fn inc() { } } .into_view() - .build(None) + .build() .outer_html() ); } diff --git a/leptos/src/attribute_interceptor.rs b/leptos/src/attribute_interceptor.rs index 154f365c7f..5133754266 100644 --- a/leptos/src/attribute_interceptor.rs +++ b/leptos/src/attribute_interceptor.rs @@ -3,7 +3,6 @@ use crate::attr::{ Attribute, NextAttribute, }; use leptos::prelude::*; -use tachys::view::any_view::ExtraAttrsMut; /// Function stored to build/rebuild the wrapped children when attributes are added. type ChildBuilder = dyn Fn(AnyAttribute) -> T + Send + Sync + 'static; @@ -44,7 +43,7 @@ pub fn AttributeInterceptor( ) -> impl IntoView where Chil: Fn(AnyAttribute) -> T + Send + Sync + 'static, - T: IntoView + 'static, + T: IntoView, { AttributeInterceptorInner::new(children) } @@ -78,20 +77,16 @@ impl AttributeInterceptorInner { impl Render for AttributeInterceptorInner { type State = ::State; - fn build(self, extra_attrs: Option>) -> Self::State { - self.children.build(extra_attrs) + fn build(self) -> Self::State { + self.children.build() } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - self.children.rebuild(state, extra_attrs); + fn rebuild(self, state: &mut Self::State) { + self.children.rebuild(state); } } -impl AddAnyAttr for AttributeInterceptorInner +impl AddAnyAttr for AttributeInterceptorInner where A: Attribute, { @@ -119,23 +114,19 @@ where } } -impl RenderHtml - for AttributeInterceptorInner -{ +impl RenderHtml for AttributeInterceptorInner { type AsyncOutput = T::AsyncOutput; - type Owned = AttributeInterceptorInner; const MIN_LENGTH: usize = T::MIN_LENGTH; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.children.dry_resolve(extra_attrs) + fn dry_resolve(&mut self) { + self.children.dry_resolve() } fn resolve( self, - extra_attrs: ExtraAttrsMut<'_>, ) -> impl std::future::Future + Send { - self.children.resolve(extra_attrs) + self.children.resolve() } fn to_html_with_buf( @@ -144,14 +135,14 @@ impl RenderHtml position: &mut leptos::tachys::view::Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + _extra_attrs: Vec, ) { self.children.to_html_with_buf( buf, position, escape, mark_branches, - extra_attrs, + vec![], ) } @@ -159,17 +150,7 @@ impl RenderHtml self, cursor: &leptos::tachys::hydration::Cursor, position: &leptos::tachys::view::PositionState, - extra_attrs: Option>, ) -> Self::State { - self.children - .hydrate::(cursor, position, extra_attrs) - } - - fn into_owned(self) -> Self::Owned { - AttributeInterceptorInner { - children_builder: self.children_builder, - children: self.children, - attributes: self.attributes.into_cloneable_owned(), - } + self.children.hydrate::(cursor, position) } } diff --git a/leptos/src/error_boundary.rs b/leptos/src/error_boundary.rs index c09881bc99..774fe29b4b 100644 --- a/leptos/src/error_boundary.rs +++ b/leptos/src/error_boundary.rs @@ -16,8 +16,8 @@ use tachys::{ reactive_graph::OwnedView, ssr::StreamBuilder, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }, }; use throw_error::{Error, ErrorHook, ErrorId}; @@ -163,6 +163,14 @@ where self.children.insert_before_this(child) } } + + fn elements(&self) -> Vec { + if let Some(fallback) = &self.fallback { + fallback.elements() + } else { + self.children.elements() + } + } } impl Render for ErrorBoundaryView @@ -173,10 +181,10 @@ where { type State = RenderEffect>; - fn build(mut self, extra_attrs: Option>) -> Self::State { + fn build(mut self) -> Self::State { let hook = Arc::clone(&self.hook); let _hook = throw_error::set_error_hook(Arc::clone(&hook)); - let mut children = Some(self.children.build(extra_attrs.clone())); + let mut children = Some(self.children.build()); RenderEffect::new( move |prev: Option< ErrorBoundaryViewState, @@ -193,8 +201,7 @@ where // yes errors, and was showing children (false, None) => { state.fallback = Some( - (self.fallback)(self.errors.clone()) - .build(extra_attrs.clone()), + (self.fallback)(self.errors.clone()).build(), ); state .children @@ -208,10 +215,8 @@ where } state } else { - let fallback = (!self.errors_empty.get()).then(|| { - (self.fallback)(self.errors.clone()) - .build(extra_attrs.clone()) - }); + let fallback = (!self.errors_empty.get()) + .then(|| (self.fallback)(self.errors.clone()).build()); ErrorBoundaryViewState { children: children.take().unwrap(), fallback, @@ -221,12 +226,8 @@ where ) } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - let new = self.build(extra_attrs); + fn rebuild(self, state: &mut Self::State) { + let new = self.build(); let mut old = std::mem::replace(state, new); old.insert_before_this(state); old.unmount(); @@ -275,18 +276,14 @@ where Fal: RenderHtml + Send + 'static, { type AsyncOutput = ErrorBoundaryView; - type Owned = Self; const MIN_LENGTH: usize = Chil::MIN_LENGTH; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.children.dry_resolve(extra_attrs); + fn dry_resolve(&mut self) { + self.children.dry_resolve(); } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { let ErrorBoundaryView { hook, boundary_id, @@ -300,7 +297,7 @@ where hook, boundary_id, errors_empty, - children: children.resolve(extra_attrs).await, + children: children.resolve().await, fallback, errors, } @@ -312,7 +309,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { // first, attempt to serialize the children to HTML, then check for errors let _hook = throw_error::set_error_hook(self.hook); @@ -347,7 +344,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -384,7 +381,6 @@ where mut self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let mut children = Some(self.children); let hook = Arc::clone(&self.hook); @@ -406,8 +402,7 @@ where // yes errors, and was showing children (false, None) => { state.fallback = Some( - (self.fallback)(self.errors.clone()) - .build(extra_attrs.clone()), + (self.fallback)(self.errors.clone()).build(), ); state .children @@ -424,23 +419,15 @@ where let children = children.take().unwrap(); let (children, fallback) = if self.errors_empty.get() { ( - children.hydrate::( - &cursor, - &position, - extra_attrs.clone(), - ), + children.hydrate::(&cursor, &position), None, ) } else { ( - children.build(extra_attrs.clone()), + children.build(), Some( (self.fallback)(self.errors.clone()) - .hydrate::( - &cursor, - &position, - extra_attrs.clone(), - ), + .hydrate::(&cursor, &position), ), ) }; @@ -450,10 +437,6 @@ where }, ) } - - fn into_owned(self) -> Self::Owned { - self - } } #[derive(Debug)] diff --git a/leptos/src/into_view.rs b/leptos/src/into_view.rs index 5c660970de..fda32e67a2 100644 --- a/leptos/src/into_view.rs +++ b/leptos/src/into_view.rs @@ -4,8 +4,8 @@ use tachys::{ hydration::Cursor, ssr::StreamBuilder, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Position, PositionState, - Render, RenderHtml, ToTemplate, + add_attr::AddAnyAttr, Position, PositionState, Render, RenderHtml, + ToTemplate, }, }; @@ -76,34 +76,26 @@ where impl Render for View { type State = T::State; - fn build(self, extra_attrs: Option>) -> Self::State { - self.inner.build(extra_attrs) + fn build(self) -> Self::State { + self.inner.build() } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - self.inner.rebuild(state, extra_attrs) + fn rebuild(self, state: &mut Self::State) { + self.inner.rebuild(state) } } impl RenderHtml for View { type AsyncOutput = T::AsyncOutput; - type Owned = View; const MIN_LENGTH: usize = ::MIN_LENGTH; - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - self.inner.resolve(extra_attrs).await + async fn resolve(self) -> Self::AsyncOutput { + self.inner.resolve().await } - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.inner.dry_resolve(extra_attrs); + fn dry_resolve(&mut self) { + self.inner.dry_resolve(); } fn to_html_with_buf( @@ -112,7 +104,7 @@ impl RenderHtml for View { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { #[cfg(debug_assertions)] let vm = self.view_marker.to_owned(); @@ -141,7 +133,7 @@ impl RenderHtml for View { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -170,18 +162,8 @@ impl RenderHtml for View { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - self.inner - .hydrate::(cursor, position, extra_attrs) - } - - fn into_owned(self) -> Self::Owned { - View { - inner: self.inner.into_owned(), - #[cfg(debug_assertions)] - view_marker: self.view_marker, - } + self.inner.hydrate::(cursor, position) } } diff --git a/leptos/src/mount.rs b/leptos/src/mount.rs index 0ff36f463d..526bd8d6ac 100644 --- a/leptos/src/mount.rs +++ b/leptos/src/mount.rs @@ -71,7 +71,6 @@ where view.hydrate::( &Cursor::new(parent.unchecked_into()), &PositionState::default(), - None, ) }); @@ -125,7 +124,7 @@ where let owner = Owner::new(); let mountable = owner.with(move || { let view = f().into_view(); - let mut mountable = view.build(None); + let mut mountable = view.build(); mountable.mount(&parent, None); mountable }); @@ -153,7 +152,7 @@ where let owner = Owner::new(); let mountable = owner.with(move || { let view = f(); - let mut mountable = view.build(None); + let mut mountable = view.build(); mountable.mount(parent, None); mountable }); diff --git a/leptos/src/suspense_component.rs b/leptos/src/suspense_component.rs index 3b677084bb..e54fb48193 100644 --- a/leptos/src/suspense_component.rs +++ b/leptos/src/suspense_component.rs @@ -25,7 +25,6 @@ use tachys::{ ssr::StreamBuilder, view::{ add_attr::AddAnyAttr, - any_view::ExtraAttrsMut, either::{EitherKeepAlive, EitherKeepAliveState}, Mountable, Position, PositionState, Render, RenderHtml, }, @@ -163,7 +162,7 @@ where OwnedViewState>, >; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let mut children = Some(self.children); let mut fallback = Some(self.fallback); let none_pending = self.none_pending; @@ -188,20 +187,16 @@ where ); if let Some(mut state) = prev { - this.rebuild(&mut state, extra_attrs.clone()); + this.rebuild(&mut state); state } else { - this.build(extra_attrs.clone()) + this.build() } }) } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - let new = self.build(extra_attrs); + fn rebuild(self, state: &mut Self::State) { + let new = self.build(); let mut old = std::mem::replace(state, new); old.insert_before_this(state); old.unmount(); @@ -252,16 +247,12 @@ where // i.e., if this is the child of another Suspense during SSR, don't wait for it: it will handle // itself type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = Chil::MIN_LENGTH; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -271,7 +262,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { self.fallback.to_html_with_buf( buf, @@ -288,7 +279,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - mut extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -313,8 +304,7 @@ where provide_context(LocalResourceNotifier::from(local_tx)); // walk over the tree of children once to make sure that all resource loads are registered - self.children - .dry_resolve(ExtraAttrsMut::from_owned(&mut extra_attrs)); + self.children.dry_resolve(); // check the set of tasks to see if it is empty, now or later let eff = reactive_graph::effect::Effect::new_isomorphic({ @@ -330,8 +320,7 @@ where } }); - let mut fut = Box::pin(ScopedFuture::new(ErrorHookFuture::new({ - let mut extra_attrs = extra_attrs.clone(); + let mut fut = Box::pin(ScopedFuture::new(ErrorHookFuture::new( async move { // race the local resource notifier against the set of tasks // @@ -358,7 +347,7 @@ where // but in situations like a we actually // want to be able to 1) synchronously read a resource's value, but still 2) wait // for it to load before we render everything - let mut children = Box::pin(self.children.resolve(ExtraAttrsMut::from_owned(&mut extra_attrs)).fuse()); + let mut children = Box::pin(self.children.resolve().fuse()); // we continue racing the children against the "do we have any local // resources?" Future @@ -377,8 +366,8 @@ where } } } - } - }))); + }, + ))); match fut.as_mut().now_or_never() { Some(Some(resolved)) => { Either::::Right(resolved) @@ -449,7 +438,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let cursor = cursor.to_owned(); let position = position.to_owned(); @@ -478,21 +466,13 @@ where ); if let Some(mut state) = prev { - this.rebuild(&mut state, extra_attrs.clone()); + this.rebuild(&mut state); state } else { - this.hydrate::( - &cursor, - &position, - extra_attrs.clone(), - ) + this.hydrate::(&cursor, &position) } }) } - - fn into_owned(self) -> Self::Owned { - self - } } /// A wrapper that prevents [`Suspense`] from waiting for any resource reads that happen inside @@ -512,16 +492,12 @@ where { type State = T::State; - fn build(self, extra_attrs: Option>) -> Self::State { - (self.0)().build(extra_attrs) + fn build(self) -> Self::State { + (self.0)().build() } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - (self.0)().rebuild(state, extra_attrs); + fn rebuild(self, state: &mut Self::State) { + (self.0)().rebuild(state); } } @@ -549,16 +525,12 @@ where T: RenderHtml + 'static, { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = T::MIN_LENGTH; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -568,7 +540,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { (self.0)().to_html_with_buf( buf, @@ -585,7 +557,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -602,12 +574,7 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - (self.0)().hydrate::(cursor, position, extra_attrs) - } - - fn into_owned(self) -> Self::Owned { - self + (self.0)().hydrate::(cursor, position) } } diff --git a/leptos_server/src/lib.rs b/leptos_server/src/lib.rs index ac6b5212c6..8583e9462a 100644 --- a/leptos_server/src/lib.rs +++ b/leptos_server/src/lib.rs @@ -84,8 +84,7 @@ mod view_implementations { reactive_graph::{RenderEffectState, Suspend, SuspendState}, ssr::StreamBuilder, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Position, - PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, Position, PositionState, Render, RenderHtml, }, }; @@ -96,17 +95,12 @@ mod view_implementations { { type State = RenderEffectState>; - fn build(self, extra_attrs: Option>) -> Self::State { - (move || Suspend::new(async move { self.await })).build(extra_attrs) + fn build(self) -> Self::State { + (move || Suspend::new(async move { self.await })).build() } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - (move || Suspend::new(async move { self.await })) - .rebuild(state, extra_attrs) + fn rebuild(self, state: &mut Self::State) { + (move || Suspend::new(async move { self.await })).rebuild(state) } } @@ -141,20 +135,15 @@ mod view_implementations { Ser: Send + 'static, { type AsyncOutput = Option; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { self.read(); } - fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> impl Future + Send { - (move || Suspend::new(async move { self.await })) - .resolve(extra_attrs) + fn resolve(self) -> impl Future + Send { + (move || Suspend::new(async move { self.await })).resolve() } fn to_html_with_buf( @@ -163,7 +152,7 @@ mod view_implementations { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { (move || Suspend::new(async move { self.await })).to_html_with_buf( buf, @@ -180,7 +169,7 @@ mod view_implementations { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -198,14 +187,9 @@ mod view_implementations { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { (move || Suspend::new(async move { self.await })) - .hydrate::(cursor, position, extra_attrs) - } - - fn into_owned(self) -> Self::Owned { - self + .hydrate::(cursor, position) } } } diff --git a/meta/src/body.rs b/meta/src/body.rs index 2e745a7fbe..2a80fc8670 100644 --- a/meta/src/body.rs +++ b/meta/src/body.rs @@ -1,9 +1,6 @@ use crate::ServerMetaContext; use leptos::{ - attr::{ - any_attribute::{AnyAttribute, AnyAttributeState}, - NextAttribute, - }, + attr::{any_attribute::AnyAttribute, NextAttribute}, component, html, reactive::owner::use_context, tachys::{ @@ -11,8 +8,8 @@ use leptos::{ html::attribute::Attribute, hydration::Cursor, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }, }, IntoView, @@ -61,7 +58,6 @@ where At: Attribute, { attributes: At::State, - extra_attrs: Option>, } impl Render for BodyView @@ -70,27 +66,15 @@ where { type State = BodyViewState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let el = document().body().expect("there to be a element"); let attributes = self.attributes.build(&el); - let extra_attrs = extra_attrs.map(|attrs| attrs.build(&el)); - BodyViewState { - attributes, - extra_attrs, - } + + BodyViewState { attributes } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { self.attributes.rebuild(&mut state.attributes); - if let (Some(extra_attrs), Some(extra_attr_states)) = - (extra_attrs, &mut state.extra_attrs) - { - extra_attrs.rebuild(extra_attr_states); - } } } @@ -119,24 +103,17 @@ where At: Attribute, { type AsyncOutput = BodyView; - type Owned = BodyView; const MIN_LENGTH: usize = At::MIN_LENGTH; - fn dry_resolve(&mut self, mut extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { self.attributes.dry_resolve(); - extra_attrs.iter_mut().for_each(Attribute::dry_resolve); } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - let (attributes, _) = futures::join!( - self.attributes.resolve(), - ExtraAttrsMut::resolve(extra_attrs) - ); - BodyView { attributes } + async fn resolve(self) -> Self::AsyncOutput { + BodyView { + attributes: self.attributes.resolve().await, + } } fn to_html_with_buf( @@ -145,13 +122,12 @@ where _position: &mut Position, _escape: bool, _mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { if let Some(meta) = use_context::() { let mut buf = String::new(); _ = html::attributes_to_html( - self.attributes, - extra_attrs, + (self.attributes, extra_attrs), &mut buf, ); if !buf.is_empty() { @@ -164,23 +140,11 @@ where self, _cursor: &Cursor, _position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let el = document().body().expect("there to be a element"); let attributes = self.attributes.hydrate::(&el); - let extra_attrs = - extra_attrs.map(|attrs| attrs.hydrate::(&el)); - - BodyViewState { - attributes, - extra_attrs, - } - } - fn into_owned(self) -> Self::Owned { - BodyView { - attributes: self.attributes.into_cloneable_owned(), - } + BodyViewState { attributes } } } @@ -200,4 +164,11 @@ where fn insert_before_this(&self, _child: &mut dyn Mountable) -> bool { false } + + fn elements(&self) -> Vec { + vec![document() + .body() + .expect("there to be a element") + .into()] + } } diff --git a/meta/src/html.rs b/meta/src/html.rs index 52d5bec63b..edda1ad7cf 100644 --- a/meta/src/html.rs +++ b/meta/src/html.rs @@ -1,9 +1,6 @@ use crate::ServerMetaContext; use leptos::{ - attr::{ - any_attribute::{AnyAttribute, AnyAttributeState}, - NextAttribute, - }, + attr::{any_attribute::AnyAttribute, NextAttribute}, component, html, reactive::owner::use_context, tachys::{ @@ -11,8 +8,8 @@ use leptos::{ html::attribute::Attribute, hydration::Cursor, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }, }, IntoView, @@ -58,7 +55,6 @@ where At: Attribute, { attributes: At::State, - extra_attrs: Option>, } impl Render for HtmlView @@ -67,33 +63,18 @@ where { type State = HtmlViewState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let el = document() .document_element() .expect("there to be a element"); let attributes = self.attributes.build(&el); - let extra_attrs = extra_attrs.map(|attrs| { - attrs.into_iter().map(|attr| attr.build(&el)).collect() - }); - HtmlViewState { - attributes, - extra_attrs, - } + HtmlViewState { attributes } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { self.attributes.rebuild(&mut state.attributes); - if let (Some(extra_attrs), Some(extra_attr_states)) = - (extra_attrs, &mut state.extra_attrs) - { - extra_attrs.rebuild(extra_attr_states); - } } } @@ -122,24 +103,17 @@ where At: Attribute, { type AsyncOutput = HtmlView; - type Owned = HtmlView; const MIN_LENGTH: usize = At::MIN_LENGTH; - fn dry_resolve(&mut self, mut extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { self.attributes.dry_resolve(); - extra_attrs.iter_mut().for_each(Attribute::dry_resolve); } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - let (attributes, _) = futures::join!( - self.attributes.resolve(), - ExtraAttrsMut::resolve(extra_attrs) - ); - HtmlView { attributes } + async fn resolve(self) -> Self::AsyncOutput { + HtmlView { + attributes: self.attributes.resolve().await, + } } fn to_html_with_buf( @@ -148,13 +122,12 @@ where _position: &mut Position, _escape: bool, _mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { if let Some(meta) = use_context::() { let mut buf = String::new(); _ = html::attributes_to_html( - self.attributes, - extra_attrs, + (self.attributes, extra_attrs), &mut buf, ); if !buf.is_empty() { @@ -167,30 +140,14 @@ where self, _cursor: &Cursor, _position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let el = document() .document_element() .expect("there to be a element"); let attributes = self.attributes.hydrate::(&el); - let extra_attrs = extra_attrs.map(|attrs| { - attrs - .into_iter() - .map(|attr| attr.hydrate::(&el)) - .collect() - }); - - HtmlViewState { - attributes, - extra_attrs, - } - } - fn into_owned(self) -> Self::Owned { - HtmlView { - attributes: self.attributes.into_cloneable_owned(), - } + HtmlViewState { attributes } } } @@ -212,4 +169,10 @@ where fn insert_before_this(&self, _child: &mut dyn Mountable) -> bool { false } + + fn elements(&self) -> Vec { + vec![document() + .document_element() + .expect("there to be a element")] + } } diff --git a/meta/src/lib.rs b/meta/src/lib.rs index 9c5b8bfd20..524ab8e07b 100644 --- a/meta/src/lib.rs +++ b/meta/src/lib.rs @@ -57,8 +57,8 @@ use leptos::{ }, hydration::Cursor, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }, }, IntoView, @@ -334,7 +334,7 @@ where &mut Position::NextChild, false, false, - None, + vec![], ); _ = cx.elements.send(buf); // fails only if the receiver is already dropped } else { @@ -391,17 +391,13 @@ where { type State = RegisteredMetaTagState; - fn build(self, extra_attrs: Option>) -> Self::State { - let state = self.el.unwrap().build(extra_attrs); + fn build(self) -> Self::State { + let state = self.el.unwrap().build(); RegisteredMetaTagState { state } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - self.el.unwrap().rebuild(&mut state.state, extra_attrs); + fn rebuild(self, state: &mut Self::State) { + self.el.unwrap().rebuild(&mut state.state); } } @@ -434,18 +430,14 @@ where Ch: RenderHtml + Send, { type AsyncOutput = Self; - type Owned = RegisteredMetaTag; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.el.dry_resolve(extra_attrs) + fn dry_resolve(&mut self) { + self.el.dry_resolve() } - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self // TODO? } @@ -455,7 +447,7 @@ where _position: &mut Position, _escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { // meta tags are rendered into the buffer stored into the context // the value has already been taken out, when we're on the server @@ -465,7 +457,6 @@ where self, _cursor: &Cursor, _position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let cursor = use_context::() .expect( @@ -476,16 +467,9 @@ where let state = self.el.unwrap().hydrate::( &cursor, &PositionState::new(Position::NextChild), - extra_attrs, ); RegisteredMetaTagState { state } } - - fn into_owned(self) -> Self::Owned { - RegisteredMetaTag { - el: self.el.map(|inner| inner.into_owned()), - } - } } impl Mountable for RegisteredMetaTagState @@ -518,6 +502,10 @@ where // we intended! false } + + fn elements(&self) -> Vec { + self.state.elements() + } } /// During server rendering, inserts the meta tags that have been generated by the other components @@ -538,14 +526,9 @@ struct MetaTagsView; impl Render for MetaTagsView { type State = (); - fn build(self, _extra_attrs: Option>) -> Self::State {} + fn build(self) -> Self::State {} - fn rebuild( - self, - _state: &mut Self::State, - _extra_attrs: Option>, - ) { - } + fn rebuild(self, _state: &mut Self::State) {} } impl AddAnyAttr for MetaTagsView { @@ -564,16 +547,12 @@ impl AddAnyAttr for MetaTagsView { impl RenderHtml for MetaTagsView { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -583,7 +562,7 @@ impl RenderHtml for MetaTagsView { _position: &mut Position, _escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { buf.push_str(""); } @@ -592,13 +571,8 @@ impl RenderHtml for MetaTagsView { self, _cursor: &Cursor, _position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { } - - fn into_owned(self) -> Self::Owned { - self - } } pub(crate) trait OrDefaultNonce { diff --git a/meta/src/title.rs b/meta/src/title.rs index 358f44f4fc..37ef49a5bc 100644 --- a/meta/src/title.rs +++ b/meta/src/title.rs @@ -11,8 +11,8 @@ use leptos::{ dom::document, hydration::Cursor, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }, }, text_prop::TextProp, @@ -189,7 +189,7 @@ struct TitleViewState { impl Render for TitleView { type State = TitleViewState; - fn build(mut self, _extra_attrs: Option>) -> Self::State { + fn build(mut self) -> Self::State { let el = self.el(); let meta = self.meta; if let Some(formatter) = self.formatter.take() { @@ -213,12 +213,8 @@ impl Render for TitleView { TitleViewState { effect } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - *state = self.build(extra_attrs); + fn rebuild(self, state: &mut Self::State) { + *state = self.build(); } } @@ -238,16 +234,12 @@ impl AddAnyAttr for TitleView { impl RenderHtml for TitleView { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -257,7 +249,7 @@ impl RenderHtml for TitleView { _position: &mut Position, _escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { // meta tags are rendered into the buffer stored into the context // the value has already been taken out, when we're on the server @@ -267,7 +259,6 @@ impl RenderHtml for TitleView { mut self, _cursor: &Cursor, _position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { let el = self.el(); let meta = self.meta; @@ -292,10 +283,6 @@ impl RenderHtml for TitleView { }); TitleViewState { effect } } - - fn into_owned(self) -> Self::Owned { - self - } } impl Mountable for TitleViewState { @@ -313,4 +300,8 @@ impl Mountable for TitleViewState { fn insert_before_this(&self, _child: &mut dyn Mountable) -> bool { false } + + fn elements(&self) -> Vec { + vec![] + } } diff --git a/router/src/flat_router.rs b/router/src/flat_router.rs index 80c7f8a375..1fac582e49 100644 --- a/router/src/flat_router.rs +++ b/router/src/flat_router.rs @@ -26,7 +26,7 @@ use tachys::{ ssr::StreamBuilder, view::{ add_attr::AddAnyAttr, - any_view::{AnyView, AnyViewState, ExtraAttrsMut, IntoAny}, + any_view::{AnyView, AnyViewState, IntoAny}, Mountable, Position, PositionState, Render, RenderHtml, }, }; @@ -69,6 +69,10 @@ impl Mountable for FlatRoutesViewState { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.view.insert_before_this(child) } + + fn elements(&self) -> Vec { + self.view.elements() + } } impl Render for FlatRoutesView @@ -80,7 +84,7 @@ where { type State = Rc>; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let FlatRoutesView { current_url, routes, @@ -118,7 +122,7 @@ where match new_match { None => Rc::new(RefCell::new(FlatRoutesViewState { - view: fallback().into_any().build(extra_attrs), + view: fallback().into_any().build(), id, owner, params, @@ -151,7 +155,7 @@ where match view.as_mut().now_or_never() { Some(view) => Rc::new(RefCell::new(FlatRoutesViewState { - view: view.into_any().build(extra_attrs), + view: view.into_any().build(), id, owner, params, @@ -162,7 +166,7 @@ where None => { let state = Rc::new(RefCell::new(FlatRoutesViewState { - view: ().into_any().build(extra_attrs.clone()), + view: ().into_any().build(), id, owner, params, @@ -175,10 +179,8 @@ where let state = Rc::clone(&state); async move { let view = view.await; - view.into_any().rebuild( - &mut state.borrow_mut().view, - extra_attrs, - ); + view.into_any() + .rebuild(&mut state.borrow_mut().view); } }); @@ -189,11 +191,7 @@ where } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let FlatRoutesView { current_url, location, @@ -271,9 +269,7 @@ where provide_context(url); provide_context(params_memo); provide_context(Matched(ArcMemo::from(new_matched))); - fallback() - .into_any() - .rebuild(&mut state.borrow_mut().view, extra_attrs) + fallback().into_any().rebuild(&mut state.borrow_mut().view) }); if let Some(location) = location { location.ready_to_complete(); @@ -323,10 +319,8 @@ where == spawned_path { let rebuild = move || { - view.into_any().rebuild( - &mut state.borrow_mut().view, - extra_attrs, - ); + view.into_any() + .rebuild(&mut state.borrow_mut().view); }; if transition { start_view_transition(0, is_back, rebuild); @@ -354,7 +348,7 @@ impl AddAnyAttr for FlatRoutesView where Loc: LocationProvider + Send, Defs: MatchNestedRoutes + Send + 'static, - FalFn: FnOnce() -> Fal + Send + 'static, + FalFn: FnOnce() -> Fal + Send, Fal: RenderHtml + 'static, { type Output = @@ -427,20 +421,16 @@ impl RenderHtml for FlatRoutesView where Loc: LocationProvider + Send, Defs: MatchNestedRoutes + Send + 'static, - FalFn: FnOnce() -> Fal + Send + 'static, + FalFn: FnOnce() -> Fal + Send, Fal: RenderHtml + 'static, { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = as RenderHtml>::MIN_LENGTH; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -450,7 +440,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { // if this is being run on the server for the first time, generating all possible routes if RouteList::is_generating() { @@ -513,7 +503,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -531,7 +521,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { // this can be mostly the same as the build() implementation, but with hydrate() // @@ -576,11 +565,9 @@ where match new_match { None => Rc::new(RefCell::new(FlatRoutesViewState { - view: fallback().into_any().hydrate::( - cursor, - position, - extra_attrs, - ), + view: fallback() + .into_any() + .hydrate::(cursor, position), id, owner, params, @@ -613,11 +600,9 @@ where match view.as_mut().now_or_never() { Some(view) => Rc::new(RefCell::new(FlatRoutesViewState { - view: view.into_any().hydrate::( - cursor, - position, - extra_attrs, - ), + view: view + .into_any() + .hydrate::(cursor, position), id, owner, params, @@ -633,8 +618,4 @@ where } } } - - fn into_owned(self) -> Self::Owned { - self - } } diff --git a/router/src/nested_router.rs b/router/src/nested_router.rs index 70844f4a76..2bc0679bb6 100644 --- a/router/src/nested_router.rs +++ b/router/src/nested_router.rs @@ -36,7 +36,7 @@ use tachys::{ ssr::StreamBuilder, view::{ add_attr::AddAnyAttr, - any_view::{AnyView, ExtraAttrsMut, IntoAny}, + any_view::{AnyView, IntoAny}, either::EitherOf3State, Mountable, Position, PositionState, Render, RenderHtml, }, @@ -76,7 +76,7 @@ where // TODO support fallback while loading type State = NestedRouteViewState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let NestedRoutesView { routes, outer_owner, @@ -95,7 +95,7 @@ where let new_match = routes.match_route(url.path()); // start with an empty view because we'll be loading routes async - let view = EitherOf3::A(()).build(extra_attrs.clone()); + let view = EitherOf3::A(()).build(); let view = Rc::new(RefCell::new(view)); let matched_view = match new_match { None => EitherOf3::B(fallback()), @@ -120,7 +120,7 @@ where for trigger in triggers { trigger.notify(); } - matched_view.rebuild(&mut *view.borrow_mut(), extra_attrs); + matched_view.rebuild(&mut *view.borrow_mut()); }) }); @@ -132,11 +132,7 @@ where } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let url_snapshot = self.current_url.get_untracked(); // if the path is the same, we do not need to re-route @@ -158,7 +154,7 @@ where match new_match { None => { EitherOf3::<(), Fal, AnyView>::B((self.fallback)()) - .rebuild(&mut state.view.borrow_mut(), extra_attrs); + .rebuild(&mut state.view.borrow_mut()); state.outlets.clear(); if let Some(loc) = self.location { loc.ready_to_complete(); @@ -217,10 +213,7 @@ where if matches!(state.view.borrow().state, EitherOf3::B(_)) { self.outer_owner.with(|| { EitherOf3::<(), Fal, AnyView>::C(Outlet().into_any()) - .rebuild( - &mut *state.view.borrow_mut(), - extra_attrs, - ); + .rebuild(&mut *state.view.borrow_mut()); }) } } @@ -235,8 +228,8 @@ where impl AddAnyAttr for NestedRoutesView where Loc: LocationProvider + Send, - Defs: MatchNestedRoutes + Send + 'static, - FalFn: FnOnce() -> Fal + Send + 'static, + Defs: MatchNestedRoutes + Send, + FalFn: FnOnce() -> Fal + Send, Fal: RenderHtml + 'static, { type Output = @@ -256,21 +249,17 @@ where impl RenderHtml for NestedRoutesView where Loc: LocationProvider + Send, - Defs: MatchNestedRoutes + Send + 'static, - FalFn: FnOnce() -> Fal + Send + 'static, + Defs: MatchNestedRoutes + Send, + FalFn: FnOnce() -> Fal + Send, Fal: RenderHtml + 'static, { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; // TODO - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -280,7 +269,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { // if this is being run on the server for the first time, generating all possible routes if RouteList::is_generating() { @@ -376,7 +365,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -427,7 +416,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let NestedRoutesView { routes, @@ -467,7 +455,7 @@ where outer_owner.with(|| EitherOf3::C(Outlet().into_any())) } } - .hydrate::(cursor, position, extra_attrs), + .hydrate::(cursor, position), )); NestedRouteViewState { @@ -477,10 +465,6 @@ where view, } } - - fn into_owned(self) -> Self::Owned { - self - } } type OutletViewFn = Box Suspend + Send>; @@ -897,6 +881,10 @@ where fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.view.insert_before_this(child) } + + fn elements(&self) -> Vec { + self.view.elements() + } } /// Displays the child route nested in a parent route, allowing you to control exactly where diff --git a/router/src/reactive.rs b/router/src/reactive.rs index 41949c76d6..9f7c97bf4c 100644 --- a/router/src/reactive.rs +++ b/router/src/reactive.rs @@ -89,7 +89,7 @@ where type State = ReactiveRouterInnerState; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let (prev_id, inner) = self.inner.fallback_or_view(); let owner = self.owner.with(Owner::new); ReactiveRouterInnerState { @@ -100,11 +100,7 @@ where } } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let (new_id, view) = self.inner.fallback_or_view(); if new_id != state.prev_id { state.owner = self.owner.with(Owner::new) @@ -133,9 +129,7 @@ where buf: &mut String, position: &mut Position, escape: bool, - mark_branches: bool, - _extra_attrs: Option>, - ) { + mark_branches: bool, extra_attrs: Vec) { // if this is being run on the server for the first time, generating all possible routes if RouteList::is_generating() { let mut routes = RouteList::new(); @@ -160,9 +154,7 @@ where buf: &mut StreamBuilder, position: &mut Position, escape: bool, - mark_branches: bool, - _extra_attrs: Option>, - ) where + mark_branches: bool, extra_attrs: Vec) where Self: Sized, { self.inner @@ -175,7 +167,6 @@ where self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { let (prev_id, inner) = self.inner.fallback_or_view(); let owner = self.owner.with(Owner::new); @@ -287,7 +278,7 @@ where { type State = ReactiveRouteState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let MatchedRoute { search_params, params, @@ -298,19 +289,14 @@ where params: ArcRwSignal::new(params), matched: ArcRwSignal::new(matched), }; - let view_state = - untrack(|| (self.view_fn)(&matched).build(extra_attrs.clone())); + let view_state = untrack(|| (self.view_fn)(&matched).build()); ReactiveRouteState { matched, view_state, } } - fn rebuild( - mut self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(mut self, state: &mut Self::State) { let ReactiveRouteState { matched, .. } = state; matched .search_params @@ -335,9 +321,7 @@ where buf: &mut String, position: &mut Position, escape: bool, - mark_branches: bool, - extra_attrs: Option>, - ) { + mark_branches: bool, extra_attrs: Vec) { let MatchedRoute { search_params, params, @@ -349,12 +333,7 @@ where matched: ArcRwSignal::new(matched), }; untrack(|| { - (self.view_fn)(&matched).to_html_with_buf( - buf, - position, - escape, - extra_attrs.clone(), - ) + (self.view_fn)(&matched).to_html_with_buf(buf, position, escape) }); } @@ -363,9 +342,7 @@ where buf: &mut StreamBuilder, position: &mut Position, escape: bool, - mark_branches: bool, - extra_attrs: Option>, - ) where + mark_branches: bool, extra_attrs: Vec) where Self: Sized, { let MatchedRoute { @@ -379,12 +356,8 @@ where matched: ArcRwSignal::new(matched), }; untrack(|| { - (self.view_fn)(&matched).to_html_async_with_buf::( - buf, - position, - escape, - extra_attrs.clone(), - ) + (self.view_fn)(&matched) + .to_html_async_with_buf::(buf, position, escape) }); } @@ -392,7 +365,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let MatchedRoute { search_params, @@ -405,11 +377,7 @@ where matched: ArcRwSignal::new(matched), }; let view_state = untrack(|| { - (self.view_fn)(&matched).hydrate::( - cursor, - position, - extra_attrs.clone(), - ) + (self.view_fn)(&matched).hydrate::(cursor, position) }); ReactiveRouteState { matched, diff --git a/tachys/src/html/attribute/any_attribute.rs b/tachys/src/html/attribute/any_attribute.rs index 33b58ff43f..d8a8c01cb9 100644 --- a/tachys/src/html/attribute/any_attribute.rs +++ b/tachys/src/html/attribute/any_attribute.rs @@ -1,4 +1,3 @@ -#![allow(unused_mut)] use super::{Attribute, NextAttribute}; use dyn_clone::DynClone; use std::{ @@ -36,10 +35,6 @@ pub struct AnyAttribute { type_id: TypeId, html_len: usize, value: Box, - - /// Temporary attribute set during the resolving cycle, to resolve only once. - pub(crate) resolved: bool, - #[cfg(feature = "ssr")] to_html: fn( Box, @@ -202,7 +197,6 @@ where type_id: TypeId::of::(), html_len: value.html_len(), value, - resolved: false, #[cfg(feature = "ssr")] to_html, build, @@ -309,13 +303,10 @@ impl Attribute for AnyAttribute { ); } - async fn resolve(mut self) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { #[cfg(feature = "ssr")] { - let res = (self.resolve)(self.value).await; - // Used by batch_resolve_items_with_extra_attrs() for optimisations. - self.resolved = true; - res + (self.resolve)(self.value).await } #[cfg(not(feature = "ssr"))] panic!( diff --git a/tachys/src/html/element/element_ext.rs b/tachys/src/html/element/element_ext.rs index 230af1d174..b259d7f9a1 100644 --- a/tachys/src/html/element/element_ext.rs +++ b/tachys/src/html/element/element_ext.rs @@ -24,7 +24,7 @@ use web_sys::Element; /// let view = element.on(ev::click, move |_| /* ... */); /// /// // `element` now contains the actual element -/// let element = element.build(None); +/// let element = element.build(); /// let remove = element.on(ev::blur, move |_| /* ... */); /// ``` pub trait ElementExt { diff --git a/tachys/src/html/element/mod.rs b/tachys/src/html/element/mod.rs index 23380ab8be..82dab71c75 100644 --- a/tachys/src/html/element/mod.rs +++ b/tachys/src/html/element/mod.rs @@ -3,17 +3,18 @@ use crate::hydration::set_currently_hydrating; use crate::{ html::attribute::Attribute, hydration::{failed_to_cast_element, Cursor}, + prelude::IntoAttribute, renderer::{CastFrom, Rndr}, ssr::StreamBuilder, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, IntoRender, Mountable, - Position, PositionState, Render, RenderHtml, ToTemplate, + add_attr::AddAnyAttr, IntoRender, Mountable, Position, PositionState, + Render, RenderHtml, ToTemplate, }, }; use const_str_slice_concat::{ const_concat, const_concat_with_prefix, str_from_buffer, }; -use futures::future::join3; +use futures::future::join; use next_tuple::NextTuple; use std::ops::Deref; @@ -22,8 +23,7 @@ mod element_ext; mod elements; mod inner_html; use super::attribute::{ - any_attribute::{AnyAttribute, AnyAttributeState}, - escape_attr, NextAttribute, + any_attribute::AnyAttribute, escape_attr, NextAttribute, }; pub use custom::*; pub use element_ext::*; @@ -186,42 +186,31 @@ where { type State = ElementState; - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let ElementState { attrs, children, .. } = state; self.attributes.rebuild(attrs); - if let (Some(extra_attrs), Some(extra_attr_states)) = - (extra_attrs, &mut state.extra_attrs) - { - extra_attrs.rebuild(extra_attr_states); - } if let Some(children) = children { - self.children.rebuild(children, None); + self.children.rebuild(children); } } - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let el = Rndr::create_element(self.tag.tag(), E::NAMESPACE); let attrs = self.attributes.build(&el); - let extra_attrs = extra_attrs.map(|attrs| attrs.build(&el)); let children = if E::SELF_CLOSING { None } else { - let mut children = self.children.build(None); + let mut children = self.children.build(); children.mount(&el, None); Some(children) }; ElementState { el, - children, attrs, - extra_attrs, + children, } } } @@ -233,7 +222,6 @@ where Ch: RenderHtml + Send, { type AsyncOutput = HtmlElement; - type Owned = HtmlElement; const MIN_LENGTH: usize = if E::SELF_CLOSING { 3 // < ... /> @@ -248,22 +236,14 @@ where + E::TAG.len() }; - fn dry_resolve(&mut self, mut extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { self.attributes.dry_resolve(); - extra_attrs.iter_mut().for_each(Attribute::dry_resolve); - self.children.dry_resolve(ExtraAttrsMut::default()); + self.children.dry_resolve(); } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - let (attributes, _, children) = join3( - self.attributes.resolve(), - ExtraAttrsMut::resolve(extra_attrs), - self.children.resolve(ExtraAttrsMut::default()), - ) - .await; + async fn resolve(self) -> Self::AsyncOutput { + let (attributes, children) = + join(self.attributes.resolve(), self.children.resolve()).await; HtmlElement { #[cfg(any(debug_assertions, leptos_debuginfo))] defined_at: self.defined_at, @@ -273,7 +253,7 @@ where } } - fn html_len(&self, extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { if E::SELF_CLOSING { 3 // < ... /> + E::TAG.len() @@ -282,10 +262,7 @@ where 2 // < ... > + E::TAG.len() + self.attributes.html_len() - + extra_attrs.map(|attrs| { - attrs.into_iter().map(Attribute::html_len).sum::() - }).unwrap_or(0) - + self.children.html_len(None) + + self.children.html_len() + 3 // + E::TAG.len() } @@ -297,13 +274,14 @@ where position: &mut Position, _escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attributes: Vec, ) { // opening tag buf.push('<'); buf.push_str(self.tag.tag()); - let inner_html = attributes_to_html(self.attributes, extra_attrs, buf); + let inner_html = + attributes_to_html((self.attributes, extra_attributes), buf); buf.push('>'); @@ -318,7 +296,7 @@ where position, E::ESCAPE_CHILDREN, mark_branches, - None, + vec![], ); } @@ -336,7 +314,7 @@ where position: &mut Position, _escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attributes: Vec, ) where Self: Sized, { @@ -346,7 +324,7 @@ where buf.push_str(self.tag.tag()); let inner_html = - attributes_to_html(self.attributes, extra_attrs, &mut buf); + attributes_to_html((self.attributes, extra_attributes), &mut buf); buf.push('>'); buffer.push_sync(&buf); @@ -362,7 +340,7 @@ where position, E::ESCAPE_CHILDREN, mark_branches, - None, + vec![], ); } @@ -380,7 +358,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { #[cfg(any(debug_assertions, leptos_debuginfo))] { @@ -405,15 +382,13 @@ where }); let attrs = self.attributes.hydrate::(&el); - let extra_attrs = extra_attrs - .map(|attrs| Attribute::hydrate::(attrs, &el)); // hydrate children let children = if !Ch::EXISTS || !E::ESCAPE_CHILDREN { None } else { position.set(Position::FirstChild); - Some(self.children.hydrate::(cursor, position, None)) + Some(self.children.hydrate::(cursor, position)) }; // go to next sibling @@ -427,32 +402,19 @@ where ElementState { el, - children, attrs, - extra_attrs, - } - } - - fn into_owned(self) -> Self::Owned { - HtmlElement { - #[cfg(any(debug_assertions, leptos_debuginfo))] - defined_at: self.defined_at, - tag: self.tag, - attributes: self.attributes.into_cloneable_owned(), - children: self.children.into_owned(), + children, } } } /// Renders an [`Attribute`] (which can be one or more HTML attributes) into an HTML buffer. -pub fn attributes_to_html( - attr: At, - extra_attrs: Option>, - buf: &mut String, -) -> String +pub fn attributes_to_html(attr: At, buf: &mut String) -> String where - At: Attribute, + At: IntoAttribute, { + let attr = attr.into_attr(); + // `class` and `style` are created first, and pushed later // this is because they can be filled by a mixture of values that include // either the whole value (`class="..."` or `style="..."`) and individual @@ -468,11 +430,6 @@ where // inject regular attributes, and fill class and style attr.to_html(buf, &mut class, &mut style, &mut inner_html); - if let Some(extra_attrs) = extra_attrs { - for attr in extra_attrs { - attr.to_html(buf, &mut class, &mut style, &mut inner_html); - } - } if !class.is_empty() { buf.push(' '); @@ -493,10 +450,8 @@ where /// The retained view state for an HTML element. pub struct ElementState { pub(crate) el: crate::renderer::types::Element, + pub(crate) attrs: At, pub(crate) children: Option, - - attrs: At, - extra_attrs: Option>, } impl Deref for ElementState { @@ -531,6 +486,10 @@ impl Mountable for ElementState { } false } + + fn elements(&self) -> Vec { + vec![self.el.clone()] + } } impl ToTemplate for HtmlElement @@ -639,7 +598,7 @@ mod tests { fn mock_dom_creates_element() { let el: HtmlElement = main().child(p().id("test").lang("en").child("Hello, world!")); - let el = el.build(None); + let el = el.build(); assert_eq!( el.el.to_debug_html(), "

Hello, world!

" @@ -653,7 +612,7 @@ mod tests { em().child("beautiful"), " world!", ))); - let el = el.build(None); + let el = el.build(); assert_eq!( el.el.to_debug_html(), "

Hello, beautiful world!

" diff --git a/tachys/src/html/islands.rs b/tachys/src/html/islands.rs index 68e264b530..e8590a9603 100644 --- a/tachys/src/html/islands.rs +++ b/tachys/src/html/islands.rs @@ -3,9 +3,7 @@ use crate::{ hydration::Cursor, prelude::{Render, RenderHtml}, ssr::StreamBuilder, - view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Position, PositionState, - }, + view::{add_attr::AddAnyAttr, Position, PositionState}, }; /// An island of interactivity in an otherwise-inert HTML document. @@ -61,16 +59,12 @@ where { type State = View::State; - fn build(self, extra_attrs: Option>) -> Self::State { - self.view.build(extra_attrs) + fn build(self) -> Self::State { + self.view.build() } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - self.view.rebuild(state, extra_attrs); + fn rebuild(self, state: &mut Self::State) { + self.view.rebuild(state); } } @@ -106,7 +100,6 @@ where View: RenderHtml, { type AsyncOutput = Island; - type Owned = Island; const MIN_LENGTH: usize = ISLAND_TAG.len() * 2 + "<>".len() @@ -114,14 +107,11 @@ where + "data-component".len() + View::MIN_LENGTH; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.view.dry_resolve(extra_attrs) + fn dry_resolve(&mut self) { + self.view.dry_resolve() } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { let Island { component, props_json, @@ -130,7 +120,7 @@ where Island { component, props_json, - view: view.resolve(extra_attrs).await, + view: view.resolve().await, } } @@ -140,7 +130,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { Self::open_tag(self.component, &self.props_json, buf); self.view.to_html_with_buf( @@ -159,7 +149,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -187,7 +177,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { if position.get() == Position::FirstChild { cursor.child(); @@ -196,16 +185,7 @@ where } position.set(Position::FirstChild); - self.view - .hydrate::(cursor, position, extra_attrs) - } - - fn into_owned(self) -> Self::Owned { - Island { - component: self.component, - props_json: self.props_json, - view: self.view.into_owned(), - } + self.view.hydrate::(cursor, position) } } @@ -255,14 +235,9 @@ where { type State = (); - fn build(self, _extra_attrs: Option>) -> Self::State {} + fn build(self) -> Self::State {} - fn rebuild( - self, - _state: &mut Self::State, - _extra_attrs: Option>, - ) { - } + fn rebuild(self, _state: &mut Self::State) {} } impl AddAnyAttr for IslandChildren @@ -292,24 +267,20 @@ where View: RenderHtml, { type AsyncOutput = IslandChildren; - type Owned = IslandChildren; const MIN_LENGTH: usize = ISLAND_CHILDREN_TAG.len() * 2 + "<>".len() + "".len() + View::MIN_LENGTH; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.view.dry_resolve(extra_attrs) + fn dry_resolve(&mut self) { + self.view.dry_resolve() } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { let IslandChildren { view, on_hydrate } = self; IslandChildren { - view: view.resolve(extra_attrs).await, + view: view.resolve().await, on_hydrate, } } @@ -320,7 +291,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { Self::open_tag(buf); self.view.to_html_with_buf( @@ -339,7 +310,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -367,7 +338,6 @@ where self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { // island children aren't hydrated // we update the walk to pass over them @@ -402,11 +372,4 @@ where ); } } - - fn into_owned(self) -> Self::Owned { - IslandChildren { - view: self.view.into_owned(), - on_hydrate: self.on_hydrate, - } - } } diff --git a/tachys/src/html/mod.rs b/tachys/src/html/mod.rs index b820d8f5b2..c4e8cba1fd 100644 --- a/tachys/src/html/mod.rs +++ b/tachys/src/html/mod.rs @@ -7,9 +7,7 @@ use crate::{ dom::{Element, Node}, CastFrom, Rndr, }, - view::{ - any_view::ExtraAttrsMut, Position, PositionState, Render, RenderHtml, - }, + view::{Position, PositionState, Render, RenderHtml}, }; use attribute::any_attribute::AnyAttribute; use std::borrow::Cow; @@ -46,30 +44,21 @@ pub fn doctype(value: &'static str) -> Doctype { impl Render for Doctype { type State = (); - fn build(self, _extra_attrs: Option>) -> Self::State {} + fn build(self) -> Self::State {} - fn rebuild( - self, - _state: &mut Self::State, - _extra_attrs: Option>, - ) { - } + fn rebuild(self, _state: &mut Self::State) {} } no_attrs!(Doctype); impl RenderHtml for Doctype { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = "".len(); - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -79,7 +68,7 @@ impl RenderHtml for Doctype { _position: &mut Position, _escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { buf.push_str(">, ) -> Self::State { } - - fn into_owned(self) -> Self::Owned { - self - } } /// An element that contains no interactivity, and whose contents can be known at compile time. @@ -126,21 +110,21 @@ impl Mountable for InertElementState { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.1.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![self.1.clone()] + } } impl Render for InertElement { type State = InertElementState; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let el = Rndr::create_element_from_html(&self.html); InertElementState(self.html, el) } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let InertElementState(prev, el) = state; if &self.html != prev { let mut new_el = Rndr::create_element_from_html(&self.html); @@ -171,17 +155,16 @@ impl AddAnyAttr for InertElement { impl RenderHtml for InertElement { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { self.html.len() } - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve(self, _extra_attrs: ExtraAttrsMut<'_>) -> Self { + async fn resolve(self) -> Self { self } @@ -191,7 +174,7 @@ impl RenderHtml for InertElement { position: &mut Position, _escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { buf.push_str(&self.html); *position = Position::NextChild; @@ -201,7 +184,6 @@ impl RenderHtml for InertElement { self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { let curr_position = position.get(); if curr_position == Position::FirstChild { @@ -214,8 +196,4 @@ impl RenderHtml for InertElement { position.set(Position::NextChild); InertElementState(self.html, el) } - - fn into_owned(self) -> Self::Owned { - self - } } diff --git a/tachys/src/oco.rs b/tachys/src/oco.rs index a5143e7c8a..1d43a4967e 100644 --- a/tachys/src/oco.rs +++ b/tachys/src/oco.rs @@ -8,10 +8,7 @@ use crate::{ no_attrs, prelude::{Mountable, Render, RenderHtml}, renderer::Rndr, - view::{ - any_view::ExtraAttrsMut, strings::StrState, Position, PositionState, - ToTemplate, - }, + view::{strings::StrState, Position, PositionState, ToTemplate}, }; use oco_ref::Oco; @@ -24,16 +21,12 @@ pub struct OcoStrState { impl Render for Oco<'static, str> { type State = OcoStrState; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let node = Rndr::create_text_node(&self); OcoStrState { node, str: self } } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let OcoStrState { node, str } = state; if &self != str { Rndr::set_text(node, &self); @@ -46,16 +39,12 @@ no_attrs!(Oco<'static, str>); impl RenderHtml for Oco<'static, str> { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } @@ -65,7 +54,7 @@ impl RenderHtml for Oco<'static, str> { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { <&str as RenderHtml>::to_html_with_buf( &self, @@ -81,21 +70,13 @@ impl RenderHtml for Oco<'static, str> { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let this: &str = self.as_ref(); let StrState { node, .. } = <&str as RenderHtml>::hydrate::( - this, - cursor, - position, - extra_attrs, + this, cursor, position, ); OcoStrState { node, str: self } } - - fn into_owned(self) -> ::Owned { - self - } } impl ToTemplate for Oco<'static, str> { @@ -130,6 +111,10 @@ impl Mountable for OcoStrState { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.node.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![] + } } impl AttributeValue for Oco<'static, str> { diff --git a/tachys/src/reactive_graph/class.rs b/tachys/src/reactive_graph/class.rs index f5e51edd56..272cf52243 100644 --- a/tachys/src/reactive_graph/class.rs +++ b/tachys/src/reactive_graph/class.rs @@ -352,7 +352,7 @@ where }) } - fn rebuild(self, state: &mut Self::State, _extra_attrs: Option>) { + fn rebuild(self, state: &mut Self::State) { let (names, mut f) = self; let prev_value = state.take_value(); @@ -433,7 +433,7 @@ where ::build(self.deref().to_owned(), el) } - fn rebuild(self, state: &mut Self::State, _extra_attrs: Option>) { + fn rebuild(self, state: &mut Self::State) { ::rebuild(self.deref().to_owned(), state) } @@ -447,7 +447,7 @@ where fn dry_resolve(&mut self) {} - async fn resolve(self, _extra_attrs: Option>) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } } @@ -489,7 +489,7 @@ where ) } - fn rebuild(self, state: &mut Self::State, _extra_attrs: Option>) { + fn rebuild(self, state: &mut Self::State) { <(&'static str, bool) as IntoClass>::rebuild( (self.0, *self.1.deref()), state, @@ -506,7 +506,7 @@ where fn dry_resolve(&mut self) {} - async fn resolve(self, _extra_attrs: Option>) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } } @@ -901,7 +901,7 @@ where state } - fn rebuild(self, state: &mut Self::State, _extra_attrs: Option>) { + fn rebuild(self, state: &mut Self::State) { reactive_graph::spawn_local_scoped({ let state = Rc::clone(state); async move { @@ -925,7 +925,7 @@ where fn dry_resolve(&mut self) {} - async fn resolve(self, _extra_attrs: Option>) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self.inner.await } } diff --git a/tachys/src/reactive_graph/mod.rs b/tachys/src/reactive_graph/mod.rs index 39513c44a9..7274f4d61d 100644 --- a/tachys/src/reactive_graph/mod.rs +++ b/tachys/src/reactive_graph/mod.rs @@ -4,8 +4,8 @@ use crate::{ renderer::Rndr, ssr::StreamBuilder, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, ToTemplate, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, ToTemplate, }, }; use reactive_graph::effect::RenderEffect; @@ -57,7 +57,7 @@ where type State = RenderEffectState; #[track_caller] - fn build(mut self, extra_attrs: Option>) -> Self::State { + fn build(mut self) -> Self::State { let hook = throw_error::get_error_hook(); RenderEffect::new(move |prev| { let _guard = hook @@ -65,22 +65,18 @@ where .map(|h| throw_error::set_error_hook(Arc::clone(h))); let value = self.invoke(); if let Some(mut state) = prev { - value.rebuild(&mut state, extra_attrs.clone()); + value.rebuild(&mut state); state } else { - value.build(extra_attrs.clone()) + value.build() } }) .into() } #[track_caller] - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - let new = self.build(extra_attrs); + fn rebuild(self, state: &mut Self::State) { + let new = self.build(); let mut old = std::mem::replace(state, new); old.insert_before_this(state); old.unmount(); @@ -123,6 +119,13 @@ where false } } + + fn elements(&self) -> Vec { + self.0 + .as_ref() + .map(|inner| inner.elements()) + .unwrap_or_default() + } } impl RenderHtml for F @@ -132,22 +135,18 @@ where V::State: 'static, { type AsyncOutput = V::AsyncOutput; - type Owned = F; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.invoke().dry_resolve(extra_attrs); + fn dry_resolve(&mut self) { + self.invoke().dry_resolve(); } - async fn resolve( - mut self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - self.invoke().resolve(extra_attrs).await + async fn resolve(mut self) -> Self::AsyncOutput { + self.invoke().resolve().await } - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { V::MIN_LENGTH } @@ -157,7 +156,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { let value = self.invoke(); value.to_html_with_buf( @@ -175,7 +174,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -193,7 +192,6 @@ where mut self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let cursor = cursor.clone(); let position = position.clone(); @@ -204,22 +202,14 @@ where .map(|h| throw_error::set_error_hook(Arc::clone(h))); let value = self.invoke(); if let Some(mut state) = prev { - value.rebuild(&mut state, extra_attrs.clone()); + value.rebuild(&mut state); state } else { - value.hydrate::( - &cursor, - &position, - extra_attrs.clone(), - ) + value.hydrate::(&cursor, &position) } }) .into() } - - fn into_owned(self) -> Self::Owned { - self - } } impl AddAnyAttr for F @@ -264,6 +254,11 @@ where self.with_value_mut(|value| value.insert_before_this(child)) .unwrap_or(false) } + + fn elements(&self) -> Vec { + self.with_value_mut(|inner| inner.elements()) + .unwrap_or_default() + } } impl Mountable for Result @@ -293,6 +288,12 @@ where false } } + + fn elements(&self) -> Vec { + self.as_ref() + .map(|inner| inner.elements()) + .unwrap_or_default() + } } // Dynamic attributes @@ -539,8 +540,8 @@ mod stable { hydration::Cursor, ssr::StreamBuilder, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }, }; #[allow(deprecated)] @@ -565,20 +566,13 @@ mod stable { type State = RenderEffectState; #[track_caller] - fn build( - self, - extra_attrs: Option>, - ) -> Self::State { - (move || self.get()).build(extra_attrs) + fn build(self) -> Self::State { + (move || self.get()).build() } #[track_caller] - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - let new = self.build(extra_attrs); + fn rebuild(self, state: &mut Self::State) { + let new = self.build(); let mut old = std::mem::replace(state, new); old.insert_before_this(state); old.unmount(); @@ -611,27 +605,20 @@ mod stable { V::State: 'static, { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { if $dry_resolve { _ = self.get(); } } - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn html_len( - &self, - _extra_attrs: Option>, - ) -> usize { + fn html_len(&self) -> usize { V::MIN_LENGTH } @@ -641,7 +628,7 @@ mod stable { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { let value = self.get(); value.to_html_with_buf( @@ -659,7 +646,7 @@ mod stable { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -677,17 +664,9 @@ mod stable { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - (move || self.get()).hydrate::( - cursor, - position, - extra_attrs, - ) - } - - fn into_owned(self) -> Self::Owned { - self + (move || self.get()) + .hydrate::(cursor, position) } } @@ -764,20 +743,13 @@ mod stable { type State = RenderEffectState; #[track_caller] - fn build( - self, - extra_attrs: Option>, - ) -> Self::State { - (move || self.get()).build(extra_attrs) + fn build(self) -> Self::State { + (move || self.get()).build() } #[track_caller] - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - let new = self.build(extra_attrs); + fn rebuild(self, state: &mut Self::State) { + let new = self.build(); let mut old = std::mem::replace(state, new); old.insert_before_this(state); old.unmount(); @@ -816,27 +788,20 @@ mod stable { V::State: 'static, { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { if $dry_resolve { _ = self.get(); } } - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn html_len( - &self, - _extra_attrs: Option>, - ) -> usize { + fn html_len(&self) -> usize { V::MIN_LENGTH } @@ -846,7 +811,7 @@ mod stable { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { let value = self.get(); value.to_html_with_buf( @@ -864,7 +829,7 @@ mod stable { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -882,17 +847,9 @@ mod stable { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - (move || self.get()).hydrate::( - cursor, - position, - extra_attrs, - ) - } - - fn into_owned(self) -> Self::Owned { - self + (move || self.get()) + .hydrate::(cursor, position) } } @@ -985,7 +942,7 @@ mod tests { let count = RwSignal::new(0); let app: HtmlElement<_, _, _, MockDom> = button((), move || count.get().to_string()); - let el = app.build(None); + let el = app.build(); assert_eq!(el.el.to_debug_html(), ""); rt.dispose(); } @@ -996,7 +953,7 @@ mod tests { let count = RwSignal::new(0); let app: HtmlElement<_, _, _, MockDom> = button((), move || count.get().to_string()); - let el = app.build(None); + let el = app.build(); assert_eq!(el.el.to_debug_html(), ""); count.set(1); assert_eq!(el.el.to_debug_html(), ""); @@ -1014,7 +971,7 @@ mod tests { ("Hello, my ", move || count.get().to_string(), " friends."), ), ); - let el = app.build(None); + let el = app.build(); assert_eq!( el.el.to_debug_html(), "
" diff --git a/tachys/src/reactive_graph/owned.rs b/tachys/src/reactive_graph/owned.rs index 4ec45b7048..14446407ea 100644 --- a/tachys/src/reactive_graph/owned.rs +++ b/tachys/src/reactive_graph/owned.rs @@ -3,10 +3,7 @@ use crate::{ hydration::Cursor, prelude::Mountable, ssr::StreamBuilder, - view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Position, PositionState, - Render, RenderHtml, - }, + view::{add_attr::AddAnyAttr, Position, PositionState, Render, RenderHtml}, }; use reactive_graph::{computed::ScopedFuture, owner::Owner}; @@ -56,18 +53,14 @@ where { type State = OwnedViewState; - fn build(self, extra_attrs: Option>) -> Self::State { - let state = self.owner.with(|| self.view.build(extra_attrs)); + fn build(self) -> Self::State { + let state = self.owner.with(|| self.view.build()); OwnedViewState::new(state, self.owner) } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let OwnedView { owner, view, .. } = self; - owner.with(|| view.rebuild(&mut state.state, extra_attrs)); + owner.with(|| view.rebuild(&mut state.state)); state.owner = owner; } } @@ -99,7 +92,6 @@ where { // TODO type AsyncOutput = OwnedView; - type Owned = OwnedView; const MIN_LENGTH: usize = T::MIN_LENGTH; @@ -109,7 +101,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { self.owner.with(|| { self.view.to_html_with_buf( @@ -128,7 +120,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -153,39 +145,23 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - let state = self.owner.with(|| { - self.view - .hydrate::(cursor, position, extra_attrs) - }); + let state = self + .owner + .with(|| self.view.hydrate::(cursor, position)); OwnedViewState::new(state, self.owner) } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { let OwnedView { owner, view } = self; let view = owner - .with(|| { - ScopedFuture::new( - async move { view.resolve(extra_attrs).await }, - ) - }) + .with(|| ScopedFuture::new(async move { view.resolve().await })) .await; OwnedView { owner, view } } - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.owner.with(|| self.view.dry_resolve(extra_attrs)); - } - - fn into_owned(self) -> Self::Owned { - OwnedView { - owner: self.owner, - view: self.view.into_owned(), - } + fn dry_resolve(&mut self) { + self.owner.with(|| self.view.dry_resolve()); } } @@ -208,4 +184,8 @@ where fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.state.insert_before_this(child) } + + fn elements(&self) -> Vec { + self.state.elements() + } } diff --git a/tachys/src/reactive_graph/suspense.rs b/tachys/src/reactive_graph/suspense.rs index b66fb780df..d6846e8a89 100644 --- a/tachys/src/reactive_graph/suspense.rs +++ b/tachys/src/reactive_graph/suspense.rs @@ -3,8 +3,8 @@ use crate::{ hydration::Cursor, ssr::StreamBuilder, view::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, iterators::OptionState, - Mountable, Position, PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, iterators::OptionState, Mountable, Position, + PositionState, Render, RenderHtml, }, }; use any_spawner::Executor; @@ -161,6 +161,10 @@ where fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.inner.borrow_mut().insert_before_this(child) } + + fn elements(&self) -> Vec { + self.inner.borrow().elements() + } } impl Render for Suspend @@ -169,7 +173,7 @@ where { type State = SuspendState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let Self { subscriber, inner } = self; // create a Future that will be aborted on on_cleanup @@ -184,7 +188,7 @@ where // otherwise, start with the fallback let initial = fut.as_mut().now_or_never().and_then(Result::ok); let initially_pending = initial.is_none(); - let inner = Rc::new(RefCell::new(initial.build(extra_attrs.clone()))); + let inner = Rc::new(RefCell::new(initial.build())); // get a unique ID if there's a SuspenseContext let id = use_context::().map(|sc| sc.task_id()); @@ -205,8 +209,7 @@ where drop(id); if let Ok(value) = value { - Some(value) - .rebuild(&mut *state.borrow_mut(), extra_attrs); + Some(value).rebuild(&mut *state.borrow_mut()); } subscriber.forward(); @@ -219,11 +222,7 @@ where SuspendState { inner } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let Self { subscriber, inner } = self; // create a Future that will be aborted on on_cleanup @@ -253,7 +252,7 @@ where // has no parent Executor::tick().await; if let Ok(value) = value { - Some(value).rebuild(&mut *state.borrow_mut(), extra_attrs); + Some(value).rebuild(&mut *state.borrow_mut()); } subscriber.forward(); @@ -289,7 +288,6 @@ where T: RenderHtml + Sized + 'static, { type AsyncOutput = Option; - type Owned = Self; const MIN_LENGTH: usize = T::MIN_LENGTH; @@ -299,7 +297,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { // TODO wrap this with a Suspense as needed // currently this is just used for Routes, which creates a Suspend but never actually needs @@ -321,7 +319,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -399,7 +397,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let Self { subscriber, inner } = self; @@ -415,11 +412,9 @@ where // otherwise, start with the fallback let initial = fut.as_mut().now_or_never().and_then(Result::ok); let initially_pending = initial.is_none(); - let inner = Rc::new(RefCell::new(initial.hydrate::( - cursor, - position, - extra_attrs.clone(), - ))); + let inner = Rc::new(RefCell::new( + initial.hydrate::(cursor, position), + )); // get a unique ID if there's a SuspenseContext let id = use_context::().map(|sc| sc.task_id()); @@ -440,8 +435,7 @@ where drop(id); if let Ok(value) = value { - Some(value) - .rebuild(&mut *state.borrow_mut(), extra_attrs); + Some(value).rebuild(&mut *state.borrow_mut()); } subscriber.forward(); @@ -454,14 +448,11 @@ where SuspendState { inner } } - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { Some(self.inner.await) } - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { // this is a little crazy, but if a Suspend is immediately available, we end up // with a situation where polling it multiple times (here in dry_resolve and then in // resolve) causes a runtime panic @@ -481,8 +472,4 @@ where as Pin + Send>>; } } - - fn into_owned(self) -> Self::Owned { - self - } } diff --git a/tachys/src/renderer/dom.rs b/tachys/src/renderer/dom.rs index bcac94fe52..0a56baf1bd 100644 --- a/tachys/src/renderer/dom.rs +++ b/tachys/src/renderer/dom.rs @@ -466,6 +466,10 @@ impl Mountable for Node { } false } + + fn elements(&self) -> Vec { + vec![] + } } impl Mountable for Text { @@ -486,6 +490,10 @@ impl Mountable for Text { } false } + + fn elements(&self) -> Vec { + vec![] + } } impl Mountable for Comment { @@ -506,6 +514,10 @@ impl Mountable for Comment { } false } + + fn elements(&self) -> Vec { + vec![] + } } impl Mountable for Element { @@ -526,6 +538,10 @@ impl Mountable for Element { } false } + + fn elements(&self) -> Vec { + vec![self.clone()] + } } impl CastFrom for Text { diff --git a/tachys/src/ssr/mod.rs b/tachys/src/ssr/mod.rs index 8476ac6bd7..e68cb11a14 100644 --- a/tachys/src/ssr/mod.rs +++ b/tachys/src/ssr/mod.rs @@ -106,7 +106,7 @@ impl StreamBuilder { fallback: View, position: &mut Position, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where View: RenderHtml, { @@ -165,7 +165,7 @@ impl StreamBuilder { view: impl Future> + Send + 'static, position: &mut Position, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where View: RenderHtml, { @@ -185,7 +185,7 @@ impl StreamBuilder { position: &mut Position, mark_branches: bool, nonce: Option>, - extra_attrs: Option>, + extra_attrs: Vec, ) where View: RenderHtml, { diff --git a/tachys/src/view/any_view.rs b/tachys/src/view/any_view.rs index 4af052a89a..8f5ab9775a 100644 --- a/tachys/src/view/any_view.rs +++ b/tachys/src/view/any_view.rs @@ -1,5 +1,3 @@ -#![allow(unused_mut)] -#![allow(clippy::type_complexity)] #[cfg(feature = "ssr")] use super::MarkBranch; use super::{ @@ -8,12 +6,13 @@ use super::{ }; use crate::{ html::attribute::{ - any_attribute::{AnyAttribute, IntoAnyAttribute}, + any_attribute::{AnyAttribute, AnyAttributeState, IntoAnyAttribute}, Attribute, }, hydration::Cursor, ssr::StreamBuilder, }; +use futures::future::{join, join_all}; use std::{ any::{Any, TypeId}, fmt::Debug, @@ -34,15 +33,14 @@ use std::{future::Future, pin::Pin}; pub struct AnyView { type_id: TypeId, value: Box, - extra_attrs: Vec, - build: fn(Box, Option>) -> AnyViewState, - rebuild: fn(Box, &mut AnyViewState, Option>), + build: fn(Box) -> AnyViewState, + rebuild: fn(TypeId, Box, &mut AnyViewState), // The fields below are cfg-gated so they will not be included in WASM bundles if not needed. // Ordinarily, the compiler can simply omit this dead code because the methods are not called. // With this type-erased wrapper, however, the compiler is not *always* able to correctly // eliminate that code. #[cfg(feature = "ssr")] - html_len: fn(&Box, Option>) -> usize, + html_len: usize, #[cfg(feature = "ssr")] to_html: fn( Box, @@ -50,7 +48,7 @@ pub struct AnyView { &mut Position, bool, bool, - Option>, + Vec, ), #[cfg(feature = "ssr")] to_html_async: fn( @@ -59,7 +57,7 @@ pub struct AnyView { &mut Position, bool, bool, - Option>, + Vec, ), #[cfg(feature = "ssr")] to_html_async_ooo: fn( @@ -68,26 +66,18 @@ pub struct AnyView { &mut Position, bool, bool, - Option>, + Vec, ), #[cfg(feature = "ssr")] #[allow(clippy::type_complexity)] - resolve: for<'a> fn( - Box, - ExtraAttrsMut<'a>, - ) - -> Pin + Send + 'a>>, + resolve: fn(Box) -> Pin + Send>>, #[cfg(feature = "ssr")] - dry_resolve: fn(&mut Box, ExtraAttrsMut<'_>), + dry_resolve: fn(&mut Box), #[cfg(feature = "hydrate")] #[cfg(feature = "hydrate")] #[allow(clippy::type_complexity)] - hydrate_from_server: fn( - Box, - &Cursor, - &PositionState, - Option>, - ) -> AnyViewState, + hydrate_from_server: + fn(Box, &Cursor, &PositionState) -> AnyViewState, } /// Retained view state for [`AnyView`]. @@ -101,6 +91,7 @@ pub struct AnyViewState { marker: Option<&crate::renderer::types::Node>, ), insert_before_this: fn(&dyn Any, child: &mut dyn Mountable) -> bool, + elements: fn(&dyn Any) -> Vec, } impl Debug for AnyViewState { @@ -157,51 +148,49 @@ where state.insert_before_this(child) } -#[cfg(feature = "ssr")] -fn resolve<'a, T>( - value: Box, - extra_attrs: ExtraAttrsMut<'a>, -) -> Pin + Send + 'a>> +fn elements(state: &dyn Any) -> Vec where - T: RenderHtml + 'static, + T: Render, + T::State: 'static, { - let value = value - .downcast::() - .expect("AnyView::resolve could not be downcast"); - Box::pin(async move { value.resolve(extra_attrs).await.into_any() }) + let state = state + .downcast_ref::() + .expect("AnyViewState::insert_before_this couldn't downcast state"); + state.elements() } impl IntoAny for T where - T: RenderHtml, - T::Owned: Send, + T: Send, + T: RenderHtml + 'static, + T::State: 'static, { fn into_any(self) -> AnyView { - let value = Box::new(self.into_owned()) as Box; + #[cfg(feature = "ssr")] + let html_len = self.html_len(); + + let value = Box::new(self) as Box; match value.downcast::() { // if it's already an AnyView, we don't need to double-wrap it Ok(any_view) => *any_view, Err(value) => { #[cfg(feature = "ssr")] - let html_len = - |value: &Box, extra_attrs: Option>| { - let value = value - .downcast_ref::() - .expect("AnyView::html_len could not be downcast"); - value.html_len(extra_attrs) - }; + let dry_resolve = |value: &mut Box| { + let value = value + .downcast_mut::() + .expect("AnyView::resolve could not be downcast"); + value.dry_resolve(); + }; #[cfg(feature = "ssr")] - let dry_resolve = - |value: &mut Box, - extra_attrs: ExtraAttrsMut<'_>| { - let value = value - .downcast_mut::() - .expect("AnyView::resolve could not be downcast"); - value.dry_resolve(extra_attrs); - }; - + let resolve = |value: Box| { + let value = value + .downcast::() + .expect("AnyView::resolve could not be downcast"); + Box::pin(async move { value.resolve().await.into_any() }) + as Pin + Send>> + }; #[cfg(feature = "ssr")] let to_html = |value: Box, @@ -209,12 +198,12 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>| { + extra_attrs: Vec| { let type_id = mark_branches - .then(|| format!("{:?}", TypeId::of::())) + .then(|| format!("{:?}", TypeId::of::())) .unwrap_or_default(); let value = value - .downcast::() + .downcast::() .expect("AnyView::to_html could not be downcast"); if mark_branches { buf.open_branch(&type_id); @@ -237,12 +226,12 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>| { + extra_attrs: Vec| { let type_id = mark_branches - .then(|| format!("{:?}", TypeId::of::())) + .then(|| format!("{:?}", TypeId::of::())) .unwrap_or_default(); let value = value - .downcast::() + .downcast::() .expect("AnyView::to_html could not be downcast"); if mark_branches { buf.open_branch(&type_id); @@ -259,91 +248,92 @@ where } }; #[cfg(feature = "ssr")] - let to_html_async_ooo = |value: Box, - buf: &mut StreamBuilder, - position: &mut Position, - escape: bool, - mark_branches: bool, - extra_attrs: Option< - Vec, - >| { - let value = value - .downcast::() - .expect("AnyView::to_html could not be downcast"); - value.to_html_async_with_buf::( - buf, - position, - escape, - mark_branches, - extra_attrs, - ); - }; - let build = |value: Box, extra_attrs: Option>| { + let to_html_async_ooo = + |value: Box, + buf: &mut StreamBuilder, + position: &mut Position, + escape: bool, + mark_branches: bool, + extra_attrs: Vec| { + let value = value + .downcast::() + .expect("AnyView::to_html could not be downcast"); + value.to_html_async_with_buf::( + buf, + position, + escape, + mark_branches, + extra_attrs, + ); + }; + let build = |value: Box| { let value = value - .downcast::() + .downcast::() .expect("AnyView::build couldn't downcast"); - let state = Box::new(value.build(extra_attrs)); + let state = Box::new(value.build()); AnyViewState { - type_id: TypeId::of::(), + type_id: TypeId::of::(), state, - - mount: mount_any::, - unmount: unmount_any::, - insert_before_this: insert_before_this::, + mount: mount_any::, + unmount: unmount_any::, + insert_before_this: insert_before_this::, + elements: elements::, } }; #[cfg(feature = "hydrate")] - let hydrate_from_server = |value: Box, - cursor: &Cursor, - position: &PositionState, - extra_attrs: Option< - Vec, - >| { - let value = value.downcast::().expect( - "AnyView::hydrate_from_server couldn't downcast", - ); - let state = Box::new(value.hydrate::( - cursor, - position, - extra_attrs, - )); - - AnyViewState { - type_id: TypeId::of::(), - state, - - mount: mount_any::, - unmount: unmount_any::, - insert_before_this: insert_before_this::, - } - }; + let hydrate_from_server = + |value: Box, + cursor: &Cursor, + position: &PositionState| { + let value = value.downcast::().expect( + "AnyView::hydrate_from_server couldn't downcast", + ); + let state = + Box::new(value.hydrate::(cursor, position)); + + AnyViewState { + type_id: TypeId::of::(), + state, + mount: mount_any::, + unmount: unmount_any::, + insert_before_this: insert_before_this::, + elements: elements::, + } + }; let rebuild = - |value: Box, - state: &mut AnyViewState, extra_attrs: Option>| { + |new_type_id: TypeId, + value: Box, + state: &mut AnyViewState| { let value = value - .downcast::() + .downcast::() .expect("AnyView::rebuild couldn't downcast value"); - let state = state.state.downcast_mut().expect( - "AnyView::rebuild couldn't downcast state", - ); - value.rebuild(state, extra_attrs); + if new_type_id == state.type_id { + let state = state.state.downcast_mut().expect( + "AnyView::rebuild couldn't downcast state", + ); + value.rebuild(state); + } else { + let mut new = value.into_any().build(); + state.insert_before_this(&mut new); + state.unmount(); + *state = new; + } }; AnyView { - type_id: TypeId::of::(), + type_id: TypeId::of::(), value, - extra_attrs: vec![], build, rebuild, #[cfg(feature = "ssr")] - html_len, - #[cfg(feature = "ssr")] - resolve: resolve::, + resolve, #[cfg(feature = "ssr")] dry_resolve, #[cfg(feature = "ssr")] + html_len, + #[cfg(feature = "ssr")] to_html, #[cfg(feature = "ssr")] to_html_async, @@ -357,206 +347,61 @@ where } } -/// Ignore, this is a hack for pre use<..> syntax. -/// https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md#the-captures-trick -pub trait __Captures {} -impl __Captures for U {} - -/// A mutable view into the extra attributes stored in an [`AnyView`]. -#[derive(Default)] -pub struct ExtraAttrsMut<'a>(Option>>); -impl<'a> ExtraAttrsMut<'a> { - /// Create a new mutable view from owned attributes. - pub fn from_owned(extra_attrs: &'a mut Option>) -> Self { - match extra_attrs { - Some(extra_attrs) => { - if extra_attrs.is_empty() { - Self(None) - } else { - Self(Some(vec![extra_attrs])) - } - } - None => Self(None), - } - } - - #[cfg(feature = "ssr")] - fn add_layer<'b>( - mut self, - extra_attrs: &'b mut Vec, - ) -> ExtraAttrsMut<'b> - where - 'a: 'b, - { - match (self.0, extra_attrs.is_empty()) { - (Some(mut extra), false) => { - extra.push(extra_attrs); - ExtraAttrsMut(Some(extra)) - } - (Some(mut extra), true) => { - self.0 = Some(extra); - self - } - (None, false) => ExtraAttrsMut(Some(vec![extra_attrs])), - (None, true) => ExtraAttrsMut(None), - } - } - - /// Check if there are any extra attributes. - pub fn is_some(&self) -> bool { - match &self.0 { - Some(extra) => extra.is_empty(), - None => true, - } - } - - /// "clone" the mutable view, to allow reuse in e.g. a for loop. - /// The same as .as_deref_mut() on Option<&mut T>. - pub fn as_deref_mut(&mut self) -> ExtraAttrsMut<'_> { - ExtraAttrsMut( - self.0 - .as_mut() - .map(|inner| inner.iter_mut().map(|v| &mut **v).collect()), - ) - } - - /// Iterate over the extra attributes. - pub fn iter_mut( - &mut self, - ) -> impl Iterator + __Captures<&'a ()> + '_ { - match &mut self.0 { - Some(inner) => itertools::Either::Left( - inner.iter_mut().flat_map(|v| v.iter_mut()), - ), - None => itertools::Either::Right(std::iter::empty()), - } - } - - /// Call [`RenderHtml::resolve`] on any extra attributes in parallel. - pub async fn resolve(self) { - if let Some(extra_attr_groups) = self.0 { - futures::future::join_all(extra_attr_groups.into_iter().map( - |extra_attrs| async move { - *extra_attrs = - Attribute::resolve(std::mem::take(extra_attrs)).await; - }, - )) - .await; - } - } -} - -fn combine_owned_extra_attrs( - parent_extra_attrs: Option>, - extra_attrs: Vec, -) -> Option> { - let extra_attrs = if let Some(mut parent_extra_attrs) = parent_extra_attrs { - for attr in extra_attrs { - parent_extra_attrs.push(attr); - } - parent_extra_attrs - } else { - extra_attrs - }; - if extra_attrs.is_empty() { - None - } else { - Some(extra_attrs) - } -} - impl Render for AnyView { type State = AnyViewState; - fn build(self, extra_attrs: Option>) -> Self::State { - (self.build)( - self.value, - combine_owned_extra_attrs(extra_attrs, self.extra_attrs), - ) + fn build(self) -> Self::State { + (self.build)(self.value) } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - if self.type_id == state.type_id { - (self.rebuild)( - self.value, - state, - combine_owned_extra_attrs(extra_attrs, self.extra_attrs), - ) - } else { - let mut new = (self.build)( - self.value, - combine_owned_extra_attrs(extra_attrs, self.extra_attrs), - ); - state.insert_before_this(&mut new); - state.unmount(); - *state = new; - } + fn rebuild(self, state: &mut Self::State) { + (self.rebuild)(self.type_id, self.value, state) } } impl AddAnyAttr for AnyView { - type Output = Self; + type Output = AnyViewWithAttrs; #[allow(unused_variables)] fn add_any_attr( - mut self, + self, attr: NewAttr, ) -> Self::Output where Self::Output: RenderHtml, { - self.extra_attrs - .push(attr.into_cloneable_owned().into_any_attr()); - self + AnyViewWithAttrs { + view: self, + attrs: vec![attr.into_cloneable_owned().into_any_attr()], + } } } impl RenderHtml for AnyView { type AsyncOutput = Self; - type Owned = Self; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { #[cfg(feature = "ssr")] { - (self.dry_resolve)( - &mut self.value, - extra_attrs.add_layer(&mut self.extra_attrs), - ); + (self.dry_resolve)(&mut self.value) } #[cfg(not(feature = "ssr"))] - { - _ = extra_attrs; - panic!( - "You are rendering AnyView to HTML without the `ssr` feature \ - enabled." - ); - } + panic!( + "You are rendering AnyView to HTML without the `ssr` feature \ + enabled." + ); } - async fn resolve( - mut self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { #[cfg(feature = "ssr")] { - (self.resolve)( - self.value, - extra_attrs.add_layer(&mut self.extra_attrs), - ) - .await + (self.resolve)(self.value).await } #[cfg(not(feature = "ssr"))] - { - _ = extra_attrs; - panic!( - "You are rendering AnyView to HTML without the `ssr` feature \ - enabled." - ); - } + panic!( + "You are rendering AnyView to HTML without the `ssr` feature \ + enabled." + ); } const MIN_LENGTH: usize = 0; @@ -567,19 +412,17 @@ impl RenderHtml for AnyView { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { #[cfg(feature = "ssr")] - { - (self.to_html)( - self.value, - buf, - position, - escape, - mark_branches, - combine_owned_extra_attrs(extra_attrs, self.extra_attrs), - ); - } + (self.to_html)( + self.value, + buf, + position, + escape, + mark_branches, + extra_attrs, + ); #[cfg(not(feature = "ssr"))] { _ = mark_branches; @@ -600,31 +443,29 @@ impl RenderHtml for AnyView { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { #[cfg(feature = "ssr")] - { - if OUT_OF_ORDER { - (self.to_html_async_ooo)( - self.value, - buf, - position, - escape, - mark_branches, - combine_owned_extra_attrs(extra_attrs, self.extra_attrs), - ); - } else { - (self.to_html_async)( - self.value, - buf, - position, - escape, - mark_branches, - combine_owned_extra_attrs(extra_attrs, self.extra_attrs), - ); - } + if OUT_OF_ORDER { + (self.to_html_async_ooo)( + self.value, + buf, + position, + escape, + mark_branches, + extra_attrs, + ); + } else { + (self.to_html_async)( + self.value, + buf, + position, + escape, + mark_branches, + extra_attrs, + ); } #[cfg(not(feature = "ssr"))] { @@ -644,29 +485,20 @@ impl RenderHtml for AnyView { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { #[cfg(feature = "hydrate")] - { - if FROM_SERVER { - (self.hydrate_from_server)( - self.value, - cursor, - position, - combine_owned_extra_attrs(extra_attrs, self.extra_attrs), - ) - } else { - panic!( - "hydrating AnyView from inside a ViewTemplate is not \ - supported." - ); - } + if FROM_SERVER { + (self.hydrate_from_server)(self.value, cursor, position) + } else { + panic!( + "hydrating AnyView from inside a ViewTemplate is not \ + supported." + ); } #[cfg(not(feature = "hydrate"))] { _ = cursor; _ = position; - _ = extra_attrs; panic!( "You are trying to hydrate AnyView without the `hydrate` \ feature enabled." @@ -674,34 +506,16 @@ impl RenderHtml for AnyView { } } - fn html_len(&self, extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { #[cfg(feature = "ssr")] { - (self.html_len)( - &self.value, - match (extra_attrs, self.extra_attrs.is_empty()) { - (Some(mut extra_attrs), false) => { - for attr in &self.extra_attrs { - extra_attrs.push(attr); - } - Some(extra_attrs) - } - (Some(extra_attrs), true) => Some(extra_attrs), - (None, false) => Some(self.extra_attrs.iter().collect()), - (None, true) => None, - }, - ) + self.html_len } #[cfg(not(feature = "ssr"))] { - _ = extra_attrs; 0 } } - - fn into_owned(self) -> Self::Owned { - self - } } impl Mountable for AnyViewState { @@ -720,7 +534,163 @@ impl Mountable for AnyViewState { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { (self.insert_before_this)(&*self.state, child) } + + fn elements(&self) -> Vec { + (self.elements)(&*self.state) + } +} + +/// wip +pub struct AnyViewWithAttrs { + view: AnyView, + attrs: Vec, +} + +impl Render for AnyViewWithAttrs { + type State = AnyViewWithAttrsState; + + fn build(self) -> Self::State { + let view = self.view.build(); + let elements = view.elements(); + let mut attrs = Vec::with_capacity(elements.len() * self.attrs.len()); + for attr in self.attrs { + for el in &elements { + attrs.push(attr.clone().build(el)) + } + } + AnyViewWithAttrsState { view, attrs } + } + + fn rebuild(self, state: &mut Self::State) { + self.view.rebuild(&mut state.view); + self.attrs.rebuild(&mut state.attrs); + } +} + +impl RenderHtml for AnyViewWithAttrs { + type AsyncOutput = Self; + const MIN_LENGTH: usize = 0; + + fn dry_resolve(&mut self) { + self.view.dry_resolve(); + for attr in &mut self.attrs { + attr.dry_resolve(); + } + } + + async fn resolve(self) -> Self::AsyncOutput { + let resolve_view = self.view.resolve(); + let resolve_attrs = + join_all(self.attrs.into_iter().map(|attr| attr.resolve())); + let (view, attrs) = join(resolve_view, resolve_attrs).await; + Self { view, attrs } + } + + fn to_html_with_buf( + self, + buf: &mut String, + position: &mut Position, + escape: bool, + mark_branches: bool, + mut extra_attrs: Vec, + ) { + // `extra_attrs` will be empty here in most cases, but it will have + // attributes in it already if this is, itself, receiving additional attrs + extra_attrs.extend(self.attrs); + self.view.to_html_with_buf( + buf, + position, + escape, + mark_branches, + extra_attrs, + ); + } + + fn to_html_async_with_buf( + self, + buf: &mut StreamBuilder, + position: &mut Position, + escape: bool, + mark_branches: bool, + mut extra_attrs: Vec, + ) where + Self: Sized, + { + extra_attrs.extend(self.attrs); + self.view.to_html_async_with_buf::( + buf, + position, + escape, + mark_branches, + extra_attrs, + ); + } + + fn hydrate( + self, + cursor: &Cursor, + position: &PositionState, + ) -> Self::State { + let view = self.view.hydrate::(cursor, position); + let elements = view.elements(); + let mut attrs = Vec::with_capacity(elements.len() * self.attrs.len()); + for attr in self.attrs { + for el in &elements { + attrs.push(attr.clone().hydrate::(el)); + } + } + AnyViewWithAttrsState { view, attrs } + } + + fn html_len(&self) -> usize { + self.view.html_len() + + self.attrs.iter().map(|attr| attr.html_len()).sum::() + } } + +impl AddAnyAttr for AnyViewWithAttrs { + type Output = AnyViewWithAttrs; + + fn add_any_attr( + mut self, + attr: NewAttr, + ) -> Self::Output + where + Self::Output: RenderHtml, + { + self.attrs.push(attr.into_cloneable_owned().into_any_attr()); + self + } +} + +/// wip +pub struct AnyViewWithAttrsState { + view: AnyViewState, + attrs: Vec, +} + +impl Mountable for AnyViewWithAttrsState { + fn unmount(&mut self) { + self.view.unmount(); + } + + fn mount( + &mut self, + parent: &crate::renderer::types::Element, + marker: Option<&crate::renderer::types::Node>, + ) { + self.view.mount(parent, marker) + } + + fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { + self.view.insert_before_this(child) + } + + fn elements(&self) -> Vec { + self.view.elements() + } +} + /* #[cfg(test)] mod tests { diff --git a/tachys/src/view/either.rs b/tachys/src/view/either.rs index e4a91ece62..19b4d02178 100644 --- a/tachys/src/view/either.rs +++ b/tachys/src/view/either.rs @@ -1,6 +1,6 @@ use super::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, MarkBranch, Mountable, - Position, PositionState, Render, RenderHtml, + add_attr::AddAnyAttr, MarkBranch, Mountable, Position, PositionState, + Render, RenderHtml, }; use crate::{ html::attribute::{any_attribute::AnyAttribute, Attribute}, @@ -17,33 +17,29 @@ where { type State = Either; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { match self { - Either::Left(left) => Either::Left(left.build(extra_attrs)), - Either::Right(right) => Either::Right(right.build(extra_attrs)), + Either::Left(left) => Either::Left(left.build()), + Either::Right(right) => Either::Right(right.build()), } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { match (self, &mut *state) { (Either::Left(new), Either::Left(old)) => { - new.rebuild(old, extra_attrs); + new.rebuild(old); } (Either::Right(new), Either::Right(old)) => { - new.rebuild(old, extra_attrs); + new.rebuild(old); } (Either::Right(new), Either::Left(old)) => { - let mut new_state = new.build(extra_attrs); + let mut new_state = new.build(); old.insert_before_this(&mut new_state); old.unmount(); *state = Either::Right(new_state); } (Either::Left(new), Either::Right(old)) => { - let mut new_state = new.build(extra_attrs); + let mut new_state = new.build(); old.insert_before_this(&mut new_state); old.unmount(); *state = Either::Left(new_state); @@ -81,6 +77,13 @@ where Either::Right(right) => right.insert_before_this(child), } } + + fn elements(&self) -> Vec { + match &self { + Either::Left(left) => left.elements(), + Either::Right(right) => right.elements(), + } + } } impl AddAnyAttr for Either @@ -126,34 +129,28 @@ where B: RenderHtml, { type AsyncOutput = Either; - type Owned = Either; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { match self { - Either::Left(left) => left.dry_resolve(extra_attrs), - Either::Right(right) => right.dry_resolve(extra_attrs), + Either::Left(left) => left.dry_resolve(), + Either::Right(right) => right.dry_resolve(), } } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { match self { - Either::Left(left) => Either::Left(left.resolve(extra_attrs).await), - Either::Right(right) => { - Either::Right(right.resolve(extra_attrs).await) - } + Either::Left(left) => Either::Left(left.resolve().await), + Either::Right(right) => Either::Right(right.resolve().await), } } const MIN_LENGTH: usize = max_usize(&[A::MIN_LENGTH, B::MIN_LENGTH]); #[inline(always)] - fn html_len(&self, extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { match self { - Either::Left(i) => i.html_len(extra_attrs), - Either::Right(i) => i.html_len(extra_attrs), + Either::Left(i) => i.html_len(), + Either::Right(i) => i.html_len(), } } @@ -163,7 +160,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { match self { Either::Left(left) => { @@ -205,7 +202,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -247,24 +244,14 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { match self { - Either::Left(left) => Either::Left(left.hydrate::( - cursor, - position, - extra_attrs, - )), - Either::Right(right) => Either::Right( - right.hydrate::(cursor, position, extra_attrs), - ), - } - } - - fn into_owned(self) -> Self::Owned { - match self { - Either::Left(left) => Either::Left(left.into_owned()), - Either::Right(right) => Either::Right(right.into_owned()), + Either::Left(left) => { + Either::Left(left.hydrate::(cursor, position)) + } + Either::Right(right) => { + Either::Right(right.hydrate::(cursor, position)) + } } } } @@ -293,29 +280,25 @@ where { type State = EitherKeepAliveState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let showing_b = self.show_b; - let a = self.a.map(|val| Render::build(val, extra_attrs.clone())); - let b = self.b.map(|val| Render::build(val, extra_attrs)); + let a = self.a.map(Render::build); + let b = self.b.map(Render::build); EitherKeepAliveState { a, b, showing_b } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { // set or update A -- `None` just means "no change" match (self.a, &mut state.a) { - (Some(new), Some(old)) => new.rebuild(old, extra_attrs.clone()), - (Some(new), None) => state.a = Some(new.build(extra_attrs.clone())), + (Some(new), Some(old)) => new.rebuild(old), + (Some(new), None) => state.a = Some(new.build()), _ => {} } // set or update B match (self.b, &mut state.b) { - (Some(new), Some(old)) => new.rebuild(old, extra_attrs), - (Some(new), None) => state.b = Some(new.build(extra_attrs)), + (Some(new), Some(old)) => new.rebuild(old), + (Some(new), None) => state.b = Some(new.build()), _ => {} } @@ -375,58 +358,35 @@ where B: RenderHtml, { type AsyncOutput = EitherKeepAlive; - type Owned = EitherKeepAlive; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, mut extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { if let Some(inner) = &mut self.a { - inner.dry_resolve(extra_attrs.as_deref_mut()); + inner.dry_resolve(); } if let Some(inner) = &mut self.b { - inner.dry_resolve(extra_attrs); + inner.dry_resolve(); } } - async fn resolve( - self, - mut extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { let EitherKeepAlive { a, b, show_b } = self; - - // Has to be sequential if extra attrs are present: - let (a, b) = if extra_attrs.is_some() { - let a = match a { - Some(a) => Some(a.resolve(extra_attrs.as_deref_mut()).await), - None => None, - }; - let b = match b { - Some(b) => Some(b.resolve(extra_attrs.as_deref_mut()).await), - None => None, - }; - (a, b) - } else { - join( - async move { - match a { - Some(a) => { - Some(a.resolve(ExtraAttrsMut::default()).await) - } - None => None, - } - }, - async move { - match b { - Some(b) => { - Some(b.resolve(ExtraAttrsMut::default()).await) - } - None => None, - } - }, - ) - .await - }; - + let (a, b) = join( + async move { + match a { + Some(a) => Some(a.resolve().await), + None => None, + } + }, + async move { + match b { + Some(b) => Some(b.resolve().await), + None => None, + } + }, + ) + .await; EitherKeepAlive { a, b, show_b } } @@ -436,7 +396,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { if self.show_b { self.b @@ -467,7 +427,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -498,34 +458,25 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let showing_b = self.show_b; let a = self.a.map(|a| { if showing_b { - a.build(extra_attrs.clone()) + a.build() } else { - a.hydrate::(cursor, position, extra_attrs.clone()) + a.hydrate::(cursor, position) } }); let b = self.b.map(|b| { if showing_b { - b.hydrate::(cursor, position, extra_attrs) + b.hydrate::(cursor, position) } else { - b.build(extra_attrs) + b.build() } }); EitherKeepAliveState { showing_b, a, b } } - - fn into_owned(self) -> Self::Owned { - EitherKeepAlive { - a: self.a.map(|a| a.into_owned()), - b: self.b.map(|b| b.into_owned()), - show_b: self.show_b, - } - } } impl Mountable for EitherKeepAliveState @@ -572,6 +523,20 @@ where .insert_before_this(child) } } + + fn elements(&self) -> Vec { + if self.showing_b { + self.b + .as_ref() + .map(|inner| inner.elements()) + .unwrap_or_default() + } else { + self.a + .as_ref() + .map(|inner| inner.elements()) + .unwrap_or_default() + } + } } macro_rules! tuples { @@ -615,6 +580,12 @@ macro_rules! tuples { $([]::$ty(this) =>this.insert_before_this(child),)* } } + + fn elements(&self) -> Vec { + match &self.state { + $([]::$ty(this) => this.elements(),)* + } + } } impl<$($ty,)*> Render for []<$($ty,)*> @@ -625,20 +596,20 @@ macro_rules! tuples { type State = []<$($ty,)*>; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let state = match self { - $([]::$ty(this) => []::$ty(this.build(extra_attrs)),)* + $([]::$ty(this) => []::$ty(this.build()),)* }; Self::State { state } } - fn rebuild(self, state: &mut Self::State, extra_attrs: Option>) { + fn rebuild(self, state: &mut Self::State) { let new_state = match (self, &mut state.state) { // rebuild same state and return early - $(([]::$ty(new), []::$ty(old)) => { return new.rebuild(old, extra_attrs); },)* + $(([]::$ty(new), []::$ty(old)) => { return new.rebuild(old); },)* // or mount new state $(([]::$ty(new), _) => { - let mut new = new.build(extra_attrs); + let mut new = new.build(); state.insert_before_this(&mut new); []::$ty(new) },)* @@ -682,33 +653,39 @@ macro_rules! tuples { { type AsyncOutput = []<$($ty::AsyncOutput,)*>; - type Owned = []<$($ty::Owned,)*>; const MIN_LENGTH: usize = max_usize(&[$($ty ::MIN_LENGTH,)*]); - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { match self { $([]::$ty(this) => { - this.dry_resolve(extra_attrs); + this.dry_resolve(); })* } } - async fn resolve(self, extra_attrs: ExtraAttrsMut<'_>) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { match self { - $([]::$ty(this) => []::$ty(this.resolve(extra_attrs).await),)* + $([]::$ty(this) => []::$ty(this.resolve().await),)* } } #[inline(always)] - fn html_len(&self, extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { match self { - $([]::$ty(i) => i.html_len(extra_attrs),)* + $([]::$ty(i) => i.html_len(),)* } } - fn to_html_with_buf(self, buf: &mut String, position: &mut Position, escape: bool, mark_branches: bool, extra_attrs: Option>) { + fn to_html_with_buf( + self, + buf: &mut String, + position: &mut Position, + escape: bool, + mark_branches: bool, + extra_attrs: Vec + ) { match self { $([]::$ty(this) => { if mark_branches { @@ -724,7 +701,12 @@ macro_rules! tuples { fn to_html_async_with_buf( self, - buf: &mut StreamBuilder, position: &mut Position, escape: bool, mark_branches: bool, extra_attrs: Option>) where + buf: &mut StreamBuilder, + position: &mut Position, + escape: bool, + mark_branches: bool, + extra_attrs: Vec + ) where Self: Sized, { match self { @@ -744,24 +726,15 @@ macro_rules! tuples { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let state = match self { $([]::$ty(this) => { - []::$ty(this.hydrate::(cursor, position, extra_attrs)) + []::$ty(this.hydrate::(cursor, position)) })* }; Self::State { state } } - - fn into_owned(self) -> Self::Owned { - match self { - $([]::$ty(this) => { - []::$ty(this.into_owned()) - })* - } - } } } } diff --git a/tachys/src/view/error_boundary.rs b/tachys/src/view/error_boundary.rs index e7ba019be9..1bd238af7d 100644 --- a/tachys/src/view/error_boundary.rs +++ b/tachys/src/view/error_boundary.rs @@ -1,7 +1,4 @@ -use super::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Position, PositionState, - RenderHtml, -}; +use super::{add_attr::AddAnyAttr, Position, PositionState, RenderHtml}; use crate::{ html::attribute::{any_attribute::AnyAttribute, Attribute}, hydration::Cursor, @@ -19,23 +16,19 @@ where { type State = ResultState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let hook = throw_error::get_error_hook(); let (state, error) = match self { - Ok(view) => (Either::Left(view.build(extra_attrs)), None), + Ok(view) => (Either::Left(view.build()), None), Err(e) => ( - Either::Right(Render::build((), None)), + Either::Right(Render::build(())), Some(throw_error::throw(e.into())), ), }; ResultState { state, error, hook } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let _guard = state.hook.clone().map(throw_error::set_error_hook); match (&mut state.state, self) { // both errors: throw the new error and replace @@ -44,11 +37,11 @@ where } // both Ok: need to rebuild child (Either::Left(old), Ok(new)) => { - T::rebuild(new, old, extra_attrs); + T::rebuild(new, old); } // Ok => Err: unmount, replace with marker, and throw (Either::Left(old), Err(err)) => { - let mut new_state = Render::build((), None); + let mut new_state = Render::build(()); old.insert_before_this(&mut new_state); old.unmount(); state.state = Either::Right(new_state); @@ -59,7 +52,7 @@ where if let Some(err) = state.error.take() { throw_error::clear(&err); } - let mut new_state = new.build(extra_attrs); + let mut new_state = new.build(); old.insert_before_this(&mut new_state); old.unmount(); state.state = Either::Left(new_state); @@ -111,6 +104,10 @@ where fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.state.insert_before_this(child) } + + fn elements(&self) -> Vec { + self.state.elements() + } } impl AddAnyAttr for Result @@ -139,29 +136,25 @@ where E: Into + Send + 'static, { type AsyncOutput = Result; - type Owned = Result; const MIN_LENGTH: usize = T::MIN_LENGTH; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { if let Ok(inner) = self.as_mut() { - inner.dry_resolve(extra_attrs) + inner.dry_resolve() } } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { match self { - Ok(view) => Ok(view.resolve(extra_attrs).await), + Ok(view) => Ok(view.resolve().await), Err(e) => Err(e), } } - fn html_len(&self, extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { match self { - Ok(i) => i.html_len(extra_attrs) + 3, + Ok(i) => i.html_len() + 3, Err(_) => 0, } } @@ -172,16 +165,18 @@ where position: &mut super::Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { match self { - Ok(inner) => inner.to_html_with_buf( - buf, - position, - escape, - mark_branches, - extra_attrs, - ), + Ok(inner) => { + inner.to_html_with_buf( + buf, + position, + escape, + mark_branches, + extra_attrs, + ); + } Err(e) => { buf.push_str(""); throw_error::throw(e); @@ -195,7 +190,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -218,35 +213,19 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let hook = throw_error::get_error_hook(); let (state, error) = match self { Ok(view) => ( - Either::Left(view.hydrate::( - cursor, - position, - extra_attrs, - )), + Either::Left(view.hydrate::(cursor, position)), None, ), Err(e) => { - let state = RenderHtml::hydrate::( - (), - cursor, - position, - extra_attrs, - ); + let state = + RenderHtml::hydrate::((), cursor, position); (Either::Right(state), Some(throw_error::throw(e.into()))) } }; ResultState { state, error, hook } } - - fn into_owned(self) -> Self::Owned { - match self { - Ok(view) => Ok(view.into_owned()), - Err(e) => Err(e), - } - } } diff --git a/tachys/src/view/iterators.rs b/tachys/src/view/iterators.rs index 4a38748c6b..66d71c8163 100644 --- a/tachys/src/view/iterators.rs +++ b/tachys/src/view/iterators.rs @@ -1,7 +1,6 @@ use super::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, - batch_resolve_items_with_extra_attrs, Mountable, Position, PositionState, - Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }; use crate::{ html::attribute::{any_attribute::AnyAttribute, Attribute}, @@ -21,24 +20,20 @@ where { type State = OptionState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { match self { Some(value) => Either::Left(value), None => Either::Right(()), } - .build(extra_attrs) + .build() } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { match self { Some(value) => Either::Left(value), None => Either::Right(()), } - .rebuild(state, extra_attrs) + .rebuild(state) } } @@ -65,29 +60,25 @@ where T: RenderHtml, { type AsyncOutput = Option; - type Owned = Option; const MIN_LENGTH: usize = T::MIN_LENGTH; - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { if let Some(inner) = self.as_mut() { - inner.dry_resolve(extra_attrs); + inner.dry_resolve(); } } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { match self { None => None, - Some(value) => Some(value.resolve(extra_attrs).await), + Some(value) => Some(value.resolve().await), } } - fn html_len(&self, extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { match self { - Some(i) => i.html_len(extra_attrs) + 3, + Some(i) => i.html_len() + 3, None => 3, } } @@ -98,7 +89,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { match self { Some(value) => Either::Left(value), @@ -119,7 +110,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -141,17 +132,12 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { match self { Some(value) => Either::Left(value), None => Either::Right(()), } - .hydrate::(cursor, position, extra_attrs) - } - - fn into_owned(self) -> Self::Owned { - self.map(RenderHtml::into_owned) + .hydrate::(cursor, position) } } @@ -161,27 +147,20 @@ where { type State = VecState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let marker = Rndr::create_placeholder(); VecState { - states: self - .into_iter() - .map(|val| T::build(val, extra_attrs.clone())) - .collect(), + states: self.into_iter().map(T::build).collect(), marker, } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let VecState { states, marker } = state; let old = states; // this is an unkeyed diff if old.is_empty() { - let mut new = self.build(extra_attrs).states; + let mut new = self.build().states; for item in new.iter_mut() { Rndr::mount_before(item, marker.as_ref()); } @@ -198,10 +177,10 @@ where for item in self.into_iter().zip_longest(old.iter_mut()) { match item { itertools::EitherOrBoth::Both(new, old) => { - T::rebuild(new, old, extra_attrs.clone()) + T::rebuild(new, old) } itertools::EitherOrBoth::Left(new) => { - let mut new_state = new.build(extra_attrs.clone()); + let mut new_state = new.build(); Rndr::mount_before(&mut new_state, marker.as_ref()); adds.push(new_state); } @@ -259,6 +238,13 @@ where self.marker.insert_before_this(child) } } + + fn elements(&self) -> Vec { + self.states + .iter() + .flat_map(|item| item.elements()) + .collect() + } } impl AddAnyAttr for Vec @@ -287,31 +273,24 @@ where T: RenderHtml, { type AsyncOutput = Vec; - type Owned = Vec; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, mut extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { for inner in self.iter_mut() { - inner.dry_resolve(extra_attrs.as_deref_mut()); + inner.dry_resolve(); } } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - batch_resolve_items_with_extra_attrs(self, extra_attrs) + async fn resolve(self) -> Self::AsyncOutput { + futures::future::join_all(self.into_iter().map(T::resolve)) .await .into_iter() .collect() } - fn html_len(&self, extra_attrs: Option>) -> usize { - self.iter() - .map(|n| n.html_len(extra_attrs.clone())) - .sum::() - + 3 + fn html_len(&self) -> usize { + self.iter().map(|n| n.html_len()).sum::() + 3 } fn to_html_with_buf( @@ -320,7 +299,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { let mut children = self.into_iter(); if let Some(first) = children.next() { @@ -338,6 +317,7 @@ where position, escape, mark_branches, + // each child will have the extra attributes applied extra_attrs.clone(), ); } @@ -350,7 +330,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -380,27 +360,16 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let states = self .into_iter() - .map(|child| { - child.hydrate::( - cursor, - position, - extra_attrs.clone(), - ) - }) + .map(|child| child.hydrate::(cursor, position)) .collect(); let marker = cursor.next_placeholder(position); VecState { states, marker } } - - fn into_owned(self) -> Self::Owned { - self.into_iter().map(RenderHtml::into_owned).collect() - } } impl Render for [T; N] @@ -409,23 +378,19 @@ where { type State = ArrayState; - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { Self::State { - states: self.map(|val| T::build(val, extra_attrs.clone())), + states: self.map(T::build), } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let Self::State { states } = state; let old = states; // this is an unkeyed diff self.into_iter() .zip(old.iter_mut()) - .for_each(|(new, old)| T::rebuild(new, old, extra_attrs.clone())); + .for_each(|(new, old)| T::rebuild(new, old)); } } @@ -462,6 +427,13 @@ where false } } + + fn elements(&self) -> Vec { + self.states + .iter() + .flat_map(|item| item.elements()) + .collect() + } } impl AddAnyAttr for [T; N] where @@ -487,21 +459,17 @@ where T: RenderHtml, { type AsyncOutput = [T::AsyncOutput; N]; - type Owned = Vec; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, mut extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { for inner in self.iter_mut() { - inner.dry_resolve(extra_attrs.as_deref_mut()); + inner.dry_resolve(); } } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - batch_resolve_items_with_extra_attrs(self, extra_attrs) + async fn resolve(self) -> Self::AsyncOutput { + futures::future::join_all(self.into_iter().map(T::resolve)) .await .into_iter() .collect::>() @@ -509,10 +477,8 @@ where .unwrap_or_else(|_| unreachable!()) } - fn html_len(&self, extra_attrs: Option>) -> usize { - self.iter() - .map(|val| RenderHtml::html_len(val, extra_attrs.clone())) - .sum::() + fn html_len(&self) -> usize { + self.iter().map(RenderHtml::html_len).sum::() } fn to_html_with_buf( @@ -521,7 +487,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { for child in self.into_iter() { child.to_html_with_buf( @@ -540,7 +506,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -559,17 +525,9 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - let states = self.map(|child| { - child.hydrate::(cursor, position, extra_attrs.clone()) - }); + let states = + self.map(|child| child.hydrate::(cursor, position)); ArrayState { states } } - - fn into_owned(self) -> Self::Owned { - self.into_iter() - .map(RenderHtml::into_owned) - .collect::>() - } } diff --git a/tachys/src/view/keyed.rs b/tachys/src/view/keyed.rs index 4dc74af2cd..702042b859 100644 --- a/tachys/src/view/keyed.rs +++ b/tachys/src/view/keyed.rs @@ -1,7 +1,6 @@ use super::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, - batch_resolve_items_with_extra_attrs, Mountable, Position, PositionState, - Render, RenderHtml, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, }; use crate::{ html::attribute::{any_attribute::AnyAttribute, Attribute}, @@ -76,7 +75,7 @@ where type State = KeyedState; // TODO fallible state and try_build()/try_rebuild() here - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let items = self.items.into_iter(); let (capacity, _) = items.size_hint(); let mut hashed_items = @@ -85,8 +84,7 @@ where for (index, item) in items.enumerate() { hashed_items.insert((self.key_fn)(&item)); let (set_index, view) = (self.view_fn)(index, item); - rendered_items - .push(Some((set_index, view.build(extra_attrs.clone())))); + rendered_items.push(Some((set_index, view.build()))); } KeyedState { parent: None, @@ -96,11 +94,7 @@ where } } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let KeyedState { parent, marker, @@ -129,7 +123,6 @@ where rendered_items, &self.view_fn, items, - extra_attrs, ); *hashed_items = new_hashed_items; @@ -138,9 +131,9 @@ where impl AddAnyAttr for Keyed where - I: IntoIterator + Send + 'static, + I: IntoIterator + Send, K: Eq + Hash + 'static, - KF: Fn(&T) -> K + Send + 'static, + KF: Fn(&T) -> K + Send, V: RenderHtml, V: 'static, VF: Fn(usize, T) -> (VFS, V) + Send + 'static, @@ -191,38 +184,29 @@ where impl RenderHtml for Keyed where - I: IntoIterator + Send + 'static, + I: IntoIterator + Send, K: Eq + Hash + 'static, - KF: Fn(&T) -> K + Send + 'static, + KF: Fn(&T) -> K + Send, V: RenderHtml + 'static, VF: Fn(usize, T) -> (VFS, V) + Send + 'static, VFS: Fn(usize) + 'static, T: 'static, { type AsyncOutput = Vec; // TODO - type Owned = Keyed; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) { + fn dry_resolve(&mut self) { // TODO... } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - batch_resolve_items_with_extra_attrs( - self.items - .into_iter() - .enumerate() - .map(|(index, item)| { - let (_, view) = (self.view_fn)(index, item); - view - }) - .collect::>(), - extra_attrs, - ) + async fn resolve(self) -> Self::AsyncOutput { + futures::future::join_all(self.items.into_iter().enumerate().map( + |(index, item)| { + let (_, view) = (self.view_fn)(index, item); + view.resolve() + }, + )) .await .into_iter() .collect::>() @@ -234,7 +218,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { for (index, item) in self.items.into_iter().enumerate() { let (_, item) = (self.view_fn)(index, item); @@ -256,7 +240,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { for (index, item) in self.items.into_iter().enumerate() { let (_, item) = (self.view_fn)(index, item); @@ -276,7 +260,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { // get parent and position let current = cursor.current(); @@ -298,11 +281,7 @@ where for (index, item) in items.enumerate() { hashed_items.insert((self.key_fn)(&item)); let (set_index, view) = (self.view_fn)(index, item); - let item = view.hydrate::( - cursor, - position, - extra_attrs.clone(), - ); + let item = view.hydrate::(cursor, position); rendered_items.push(Some((set_index, item))); } let marker = cursor.next_placeholder(position); @@ -313,10 +292,6 @@ where rendered_items, } } - - fn into_owned(self) -> Self::Owned { - self - } } impl Mountable for KeyedState @@ -356,6 +331,14 @@ where }) .unwrap_or_else(|| self.marker.insert_before_this(child)) } + + fn elements(&self) -> Vec { + self.rendered_items + .iter() + .flatten() + .flat_map(|item| item.1.elements()) + .collect() + } } trait VecExt { @@ -544,7 +527,6 @@ fn apply_diff( children: &mut Vec>, view_fn: impl Fn(usize, T) -> (VFS, V), mut items: Vec>, - extra_attrs: Option>, ) where VFS: Fn(usize), V: Render, @@ -618,7 +600,7 @@ fn apply_diff( for DiffOpAdd { at, mode } in add_cmds { let item = items[at].take().unwrap(); let (set_index, item) = view_fn(at, item); - let mut item = item.build(extra_attrs.clone()); + let mut item = item.build(); match mode { DiffOpAddMode::Normal => { @@ -729,7 +711,7 @@ mod tests { #[test] fn keyed_creates_list() { let el = ul((), keyed(1..=3, |k| *k, item)); - let el_state = el.build(None); + let el_state = el.build(); assert_eq!( el_state.el.to_debug_html(), "
  • 1
  • 2
  • 3
" @@ -739,7 +721,7 @@ mod tests { #[test] fn adding_items_updates_list() { let el = ul((), keyed(1..=3, |k| *k, item)); - let mut el_state = el.build(None); + let mut el_state = el.build(); let el = ul((), keyed(1..=5, |k| *k, item)); el.rebuild(&mut el_state); assert_eq!( @@ -751,7 +733,7 @@ mod tests { #[test] fn removing_items_updates_list() { let el = ul((), keyed(1..=3, |k| *k, item)); - let mut el_state = el.build(None); + let mut el_state = el.build(); let el = ul((), keyed(1..=2, |k| *k, item)); el.rebuild(&mut el_state); assert_eq!( @@ -763,7 +745,7 @@ mod tests { #[test] fn swapping_items_updates_list() { let el = ul((), keyed([1, 2, 3, 4, 5], |k| *k, item)); - let mut el_state = el.build(None); + let mut el_state = el.build(); let el = ul((), keyed([1, 4, 3, 2, 5], |k| *k, item)); el.rebuild(&mut el_state); assert_eq!( @@ -775,7 +757,7 @@ mod tests { #[test] fn swapping_and_removing_orders_correctly() { let el = ul((), keyed([1, 2, 3, 4, 5], |k| *k, item)); - let mut el_state = el.build(None); + let mut el_state = el.build(); let el = ul((), keyed([1, 4, 3, 5], |k| *k, item)); el.rebuild(&mut el_state); assert_eq!( @@ -787,7 +769,7 @@ mod tests { #[test] fn arbitrarily_hard_adjustment() { let el = ul((), keyed([1, 2, 3, 4, 5], |k| *k, item)); - let mut el_state = el.build(None); + let mut el_state = el.build(); let el = ul((), keyed([2, 4, 3], |k| *k, item)); el.rebuild(&mut el_state); assert_eq!( @@ -799,7 +781,7 @@ mod tests { #[test] fn a_series_of_moves() { let el = ul((), keyed([1, 2, 3, 4, 5], |k| *k, item)); - let mut el_state = el.build(None); + let mut el_state = el.build(); let el = ul((), keyed([2, 4, 3], |k| *k, item)); el.rebuild(&mut el_state); let el = ul((), keyed([1, 7, 5, 11, 13, 17], |k| *k, item)); @@ -819,7 +801,7 @@ mod tests { #[test] fn clearing_works() { let el = ul((), keyed([1, 2, 3, 4, 5], |k| *k, item)); - let mut el_state = el.build(None); + let mut el_state = el.build(); let el = ul((), keyed([], |k| *k, item)); el.rebuild(&mut el_state); assert_eq!(el_state.el.to_debug_html(), "
    "); diff --git a/tachys/src/view/mod.rs b/tachys/src/view/mod.rs index 81c18d36c6..1984d50838 100644 --- a/tachys/src/view/mod.rs +++ b/tachys/src/view/mod.rs @@ -3,7 +3,6 @@ use crate::{ html::attribute::any_attribute::AnyAttribute, hydration::Cursor, ssr::StreamBuilder, }; -use any_view::ExtraAttrsMut; use parking_lot::RwLock; use std::{cell::RefCell, future::Future, rc::Rc, sync::Arc}; @@ -41,14 +40,10 @@ pub trait Render: Sized { type State: Mountable; /// Creates the view for the first time, without hydrating from existing HTML. - fn build(self, extra_attrs: Option>) -> Self::State; + fn build(self) -> Self::State; /// Updates the view with new data. - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ); + fn rebuild(self, state: &mut Self::State); } pub(crate) trait MarkBranch { @@ -104,9 +99,6 @@ where /// The type of the view after waiting for all asynchronous data to load. type AsyncOutput: RenderHtml; - /// A static version of this type. - type Owned: RenderHtml + 'static; - /// The minimum length of HTML created when this view is rendered. const MIN_LENGTH: usize; @@ -116,20 +108,17 @@ where /// “Runs” the view without other side effects. For primitive types, this is a no-op. For /// reactive types, this can be used to gather data about reactivity or about asynchronous data /// that needs to be loaded. - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>); + fn dry_resolve(&mut self); /// Waits for any asynchronous sections of the view to load and returns the output. - fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> impl Future + Send; + fn resolve(self) -> impl Future + Send; /// An estimated length for this view, when rendered to HTML. /// /// This is used for calculating the string buffer size when rendering HTML. It does not need /// to be precise, but should be an appropriate estimate. The more accurate, the fewer /// reallocations will be required and the faster server-side rendering will be. - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { Self::MIN_LENGTH } @@ -138,13 +127,13 @@ where where Self: Sized, { - let mut buf = String::with_capacity(self.html_len(None)); + let mut buf = String::with_capacity(self.html_len()); self.to_html_with_buf( &mut buf, &mut Position::FirstChild, true, false, - None, + vec![], ); buf } @@ -156,13 +145,13 @@ where where Self: Sized, { - let mut buf = String::with_capacity(self.html_len(None)); + let mut buf = String::with_capacity(self.html_len()); self.to_html_with_buf( &mut buf, &mut Position::FirstChild, true, true, - None, + vec![], ); buf } @@ -172,14 +161,13 @@ where where Self: Sized, { - let mut builder = - StreamBuilder::with_capacity(self.html_len(None), None); + let mut builder = StreamBuilder::with_capacity(self.html_len(), None); self.to_html_async_with_buf::( &mut builder, &mut Position::FirstChild, true, false, - None, + vec![], ); builder.finish() } @@ -191,14 +179,13 @@ where where Self: Sized, { - let mut builder = - StreamBuilder::with_capacity(self.html_len(None), None); + let mut builder = StreamBuilder::with_capacity(self.html_len(), None); self.to_html_async_with_buf::( &mut builder, &mut Position::FirstChild, true, true, - None, + vec![], ); builder.finish() } @@ -210,14 +197,14 @@ where { //let capacity = self.html_len(); let mut builder = - StreamBuilder::with_capacity(self.html_len(None), Some(vec![0])); + StreamBuilder::with_capacity(self.html_len(), Some(vec![0])); self.to_html_async_with_buf::( &mut builder, &mut Position::FirstChild, true, false, - None, + vec![], ); builder.finish() } @@ -230,14 +217,14 @@ where Self: Sized, { let mut builder = - StreamBuilder::with_capacity(self.html_len(None), Some(vec![0])); + StreamBuilder::with_capacity(self.html_len(), Some(vec![0])); self.to_html_async_with_buf::( &mut builder, &mut Position::FirstChild, true, true, - None, + vec![], ); builder.finish() } @@ -249,7 +236,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ); /// Renders a view into a buffer of (synchronous or asynchronous) HTML chunks. @@ -259,7 +246,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -285,7 +272,6 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State; /// Hydrates using [`RenderHtml::hydrate`], beginning at the given element. @@ -310,49 +296,8 @@ where { let cursor = Cursor::new(el.clone()); let position = PositionState::new(position); - self.hydrate::(&cursor, &position, None) + self.hydrate::(&cursor, &position) } - - /// Converts this view into a owned/static type. - fn into_owned(self) -> Self::Owned; -} - -/// Resolving multiple children when extra_attrs exist is tricky, because the extra_attrs are potentially shared. -/// -/// The current assumption is: -/// - resolve() should not be run on an AnyAttribute more than once, -/// - any of the children could resolve() the extra_attr_states -/// -/// Therefore, if any extra_attrs exist, resolving must happen sequentially, until any of the children resolves the extra_attrs. -/// After that, the remaining can be done in parallel, like they will be if no extra_attrs exist. -pub(crate) async fn batch_resolve_items_with_extra_attrs( - items: impl IntoIterator, - mut extra_attrs: ExtraAttrsMut<'_>, -) -> impl IntoIterator { - let mut item_iter = items.into_iter(); - let mut preresolved = vec![]; - if extra_attrs.is_some() { - // Reset resolved state to fresh if dirty: - extra_attrs - .as_deref_mut() - .iter_mut() - .for_each(|attr| attr.resolved = false); - for item in item_iter.by_ref() { - preresolved.push(item.resolve(extra_attrs.as_deref_mut()).await); - // Once all resolved, can switch to parallel and not pass in extra_attrs anymore, - // once they've already all resolved: - if extra_attrs.iter_mut().all(|attr| attr.resolved) { - break; - } - } - } - preresolved.into_iter().chain( - futures::future::join_all( - item_iter.map(|val| T::resolve(val, ExtraAttrsMut::default())), - ) - .await - .into_iter(), - ) } /// Allows a type to be mounted to the DOM. @@ -383,6 +328,9 @@ pub trait Mountable { child.mount(parent, marker); } } + + /// wip + fn elements(&self) -> Vec; } /// Indicates where a node should be mounted to its parent. @@ -418,6 +366,12 @@ where .map(|inner| inner.insert_before_this(child)) .unwrap_or(false) } + + fn elements(&self) -> Vec { + self.as_ref() + .map(|inner| inner.elements()) + .unwrap_or_default() + } } impl Mountable for Rc> @@ -439,6 +393,10 @@ where fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.borrow().insert_before_this(child) } + + fn elements(&self) -> Vec { + self.borrow().elements() + } } /// Allows data to be added to a static template. diff --git a/tachys/src/view/primitives.rs b/tachys/src/view/primitives.rs index 0198a26b39..a96f1a7f61 100644 --- a/tachys/src/view/primitives.rs +++ b/tachys/src/view/primitives.rs @@ -1,7 +1,4 @@ -use super::{ - any_view::ExtraAttrsMut, Mountable, Position, PositionState, Render, - RenderHtml, -}; +use super::{Mountable, Position, PositionState, Render, RenderHtml}; use crate::{ html::attribute::any_attribute::AnyAttribute, hydration::Cursor, @@ -44,18 +41,22 @@ macro_rules! render_primitive { ) -> bool { self.0.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![] + } } impl Render for $child_type { type State = [<$child_type:camel State>]; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let node = Rndr::create_text_node(&self.to_string()); [<$child_type:camel State>](node, self) } - fn rebuild(self, state: &mut Self::State, _extra_attrs: Option>) { + fn rebuild(self, state: &mut Self::State) { let [<$child_type:camel State>](node, this) = state; if &self != this { Rndr::set_text(node, &self.to_string()); @@ -69,17 +70,16 @@ macro_rules! render_primitive { impl RenderHtml for $child_type { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve(self, _extra_attrs: ExtraAttrsMut<'_>) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn to_html_with_buf(self, buf: &mut String, position: &mut Position, _escape: bool, _mark_branches: bool, _extra_attrs: Option>) { + fn to_html_with_buf(self, buf: &mut String, position: &mut Position, _escape: bool, _mark_branches: bool, _extra_attrs: Vec) { // add a comment node to separate from previous sibling, if any if matches!(position, Position::NextChildAfterText) { buf.push_str("") @@ -92,7 +92,6 @@ macro_rules! render_primitive { self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { if position.get() == Position::FirstChild { cursor.child(); @@ -116,10 +115,6 @@ macro_rules! render_primitive { [<$child_type:camel State>](node, self) } - - fn into_owned(self) -> Self::Owned { - self - } } impl<'a> ToTemplate for $child_type { diff --git a/tachys/src/view/static_types.rs b/tachys/src/view/static_types.rs index f7156fc478..750ad53d57 100644 --- a/tachys/src/view/static_types.rs +++ b/tachys/src/view/static_types.rs @@ -1,6 +1,6 @@ use super::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, ToTemplate, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, ToTemplate, }; use crate::{ html::attribute::{ @@ -148,36 +148,27 @@ where { type State = Option; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { // a view state has to be returned so it can be mounted Some(Rndr::create_text_node(V)) } // This type is specified as static, so no rebuilding is done. - fn rebuild( - self, - _state: &mut Self::State, - _extra_attrs: Option>, - ) { - } + fn rebuild(self, _state: &mut Self::State) {} } impl RenderHtml for Static { type AsyncOutput = Self; - type Owned = Self; const MIN_LENGTH: usize = V.len(); - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} // this won't actually compile because if a weird interaction because the const &'static str and // the RPITIT, so we just refine it to a concrete future type; this will never change in any // case #[allow(refining_impl_trait)] - fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> std::future::Ready { + fn resolve(self) -> std::future::Ready { std::future::ready(self) } @@ -187,7 +178,7 @@ impl RenderHtml for Static { position: &mut Position, escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { // add a comment node to separate from previous sibling, if any if matches!(position, Position::NextChildAfterText) { @@ -208,7 +199,6 @@ impl RenderHtml for Static { self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { if position.get() == Position::FirstChild { cursor.child(); @@ -231,10 +221,6 @@ impl RenderHtml for Static { Some(node) } - - fn into_owned(self) -> Self::Owned { - self - } } impl AddAnyAttr for Static { diff --git a/tachys/src/view/strings.rs b/tachys/src/view/strings.rs index cf95f03bf7..62ae18498e 100644 --- a/tachys/src/view/strings.rs +++ b/tachys/src/view/strings.rs @@ -1,6 +1,5 @@ use super::{ - any_view::ExtraAttrsMut, Mountable, Position, PositionState, Render, - RenderHtml, ToTemplate, + Mountable, Position, PositionState, Render, RenderHtml, ToTemplate, }; use crate::{ html::attribute::any_attribute::AnyAttribute, @@ -24,16 +23,12 @@ pub struct StrState<'a> { impl<'a> Render for &'a str { type State = StrState<'a>; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let node = Rndr::create_text_node(self); StrState { node, str: self } } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let StrState { node, str } = state; if &self != str { Rndr::set_text(node, self); @@ -44,20 +39,16 @@ impl<'a> Render for &'a str { impl RenderHtml for &str { type AsyncOutput = Self; - type Owned = String; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { self.len() } @@ -67,7 +58,7 @@ impl RenderHtml for &str { position: &mut Position, escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { // add a comment node to separate from previous sibling, if any if matches!(position, Position::NextChildAfterText) { @@ -88,7 +79,6 @@ impl RenderHtml for &str { self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { if position.get() == Position::FirstChild { cursor.child(); @@ -114,10 +104,6 @@ impl RenderHtml for &str { StrState { node, str: self } } - - fn into_owned(self) -> Self::Owned { - self.to_string() - } } impl ToTemplate for &str { @@ -154,6 +140,10 @@ impl Mountable for StrState<'_> { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.node.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![] + } } /// Retained view state for `String`. @@ -165,16 +155,12 @@ pub struct StringState { impl Render for String { type State = StringState; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let node = Rndr::create_text_node(&self); StringState { node, str: self } } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let StringState { node, str } = state; if &self != str { Rndr::set_text(node, &self); @@ -186,18 +172,14 @@ impl Render for String { impl RenderHtml for String { const MIN_LENGTH: usize = 0; type AsyncOutput = Self; - type Owned = Self; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { self.len() } @@ -207,7 +189,7 @@ impl RenderHtml for String { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { <&str as RenderHtml>::to_html_with_buf( self.as_str(), @@ -223,17 +205,11 @@ impl RenderHtml for String { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let StrState { node, .. } = - self.as_str() - .hydrate::(cursor, position, extra_attrs); + self.as_str().hydrate::(cursor, position); StringState { node, str: self } } - - fn into_owned(self) -> Self::Owned { - self - } } impl ToTemplate for String { @@ -268,6 +244,10 @@ impl Mountable for StringState { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.node.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![] + } } /// Retained view state for `Rc`. @@ -279,16 +259,12 @@ pub struct RcStrState { impl Render for Rc { type State = RcStrState; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let node = Rndr::create_text_node(&self); RcStrState { node, str: self } } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let RcStrState { node, str } = state; if !Rc::ptr_eq(&self, str) { Rndr::set_text(node, &self); @@ -308,11 +284,11 @@ where const MIN_LENGTH: usize = 0; - async fn resolve(self, _extra_attrs: Option>) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { self.len() } @@ -324,7 +300,6 @@ where self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { let this: &str = self.as_ref(); let StrState { node, .. } = @@ -365,6 +340,10 @@ impl Mountable for RcStrState { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.node.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![] + } } /// Retained view state for `Arc`. @@ -376,16 +355,12 @@ pub struct ArcStrState { impl Render for Arc { type State = ArcStrState; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let node = Rndr::create_text_node(&self); ArcStrState { node, str: self } } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let ArcStrState { node, str } = state; if !Arc::ptr_eq(&self, str) { Rndr::set_text(node, &self); @@ -396,20 +371,16 @@ impl Render for Arc { impl RenderHtml for Arc { type AsyncOutput = Self; - type Owned = Arc; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { self.len() } @@ -419,7 +390,7 @@ impl RenderHtml for Arc { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { <&str as RenderHtml>::to_html_with_buf( &self, @@ -435,17 +406,12 @@ impl RenderHtml for Arc { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let this: &str = self.as_ref(); let StrState { node, .. } = - this.hydrate::(cursor, position, extra_attrs); + this.hydrate::(cursor, position); ArcStrState { node, str: self } } - - fn into_owned(self) -> Self::Owned { - self - } } impl ToTemplate for Arc { @@ -480,6 +446,10 @@ impl Mountable for ArcStrState { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.node.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![] + } } /// Retained view state for `Cow<'_, str>`. @@ -491,16 +461,12 @@ pub struct CowStrState<'a> { impl<'a> Render for Cow<'a, str> { type State = CowStrState<'a>; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let node = Rndr::create_text_node(&self); CowStrState { node, str: self } } - fn rebuild( - self, - state: &mut Self::State, - _extra_attrs: Option>, - ) { + fn rebuild(self, state: &mut Self::State) { let CowStrState { node, str } = state; if self != *str { Rndr::set_text(node, &self); @@ -511,20 +477,16 @@ impl<'a> Render for Cow<'a, str> { impl RenderHtml for Cow<'_, str> { type AsyncOutput = Self; - type Owned = String; const MIN_LENGTH: usize = 0; - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + fn dry_resolve(&mut self) {} - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { + async fn resolve(self) -> Self::AsyncOutput { self } - fn html_len(&self, _extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { self.len() } @@ -534,7 +496,7 @@ impl RenderHtml for Cow<'_, str> { position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { <&str as RenderHtml>::to_html_with_buf( &self, @@ -550,17 +512,12 @@ impl RenderHtml for Cow<'_, str> { self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { let this: &str = self.as_ref(); let StrState { node, .. } = - this.hydrate::(cursor, position, extra_attrs); + this.hydrate::(cursor, position); CowStrState { node, str: self } } - - fn into_owned(self) -> ::Owned { - self.into_owned() - } } impl ToTemplate for Cow<'_, str> { @@ -595,4 +552,8 @@ impl Mountable for CowStrState<'_> { fn insert_before_this(&self, child: &mut dyn Mountable) -> bool { self.node.insert_before_this(child) } + + fn elements(&self) -> Vec { + vec![] + } } diff --git a/tachys/src/view/template.rs b/tachys/src/view/template.rs index 343d0899bf..acc7b0080e 100644 --- a/tachys/src/view/template.rs +++ b/tachys/src/view/template.rs @@ -1,6 +1,6 @@ use super::{ - add_attr::AddAnyAttr, any_view::ExtraAttrsMut, Mountable, Position, - PositionState, Render, RenderHtml, ToTemplate, + add_attr::AddAnyAttr, Mountable, Position, PositionState, Render, + RenderHtml, ToTemplate, }; use crate::{ html::attribute::{any_attribute::AnyAttribute, Attribute}, @@ -40,22 +40,15 @@ where // TODO try_build/try_rebuild() - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { let tpl = Self::to_template(); let contents = Rndr::clone_template(&tpl); - self.view.hydrate::( - &Cursor::new(contents), - &Default::default(), - extra_attrs, - ) + self.view + .hydrate::(&Cursor::new(contents), &Default::default()) } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - self.view.rebuild(state, extra_attrs) + fn rebuild(self, state: &mut Self::State) { + self.view.rebuild(state) } } @@ -83,7 +76,6 @@ where V::State: Mountable, { type AsyncOutput = V::AsyncOutput; - type Owned = V::Owned; const MIN_LENGTH: usize = V::MIN_LENGTH; @@ -93,7 +85,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { self.view.to_html_with_buf( buf, @@ -108,25 +100,16 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - self.view - .hydrate::(cursor, position, extra_attrs) - } - - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.view.dry_resolve(extra_attrs); + self.view.hydrate::(cursor, position) } - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - self.view.resolve(extra_attrs).await + fn dry_resolve(&mut self) { + self.view.dry_resolve(); } - fn into_owned(self) -> Self::Owned { - self.view.into_owned() + async fn resolve(self) -> Self::AsyncOutput { + self.view.resolve().await } } diff --git a/tachys/src/view/tuples.rs b/tachys/src/view/tuples.rs index e05410b858..f8e5591c21 100644 --- a/tachys/src/view/tuples.rs +++ b/tachys/src/view/tuples.rs @@ -1,6 +1,5 @@ use super::{ - any_view::ExtraAttrsMut, Mountable, Position, PositionState, Render, - RenderHtml, ToTemplate, + Mountable, Position, PositionState, Render, RenderHtml, ToTemplate, }; use crate::{ html::attribute::{any_attribute::AnyAttribute, Attribute}, @@ -15,21 +14,15 @@ use const_str_slice_concat::{ impl Render for () { type State = crate::renderer::types::Placeholder; - fn build(self, _extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { Rndr::create_placeholder() } - fn rebuild( - self, - _state: &mut Self::State, - _extra_attrs: Option>, - ) { - } + fn rebuild(self, _state: &mut Self::State) {} } impl RenderHtml for () { type AsyncOutput = (); - type Owned = (); const MIN_LENGTH: usize = 3; const EXISTS: bool = false; @@ -40,7 +33,7 @@ impl RenderHtml for () { position: &mut Position, escape: bool, _mark_branches: bool, - _extra_attrs: Option>, + _extra_attrs: Vec, ) { if escape { buf.push_str(""); @@ -52,20 +45,13 @@ impl RenderHtml for () { self, cursor: &Cursor, position: &PositionState, - _extra_attrs: Option>, ) -> Self::State { cursor.next_placeholder(position) } - async fn resolve( - self, - _extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - } - - fn dry_resolve(&mut self, _extra_attrs: ExtraAttrsMut<'_>) {} + async fn resolve(self) -> Self::AsyncOutput {} - fn into_owned(self) -> Self::Owned {} + fn dry_resolve(&mut self) {} } impl AddAnyAttr for () { @@ -94,6 +80,10 @@ impl Mountable for () { fn insert_before_this(&self, _child: &mut dyn Mountable) -> bool { false } + + fn elements(&self) -> Vec { + vec![] + } } impl ToTemplate for () { @@ -113,16 +103,12 @@ impl ToTemplate for () { impl Render for (A,) { type State = A::State; - fn build(self, extra_attrs: Option>) -> Self::State { - self.0.build(extra_attrs) + fn build(self) -> Self::State { + self.0.build() } - fn rebuild( - self, - state: &mut Self::State, - extra_attrs: Option>, - ) { - self.0.rebuild(state, extra_attrs) + fn rebuild(self, state: &mut Self::State) { + self.0.rebuild(state) } } @@ -131,12 +117,11 @@ where A: RenderHtml, { type AsyncOutput = (A::AsyncOutput,); - type Owned = (A::Owned,); const MIN_LENGTH: usize = A::MIN_LENGTH; - fn html_len(&self, extra_attrs: Option>) -> usize { - self.0.html_len(extra_attrs) + fn html_len(&self) -> usize { + self.0.html_len() } fn to_html_with_buf( @@ -145,7 +130,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) { self.0.to_html_with_buf( buf, @@ -162,7 +147,7 @@ where position: &mut Position, escape: bool, mark_branches: bool, - extra_attrs: Option>, + extra_attrs: Vec, ) where Self: Sized, { @@ -179,24 +164,16 @@ where self, cursor: &Cursor, position: &PositionState, - extra_attrs: Option>, ) -> Self::State { - self.0.hydrate::(cursor, position, extra_attrs) - } - - async fn resolve( - self, - extra_attrs: ExtraAttrsMut<'_>, - ) -> Self::AsyncOutput { - (self.0.resolve(extra_attrs).await,) + self.0.hydrate::(cursor, position) } - fn dry_resolve(&mut self, extra_attrs: ExtraAttrsMut<'_>) { - self.0.dry_resolve(extra_attrs); + async fn resolve(self) -> Self::AsyncOutput { + (self.0.resolve().await,) } - fn into_owned(self) -> Self::Owned { - (self.0.into_owned(),) + fn dry_resolve(&mut self) { + self.0.dry_resolve(); } } @@ -244,21 +221,21 @@ macro_rules! impl_view_for_tuples { type State = ($first::State, $($ty::State,)*); - fn build(self, extra_attrs: Option>) -> Self::State { + fn build(self) -> Self::State { #[allow(non_snake_case)] let ($first, $($ty,)*) = self; ( - $first.build(extra_attrs.clone()), - $($ty.build(extra_attrs.clone())),* + $first.build(), + $($ty.build()),* ) } - fn rebuild(self, state: &mut Self::State, extra_attrs: Option>) { + fn rebuild(self, state: &mut Self::State) { paste::paste! { let ([<$first:lower>], $([<$ty:lower>],)*) = self; let ([], $([],)*) = state; - [<$first:lower>].rebuild([], extra_attrs.clone()); - $([<$ty:lower>].rebuild([], extra_attrs.clone()));* + [<$first:lower>].rebuild([]); + $([<$ty:lower>].rebuild([]));* } } } @@ -270,18 +247,24 @@ macro_rules! impl_view_for_tuples { { type AsyncOutput = ($first::AsyncOutput, $($ty::AsyncOutput,)*); - type Owned = ($first::Owned, $($ty::Owned,)*); const MIN_LENGTH: usize = $first::MIN_LENGTH $(+ $ty::MIN_LENGTH)*; #[inline(always)] - fn html_len(&self, extra_attrs: Option>) -> usize { + fn html_len(&self) -> usize { #[allow(non_snake_case)] let ($first, $($ty,)* ) = self; - $($ty.html_len(extra_attrs.clone()) +)* $first.html_len(extra_attrs.clone()) + $($ty.html_len() +)* $first.html_len() } - fn to_html_with_buf(self, buf: &mut String, position: &mut Position, escape: bool, mark_branches: bool, extra_attrs: Option>) { + fn to_html_with_buf( + self, + buf: &mut String, + position: &mut Position, + escape: bool, + mark_branches: bool, + extra_attrs: Vec + ) { #[allow(non_snake_case)] let ($first, $($ty,)* ) = self; $first.to_html_with_buf(buf, position, escape, mark_branches, extra_attrs.clone()); @@ -290,7 +273,12 @@ macro_rules! impl_view_for_tuples { fn to_html_async_with_buf( self, - buf: &mut StreamBuilder, position: &mut Position, escape: bool, mark_branches: bool, extra_attrs: Option>) where + buf: &mut StreamBuilder, + position: &mut Position, + escape: bool, + mark_branches: bool, + extra_attrs: Vec + ) where Self: Sized, { #[allow(non_snake_case)] @@ -299,46 +287,29 @@ macro_rules! impl_view_for_tuples { $($ty.to_html_async_with_buf::(buf, position, escape, mark_branches, extra_attrs.clone()));* } - fn hydrate(self, cursor: &Cursor, position: &PositionState, extra_attrs: Option>) -> Self::State { + fn hydrate(self, cursor: &Cursor, position: &PositionState) -> Self::State { #[allow(non_snake_case)] let ($first, $($ty,)* ) = self; ( - $first.hydrate::(cursor, position, extra_attrs.clone()), - $($ty.hydrate::(cursor, position, extra_attrs.clone())),* + $first.hydrate::(cursor, position), + $($ty.hydrate::(cursor, position)),* ) } - async fn resolve(self, mut extra_attrs: ExtraAttrsMut<'_>) -> Self::AsyncOutput { - #[allow(non_snake_case)] - let ($first, $($ty,)*) = self; - if extra_attrs.is_some() { - // TODO: any good way to make this only partially sequantial like with batch_resolve_items_with_extra_attrs_tuples_inner()? - ( - $first.resolve(extra_attrs.as_deref_mut()).await, - $($ty.resolve(extra_attrs.as_deref_mut()).await),* - ) - } else { - futures::join!( - $first.resolve(ExtraAttrsMut::default()), - $($ty.resolve(ExtraAttrsMut::default())),* - ) - } - } - - fn dry_resolve(&mut self, mut extra_attrs: ExtraAttrsMut<'_>) { + async fn resolve(self) -> Self::AsyncOutput { #[allow(non_snake_case)] let ($first, $($ty,)*) = self; - $first.dry_resolve(extra_attrs.as_deref_mut()); - $($ty.dry_resolve(extra_attrs.as_deref_mut()));* + futures::join!( + $first.resolve(), + $($ty.resolve()),* + ) } - fn into_owned(self) -> Self::Owned { + fn dry_resolve(&mut self) { #[allow(non_snake_case)] let ($first, $($ty,)*) = self; - ( - $first.into_owned(), - $($ty.into_owned()),* - ) + $first.dry_resolve(); + $($ty.dry_resolve());* } } @@ -394,6 +365,14 @@ macro_rules! impl_view_for_tuples { $first.insert_before_this(child) $(|| $ty.insert_before_this(child))* } + + fn elements(&self) -> Vec { + #[allow(non_snake_case)] // better macro performance + let ($first, $($ty,)*) = self; + $first.elements().into_iter() + $(.chain($ty.elements()))* + .collect() + } } impl<$first, $($ty,)*> AddAnyAttr for ($first, $($ty,)*)