mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 15:44:42 -05:00
Compare commits
49 Commits
wasm-split
...
v0.8.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b54f80f529 | ||
|
|
a48a2994ee | ||
|
|
aedcd5148c | ||
|
|
9160d8aaa6 | ||
|
|
274fe07dae | ||
|
|
7add26fc41 | ||
|
|
d9213850f7 | ||
|
|
db9f323f8d | ||
|
|
1d0f668dc3 | ||
|
|
a97eceacf1 | ||
|
|
3d6ea6d285 | ||
|
|
99c3d8f9e9 | ||
|
|
a394eb211f | ||
|
|
ceb7dd8ae5 | ||
|
|
f50adc00bc | ||
|
|
1340deee96 | ||
|
|
8da3011a7f | ||
|
|
959677f018 | ||
|
|
03529b3992 | ||
|
|
8bfd0ce143 | ||
|
|
47199bbbf3 | ||
|
|
9ed7e9de61 | ||
|
|
26ecbf4df5 | ||
|
|
b3885c7be4 | ||
|
|
436e5aa141 | ||
|
|
05cafa8b06 | ||
|
|
9e3c0cc402 | ||
|
|
30141293f6 | ||
|
|
8f623a2d5b | ||
|
|
f2fe791f6b | ||
|
|
30dbb7ccc8 | ||
|
|
b986fe11dc | ||
|
|
e2e28ef180 | ||
|
|
a5e0053bab | ||
|
|
6c04a1cd76 | ||
|
|
87fb947465 | ||
|
|
5ba818132a | ||
|
|
30b917cfc3 | ||
|
|
6cd731cbb1 | ||
|
|
f1b6b79e27 | ||
|
|
623ee08f82 | ||
|
|
877849a5dd | ||
|
|
fb59da90c2 | ||
|
|
d33f5c9e77 | ||
|
|
deb8e96eb0 | ||
|
|
181e4d0566 | ||
|
|
525379a9b3 | ||
|
|
783a233167 | ||
|
|
8079956d1b |
11
.github/workflows/autofix.yml
vendored
11
.github/workflows/autofix.yml
vendored
@@ -17,17 +17,10 @@ env:
|
||||
jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
{
|
||||
toolchain: "nightly-2025-07-16",
|
||||
components: "rustfmt, clippy",
|
||||
target: "wasm32-unknown-unknown",
|
||||
rustflags: "",
|
||||
}
|
||||
with: {toolchain: "nightly-2025-07-16", components: "rustfmt, clippy", target: "wasm32-unknown-unknown", rustflags: ""}
|
||||
- name: Install Glib
|
||||
run: |
|
||||
sudo apt-get update
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -63,6 +63,6 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libglib2.0-dev
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Semver Checks
|
||||
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||
|
||||
2
.github/workflows/get-example-changed.yml
vendored
2
.github/workflows/get-example-changed.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
matrix: ${{ steps.set-example-changed.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Get example files that changed
|
||||
|
||||
2
.github/workflows/get-examples-matrix.yml
vendored
2
.github/workflows/get-examples-matrix.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
EXCLUDED_EXAMPLES: cargo-make
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Install jq
|
||||
run: sudo apt-get install jq
|
||||
- name: Set Matrix
|
||||
|
||||
2
.github/workflows/get-leptos-changed.yml
vendored
2
.github/workflows/get-leptos-changed.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
leptos_changed: ${{ steps.set-source-changed.outputs.leptos_changed }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Get source files that changed
|
||||
|
||||
2
.github/workflows/get-leptos-matrix.yml
vendored
2
.github/workflows/get-leptos-matrix.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Install jq
|
||||
run: sudo apt-get install jq
|
||||
- name: Set Matrix
|
||||
|
||||
2
.github/workflows/publish-book.yml
vendored
2
.github/workflows/publish-book.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
contents: write # To push a branch
|
||||
pull-requests: write # To create a PR from that branch
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install mdbook
|
||||
|
||||
2
.github/workflows/run-cargo-make-task.yml
vendored
2
.github/workflows/run-cargo-make-task.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libglib2.0-dev
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
|
||||
192
Cargo.lock
generated
192
Cargo.lock
generated
@@ -128,7 +128,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"mio",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
@@ -190,7 +190,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"smallvec",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"time",
|
||||
"tracing",
|
||||
"url",
|
||||
@@ -299,9 +299,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.0"
|
||||
version = "3.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
|
||||
checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"event-listener-strategy",
|
||||
@@ -571,15 +571,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.10"
|
||||
version = "1.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab"
|
||||
checksum = "5d07aa9a93b00c76f71bc35d598bed923f6d4f3a9ca5c24b7737ae1a292841c0"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.30"
|
||||
version = "1.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
|
||||
checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -588,9 +588,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.20.1"
|
||||
version = "0.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d0390889d58f934f01cd49736275b4c2da15bcfc328c78ff2349907e6cabf22"
|
||||
checksum = "c8d458d63f0f0f482c8da9b7c8b76c21bd885a02056cc94c6404d861ca2b8206"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
@@ -703,9 +703,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "const-str"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "041fbfcf8e7054df725fb9985297e92422cdc80fcf313665f5ca3d761bb63f4c"
|
||||
checksum = "451d0640545a0553814b4c646eb549343561618838e9b42495f466131fe3ad49"
|
||||
|
||||
[[package]]
|
||||
name = "const_format"
|
||||
@@ -859,9 +859,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive-where"
|
||||
version = "1.5.0"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b"
|
||||
checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -994,9 +994,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "5.4.0"
|
||||
version = "5.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
|
||||
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"parking",
|
||||
@@ -1116,9 +1116,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "2.6.0"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
|
||||
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"futures-core",
|
||||
@@ -1221,7 +1221,7 @@ dependencies = [
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1270,9 +1270,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "gloo-net"
|
||||
@@ -1547,9 +1547,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.15"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df"
|
||||
checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
@@ -1563,7 +1563,7 @@ dependencies = [
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@@ -1720,9 +1720,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.8"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
@@ -1788,7 +1788,7 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
|
||||
|
||||
[[package]]
|
||||
name = "leptos"
|
||||
version = "0.8.5"
|
||||
version = "0.8.8"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"base64",
|
||||
@@ -1869,7 +1869,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_axum"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"axum",
|
||||
@@ -1892,7 +1892,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_config"
|
||||
version = "0.8.5"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"config",
|
||||
"regex",
|
||||
@@ -1906,7 +1906,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_dom"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"leptos",
|
||||
@@ -1952,7 +1952,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_macro"
|
||||
version = "0.8.5"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"cfg-if",
|
||||
@@ -1972,7 +1972,7 @@ dependencies = [
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"server_fn",
|
||||
"server_fn_macro 0.8.5",
|
||||
"server_fn_macro 0.8.7",
|
||||
"syn 2.0.104",
|
||||
"tracing",
|
||||
"trybuild",
|
||||
@@ -1996,7 +1996,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"either_of",
|
||||
@@ -2054,9 +2054,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.174"
|
||||
version = "0.2.175"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
|
||||
[[package]]
|
||||
name = "linear-map"
|
||||
@@ -2238,18 +2238,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "munge"
|
||||
version = "0.4.5"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cce144fab80fbb74ec5b89d1ca9d41ddf6b644ab7e986f7d3ed0aab31625cb1"
|
||||
checksum = "d7feb0b48aa0a25f9fe0899482c6e1379ee7a11b24a53073eacdecb9adb6dc60"
|
||||
dependencies = [
|
||||
"munge_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "munge_macro"
|
||||
version = "0.4.5"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "574af9cd5b9971cbfdf535d6a8d533778481b241c447826d976101e0149392a1"
|
||||
checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2461,9 +2461,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c1de96e20f51df24ca73cafcc4690e044854d803259db27a00a461cb3b9d17a"
|
||||
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
|
||||
dependencies = [
|
||||
"cobs",
|
||||
"embedded-io 0.4.0",
|
||||
@@ -2498,9 +2498,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.35"
|
||||
version = "0.2.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a"
|
||||
checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.104",
|
||||
@@ -2574,9 +2574,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
version = "1.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
checksum = "beef09f85ae72cea1ef96ba6870c51e6382ebfa4f0e85b643459331f3daa5be0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -2627,7 +2627,7 @@ dependencies = [
|
||||
"quinn-udp",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustls",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -2664,9 +2664,9 @@ dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2746,13 +2746,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_graph"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-lock",
|
||||
"futures",
|
||||
"guardian",
|
||||
"hydration_context",
|
||||
"indexmap",
|
||||
"or_poisoned",
|
||||
"pin-project-lite",
|
||||
"rustc-hash 2.1.1",
|
||||
@@ -2788,7 +2789,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_stores_macro"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
dependencies = [
|
||||
"convert_case 0.8.0",
|
||||
"proc-macro-error2",
|
||||
@@ -2799,9 +2800,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.14"
|
||||
version = "0.5.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3a5d9f0aba1dbcec1cc47f0ff94a4b778fe55bca98a6dfa92e4e094e57b1c4"
|
||||
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@@ -2911,9 +2912,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65"
|
||||
checksum = "19f5c3e5da784cd8c69d32cdc84673f3204536ca56e1fa01be31a74b92c932ac"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
"bytes",
|
||||
@@ -2930,9 +2931,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a"
|
||||
checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2978,9 +2979,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.25"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
@@ -3018,9 +3019,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.29"
|
||||
version = "0.23.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1"
|
||||
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
@@ -3053,9 +3054,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.21"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
@@ -3194,9 +3195,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.141"
|
||||
version = "1.0.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
||||
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -3282,7 +3283,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"actix-ws",
|
||||
@@ -3345,7 +3346,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn_macro"
|
||||
version = "0.8.5"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"const_format",
|
||||
"convert_case 0.8.0",
|
||||
@@ -3360,7 +3361,7 @@ dependencies = [
|
||||
name = "server_fn_macro_default"
|
||||
version = "0.8.5"
|
||||
dependencies = [
|
||||
"server_fn_macro 0.8.5",
|
||||
"server_fn_macro 0.8.7",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
@@ -3394,9 +3395,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.5"
|
||||
version = "1.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
|
||||
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -3415,9 +3416,9 @@ checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
|
||||
[[package]]
|
||||
name = "sledgehammer_bindgen"
|
||||
@@ -3473,6 +3474,16 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
@@ -3562,7 +3573,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tachys"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-trait",
|
||||
@@ -3631,7 +3642,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3748,9 +3759,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.46.1"
|
||||
version = "1.47.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
|
||||
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -3761,9 +3772,9 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"socket2",
|
||||
"socket2 0.6.0",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3848,9 +3859,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.15"
|
||||
version = "0.7.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
|
||||
checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
@@ -3919,9 +3930,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30"
|
||||
checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
@@ -4028,9 +4039,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "trybuild"
|
||||
version = "1.0.106"
|
||||
version = "1.0.110"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65af40ad689f2527aebbd37a0a816aea88ff5f774ceabe99de5be02f2f91dae2"
|
||||
checksum = "32e257d7246e7a9fd015fb0b28b330a8d4142151a33f03e6a497754f4b1f6a8e"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"serde",
|
||||
@@ -4162,9 +4173,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.17.0"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
||||
checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
@@ -4339,15 +4350,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm_split_helpers"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"async-once-cell",
|
||||
"or_poisoned",
|
||||
"wasm_split_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm_split_macros"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"base16",
|
||||
"digest",
|
||||
@@ -4392,7 +4404,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4670,9 +4682,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.11.2"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
|
||||
checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
|
||||
dependencies = [
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
|
||||
51
Cargo.toml
51
Cargo.toml
@@ -40,7 +40,6 @@ members = [
|
||||
exclude = ["benchmarks", "examples", "projects"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.8.5"
|
||||
edition = "2021"
|
||||
rust-version = "1.88"
|
||||
|
||||
@@ -51,35 +50,35 @@ any_spawner = { path = "./any_spawner/", version = "0.3.0" }
|
||||
const_str_slice_concat = { path = "./const_str_slice_concat", version = "0.1" }
|
||||
either_of = { path = "./either_of/", version = "0.1.6" }
|
||||
hydration_context = { path = "./hydration_context", version = "0.3.0" }
|
||||
leptos = { path = "./leptos", version = "0.8.5" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.8.5" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.8.5" }
|
||||
leptos = { path = "./leptos", version = "0.8.8" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.8.7" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.8.6" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.8.5" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.8.5" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.8.5" }
|
||||
leptos_router = { path = "./router", version = "0.8.5" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.8.7" }
|
||||
leptos_router = { path = "./router", version = "0.8.6" }
|
||||
leptos_router_macro = { path = "./router_macro", version = "0.8.5" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.8.5" }
|
||||
leptos_meta = { path = "./meta", version = "0.8.5" }
|
||||
next_tuple = { path = "./next_tuple", version = "0.1.0" }
|
||||
oco_ref = { path = "./oco", version = "0.2.1" }
|
||||
or_poisoned = { path = "./or_poisoned", version = "0.1.0" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.2.5" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.2.6" }
|
||||
reactive_stores = { path = "./reactive_stores", version = "0.2.5" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.2.5" }
|
||||
server_fn = { path = "./server_fn", version = "0.8.5" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.8.5" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.2.6" }
|
||||
server_fn = { path = "./server_fn", version = "0.8.6" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.8.7" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.8.5" }
|
||||
tachys = { path = "./tachys", version = "0.2.6" }
|
||||
wasm_split_helpers = { path = "./wasm_split", version = "0.1.0" }
|
||||
wasm_split_macros = { path = "./wasm_split_macros", version = "0.1.0" }
|
||||
tachys = { path = "./tachys", version = "0.2.7" }
|
||||
wasm_split_helpers = { path = "./wasm_split", version = "0.1.2" }
|
||||
wasm_split_macros = { path = "./wasm_split_macros", version = "0.1.2" }
|
||||
|
||||
# members deps
|
||||
async-once-cell = { default-features = false, version = "0.5.3" }
|
||||
itertools = { default-features = false, version = "0.14.0" }
|
||||
convert_case = { default-features = false, version = "0.8.0" }
|
||||
serde_json = { default-features = false, version = "1.0.140" }
|
||||
trybuild = { default-features = false, version = "1.0.106" }
|
||||
serde_json = { default-features = false, version = "1.0.142" }
|
||||
trybuild = { default-features = false, version = "1.0.110" }
|
||||
typed-builder = { default-features = false, version = "0.21.0" }
|
||||
thiserror = { default-features = false, version = "2.0.12" }
|
||||
wasm-bindgen = { default-features = false, version = "0.2.100" }
|
||||
@@ -101,12 +100,12 @@ proc-macro-error2 = { default-features = false, version = "2.0.1" }
|
||||
const_format = { default-features = false, version = "0.2.34" }
|
||||
gloo-net = { default-features = false, version = "0.6.0" }
|
||||
url = { default-features = false, version = "2.5.4" }
|
||||
tokio = { default-features = false, version = "1.46.1" }
|
||||
tokio = { default-features = false, version = "1.47.1" }
|
||||
base64 = { default-features = false, version = "0.22.1" }
|
||||
cfg-if = { default-features = false, version = "1.0.0" }
|
||||
wasm-bindgen-futures = { default-features = false, version = "0.4.50" }
|
||||
tower = { default-features = false, version = "0.5.2" }
|
||||
proc-macro2 = { default-features = false, version = "1.0.95" }
|
||||
proc-macro2 = { default-features = false, version = "1.0.96" }
|
||||
serde = { default-features = false, version = "1.0.219" }
|
||||
parking_lot = { default-features = false, version = "0.12.4" }
|
||||
axum = { default-features = false, version = "0.8.4" }
|
||||
@@ -130,32 +129,32 @@ anyhow = { default-features = false, version = "1.0.98" }
|
||||
walkdir = { default-features = false, version = "2.5.0" }
|
||||
actix-ws = { default-features = false, version = "0.3.0" }
|
||||
tower-http = { default-features = false, version = "0.6.4" }
|
||||
prettyplease = { default-features = false, version = "0.2.35" }
|
||||
prettyplease = { default-features = false, version = "0.2.36" }
|
||||
inventory = { default-features = false, version = "0.3.20" }
|
||||
config = { default-features = false, version = "0.15.13" }
|
||||
camino = { default-features = false, version = "1.1.9" }
|
||||
camino = { default-features = false, version = "1.1.11" }
|
||||
ciborium = { default-features = false, version = "0.2.2" }
|
||||
multer = { default-features = false, version = "3.1.0" }
|
||||
leptos-spin-macro = { default-features = false, version = "0.2.0" }
|
||||
sledgehammer_utils = { default-features = false, version = "0.3.1" }
|
||||
sledgehammer_bindgen = { default-features = false, version = "0.6.0" }
|
||||
wasm-streams = { default-features = false, version = "0.4.2" }
|
||||
rkyv = { default-features = false, version = "0.8.10" }
|
||||
rkyv = { default-features = false, version = "0.8.11" }
|
||||
temp-env = { default-features = false, version = "0.3.6" }
|
||||
uuid = { default-features = false, version = "1.17.0" }
|
||||
uuid = { default-features = false, version = "1.18.0" }
|
||||
bytes = { default-features = false, version = "1.10.1" }
|
||||
http = { default-features = false, version = "1.3.1" }
|
||||
regex = { default-features = false, version = "1.11.1" }
|
||||
drain_filter_polyfill = { default-features = false, version = "0.1.3" }
|
||||
tempfile = { default-features = false, version = "3.20.0" }
|
||||
futures-lite = { default-features = false, version = "2.6.0" }
|
||||
futures-lite = { default-features = false, version = "2.6.1" }
|
||||
log = { default-features = false, version = "0.4.27" }
|
||||
percent-encoding = { default-features = false, version = "2.3.1" }
|
||||
async-executor = { default-features = false, version = "1.13.2" }
|
||||
const-str = { default-features = false, version = "0.6.3" }
|
||||
const-str = { default-features = false, version = "0.6.4" }
|
||||
http-body-util = { default-features = false, version = "0.1.3" }
|
||||
hyper = { default-features = false, version = "1.6.0" }
|
||||
postcard = { default-features = false, version = "1.1.1" }
|
||||
postcard = { default-features = false, version = "1.1.3" }
|
||||
rmp-serde = { default-features = false, version = "1.3.0" }
|
||||
reqwest = { default-features = false, version = "0.12.22" }
|
||||
tower-layer = { default-features = false, version = "0.3.3" }
|
||||
@@ -164,10 +163,10 @@ insta = { default-features = false, version = "1.43.1" }
|
||||
codee = { default-features = false, version = "0.3.0" }
|
||||
actix-http = { default-features = false, version = "3.11.0" }
|
||||
wasm-bindgen-test = { default-features = false, version = "0.3.50" }
|
||||
rustversion = { default-features = false, version = "1.0.21" }
|
||||
rustversion = { default-features = false, version = "1.0.22" }
|
||||
getrandom = { default-features = false, version = "0.3.3" }
|
||||
actix-files = { default-features = false, version = "0.6.6" }
|
||||
async-lock = { default-features = false, version = "3.4.0" }
|
||||
async-lock = { default-features = false, version = "3.4.1" }
|
||||
base16 = { default-features = false, version = "0.2.1" }
|
||||
digest = { default-features = false, version = "0.10.7" }
|
||||
sha2 = { default-features = false, version = "0.10.8" }
|
||||
|
||||
@@ -305,7 +305,10 @@ impl LazyRoute for ViewD {
|
||||
}
|
||||
}
|
||||
|
||||
// Server functions can be made lazy by combining the two macros,
|
||||
// with `#[server]` coming first, then `#[lazy]`
|
||||
#[server]
|
||||
#[lazy]
|
||||
async fn d_data() -> Result<Vec<i32>, ServerFnError> {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
|
||||
Ok(vec![1, 1, 2, 3, 5, 8, 13])
|
||||
|
||||
7
examples/regression/e2e/features/issue_4005.feature
Normal file
7
examples/regression/e2e/features/issue_4005.feature
Normal file
@@ -0,0 +1,7 @@
|
||||
@check_issue_4005
|
||||
Feature: Check that issue 4005 does not reappear
|
||||
|
||||
Scenario: The second item is selected.
|
||||
Given I see the app
|
||||
And I can access regression test 4005
|
||||
Then I see the value of select is 2
|
||||
9
examples/regression/e2e/features/issue_4217.feature
Normal file
9
examples/regression/e2e/features/issue_4217.feature
Normal file
@@ -0,0 +1,9 @@
|
||||
@check_issue_4217
|
||||
Feature: Check that issue 4217 does not reappear
|
||||
|
||||
Scenario: All items are selected.
|
||||
Given I see the app
|
||||
And I can access regression test 4217
|
||||
Then I see option1 is selected
|
||||
And I see option2 is selected
|
||||
And I see option3 is selected
|
||||
25
examples/regression/e2e/tests/fixtures/check.rs
vendored
25
examples/regression/e2e/tests/fixtures/check.rs
vendored
@@ -18,3 +18,28 @@ pub async fn element_exists(client: &Client, id: &str) -> Result<()> {
|
||||
.expect(&format!("could not find element with id `{id}`"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn select_option_is_selected(
|
||||
client: &Client,
|
||||
id: &str,
|
||||
) -> Result<()> {
|
||||
let el = find::element_by_id(client, id)
|
||||
.await
|
||||
.expect(&format!("could not find element with id `{id}`"));
|
||||
let selected = el.prop("selected").await?;
|
||||
assert_eq!(selected.as_deref(), Some("true"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn element_value_is(
|
||||
client: &Client,
|
||||
id: &str,
|
||||
expected: &str,
|
||||
) -> Result<()> {
|
||||
let el = find::element_by_id(client, id)
|
||||
.await
|
||||
.expect(&format!("could not find element with id `{id}`"));
|
||||
let value = el.prop("value").await?;
|
||||
assert_eq!(value.as_deref(), Some(expected));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -25,3 +25,21 @@ async fn i_see_the_navbar(world: &mut AppWorld) -> Result<()> {
|
||||
check::element_exists(client, "nav").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[then(regex = r"^I see ([\d\w]+) is selected$")]
|
||||
async fn i_see_the_select(world: &mut AppWorld, id: String) -> Result<()> {
|
||||
let client = &world.client;
|
||||
check::select_option_is_selected(client, &id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[then(regex = r"^I see the value of (\w+) is (.*)$")]
|
||||
async fn i_see_the_value(
|
||||
world: &mut AppWorld,
|
||||
id: String,
|
||||
value: String,
|
||||
) -> Result<()> {
|
||||
let client = &world.client;
|
||||
check::element_value_is(client, &id, &value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::{issue_4088::Routes4088, pr_4015::Routes4015, pr_4091::Routes4091};
|
||||
use crate::{
|
||||
issue_4005::Routes4005, issue_4088::Routes4088, issue_4217::Routes4217,
|
||||
pr_4015::Routes4015, pr_4091::Routes4091,
|
||||
};
|
||||
use leptos::prelude::*;
|
||||
use leptos_meta::{MetaTags, *};
|
||||
use leptos_router::{
|
||||
@@ -37,6 +40,8 @@ pub fn App() -> impl IntoView {
|
||||
<Routes4091/>
|
||||
<Routes4015/>
|
||||
<Routes4088/>
|
||||
<Routes4217/>
|
||||
<Routes4005/>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
@@ -59,6 +64,8 @@ fn HomePage() -> impl IntoView {
|
||||
<li><a href="/4091/">"4091"</a></li>
|
||||
<li><a href="/4015/">"4015"</a></li>
|
||||
<li><a href="/4088/">"4088"</a></li>
|
||||
<li><a href="/4217/">"4217"</a></li>
|
||||
<li><a href="/4005/">"4005"</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
}
|
||||
|
||||
24
examples/regression/src/issue_4005.rs
Normal file
24
examples/regression/src/issue_4005.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use leptos::prelude::*;
|
||||
#[allow(unused_imports)]
|
||||
use leptos_router::{
|
||||
components::Route, path, MatchNestedRoutes, NavigateOptions,
|
||||
};
|
||||
|
||||
#[component]
|
||||
pub fn Routes4005() -> impl MatchNestedRoutes + Clone {
|
||||
view! {
|
||||
<Route path=path!("4005") view=Issue4005/>
|
||||
}
|
||||
.into_inner()
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Issue4005() -> impl IntoView {
|
||||
view! {
|
||||
<select id="select" prop:value="2">
|
||||
<option value="1">"Option 1"</option>
|
||||
<option value="2">"Option 2"</option>
|
||||
<option value="3">"Option 3"</option>
|
||||
</select>
|
||||
}
|
||||
}
|
||||
24
examples/regression/src/issue_4217.rs
Normal file
24
examples/regression/src/issue_4217.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use leptos::prelude::*;
|
||||
#[allow(unused_imports)]
|
||||
use leptos_router::{
|
||||
components::Route, path, MatchNestedRoutes, NavigateOptions,
|
||||
};
|
||||
|
||||
#[component]
|
||||
pub fn Routes4217() -> impl MatchNestedRoutes + Clone {
|
||||
view! {
|
||||
<Route path=path!("4217") view=Issue4217/>
|
||||
}
|
||||
.into_inner()
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Issue4217() -> impl IntoView {
|
||||
view! {
|
||||
<select multiple=true>
|
||||
<option id="option1" value="1" selected>"Option 1"</option>
|
||||
<option id="option2" value="2" selected>"Option 2"</option>
|
||||
<option id="option3" value="3" selected>"Option 3"</option>
|
||||
</select>
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
pub mod app;
|
||||
mod issue_4005;
|
||||
mod issue_4088;
|
||||
mod issue_4217;
|
||||
mod pr_4015;
|
||||
mod pr_4091;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Actix integrations for the Leptos web framework."
|
||||
version = { workspace = true }
|
||||
version = "0.8.5"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -22,10 +22,10 @@ leptos_meta = { workspace = true, features = ["nonce"] }
|
||||
leptos_router = { workspace = true, features = ["ssr"] }
|
||||
server_fn = { workspace = true, features = ["actix-no-default"] }
|
||||
tachys = { workspace = true }
|
||||
serde_json = { workspace = true , default-features = true }
|
||||
serde_json = { workspace = true, default-features = true }
|
||||
parking_lot = { workspace = true, default-features = true }
|
||||
tracing = { optional = true , workspace = true, default-features = true }
|
||||
tokio = { features = ["rt", "fs"] , workspace = true, default-features = true }
|
||||
tracing = { optional = true, workspace = true, default-features = true }
|
||||
tokio = { features = ["rt", "fs"], workspace = true, default-features = true }
|
||||
send_wrapper = { workspace = true, default-features = true }
|
||||
dashmap = { workspace = true, default-features = true }
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Axum integrations for the Leptos web framework."
|
||||
version = { workspace = true }
|
||||
version = "0.8.6"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
|
||||
@@ -1177,7 +1177,7 @@ where
|
||||
generate_route_list_with_exclusions_and_ssg(app_fn, None).0
|
||||
}
|
||||
|
||||
/// Generates a list of all routes defined in Leptos's Router in your app. We can then use t.clone()his to automatically
|
||||
/// Generates a list of all routes defined in Leptos's Router in your app. We can then use this to automatically
|
||||
/// create routes in Axum's Router without having to use wildcard matching or fallbacks. Takes in your root app Element
|
||||
/// as an argument so it can walk you app tree. This version is tailored to generate Axum compatible paths.
|
||||
#[cfg_attr(
|
||||
@@ -2061,10 +2061,12 @@ where
|
||||
req,
|
||||
|app, chunks, _supports_ooo| {
|
||||
Box::pin(async move {
|
||||
let app = app
|
||||
.to_html_stream_in_order()
|
||||
.collect::<String>()
|
||||
.await;
|
||||
let app = if cfg!(feature = "islands-router") {
|
||||
app.to_html_stream_in_order_branching()
|
||||
} else {
|
||||
app.to_html_stream_in_order()
|
||||
};
|
||||
let app = app.collect::<String>().await;
|
||||
let chunks = chunks();
|
||||
Box::pin(once(async move { app }).chain(chunks))
|
||||
as PinnedStream<String>
|
||||
|
||||
@@ -4,7 +4,7 @@ authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Utilities to help build server integrations for the Leptos web framework."
|
||||
version = { workspace = true }
|
||||
version = "0.8.5"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos"
|
||||
version = { workspace = true }
|
||||
version = "0.8.8"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -215,12 +215,15 @@ pub mod error {
|
||||
|
||||
/// Control-flow components like `<Show>`, `<For>`, and `<Await>`.
|
||||
pub mod control_flow {
|
||||
pub use crate::{animated_show::*, await_::*, for_loop::*, show::*};
|
||||
pub use crate::{
|
||||
animated_show::*, await_::*, for_loop::*, show::*, show_let::*,
|
||||
};
|
||||
}
|
||||
mod animated_show;
|
||||
mod await_;
|
||||
mod for_loop;
|
||||
mod show;
|
||||
mod show_let;
|
||||
|
||||
/// A component that allows rendering a component somewhere else.
|
||||
pub mod portal;
|
||||
@@ -301,12 +304,17 @@ pub mod logging {
|
||||
/// Utilities for working with asynchronous tasks.
|
||||
pub mod task {
|
||||
use any_spawner::Executor;
|
||||
use reactive_graph::computed::ScopedFuture;
|
||||
use std::future::Future;
|
||||
|
||||
/// Spawns a thread-safe [`Future`].
|
||||
///
|
||||
/// This will be run with the current reactive owner and observer using a [`ScopedFuture`].
|
||||
#[track_caller]
|
||||
#[inline(always)]
|
||||
pub fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
|
||||
let fut = ScopedFuture::new(fut);
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
Executor::spawn(fut);
|
||||
|
||||
@@ -348,6 +356,7 @@ pub use web_sys;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod __reexports {
|
||||
pub use send_wrapper;
|
||||
pub use wasm_bindgen_futures;
|
||||
}
|
||||
|
||||
|
||||
162
leptos/src/show_let.rs
Normal file
162
leptos/src/show_let.rs
Normal file
@@ -0,0 +1,162 @@
|
||||
use crate::{children::ViewFn, IntoView};
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::traits::Get;
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
use tachys::either::Either;
|
||||
|
||||
/// Like `<Show>` but for `Option`. This is a shortcut for
|
||||
///
|
||||
/// ```ignore
|
||||
/// value.map(|value| {
|
||||
/// view! { ... }
|
||||
/// })
|
||||
/// ```
|
||||
///
|
||||
/// If you specify a `fallback` it is equvalent to
|
||||
///
|
||||
/// ```ignore
|
||||
/// value
|
||||
/// .map(
|
||||
/// |value| children(value),
|
||||
/// )
|
||||
/// .unwrap_or_else(fallback)
|
||||
/// ```
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```
|
||||
/// # use leptos::prelude::*;
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # pub fn Example() -> impl IntoView {
|
||||
/// let (opt_value, set_opt_value) = signal(None::<i32>);
|
||||
///
|
||||
/// view! {
|
||||
/// <ShowLet some=opt_value let:value>
|
||||
/// "We have a value: " {value}
|
||||
/// </ShowLet>
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// You can also specify a fallback:
|
||||
/// ```
|
||||
/// # use leptos::prelude::*;
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # pub fn Example() -> impl IntoView {
|
||||
/// let (opt_value, set_opt_value) = signal(None::<i32>);
|
||||
///
|
||||
/// view! {
|
||||
/// <ShowLet some=opt_value let:value fallback=|| "Got nothing">
|
||||
/// "We have a value: " {value}
|
||||
/// </ShowLet>
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// In addition to signals you can also use a closure that returns an `Option`:
|
||||
///
|
||||
/// ```
|
||||
/// # use leptos::prelude::*;
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # pub fn Example() -> impl IntoView {
|
||||
/// let (opt_value, set_opt_value) = signal(None::<i32>);
|
||||
///
|
||||
/// view! {
|
||||
/// <ShowLet some=move || opt_value.get().map(|v| v * 2) let:value>
|
||||
/// "We have a value: " {value}
|
||||
/// </ShowLet>
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[component]
|
||||
pub fn ShowLet<T, ChFn, V, M>(
|
||||
/// The children will be shown whenever `value` is `Some`.
|
||||
///
|
||||
/// They take the inner value as an argument. Use `let:` to bind the value to a variable.
|
||||
children: ChFn,
|
||||
|
||||
/// A signal of type `Option` or a closure that returns an `Option`.
|
||||
/// If the value is `Some`, the children will be shown.
|
||||
/// Otherwise the fallback will be shown, if present.
|
||||
some: impl IntoOptionGetter<T, M>,
|
||||
|
||||
/// A closure that returns what gets rendered when the value is `None`.
|
||||
/// By default this is the empty view.
|
||||
///
|
||||
/// You can think of it as the closure inside `.unwrap_or_else(|| fallback())`.
|
||||
#[prop(optional, into)]
|
||||
fallback: ViewFn,
|
||||
|
||||
/// Marker for generic parameters. Ignore this.
|
||||
#[prop(optional)]
|
||||
_marker: PhantomData<(T, M)>,
|
||||
) -> impl IntoView
|
||||
where
|
||||
ChFn: Fn(T) -> V + Send + Clone + 'static,
|
||||
V: IntoView + 'static,
|
||||
T: 'static,
|
||||
{
|
||||
let getter = some.into_option_getter();
|
||||
|
||||
move || {
|
||||
let children = children.clone();
|
||||
let fallback = fallback.clone();
|
||||
|
||||
getter
|
||||
.run()
|
||||
.map(move |t| Either::Left(children(t)))
|
||||
.unwrap_or_else(move || Either::Right(fallback.run()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Servers as a wrapper for both, an `Option` signal or a closure that returns an `Option`.
|
||||
pub struct OptionGetter<T>(Arc<dyn Fn() -> Option<T> + Send + Sync + 'static>);
|
||||
|
||||
impl<T> Clone for OptionGetter<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(Arc::clone(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OptionGetter<T> {
|
||||
/// Runs the getter and returns the result.
|
||||
pub fn run(&self) -> Option<T> {
|
||||
(self.0)()
|
||||
}
|
||||
}
|
||||
|
||||
/// Conversion trait for creating an `OptionGetter` from a closure or a signal.
|
||||
pub trait IntoOptionGetter<T, M> {
|
||||
/// Converts the given value into an `OptionGetter`.
|
||||
fn into_option_getter(self) -> OptionGetter<T>;
|
||||
}
|
||||
|
||||
/// Marker type for creating an `OptionGetter` from a closure.
|
||||
/// Used so that the compiler doesn't complain about double implementations of the trait `IntoOptionGetter`.
|
||||
pub struct FunctionMarker;
|
||||
|
||||
impl<T, F> IntoOptionGetter<T, FunctionMarker> for F
|
||||
where
|
||||
F: Fn() -> Option<T> + Send + Sync + 'static,
|
||||
{
|
||||
fn into_option_getter(self) -> OptionGetter<T> {
|
||||
OptionGetter(Arc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker type for creating an `OptionGetter` from a signal.
|
||||
/// Used so that the compiler doesn't complain about double implementations of the trait `IntoOptionGetter`.
|
||||
pub struct SignalMarker;
|
||||
|
||||
impl<T, S> IntoOptionGetter<T, SignalMarker> for S
|
||||
where
|
||||
S: Get<Value = Option<T>> + Clone + Send + Sync + 'static,
|
||||
{
|
||||
fn into_option_getter(self) -> OptionGetter<T> {
|
||||
let cloned = self.clone();
|
||||
OptionGetter(Arc::new(move || cloned.get()))
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Configuration for the Leptos web framework."
|
||||
readme = "../README.md"
|
||||
version = { workspace = true }
|
||||
version = "0.8.7"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -13,16 +13,24 @@ edition.workspace = true
|
||||
config = { default-features = false, features = [
|
||||
"toml",
|
||||
"convert-case",
|
||||
] , workspace = true }
|
||||
], workspace = true }
|
||||
regex = { workspace = true, default-features = true }
|
||||
serde = { features = ["derive", "rc"] , workspace = true, default-features = true }
|
||||
thiserror = { workspace = true , default-features = true }
|
||||
typed-builder = { workspace = true , default-features = true }
|
||||
serde = { features = [
|
||||
"derive",
|
||||
"rc",
|
||||
], workspace = true, default-features = true }
|
||||
thiserror = { workspace = true, default-features = true }
|
||||
typed-builder = { workspace = true, default-features = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { features = ["rt", "macros"] , workspace = true, default-features = true }
|
||||
tokio = { features = [
|
||||
"rt",
|
||||
"macros",
|
||||
], workspace = true, default-features = true }
|
||||
tempfile = { workspace = true, default-features = true }
|
||||
temp-env = { features = ["async_closure"] , workspace = true, default-features = true }
|
||||
temp-env = { features = [
|
||||
"async_closure",
|
||||
], workspace = true, default-features = true }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_dom"
|
||||
version = { workspace = true }
|
||||
version = "0.8.6"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -14,10 +14,10 @@ reactive_graph = { workspace = true }
|
||||
or_poisoned = { workspace = true }
|
||||
js-sys = { workspace = true, default-features = true }
|
||||
send_wrapper = { workspace = true, default-features = true }
|
||||
tracing = { optional = true , workspace = true, default-features = true }
|
||||
wasm-bindgen = { workspace = true , default-features = true }
|
||||
serde_json = { optional = true , workspace = true, default-features = true }
|
||||
serde = { optional = true , workspace = true, default-features = true }
|
||||
tracing = { optional = true, workspace = true, default-features = true }
|
||||
wasm-bindgen = { workspace = true, default-features = true }
|
||||
serde_json = { optional = true, workspace = true, default-features = true }
|
||||
serde = { optional = true, workspace = true, default-features = true }
|
||||
|
||||
[dev-dependencies]
|
||||
leptos = { path = "../leptos" }
|
||||
|
||||
@@ -258,15 +258,7 @@ pub fn request_idle_callback_with_handle(
|
||||
///
|
||||
/// <div class="warning">The task is called outside of the ownership tree, this means that if you want to access for example the context you need to reestablish the owner.</div>
|
||||
pub fn queue_microtask(task: impl FnOnce() + 'static) {
|
||||
use js_sys::{Function, Reflect};
|
||||
|
||||
let task = Closure::once_into_js(task);
|
||||
let window = web_sys::window().expect("window not available");
|
||||
let queue_microtask =
|
||||
Reflect::get(&window, &JsValue::from_str("queueMicrotask"))
|
||||
.expect("queueMicrotask not available");
|
||||
let queue_microtask = queue_microtask.unchecked_into::<Function>();
|
||||
_ = queue_microtask.call1(&JsValue::UNDEFINED, &task);
|
||||
tachys::renderer::dom::queue_microtask(task);
|
||||
}
|
||||
|
||||
/// Handle that is generated by [set_timeout_with_handle] and can be used to clear the timeout.
|
||||
@@ -593,7 +585,8 @@ impl WindowListenerHandle {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_server() -> bool {
|
||||
/// Returns `true` if the current environment is a server.
|
||||
pub fn is_server() -> bool {
|
||||
#[cfg(feature = "hydration")]
|
||||
{
|
||||
Owner::current_shared_context()
|
||||
@@ -605,3 +598,8 @@ fn is_server() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the current environment is a browser.
|
||||
pub fn is_browser() -> bool {
|
||||
!is_server()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_hot_reload"
|
||||
version = { workspace = true }
|
||||
version = "0.8.5"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -11,17 +11,20 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true, default-features = true }
|
||||
serde = { features = ["derive"] , workspace = true, default-features = true }
|
||||
serde = { features = ["derive"], workspace = true, default-features = true }
|
||||
syn = { features = [
|
||||
"full",
|
||||
"parsing",
|
||||
"extra-traits",
|
||||
"visit",
|
||||
"printing",
|
||||
] , workspace = true, default-features = true }
|
||||
], workspace = true, default-features = true }
|
||||
quote = { workspace = true, default-features = true }
|
||||
rstml = { workspace = true, default-features = true }
|
||||
proc-macro2 = { features = ["span-locations", "nightly"] , workspace = true, default-features = true }
|
||||
proc-macro2 = { features = [
|
||||
"span-locations",
|
||||
"nightly",
|
||||
], workspace = true, default-features = true }
|
||||
parking_lot = { workspace = true, default-features = true }
|
||||
walkdir = { workspace = true, default-features = true }
|
||||
camino = { workspace = true, default-features = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_macro"
|
||||
version = { workspace = true }
|
||||
version = "0.8.7"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -13,26 +13,30 @@ edition.workspace = true
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
attribute-derive = { features = ["syn-full"] , workspace = true, default-features = true }
|
||||
attribute-derive = { features = [
|
||||
"syn-full",
|
||||
], workspace = true, default-features = true }
|
||||
cfg-if = { workspace = true, default-features = true }
|
||||
html-escape = { workspace = true, default-features = true }
|
||||
itertools = { workspace = true , default-features = true }
|
||||
itertools = { workspace = true, default-features = true }
|
||||
prettyplease = { workspace = true, default-features = true }
|
||||
proc-macro-error2 = { default-features = false , workspace = true }
|
||||
proc-macro-error2 = { default-features = false, workspace = true }
|
||||
proc-macro2 = { workspace = true, default-features = true }
|
||||
quote = { workspace = true, default-features = true }
|
||||
syn = { features = ["full"] , workspace = true, default-features = true }
|
||||
rstml = { workspace = true, default-features = true }
|
||||
syn = { features = ["full"], workspace = true, default-features = true }
|
||||
rstml = { workspace = true, default-features = true, features = [
|
||||
"rawtext-stable-hack",
|
||||
] }
|
||||
leptos_hot_reload = { workspace = true }
|
||||
server_fn_macro = { workspace = true }
|
||||
convert_case = { workspace = true , default-features = true }
|
||||
uuid = { features = ["v4"] , workspace = true, default-features = true }
|
||||
tracing = { optional = true , workspace = true, default-features = true }
|
||||
convert_case = { workspace = true, default-features = true }
|
||||
uuid = { features = ["v4"], workspace = true, default-features = true }
|
||||
tracing = { optional = true, workspace = true, default-features = true }
|
||||
|
||||
[dev-dependencies]
|
||||
log = { workspace = true, default-features = true }
|
||||
typed-builder = { workspace = true, default-features = true }
|
||||
trybuild = { workspace = true , default-features = true }
|
||||
trybuild = { workspace = true, default-features = true }
|
||||
leptos = { path = "../leptos" }
|
||||
leptos_router = { path = "../router", features = ["ssr"] }
|
||||
server_fn = { path = "../server_fn", features = ["cbor"] }
|
||||
|
||||
@@ -548,7 +548,7 @@ impl ToTokens for Model {
|
||||
quote! {
|
||||
#[::leptos::prelude::lazy]
|
||||
#[allow(non_snake_case)]
|
||||
async fn #outer_name (el: ::leptos::web_sys::HtmlElement) {
|
||||
fn #outer_name (el: ::leptos::web_sys::HtmlElement) {
|
||||
#hydrate_fn_inner
|
||||
}
|
||||
|
||||
@@ -1360,7 +1360,10 @@ fn prop_to_doc(
|
||||
}
|
||||
|
||||
pub fn unmodified_fn_name_from_fn_name(ident: &Ident) -> Ident {
|
||||
Ident::new(&format!("__{ident}"), ident.span())
|
||||
Ident::new(
|
||||
&format!("__component_{}", ident.to_string().to_case(Snake)),
|
||||
ident.span(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Converts all `impl Trait`s in a function signature to use generic params instead.
|
||||
|
||||
@@ -48,7 +48,10 @@ pub fn lazy_impl(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
||||
let is_wasm = cfg!(feature = "csr") || cfg!(feature = "hydrate");
|
||||
if is_wasm {
|
||||
quote! {
|
||||
#[::leptos::wasm_split_helpers::wasm_split(#unique_name)]
|
||||
#[::leptos::wasm_split_helpers::wasm_split(
|
||||
#unique_name,
|
||||
::leptos::__reexports::send_wrapper
|
||||
)]
|
||||
#fun
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -323,7 +323,14 @@ fn view_macro_impl(tokens: TokenStream, template: bool) -> TokenStream {
|
||||
.chain(tokens)
|
||||
.collect()
|
||||
};
|
||||
let config = rstml::ParserConfig::default().recover_block(true);
|
||||
let macro_call_pattern = if let Some(class) = &global_class {
|
||||
quote!(view! { class = #class, %% })
|
||||
} else {
|
||||
quote!(view! {%%})
|
||||
};
|
||||
let config = rstml::ParserConfig::default()
|
||||
.recover_block(true)
|
||||
.macro_call_pattern(macro_call_pattern);
|
||||
let parser = rstml::Parser::new(config);
|
||||
let (mut nodes, errors) = parser.parse_recoverable(tokens).split_vec();
|
||||
let errors = errors.into_iter().map(|e| e.emit_as_expr_tokens());
|
||||
@@ -683,7 +690,11 @@ fn component_macro(
|
||||
let parse_result = syn::parse::<component::Model>(s);
|
||||
|
||||
if let (Ok(ref mut unexpanded), Ok(model)) = (&mut dummy, parse_result) {
|
||||
let expanded = model.is_transparent(is_transparent).is_lazy(is_lazy).with_island(island).into_token_stream();
|
||||
let expanded = model
|
||||
.is_transparent(is_transparent)
|
||||
.is_lazy(is_lazy)
|
||||
.with_island(island)
|
||||
.into_token_stream();
|
||||
if !matches!(unexpanded.vis, Visibility::Public(_)) {
|
||||
unexpanded.vis = Visibility::Public(Pub {
|
||||
span: unexpanded.vis.span(),
|
||||
@@ -696,7 +707,7 @@ fn component_macro(
|
||||
#expanded
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case, dead_code, clippy::too_many_arguments, clippy::needless_lifetimes)]
|
||||
#[allow(clippy::too_many_arguments, clippy::needless_lifetimes)]
|
||||
#unexpanded
|
||||
}
|
||||
} else {
|
||||
@@ -705,7 +716,7 @@ fn component_macro(
|
||||
dummy.sig.ident = unmodified_fn_name_from_fn_name(&dummy.sig.ident);
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case, dead_code, clippy::too_many_arguments, clippy::needless_lifetimes)]
|
||||
#[allow(clippy::too_many_arguments, clippy::needless_lifetimes)]
|
||||
#dummy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_server"
|
||||
version = { workspace = true }
|
||||
version = "0.8.5"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -11,11 +11,11 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
base64 = { workspace = true, default-features = true }
|
||||
codee = { features = ["json_serde"] , workspace = true, default-features = true }
|
||||
codee = { features = ["json_serde"], workspace = true, default-features = true }
|
||||
hydration_context = { workspace = true }
|
||||
reactive_graph = { workspace = true, features = ["hydration"] }
|
||||
server_fn = { workspace = true }
|
||||
tracing = { optional = true , workspace = true, default-features = true }
|
||||
tracing = { optional = true, workspace = true, default-features = true }
|
||||
futures = { workspace = true, default-features = true }
|
||||
|
||||
any_spawner = { workspace = true }
|
||||
@@ -25,9 +25,9 @@ send_wrapper = { workspace = true, default-features = true }
|
||||
|
||||
# serialization formats
|
||||
serde = { workspace = true, default-features = true }
|
||||
js-sys = { optional = true , workspace = true, default-features = true }
|
||||
wasm-bindgen = { workspace = true, optional = true , default-features = true }
|
||||
serde_json = { workspace = true , default-features = true }
|
||||
js-sys = { optional = true, workspace = true, default-features = true }
|
||||
wasm-bindgen = { workspace = true, optional = true, default-features = true }
|
||||
serde_json = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
ssr = []
|
||||
@@ -44,7 +44,8 @@ denylist = ["tracing"]
|
||||
max_combination_size = 2
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
rustdoc-args = ["--generate-link-to-definition", "--cfg", "docsrs"]
|
||||
all-features = true
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
|
||||
@@ -386,6 +386,7 @@ T: Send + Sync + 'static,
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> ArcOnceResource<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -418,6 +419,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> ArcOnceResource<T, MiniserdeCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -451,6 +453,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> ArcOnceResource<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -484,6 +487,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> ArcOnceResource<T, RkyvCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -748,6 +752,7 @@ T: Send + Sync + 'static,
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> OnceResource<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -780,6 +785,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> OnceResource<T, MiniserdeCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -813,6 +819,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> OnceResource<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -846,6 +853,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> OnceResource<T, RkyvCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
|
||||
@@ -709,6 +709,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> ArcResource<T, RkyvCodec>
|
||||
where
|
||||
RkyvCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -1048,6 +1049,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> Resource<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
JsonSerdeWasmCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -1105,6 +1107,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> Resource<T, MiniserdeCodec>
|
||||
where
|
||||
MiniserdeCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -1164,6 +1167,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> Resource<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
SerdeLite<JsonSerdeCodec>: Encoder<T> + Decoder<T>,
|
||||
@@ -1222,6 +1226,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> Resource<T, RkyvCodec>
|
||||
where
|
||||
RkyvCodec: Encoder<T> + Decoder<T>,
|
||||
|
||||
@@ -80,6 +80,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> SharedValue<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
SerdeLite<JsonSerdeCodec>: Encoder<T> + Decoder<T>,
|
||||
@@ -102,6 +103,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> SharedValue<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
JsonSerdeWasmCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -124,6 +126,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> SharedValue<T, MiniserdeCodec>
|
||||
where
|
||||
MiniserdeCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -146,6 +149,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> SharedValue<T, RkyvCodec>
|
||||
where
|
||||
RkyvCodec: Encoder<T> + Decoder<T>,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_meta"
|
||||
version = { workspace = true }
|
||||
version = "0.8.5"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_graph"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
@@ -27,6 +27,7 @@ async-lock = { workspace = true, default-features = true }
|
||||
send_wrapper = { features = [
|
||||
"futures",
|
||||
], workspace = true, default-features = true }
|
||||
indexmap = { workspace = true, default-features = true }
|
||||
|
||||
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
|
||||
web-sys = { version = "0.3.77", features = ["console"] }
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
//! a linear search is not significantly more expensive than a hash and lookup.
|
||||
|
||||
use super::{AnySource, AnySubscriber, Source};
|
||||
use core::slice;
|
||||
use std::{mem, vec::IntoIter};
|
||||
use indexmap::IndexSet;
|
||||
use rustc_hash::FxHasher;
|
||||
use std::{hash::BuildHasherDefault, mem};
|
||||
|
||||
type FxIndexSet<T> = IndexSet<T, BuildHasherDefault<FxHasher>>;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct SourceSet(Vec<AnySource>);
|
||||
pub struct SourceSet(FxIndexSet<AnySource>);
|
||||
|
||||
impl SourceSet {
|
||||
pub fn new() -> Self {
|
||||
@@ -18,16 +21,14 @@ impl SourceSet {
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, source: AnySource) {
|
||||
self.0.push(source);
|
||||
self.0.insert(source);
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, source: &AnySource) {
|
||||
if let Some(pos) = self.0.iter().position(|s| s == source) {
|
||||
self.0.remove(pos);
|
||||
}
|
||||
self.0.shift_remove(source);
|
||||
}
|
||||
|
||||
pub fn take(&mut self) -> Vec<AnySource> {
|
||||
pub fn take(&mut self) -> FxIndexSet<AnySource> {
|
||||
mem::take(&mut self.0)
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ impl SourceSet {
|
||||
|
||||
impl IntoIterator for SourceSet {
|
||||
type Item = AnySource;
|
||||
type IntoIter = IntoIter<AnySource>;
|
||||
type IntoIter = <FxIndexSet<AnySource> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
@@ -53,40 +54,36 @@ impl IntoIterator for SourceSet {
|
||||
|
||||
impl<'a> IntoIterator for &'a SourceSet {
|
||||
type Item = &'a AnySource;
|
||||
type IntoIter = slice::Iter<'a, AnySource>;
|
||||
type IntoIter = <&'a FxIndexSet<AnySource> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct SubscriberSet(Vec<AnySubscriber>);
|
||||
pub struct SubscriberSet(FxIndexSet<AnySubscriber>);
|
||||
|
||||
impl SubscriberSet {
|
||||
pub fn new() -> Self {
|
||||
Self(Vec::with_capacity(2))
|
||||
Self(FxIndexSet::with_capacity_and_hasher(2, Default::default()))
|
||||
}
|
||||
|
||||
pub fn subscribe(&mut self, subscriber: AnySubscriber) {
|
||||
if !self.0.contains(&subscriber) {
|
||||
self.0.push(subscriber);
|
||||
}
|
||||
self.0.insert(subscriber);
|
||||
}
|
||||
|
||||
pub fn unsubscribe(&mut self, subscriber: &AnySubscriber) {
|
||||
if let Some(pos) = self.0.iter().position(|s| s == subscriber) {
|
||||
// note: do not use `.swap_remove()` here.
|
||||
// using `.remove()` is slower because it shifts other items
|
||||
// but it maintains the order of the subscribers, which is important
|
||||
// to correctness when you're using this to drive something like a UI,
|
||||
// which can have nested effects, where the inner one assumes the outer
|
||||
// has already run (for example, an outer effect that checks .is_some(),
|
||||
// and an inner effect that unwraps)
|
||||
self.0.remove(pos);
|
||||
}
|
||||
// note: do not use `.swap_remove()` here.
|
||||
// using `.remove()` is slower because it shifts other items
|
||||
// but it maintains the order of the subscribers, which is important
|
||||
// to correctness when you're using this to drive something like a UI,
|
||||
// which can have nested effects, where the inner one assumes the outer
|
||||
// has already run (for example, an outer effect that checks .is_some(),
|
||||
// and an inner effect that unwraps)
|
||||
self.0.shift_remove(subscriber);
|
||||
}
|
||||
|
||||
pub fn take(&mut self) -> Vec<AnySubscriber> {
|
||||
pub fn take(&mut self) -> FxIndexSet<AnySubscriber> {
|
||||
mem::take(&mut self.0)
|
||||
}
|
||||
|
||||
@@ -97,7 +94,7 @@ impl SubscriberSet {
|
||||
|
||||
impl IntoIterator for SubscriberSet {
|
||||
type Item = AnySubscriber;
|
||||
type IntoIter = IntoIter<AnySubscriber>;
|
||||
type IntoIter = <FxIndexSet<AnySubscriber> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
@@ -106,7 +103,7 @@ impl IntoIterator for SubscriberSet {
|
||||
|
||||
impl<'a> IntoIterator for &'a SubscriberSet {
|
||||
type Item = &'a AnySubscriber;
|
||||
type IntoIter = slice::Iter<'a, AnySubscriber>;
|
||||
type IntoIter = <&'a FxIndexSet<AnySubscriber> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.iter()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_stores_macro"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -6,8 +6,8 @@ use syn::{
|
||||
parse::{Parse, ParseStream, Parser},
|
||||
punctuated::Punctuated,
|
||||
token::Comma,
|
||||
ExprClosure, Field, Fields, Generics, Ident, Index, Meta, Result, Token,
|
||||
Type, Variant, Visibility, WhereClause,
|
||||
ExprClosure, Field, Fields, GenericParam, Generics, Ident, Index, Meta,
|
||||
Result, Token, Type, TypeParam, Variant, Visibility, WhereClause,
|
||||
};
|
||||
|
||||
#[proc_macro_error]
|
||||
@@ -26,6 +26,103 @@ pub fn derive_patch(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Removes all constraints from generics arguments list.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// struct Data<
|
||||
/// 'a,
|
||||
/// T1: ToString + PatchField,
|
||||
/// T2: PatchField,
|
||||
/// T3: 'static + PatchField,
|
||||
/// T4,
|
||||
/// >
|
||||
/// where
|
||||
/// T3: ToString,
|
||||
/// T4: ToString + PatchField,
|
||||
/// {
|
||||
/// data1: &'a T1,
|
||||
/// data2: T2,
|
||||
/// data3: T3,
|
||||
/// data4: T4,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Fort the struct above the `[syn::DeriveInput::parse]` will return the instance of [syn::Generics]
|
||||
/// which will conceptually look like this
|
||||
///
|
||||
/// ```text
|
||||
/// Generics:
|
||||
/// params:
|
||||
/// [
|
||||
/// 'a,
|
||||
/// T1: ToString + PatchField,
|
||||
/// T2: PatchField,
|
||||
/// T3: 'static + PatchField,
|
||||
/// T4,
|
||||
/// ]
|
||||
/// where_clause:
|
||||
/// [
|
||||
/// T3: ToString,
|
||||
/// T4: ToString + PatchField,
|
||||
/// ]
|
||||
/// ```
|
||||
///
|
||||
/// This method would return a new instance of [syn::Generics] which will conceptually look like this
|
||||
///
|
||||
/// ```text
|
||||
/// Generics:
|
||||
/// params:
|
||||
/// [
|
||||
/// 'a,
|
||||
/// T1,
|
||||
/// T2,
|
||||
/// T3,
|
||||
/// T4,
|
||||
/// ]
|
||||
/// where_clause:
|
||||
/// []
|
||||
/// ```
|
||||
///
|
||||
/// This is useful when you want to use a generic arguments list for `impl` sections for type definitions.
|
||||
fn remove_constraint_from_generics(generics: &Generics) -> Generics {
|
||||
let mut new_generics = generics.clone();
|
||||
|
||||
// remove contraints directly placed in the generic arguments list
|
||||
//
|
||||
// For generics for `struct A<T: MyTrait>` the `T: MyTrait` becomes `T`
|
||||
for param in new_generics.params.iter_mut() {
|
||||
match param {
|
||||
GenericParam::Lifetime(lifetime) => {
|
||||
lifetime.bounds.clear(); // remove bounds
|
||||
lifetime.colon_token = None;
|
||||
}
|
||||
GenericParam::Type(type_param) => {
|
||||
type_param.bounds.clear(); // remove bounds
|
||||
type_param.colon_token = None;
|
||||
type_param.eq_token = None;
|
||||
type_param.default = None;
|
||||
}
|
||||
GenericParam::Const(const_param) => {
|
||||
// replaces const generic with type param without bounds which is basically an `ident` token
|
||||
*param = GenericParam::Type(TypeParam {
|
||||
attrs: const_param.attrs.clone(),
|
||||
ident: const_param.ident.clone(),
|
||||
colon_token: None,
|
||||
bounds: Punctuated::new(),
|
||||
eq_token: None,
|
||||
default: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new_generics.where_clause = None; // remove where clause
|
||||
|
||||
new_generics
|
||||
}
|
||||
|
||||
struct Model {
|
||||
vis: Visibility,
|
||||
name: Ident,
|
||||
@@ -111,7 +208,9 @@ impl ToTokens for Model {
|
||||
} = &self;
|
||||
let any_store_field = Ident::new("AnyStoreField", Span::call_site());
|
||||
let trait_name = Ident::new(&format!("{name}StoreFields"), name.span());
|
||||
let clear_generics = remove_constraint_from_generics(generics);
|
||||
let params = &generics.params;
|
||||
let clear_params = &clear_generics.params;
|
||||
let generics_with_orig = quote! { <#any_store_field, #params> };
|
||||
let where_with_orig = {
|
||||
generics
|
||||
@@ -124,17 +223,22 @@ impl ToTokens for Model {
|
||||
} = &w;
|
||||
quote! {
|
||||
#where_token
|
||||
#any_store_field: #library_path::StoreField<Value = #name #generics>,
|
||||
#any_store_field: #library_path::StoreField<Value = #name < #clear_params > >,
|
||||
#predicates
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| quote! { where #any_store_field: #library_path::StoreField<Value = #name #generics> })
|
||||
.unwrap_or_else(|| quote! { where #any_store_field: #library_path::StoreField<Value = #name < #clear_params > > })
|
||||
};
|
||||
|
||||
// define an extension trait that matches this struct
|
||||
// and implement that trait for all StoreFields
|
||||
let (trait_fields, read_fields): (Vec<_>, Vec<_>) =
|
||||
ty.to_field_data(&library_path, generics, &any_store_field, name);
|
||||
let (trait_fields, read_fields): (Vec<_>, Vec<_>) = ty.to_field_data(
|
||||
&library_path,
|
||||
generics,
|
||||
&clear_generics,
|
||||
&any_store_field,
|
||||
name,
|
||||
);
|
||||
|
||||
// read access
|
||||
tokens.extend(quote! {
|
||||
@@ -144,7 +248,7 @@ impl ToTokens for Model {
|
||||
#(#trait_fields)*
|
||||
}
|
||||
|
||||
impl #generics_with_orig #trait_name <AnyStoreField, #params> for AnyStoreField
|
||||
impl #generics_with_orig #trait_name <AnyStoreField, #clear_params> for AnyStoreField
|
||||
#where_with_orig
|
||||
{
|
||||
#(#read_fields)*
|
||||
@@ -158,6 +262,7 @@ impl ModelTy {
|
||||
&self,
|
||||
library_path: &TokenStream,
|
||||
generics: &Generics,
|
||||
clear_generics: &Generics,
|
||||
any_store_field: &Ident,
|
||||
name: &Ident,
|
||||
) -> (Vec<TokenStream>, Vec<TokenStream>) {
|
||||
@@ -204,6 +309,7 @@ impl ModelTy {
|
||||
library_path,
|
||||
ident.as_ref(),
|
||||
generics,
|
||||
clear_generics,
|
||||
any_store_field,
|
||||
name,
|
||||
ty,
|
||||
@@ -215,6 +321,7 @@ impl ModelTy {
|
||||
library_path,
|
||||
ident.as_ref(),
|
||||
generics,
|
||||
clear_generics,
|
||||
any_store_field,
|
||||
name,
|
||||
ty,
|
||||
@@ -233,6 +340,7 @@ impl ModelTy {
|
||||
library_path,
|
||||
ident,
|
||||
generics,
|
||||
clear_generics,
|
||||
any_store_field,
|
||||
name,
|
||||
fields,
|
||||
@@ -242,6 +350,7 @@ impl ModelTy {
|
||||
library_path,
|
||||
ident,
|
||||
generics,
|
||||
clear_generics,
|
||||
any_store_field,
|
||||
name,
|
||||
fields,
|
||||
@@ -260,7 +369,8 @@ fn field_to_tokens(
|
||||
modes: Option<&[SubfieldMode]>,
|
||||
library_path: &proc_macro2::TokenStream,
|
||||
orig_ident: Option<&Ident>,
|
||||
generics: &Generics,
|
||||
_generics: &Generics,
|
||||
clear_generics: &Generics,
|
||||
any_store_field: &Ident,
|
||||
name: &Ident,
|
||||
ty: &Type,
|
||||
@@ -285,7 +395,7 @@ fn field_to_tokens(
|
||||
SubfieldMode::Keyed(keyed_by, key_ty) => {
|
||||
let signature = quote! {
|
||||
#[track_caller]
|
||||
fn #ident(self) -> #library_path::KeyedSubfield<#any_store_field, #name #generics, #key_ty, #ty>
|
||||
fn #ident(self) -> #library_path::KeyedSubfield<#any_store_field, #name #clear_generics, #key_ty, #ty>
|
||||
};
|
||||
return if include_body {
|
||||
quote! {
|
||||
@@ -318,7 +428,7 @@ fn field_to_tokens(
|
||||
// default subfield
|
||||
if include_body {
|
||||
quote! {
|
||||
fn #ident(self) -> #library_path::Subfield<#any_store_field, #name #generics, #ty> {
|
||||
fn #ident(self) -> #library_path::Subfield<#any_store_field, #name #clear_generics, #ty> {
|
||||
#library_path::Subfield::new(
|
||||
self,
|
||||
#idx.into(),
|
||||
@@ -329,7 +439,7 @@ fn field_to_tokens(
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
fn #ident(self) -> #library_path::Subfield<#any_store_field, #name #generics, #ty>;
|
||||
fn #ident(self) -> #library_path::Subfield<#any_store_field, #name #clear_generics, #ty>;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -339,7 +449,8 @@ fn variant_to_tokens(
|
||||
include_body: bool,
|
||||
library_path: &proc_macro2::TokenStream,
|
||||
ident: &Ident,
|
||||
generics: &Generics,
|
||||
_generics: &Generics,
|
||||
clear_generics: &Generics,
|
||||
any_store_field: &Ident,
|
||||
name: &Ident,
|
||||
fields: &Fields,
|
||||
@@ -408,7 +519,7 @@ fn variant_to_tokens(
|
||||
// default subfield
|
||||
if include_body {
|
||||
quote! {
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #generics, #field_ty>> {
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #clear_generics, #field_ty>> {
|
||||
#library_path::StoreField::track_field(&self);
|
||||
let reader = #library_path::StoreField::reader(&self);
|
||||
let matches = reader
|
||||
@@ -440,7 +551,7 @@ fn variant_to_tokens(
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #generics, #field_ty>>;
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #clear_generics, #field_ty>>;
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -491,7 +602,7 @@ fn variant_to_tokens(
|
||||
// default subfield
|
||||
if include_body {
|
||||
quote! {
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #generics, #field_ty>> {
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #clear_generics, #field_ty>> {
|
||||
#library_path::StoreField::track_field(&self);
|
||||
let reader = #library_path::StoreField::reader(&self);
|
||||
let matches = reader
|
||||
@@ -523,7 +634,7 @@ fn variant_to_tokens(
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #generics, #field_ty>>;
|
||||
fn #combined_ident(self) -> Option<#library_path::Subfield<#any_store_field, #name #clear_generics, #field_ty>>;
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -665,9 +776,14 @@ impl ToTokens for PatchModel {
|
||||
}
|
||||
};
|
||||
|
||||
let clear_generics = remove_constraint_from_generics(generics);
|
||||
let params = clear_generics.params;
|
||||
let where_clause = &generics.where_clause;
|
||||
|
||||
// read access
|
||||
tokens.extend(quote! {
|
||||
impl #library_path::PatchField for #name #generics
|
||||
impl #generics #library_path::PatchField for #name <#params>
|
||||
#where_clause
|
||||
{
|
||||
fn patch_field(
|
||||
&mut self,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router"
|
||||
version = { workspace = true }
|
||||
version = "0.8.6"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -10,8 +10,17 @@ use crate::{
|
||||
};
|
||||
use any_spawner::Executor;
|
||||
use either_of::{Either, EitherOf3};
|
||||
use futures::{channel::oneshot, future::join_all, FutureExt};
|
||||
use leptos::{attr::any_attribute::AnyAttribute, component, oco::Oco};
|
||||
use futures::{
|
||||
channel::oneshot,
|
||||
future::{join_all, AbortHandle, Abortable},
|
||||
FutureExt,
|
||||
};
|
||||
use leptos::{
|
||||
attr::any_attribute::AnyAttribute,
|
||||
component,
|
||||
oco::Oco,
|
||||
prelude::{ArcStoredValue, WriteValue},
|
||||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, ScopedFuture},
|
||||
@@ -68,6 +77,7 @@ where
|
||||
// held to keep the Owner alive until the router is dropped
|
||||
#[allow(unused)]
|
||||
outer_owner: Owner,
|
||||
abort_navigation: ArcStoredValue<Option<AbortHandle>>,
|
||||
}
|
||||
|
||||
impl<Loc, Defs, FalFn, Fal> Render for NestedRoutesView<Loc, Defs, FalFn>
|
||||
@@ -134,6 +144,7 @@ where
|
||||
outlets,
|
||||
view,
|
||||
outer_owner,
|
||||
abort_navigation: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,28 +194,48 @@ where
|
||||
0,
|
||||
);
|
||||
|
||||
let (abort_handle, abort_registration) =
|
||||
AbortHandle::new_pair();
|
||||
|
||||
if let Some(prev_handle) =
|
||||
state.abort_navigation.write_value().replace(abort_handle)
|
||||
{
|
||||
prev_handle.abort();
|
||||
}
|
||||
|
||||
let location = self.location.clone();
|
||||
let is_back = location
|
||||
.as_ref()
|
||||
.map(|nav| nav.is_back().get_untracked())
|
||||
.unwrap_or(false);
|
||||
Executor::spawn_local(async move {
|
||||
let triggers = join_all(preloaders).await;
|
||||
// tell each one of the outlet triggers that it's ready
|
||||
let notify = move || {
|
||||
for trigger in triggers {
|
||||
trigger.notify();
|
||||
let triggers = Abortable::new(
|
||||
join_all(preloaders),
|
||||
abort_registration,
|
||||
);
|
||||
if let Ok(triggers) = triggers.await {
|
||||
// tell each one of the outlet triggers that it's ready
|
||||
let notify = move || {
|
||||
for trigger in triggers {
|
||||
trigger.notify();
|
||||
}
|
||||
};
|
||||
if self.transition {
|
||||
start_view_transition(
|
||||
different_level,
|
||||
is_back,
|
||||
notify,
|
||||
);
|
||||
} else {
|
||||
notify();
|
||||
}
|
||||
};
|
||||
if self.transition {
|
||||
start_view_transition(different_level, is_back, notify);
|
||||
} else {
|
||||
notify();
|
||||
}
|
||||
});
|
||||
|
||||
let abort_navigation = state.abort_navigation.clone();
|
||||
Executor::spawn_local(async move {
|
||||
join_all(full_loaders).await;
|
||||
_ = abort_navigation.write_value().take();
|
||||
if let Some(set_is_routing) = self.set_is_routing {
|
||||
set_is_routing.set(false);
|
||||
}
|
||||
@@ -463,6 +494,7 @@ where
|
||||
outlets,
|
||||
view,
|
||||
outer_owner,
|
||||
abort_navigation: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,6 +546,7 @@ where
|
||||
outlets,
|
||||
view,
|
||||
outer_owner,
|
||||
abort_navigation: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router_macro"
|
||||
version = { workspace = true }
|
||||
version = "0.8.5"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
46
scripts/bump.sh
Executable file
46
scripts/bump.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
LAST_TAG=$(git describe --tags --abbrev=0 --match "v*")
|
||||
|
||||
# Get package name and manifest_path for all members
|
||||
PACKAGES=$(cargo metadata --no-deps --format-version=1 | jq -r '.packages[] | "\(.name):::\(.manifest_path)"')
|
||||
|
||||
for PKG in $PACKAGES; do
|
||||
NAME="${PKG%%:::*}"
|
||||
MANIFEST_PATH="${PKG##*:::}"
|
||||
DIR=$(dirname "$MANIFEST_PATH")
|
||||
|
||||
# Look for release commit for this member up to the last tag
|
||||
RELEASE_COMMIT=$(git log --oneline --grep="^$NAME-v" --format="%H" "$LAST_TAG"..HEAD | head -n1)
|
||||
|
||||
if [[ -z "$RELEASE_COMMIT" ]]; then
|
||||
# No release commit found, use the latest release tag commit
|
||||
RELEASE_COMMIT=$(git rev-list -n 1 "$LAST_TAG")
|
||||
fi
|
||||
|
||||
# Check if any file in the package directory changed since the member's release commit or latest tag release
|
||||
if git diff --quiet "$RELEASE_COMMIT"..HEAD -- "$DIR"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Changes detected in $NAME ($DIR)"
|
||||
PS3="Select version bump for $NAME: "
|
||||
select BUMP in patch minor major; do
|
||||
if [[ "$BUMP" == "patch" || "$BUMP" == "minor" || "$BUMP" == "major" ]]; then
|
||||
break
|
||||
else
|
||||
echo "Invalid option"
|
||||
fi
|
||||
done
|
||||
|
||||
if cargo set-version --help >/dev/null 2>&1; then
|
||||
cargo set-version --bump "$BUMP" --package "$NAME"
|
||||
else
|
||||
echo "Please install cargo-edit first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$NAME bumped to $BUMP"
|
||||
done
|
||||
@@ -5,7 +5,7 @@ license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "RPC for any web framework."
|
||||
readme = "../README.md"
|
||||
version = { workspace = true }
|
||||
version = "0.8.6"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "The default implementation of the server_fn macro without a context"
|
||||
version = { workspace = true }
|
||||
version = "0.8.5"
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -30,8 +30,8 @@ where
|
||||
})?;
|
||||
Request::try_new_patch_bytes(
|
||||
path,
|
||||
accepts,
|
||||
Encoding::CONTENT_TYPE,
|
||||
accepts,
|
||||
data,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ where
|
||||
let data = Encoding::encode(&self).map_err(|e| {
|
||||
ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
|
||||
})?;
|
||||
Request::try_new_post_bytes(path, accepts, Encoding::CONTENT_TYPE, data)
|
||||
Request::try_new_post_bytes(path, Encoding::CONTENT_TYPE, accepts, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ where
|
||||
let data = Encoding::encode(&self).map_err(|e| {
|
||||
ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
|
||||
})?;
|
||||
Request::try_new_put_bytes(path, accepts, Encoding::CONTENT_TYPE, data)
|
||||
Request::try_new_put_bytes(path, Encoding::CONTENT_TYPE, accepts, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ pub struct GetUrl;
|
||||
/// Pass arguments as the URL-encoded body of a `POST` request.
|
||||
pub struct PostUrl;
|
||||
|
||||
/// Pass arguments as the URL-encoded body of a `DELETE` request.
|
||||
/// Pass arguments as the URL-encoded query string of a `DELETE` request.
|
||||
/// **Note**: Browser support for `DELETE` requests without JS/WASM may be poor.
|
||||
/// Consider using a `POST` request if functionality without JS/WASM is required.
|
||||
pub struct DeleteUrl;
|
||||
@@ -46,7 +46,7 @@ where
|
||||
let data = serde_qs::to_string(&self).map_err(|e| {
|
||||
ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
|
||||
})?;
|
||||
Request::try_new_get(path, accepts, GetUrl::CONTENT_TYPE, &data)
|
||||
Request::try_new_get(path, GetUrl::CONTENT_TYPE, accepts, &data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ where
|
||||
let qs = serde_qs::to_string(&self).map_err(|e| {
|
||||
ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
|
||||
})?;
|
||||
Request::try_new_post(path, accepts, PostUrl::CONTENT_TYPE, qs)
|
||||
Request::try_new_post(path, PostUrl::CONTENT_TYPE, accepts, qs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ where
|
||||
let data = serde_qs::to_string(&self).map_err(|e| {
|
||||
ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
|
||||
})?;
|
||||
Request::try_new_delete(path, accepts, GetUrl::CONTENT_TYPE, &data)
|
||||
Request::try_new_delete(path, DeleteUrl::CONTENT_TYPE, accepts, &data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ where
|
||||
let data = serde_qs::to_string(&self).map_err(|e| {
|
||||
ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
|
||||
})?;
|
||||
Request::try_new_patch(path, accepts, GetUrl::CONTENT_TYPE, data)
|
||||
Request::try_new_patch(path, PatchUrl::CONTENT_TYPE, accepts, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,9 +174,9 @@ where
|
||||
E: FromServerFnError,
|
||||
{
|
||||
async fn from_req(req: Request) -> Result<Self, E> {
|
||||
let string_data = req.as_query().unwrap_or_default();
|
||||
let string_data = req.try_into_string().await?;
|
||||
let args = serde_qs::Config::new(5, false)
|
||||
.deserialize_str::<Self>(string_data)
|
||||
.deserialize_str::<Self>(&string_data)
|
||||
.map_err(|e| {
|
||||
ServerFnErrorErr::Args(e.to_string()).into_app_error()
|
||||
})?;
|
||||
@@ -202,7 +202,7 @@ where
|
||||
let data = serde_qs::to_string(&self).map_err(|e| {
|
||||
ServerFnErrorErr::Serialization(e.to_string()).into_app_error()
|
||||
})?;
|
||||
Request::try_new_put(path, accepts, GetUrl::CONTENT_TYPE, data)
|
||||
Request::try_new_put(path, PutUrl::CONTENT_TYPE, accepts, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,9 +213,9 @@ where
|
||||
E: FromServerFnError,
|
||||
{
|
||||
async fn from_req(req: Request) -> Result<Self, E> {
|
||||
let string_data = req.as_query().unwrap_or_default();
|
||||
let string_data = req.try_into_string().await?;
|
||||
let args = serde_qs::Config::new(5, false)
|
||||
.deserialize_str::<Self>(string_data)
|
||||
.deserialize_str::<Self>(&string_data)
|
||||
.map_err(|e| {
|
||||
ServerFnErrorErr::Args(e.to_string()).into_app_error()
|
||||
})?;
|
||||
|
||||
@@ -5,16 +5,22 @@ license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "RPC for any web framework."
|
||||
readme = "../README.md"
|
||||
version = { workspace = true }
|
||||
version = "0.8.7"
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
quote = { workspace = true, default-features = true }
|
||||
syn = { features = ["full", "parsing", "extra-traits"] , workspace = true, default-features = true }
|
||||
syn = { features = [
|
||||
"full",
|
||||
"parsing",
|
||||
"extra-traits",
|
||||
], workspace = true, default-features = true }
|
||||
proc-macro2 = { workspace = true, default-features = true }
|
||||
xxhash-rust = { features = ["const_xxh64"] , workspace = true, default-features = true }
|
||||
xxhash-rust = { features = [
|
||||
"const_xxh64",
|
||||
], workspace = true, default-features = true }
|
||||
const_format = { workspace = true, default-features = true }
|
||||
convert_case = { workspace = true , default-features = true }
|
||||
convert_case = { workspace = true, default-features = true }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -1525,7 +1525,10 @@ impl Parse for ServerFnBody {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
// in ssr mode, remove the "lazy" macro
|
||||
// the lazy macro doesn't do anything on the server anyway, but it can cause confusion for rust-analyzer
|
||||
// when the lazy macro is applied to both the function and the dummy
|
||||
!(cfg!(feature = "ssr") && matches!(attr.meta.path().segments.last(), Some(PathSegment { ident, .. }) if ident == "lazy") )
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1553,7 +1556,7 @@ impl Parse for ServerFnBody {
|
||||
|
||||
impl ServerFnBody {
|
||||
fn to_dummy_ident(&self) -> Ident {
|
||||
Ident::new(&format!("__{}", self.ident), self.ident.span())
|
||||
Ident::new(&format!("__server_{}", self.ident), self.ident.span())
|
||||
}
|
||||
|
||||
fn to_dummy_output(&self) -> TokenStream2 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tachys"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -195,6 +195,10 @@ attributes! {
|
||||
cols "cols",
|
||||
/// The `colspan` attribute defines the number of columns a cell should span.
|
||||
colspan "colspan",
|
||||
/// The `command` attribute defines the command to be invoked when user clicks the `<button>` element which has `commandfor` attribute specified.
|
||||
command "command",
|
||||
/// The `commandfor` attribute defines the id of the element which button is controlling. It is generic version of `popovertarget`.
|
||||
commandfor "commandfor",
|
||||
/// The `content` attribute gives the value associated with the http-equiv or name attribute.
|
||||
content "content",
|
||||
/// The `contenteditable` attribute indicates whether the element's content is editable.
|
||||
|
||||
@@ -249,7 +249,7 @@ html_elements! {
|
||||
/// The `<body>` HTML element represents the content of an HTML document. There can be only one `<body>` element in a document.
|
||||
body HtmlBodyElement [] true,
|
||||
/// The `<button>` HTML element represents a clickable button, used to submit forms or anywhere in a document for accessible, standard button functionality.
|
||||
button HtmlButtonElement [disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, name, r#type, value, popovertarget, popovertargetaction] true,
|
||||
button HtmlButtonElement [command, commandfor, disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, name, r#type, value, popovertarget, popovertargetaction] true,
|
||||
/// Use the HTML `<canvas>` element with either the canvas scripting API or the WebGL API to draw graphics and animations.
|
||||
canvas HtmlCanvasElement [height, width] true,
|
||||
/// The `<caption>` HTML element specifies the caption (or title) of a table.
|
||||
@@ -269,7 +269,7 @@ html_elements! {
|
||||
/// The `<del>` HTML element represents a range of text that has been deleted from a document. This can be used when rendering "track changes" or source code diff information, for example. The ins element can be used for the opposite purpose: to indicate text that has been added to the document.
|
||||
del HtmlModElement [cite, datetime] true,
|
||||
/// The `<details>` HTML element creates a disclosure widget in which information is visible only when the widget is toggled into an "open" state. A summary or label must be provided using the summary element.
|
||||
details HtmlDetailsElement [open] true,
|
||||
details HtmlDetailsElement [name, open] true,
|
||||
/// The `<dfn>` HTML element is used to indicate the term being defined within the context of a definition phrase or sentence. The p element, the dt/dd pairing, or the section element which is the nearest ancestor of the `<dfn>` is considered to be the definition of the term.
|
||||
dfn HtmlElement [] true,
|
||||
/// The `<dialog>` HTML element represents a dialog box or other interactive component, such as a dismissible alert, inspector, or subwindow.
|
||||
|
||||
@@ -329,6 +329,8 @@ where
|
||||
fn build(self) -> Self::State {
|
||||
let el = Rndr::create_element(self.tag.tag(), E::NAMESPACE);
|
||||
|
||||
let attrs = self.attributes.build(&el);
|
||||
|
||||
let children = if E::SELF_CLOSING {
|
||||
None
|
||||
} else {
|
||||
@@ -337,8 +339,6 @@ where
|
||||
Some(children)
|
||||
};
|
||||
|
||||
let attrs = self.attributes.build(&el);
|
||||
|
||||
ElementState {
|
||||
el,
|
||||
attrs,
|
||||
|
||||
@@ -202,7 +202,7 @@ macro_rules! prop_type {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
@@ -212,14 +212,14 @@ macro_rules! prop_type {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ macro_rules! prop_type {
|
||||
let was_some = self.is_some();
|
||||
let value = self.into();
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -258,7 +258,7 @@ macro_rules! prop_type {
|
||||
let was_some = self.is_some();
|
||||
let value = self.into();
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -266,7 +266,7 @@ macro_rules! prop_type {
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ macro_rules! prop_type_str {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from(&*self);
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
@@ -304,14 +304,14 @@ macro_rules! prop_type_str {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from(&*self);
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from(&*self);
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ macro_rules! prop_type_str {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -352,7 +352,7 @@ macro_rules! prop_type_str {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -360,7 +360,7 @@ macro_rules! prop_type_str {
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ impl IntoProperty for Arc<str> {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
@@ -402,14 +402,14 @@ impl IntoProperty for Arc<str> {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ impl IntoProperty for Option<Arc<str>> {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -448,7 +448,7 @@ impl IntoProperty for Option<Arc<str>> {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -456,7 +456,7 @@ impl IntoProperty for Option<Arc<str>> {
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::{
|
||||
html::{
|
||||
attribute::{any_attribute::AnyAttribute, AttributeValue},
|
||||
class::IntoClass,
|
||||
property::IntoProperty,
|
||||
style::IntoStyle,
|
||||
},
|
||||
hydration::Cursor,
|
||||
@@ -11,6 +12,7 @@ use crate::{
|
||||
view::{strings::StrState, Position, PositionState, ToTemplate},
|
||||
};
|
||||
use oco_ref::Oco;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
/// Retained view state for [`Oco`].
|
||||
pub struct OcoStrState {
|
||||
@@ -248,6 +250,47 @@ impl IntoClass for Oco<'static, str> {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoProperty for Oco<'static, str> {
|
||||
type State = (crate::renderer::types::Element, JsValue);
|
||||
type Cloneable = Self;
|
||||
type CloneableOwned = Self;
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
el: &crate::renderer::types::Element,
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn build(
|
||||
self,
|
||||
el: &crate::renderer::types::Element,
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_cloneable_owned(self) -> Self::CloneableOwned {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoStyle for Oco<'static, str> {
|
||||
type AsyncOutput = Self;
|
||||
type State = (crate::renderer::types::Element, Self);
|
||||
|
||||
@@ -153,6 +153,20 @@ where
|
||||
OwnedViewState::new(state, self.owner)
|
||||
}
|
||||
|
||||
async fn hydrate_async(
|
||||
self,
|
||||
cursor: &Cursor,
|
||||
position: &PositionState,
|
||||
) -> Self::State {
|
||||
let state = self
|
||||
.owner
|
||||
.with(|| {
|
||||
ScopedFuture::new(self.view.hydrate_async(cursor, position))
|
||||
})
|
||||
.await;
|
||||
OwnedViewState::new(state, self.owner)
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
let OwnedView { owner, view } = self;
|
||||
let view = owner
|
||||
|
||||
@@ -36,6 +36,46 @@ pub type ClassList = web_sys::DomTokenList;
|
||||
pub type CssStyleDeclaration = web_sys::CssStyleDeclaration;
|
||||
pub type TemplateElement = web_sys::HtmlTemplateElement;
|
||||
|
||||
/// A microtask is a short function which will run after the current task has
|
||||
/// completed its work and when there is no other code waiting to be run before
|
||||
/// control of the execution context is returned to the browser's event loop.
|
||||
///
|
||||
/// Microtasks are especially useful for libraries and frameworks that need
|
||||
/// to perform final cleanup or other just-before-rendering tasks.
|
||||
///
|
||||
/// [MDN queueMicrotask](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
|
||||
pub fn queue_microtask(task: impl FnOnce() + 'static) {
|
||||
use js_sys::{Function, Reflect};
|
||||
|
||||
let task = Closure::once_into_js(task);
|
||||
let window = window();
|
||||
let queue_microtask =
|
||||
Reflect::get(&window, &JsValue::from_str("queueMicrotask"))
|
||||
.expect("queueMicrotask not available");
|
||||
let queue_microtask = queue_microtask.unchecked_into::<Function>();
|
||||
_ = queue_microtask.call1(&JsValue::UNDEFINED, &task);
|
||||
}
|
||||
|
||||
fn queue(fun: Box<dyn FnOnce()>) {
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
thread_local! {
|
||||
static PENDING: Cell<bool> = const { Cell::new(false) };
|
||||
static QUEUE: RefCell<Vec<Box<dyn FnOnce()>>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
QUEUE.with_borrow_mut(|q| q.push(fun));
|
||||
if !PENDING.replace(true) {
|
||||
queue_microtask(|| {
|
||||
let tasks = QUEUE.take();
|
||||
for task in tasks {
|
||||
task();
|
||||
}
|
||||
PENDING.set(false);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Dom {
|
||||
pub fn intern(text: &str) -> &str {
|
||||
intern(text)
|
||||
@@ -211,6 +251,20 @@ impl Dom {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_property_or_value(el: &Element, key: &str, value: &JsValue) {
|
||||
if key == "value" {
|
||||
queue(Box::new({
|
||||
let el = el.clone();
|
||||
let value = value.clone();
|
||||
move || {
|
||||
Self::set_property(&el, "value", &value);
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
Self::set_property(el, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_property(el: &Element, key: &str, value: &JsValue) {
|
||||
or_debug!(
|
||||
js_sys::Reflect::set(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm_split_helpers"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
@@ -14,3 +14,4 @@ async-once-cell = { default-features = true, workspace = true, features = [
|
||||
"std",
|
||||
] }
|
||||
wasm_split_macros.workspace = true
|
||||
or_poisoned.workspace = true
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use std::{
|
||||
cell::Cell,
|
||||
ffi::c_void,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
task::{Context, Poll, Waker},
|
||||
};
|
||||
|
||||
@@ -12,18 +11,19 @@ pub type LoadFn = unsafe extern "C" fn(LoadCallbackFn, *const c_void) -> ();
|
||||
|
||||
type Lazy = async_once_cell::Lazy<Option<()>, SplitLoaderFuture>;
|
||||
|
||||
use or_poisoned::OrPoisoned;
|
||||
pub use wasm_split_macros::wasm_split;
|
||||
|
||||
pub struct LazySplitLoader {
|
||||
lazy: Pin<Rc<Lazy>>,
|
||||
lazy: Pin<Arc<Lazy>>,
|
||||
}
|
||||
|
||||
impl LazySplitLoader {
|
||||
pub fn new(load: LoadFn) -> Self {
|
||||
Self {
|
||||
lazy: Rc::pin(Lazy::new(SplitLoaderFuture::new(SplitLoader::new(
|
||||
load,
|
||||
)))),
|
||||
lazy: Arc::pin(Lazy::new(SplitLoaderFuture::new(
|
||||
SplitLoader::new(load),
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,36 +42,33 @@ enum SplitLoaderState {
|
||||
}
|
||||
|
||||
struct SplitLoader {
|
||||
state: Cell<SplitLoaderState>,
|
||||
waker: Cell<Option<Waker>>,
|
||||
state: Mutex<SplitLoaderState>,
|
||||
waker: Mutex<Option<Waker>>,
|
||||
}
|
||||
|
||||
impl SplitLoader {
|
||||
fn new(load: LoadFn) -> Rc<Self> {
|
||||
Rc::new(SplitLoader {
|
||||
state: Cell::new(SplitLoaderState::Deferred(load)),
|
||||
waker: Cell::new(None),
|
||||
fn new(load: LoadFn) -> Arc<Self> {
|
||||
Arc::new(SplitLoader {
|
||||
state: Mutex::new(SplitLoaderState::Deferred(load)),
|
||||
waker: Mutex::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
fn complete(&self, value: bool) {
|
||||
self.state.set(SplitLoaderState::Completed(if value {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}));
|
||||
if let Some(waker) = self.waker.take() {
|
||||
*self.state.lock().or_poisoned() =
|
||||
SplitLoaderState::Completed(if value { Some(()) } else { None });
|
||||
if let Some(waker) = self.waker.lock().or_poisoned().take() {
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SplitLoaderFuture {
|
||||
loader: Rc<SplitLoader>,
|
||||
loader: Arc<SplitLoader>,
|
||||
}
|
||||
|
||||
impl SplitLoaderFuture {
|
||||
fn new(loader: Rc<SplitLoader>) -> Self {
|
||||
fn new(loader: Arc<SplitLoader>) -> Self {
|
||||
SplitLoaderFuture { loader }
|
||||
}
|
||||
}
|
||||
@@ -80,21 +77,24 @@ impl Future for SplitLoaderFuture {
|
||||
type Output = Option<()>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<()>> {
|
||||
match self.loader.state.get() {
|
||||
let mut loader = self.loader.state.lock().or_poisoned();
|
||||
match *loader {
|
||||
SplitLoaderState::Deferred(load) => {
|
||||
self.loader.state.set(SplitLoaderState::Pending);
|
||||
self.loader.waker.set(Some(cx.waker().clone()));
|
||||
*loader = SplitLoaderState::Pending;
|
||||
*self.loader.waker.lock().or_poisoned() =
|
||||
Some(cx.waker().clone());
|
||||
unsafe {
|
||||
load(
|
||||
load_callback,
|
||||
Rc::<SplitLoader>::into_raw(self.loader.clone())
|
||||
Arc::<SplitLoader>::into_raw(self.loader.clone())
|
||||
as *const c_void,
|
||||
)
|
||||
};
|
||||
Poll::Pending
|
||||
}
|
||||
SplitLoaderState::Pending => {
|
||||
self.loader.waker.set(Some(cx.waker().clone()));
|
||||
*self.loader.waker.lock().or_poisoned() =
|
||||
Some(cx.waker().clone());
|
||||
Poll::Pending
|
||||
}
|
||||
SplitLoaderState::Completed(value) => Poll::Ready(value),
|
||||
@@ -103,5 +103,5 @@ impl Future for SplitLoaderFuture {
|
||||
}
|
||||
|
||||
unsafe extern "C" fn load_callback(loader: *const c_void, success: bool) {
|
||||
unsafe { Rc::from_raw(loader as *const SplitLoader) }.complete(success);
|
||||
unsafe { Arc::from_raw(loader as *const SplitLoader) }.complete(success);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm_split_macros"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -1,11 +1,40 @@
|
||||
use digest::Digest;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_macro_input, Ident, ItemFn, ReturnType, Signature};
|
||||
use syn::{
|
||||
parse,
|
||||
parse::{Parse, ParseStream},
|
||||
parse_macro_input,
|
||||
token::Comma,
|
||||
Ident, ItemFn, Path, Result, ReturnType, Signature,
|
||||
};
|
||||
|
||||
struct WasmSplitArgs {
|
||||
module_ident: Ident,
|
||||
_comma: Option<Comma>,
|
||||
send_wrapper_path: Option<Path>,
|
||||
}
|
||||
|
||||
impl Parse for WasmSplitArgs {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let module_ident = input.parse()?;
|
||||
let _comma = input.parse().ok();
|
||||
let send_wrapper_path = input.parse().ok();
|
||||
Ok(Self {
|
||||
module_ident,
|
||||
_comma,
|
||||
send_wrapper_path,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn wasm_split(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let module_ident = parse_macro_input!(args as Ident);
|
||||
let WasmSplitArgs {
|
||||
module_ident,
|
||||
send_wrapper_path,
|
||||
..
|
||||
} = parse_macro_input!(args);
|
||||
let item_fn = parse_macro_input!(input as ItemFn);
|
||||
|
||||
let name = &item_fn.sig.ident;
|
||||
@@ -45,9 +74,9 @@ pub fn wasm_split(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
ReturnType::Default => quote! { () },
|
||||
ReturnType::Type(_, ty) => quote! { #ty },
|
||||
};
|
||||
let async_output = syn::parse::<ReturnType>(
|
||||
let async_output = parse::<ReturnType>(
|
||||
quote! {
|
||||
-> std::pin::Pin<Box<dyn std::future::Future<Output = #ty>>>
|
||||
-> std::pin::Pin<Box<dyn std::future::Future<Output = #ty> + Send + Sync>>
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
@@ -83,10 +112,18 @@ pub fn wasm_split(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let stmts = &item_fn.block.stmts;
|
||||
|
||||
let body = if was_async {
|
||||
quote! {
|
||||
Box::pin(async move {
|
||||
#(#stmts)*
|
||||
})
|
||||
if let Some(send_wrapper_path) = send_wrapper_path {
|
||||
quote! {
|
||||
Box::pin(#send_wrapper_path::SendWrapper::new(async move {
|
||||
#(#stmts)*
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
Box::pin(async move {
|
||||
#(#stmts)*
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! { #(#stmts)* }
|
||||
@@ -99,7 +136,7 @@ pub fn wasm_split(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
static #split_loader_ident: ::leptos::wasm_split_helpers::LazySplitLoader = ::leptos::wasm_split_helpers::LazySplitLoader::new(#load_module_ident);
|
||||
}
|
||||
|
||||
#[link(wasm_import_module = "/pkg/__wasm_split.js")]
|
||||
#[link(wasm_import_module = "/pkg/__wasm_split.______________________.js")]
|
||||
extern "C" {
|
||||
#[no_mangle]
|
||||
fn #load_module_ident (callback: unsafe extern "C" fn(*const ::std::ffi::c_void, bool), data: *const ::std::ffi::c_void) -> ();
|
||||
|
||||
Reference in New Issue
Block a user