mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-28 12:31:55 -05:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99c6134bdf | ||
|
|
c025ae59ac | ||
|
|
df46feee5d | ||
|
|
bbf5bf9170 | ||
|
|
a453b7d1bd | ||
|
|
3b9ccdf57e | ||
|
|
27cd423ebc | ||
|
|
b3907baf49 | ||
|
|
9a8bb7eb75 | ||
|
|
95db8c939e | ||
|
|
2bfa9952af | ||
|
|
4e445f43d6 | ||
|
|
5f544f67ae | ||
|
|
68477d2b76 | ||
|
|
5bd9469b93 | ||
|
|
4bca70dc2f | ||
|
|
d0295009cf | ||
|
|
3e8b5c9805 | ||
|
|
924efa8ac1 | ||
|
|
b92a14228c | ||
|
|
68967fdad3 | ||
|
|
44bc4fbc31 |
2
.github/workflows/get-example-changed.yml
vendored
2
.github/workflows/get-example-changed.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- name: Get example files that changed
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v46
|
||||
uses: tj-actions/changed-files@v47
|
||||
with:
|
||||
files: |
|
||||
examples/**
|
||||
|
||||
2
.github/workflows/get-leptos-changed.yml
vendored
2
.github/workflows/get-leptos-changed.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- name: Get source files that changed
|
||||
id: changed-source
|
||||
uses: tj-actions/changed-files@v46
|
||||
uses: tj-actions/changed-files@v47
|
||||
with:
|
||||
files_ignore: |
|
||||
.*/**/*
|
||||
|
||||
2
.github/workflows/run-cargo-make-task.yml
vendored
2
.github/workflows/run-cargo-make-task.yml
vendored
@@ -88,7 +88,7 @@ jobs:
|
||||
run: trunk --version
|
||||
- name: Install Node.js
|
||||
if: contains(inputs.directory, 'examples')
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
59
Cargo.lock
generated
59
Cargo.lock
generated
@@ -279,9 +279,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.99"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
@@ -903,12 +903,14 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dioxus-cli-config"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8cec511d8a05ed60071bb0088f07ec40325faf27a608fa19d65befdd842b57f"
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-core"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07b55eccaa5c4f35f1755ea18a5716fe8ecba60ff1f25c52be6ceda2e6a52eb6"
|
||||
dependencies = [
|
||||
"const_format",
|
||||
"dioxus-core-types",
|
||||
@@ -929,12 +931,14 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dioxus-core-types"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0ef2a94b4ceb8f7a39f56a539d07e82b0358a49a0b95028ad48635975df29d7"
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-devtools"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60af4e129968ab1713471ed0b29c3eefa4e8e09252429487d7a581e93c7ecfe5"
|
||||
dependencies = [
|
||||
"dioxus-cli-config",
|
||||
"dioxus-core",
|
||||
@@ -952,7 +956,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dioxus-devtools-types"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64274704b6a8d018112473cdce0b3db1dcccfa79bde445223592fe4e396ff5ef"
|
||||
dependencies = [
|
||||
"dioxus-core",
|
||||
"serde",
|
||||
@@ -962,7 +967,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dioxus-signals"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1d0e70a8da969c0404f5ef8cf6f47042bea55608b582079f3ea3d9fff46125c"
|
||||
dependencies = [
|
||||
"dioxus-core",
|
||||
"futures-channel",
|
||||
@@ -1051,7 +1057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1239,7 +1245,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "generational-box"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb058e0358ff765e719ab3e61629c5090fedb6a6ccf66479de21440a33d7f084"
|
||||
dependencies = [
|
||||
"parking_lot",
|
||||
"tracing",
|
||||
@@ -1873,7 +1880,7 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
|
||||
|
||||
[[package]]
|
||||
name = "leptos"
|
||||
version = "0.8.9"
|
||||
version = "0.8.10"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"base64",
|
||||
@@ -1994,7 +2001,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_dom"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"leptos",
|
||||
@@ -2027,7 +2034,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_integration_utils"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"hydration_context",
|
||||
@@ -2040,7 +2047,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_macro"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"cfg-if",
|
||||
@@ -2084,7 +2091,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"either_of",
|
||||
@@ -2148,12 +2155,12 @@ checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.53.3",
|
||||
"windows-link 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2868,7 +2875,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_graph"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-lock",
|
||||
@@ -3137,7 +3144,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3638,7 +3645,8 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
[[package]]
|
||||
name = "subsecond"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b14ed4d86ab065ffbfdb994fd3e44daf5244b02cb643bd52949d74b703f36605"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"libc",
|
||||
@@ -3656,7 +3664,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "subsecond-types"
|
||||
version = "0.7.0-rc.0"
|
||||
source = "git+https://github.com/dioxuslabs/dioxus#eef4db67b1164934eb29b7ac4d4bcd693bba25a5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "275920a8a5634e47e12253971db85946798795bbe4d9dfc1debf23533d823983"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -3735,7 +3744,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tachys"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-trait",
|
||||
@@ -3804,7 +3813,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4611,7 +4620,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
22
Cargo.toml
22
Cargo.toml
@@ -50,26 +50,26 @@ 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.9" }
|
||||
leptos = { path = "./leptos", version = "0.8.10" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.8.7" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.8.6" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.8.7" }
|
||||
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.8" }
|
||||
leptos_router = { path = "./router", version = "0.8.7" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.8.6" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.8.9" }
|
||||
leptos_router = { path = "./router", version = "0.8.8" }
|
||||
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.7" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.2.8" }
|
||||
reactive_stores = { path = "./reactive_stores", version = "0.2.5" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.2.6" }
|
||||
server_fn = { path = "./server_fn", version = "0.8.7" }
|
||||
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.8" }
|
||||
tachys = { path = "./tachys", version = "0.2.9" }
|
||||
wasm_split_helpers = { path = "./wasm_split", version = "0.1.2" }
|
||||
wasm_split_macros = { path = "./wasm_split_macros", version = "0.1.3" }
|
||||
|
||||
@@ -125,7 +125,7 @@ glib = { default-features = false, version = "0.20.12" }
|
||||
async-trait = { default-features = false, version = "0.1.89" }
|
||||
typed-builder-macro = { default-features = false, version = "0.21.0" }
|
||||
linear-map = { default-features = false, version = "1.2.0" }
|
||||
anyhow = { default-features = false, version = "1.0.99" }
|
||||
anyhow = { default-features = false, version = "1.0.100" }
|
||||
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" }
|
||||
@@ -170,9 +170,9 @@ 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" }
|
||||
subsecond = { default-features = false, git = "https://github.com/dioxuslabs/dioxus" }
|
||||
dioxus-cli-config = { default-features = false, git = "https://github.com/dioxuslabs/dioxus" }
|
||||
dioxus-devtools = { default-features = false, git = "https://github.com/dioxuslabs/dioxus" }
|
||||
subsecond = { default-features = false, version = "0.7.0-rc.0" }
|
||||
dioxus-cli-config = { default-features = false, version = "0.7.0-rc.0" }
|
||||
dioxus-devtools = { default-features = false, version = "0.7.0-rc.0" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
@@ -95,7 +95,7 @@ Here are some resources for learning more about Leptos:
|
||||
[`cargo-leptos`](https://github.com/leptos-rs/cargo-leptos) is a build tool that's designed to make it easy to build apps that run on both the client and the server, with seamless integration. The best way to get started with a real Leptos project right now is to use `cargo-leptos` and our starter templates for [Actix](https://github.com/leptos-rs/start) or [Axum](https://github.com/leptos-rs/start-axum).
|
||||
|
||||
```bash
|
||||
cargo install cargo-leptos
|
||||
cargo install cargo-leptos --locked
|
||||
cargo leptos new --git https://github.com/leptos-rs/start-axum
|
||||
cd [your project name]
|
||||
cargo leptos watch
|
||||
|
||||
13
examples/regression/e2e/features/issue_4251.feature
Normal file
13
examples/regression/e2e/features/issue_4251.feature
Normal file
@@ -0,0 +1,13 @@
|
||||
@check_issue_4251
|
||||
Feature: Check that issue 4251 does not reappear
|
||||
|
||||
Scenario: Clicking a link to the same page you’re currently on should not add the page to the history stack.
|
||||
Given I see the app
|
||||
And I can access regression test 4324
|
||||
When I select the link This page
|
||||
And I select the link This page
|
||||
And I select the link This page
|
||||
Then I see the result is the string Issue4324
|
||||
When I press the back button
|
||||
And I select the link 4324
|
||||
Then I see the result is the string Issue4324
|
||||
11
examples/regression/e2e/features/issue_4324.feature
Normal file
11
examples/regression/e2e/features/issue_4324.feature
Normal file
@@ -0,0 +1,11 @@
|
||||
@check_issue_4324
|
||||
Feature: Check that issue 4324 does not reappear
|
||||
|
||||
Scenario: Navigating to the same page after clicking "Back" should set the URL correctly
|
||||
Given I see the app
|
||||
And I can access regression test 4324
|
||||
Then I see the path is /4324/
|
||||
When I press the back button
|
||||
Then I see the path is /
|
||||
When I select the link 4324
|
||||
Then I see the path is /4324/
|
||||
10
examples/regression/e2e/tests/fixtures/check.rs
vendored
10
examples/regression/e2e/tests/fixtures/check.rs
vendored
@@ -43,3 +43,13 @@ pub async fn element_value_is(
|
||||
assert_eq!(value.as_deref(), Some(expected));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn path_is(client: &Client, expected_path: &str) -> Result<()> {
|
||||
let url = client
|
||||
.current_url()
|
||||
.await
|
||||
.expect("could not access current URL");
|
||||
let path = url.path();
|
||||
assert_eq!(expected_path, path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -45,3 +45,12 @@ async fn i_refresh_the_browser(world: &mut AppWorld) -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[given(regex = "^I press the back button$")]
|
||||
#[when(regex = "^I press the back button$")]
|
||||
async fn i_go_back(world: &mut AppWorld) -> Result<()> {
|
||||
let client = &world.client;
|
||||
client.back().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -43,3 +43,10 @@ async fn i_see_the_value(
|
||||
check::element_value_is(client, &id, &value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[then(regex = r"^I see the path is (.*)$")]
|
||||
async fn i_see_the_path(world: &mut AppWorld, path: String) -> Result<()> {
|
||||
let client = &world.client;
|
||||
check::path_is(client, &path).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
issue_4005::Routes4005, issue_4088::Routes4088, issue_4217::Routes4217,
|
||||
issue_4285::Routes4285, issue_4296::Routes4296, pr_4015::Routes4015,
|
||||
pr_4091::Routes4091,
|
||||
issue_4285::Routes4285, issue_4296::Routes4296, issue_4324::Routes4324,
|
||||
pr_4015::Routes4015, pr_4091::Routes4091,
|
||||
};
|
||||
use leptos::prelude::*;
|
||||
use leptos_meta::{MetaTags, *};
|
||||
@@ -47,6 +47,7 @@ pub fn App() -> impl IntoView {
|
||||
<Routes4005/>
|
||||
<Routes4285/>
|
||||
<Routes4296/>
|
||||
<Routes4324/>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
@@ -73,6 +74,7 @@ fn HomePage() -> impl IntoView {
|
||||
<li><a href="/4005/">"4005"</a></li>
|
||||
<li><a href="/4285/">"4285"</a></li>
|
||||
<li><a href="/4296/">"4296"</a></li>
|
||||
<li><a href="/4324/">"4324"</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
}
|
||||
|
||||
21
examples/regression/src/issue_4324.rs
Normal file
21
examples/regression/src/issue_4324.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use leptos::prelude::*;
|
||||
#[allow(unused_imports)]
|
||||
use leptos_router::{
|
||||
components::Route, path, Lazy, MatchNestedRoutes, NavigateOptions,
|
||||
};
|
||||
|
||||
#[component]
|
||||
pub fn Routes4324() -> impl MatchNestedRoutes + Clone {
|
||||
view! {
|
||||
<Route path=path!("4324") view=Issue4324/>
|
||||
}
|
||||
.into_inner()
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Issue4324() -> impl IntoView {
|
||||
view! {
|
||||
<a href="/4324/">"This page"</a>
|
||||
<p id="result">"Issue4324"</p>
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ mod issue_4088;
|
||||
mod issue_4217;
|
||||
mod issue_4285;
|
||||
mod issue_4296;
|
||||
mod issue_4324;
|
||||
mod pr_4015;
|
||||
mod pr_4091;
|
||||
|
||||
|
||||
3
examples/tailwind_csr/Trunk.toml
Normal file
3
examples/tailwind_csr/Trunk.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
[tools]
|
||||
tailwindcss = "4.1.13"
|
||||
|
||||
@@ -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 = "0.8.5"
|
||||
version = "0.8.6"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ pub trait ExtendResponse: Sized {
|
||||
let nonce =
|
||||
use_nonce().map(|n| n.to_string()).unwrap_or_default();
|
||||
if let Some(manifest) = use_context::<WasmSplitManifest>() {
|
||||
let (pkg_path, manifest) = &*manifest.0.read_value();
|
||||
let (pkg_path, manifest, wasm_split_file) =
|
||||
&*manifest.0.read_value();
|
||||
let prefetches = prefetches.0.read_value();
|
||||
|
||||
let all_prefetches = prefetches.iter().flat_map(|key| {
|
||||
@@ -90,7 +91,7 @@ pub trait ExtendResponse: Sized {
|
||||
.to_html();
|
||||
}
|
||||
_ = view! {
|
||||
<Link rel="modulepreload" href=format!("{pkg_path}/__wasm_split.js") crossorigin=nonce/>
|
||||
<Link rel="modulepreload" href=format!("{pkg_path}/{wasm_split_file}") crossorigin=nonce/>
|
||||
}
|
||||
.to_html();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos"
|
||||
version = "0.8.9"
|
||||
version = "0.8.10"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -65,16 +65,56 @@ pub fn HydrationScripts(
|
||||
if let Some(splits) = SPLIT_MANIFEST.get_or_init(|| {
|
||||
let root = root.clone().unwrap_or_default();
|
||||
|
||||
let (wasm_split_js, wasm_split_manifest) = if options.hash_files {
|
||||
let hash_path = std::env::current_exe()
|
||||
.map(|path| {
|
||||
path.parent().map(|p| p.to_path_buf()).unwrap_or_default()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
.join(options.hash_file.as_ref());
|
||||
let hashes = std::fs::read_to_string(&hash_path)
|
||||
.expect("failed to read hash file");
|
||||
|
||||
let mut split =
|
||||
"__wasm_split.______________________.js".to_string();
|
||||
let mut manifest = "__wasm_split_manifest.json".to_string();
|
||||
for line in hashes.lines() {
|
||||
let line = line.trim();
|
||||
if !line.is_empty() {
|
||||
if let Some((file, hash)) = line.split_once(':') {
|
||||
if file == "manifest" {
|
||||
manifest.clear();
|
||||
manifest.push_str("__wasm_split_manifest.");
|
||||
manifest.push_str(hash.trim());
|
||||
manifest.push_str(".json");
|
||||
}
|
||||
if file == "split" {
|
||||
split.clear();
|
||||
split.push_str("__wasm_split.");
|
||||
split.push_str(hash.trim());
|
||||
split.push_str(".js");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(split, manifest)
|
||||
} else {
|
||||
(
|
||||
"__wasm_split.______________________.js".to_string(),
|
||||
"__wasm_split_manifest.json".to_string(),
|
||||
)
|
||||
};
|
||||
|
||||
let site_dir = &options.site_root;
|
||||
let pkg_dir = &options.site_pkg_dir;
|
||||
let path = PathBuf::from(site_dir.to_string());
|
||||
let path = path
|
||||
.join(pkg_dir.to_string())
|
||||
.join("__wasm_split_manifest.json");
|
||||
let path = path.join(pkg_dir.to_string()).join(wasm_split_manifest);
|
||||
let file = std::fs::read_to_string(path).ok()?;
|
||||
|
||||
let manifest = WasmSplitManifest(ArcStoredValue::new((
|
||||
format!("{root}/{pkg_dir}"),
|
||||
serde_json::from_str(&file).expect("could not read manifest file"),
|
||||
wasm_split_js,
|
||||
)));
|
||||
|
||||
Some(manifest)
|
||||
|
||||
@@ -395,7 +395,8 @@ pub fn prefetch_lazy_fn_on_server(id: &'static str) {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct WasmSplitManifest(
|
||||
pub reactive_graph::owner::ArcStoredValue<(
|
||||
String,
|
||||
std::collections::HashMap<String, Vec<String>>,
|
||||
String, // the pkg root
|
||||
std::collections::HashMap<String, Vec<String>>, // preloads
|
||||
String, // the name of the __wasm_split.js file
|
||||
)>,
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_dom"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_macro"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -25,9 +25,8 @@ use std::{
|
||||
use syn::{
|
||||
punctuated::Pair::{End, Punctuated},
|
||||
spanned::Spanned,
|
||||
Expr,
|
||||
Expr::Tuple,
|
||||
ExprArray, ExprLit, ExprRange, Lit, LitStr, RangeLimits, Stmt,
|
||||
Expr::{self, Tuple},
|
||||
ExprArray, ExprLit, ExprPath, ExprRange, Lit, LitStr, RangeLimits, Stmt,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
@@ -1679,7 +1678,7 @@ fn attribute_value(
|
||||
}
|
||||
|
||||
// Keep list alphabetized for binary search
|
||||
const TYPED_EVENTS: [&str; 126] = [
|
||||
const TYPED_EVENTS: [&str; 127] = [
|
||||
"DOMContentLoaded",
|
||||
"abort",
|
||||
"afterprint",
|
||||
@@ -1775,6 +1774,7 @@ const TYPED_EVENTS: [&str; 126] = [
|
||||
"reset",
|
||||
"resize",
|
||||
"scroll",
|
||||
"scrollend",
|
||||
"securitypolicyviolation",
|
||||
"seeked",
|
||||
"seeking",
|
||||
@@ -1871,6 +1871,28 @@ pub(crate) fn ident_from_tag_name(tag_name: &NodeName) -> Ident {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn full_path_from_tag_name(tag_name: &NodeName) -> Option<ExprPath> {
|
||||
match tag_name {
|
||||
NodeName::Path(path) => Some(path.clone()),
|
||||
NodeName::Block(_) => {
|
||||
let span = tag_name.span();
|
||||
proc_macro_error2::emit_error!(
|
||||
span,
|
||||
"blocks not allowed in tag-name position"
|
||||
);
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
let span = tag_name.span();
|
||||
proc_macro_error2::emit_error!(
|
||||
span,
|
||||
"punctuated names not allowed in slots"
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn directive_call_from_attribute_node(
|
||||
attr: &KeyedAttribute,
|
||||
directive_name: &str,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
component_builder::maybe_optimised_component_children,
|
||||
convert_to_snake_case, ident_from_tag_name,
|
||||
convert_to_snake_case, full_path_from_tag_name,
|
||||
};
|
||||
use crate::view::{fragment_to_tokens, utils::filter_prefixed_attrs, TagType};
|
||||
use proc_macro2::{Ident, TokenStream, TokenTree};
|
||||
@@ -24,7 +24,7 @@ pub(crate) fn slot_to_tokens(
|
||||
node.name().to_string()
|
||||
});
|
||||
|
||||
let component_name = ident_from_tag_name(node.name());
|
||||
let component_path = full_path_from_tag_name(node.name());
|
||||
|
||||
let Some(parent_slots) = parent_slots else {
|
||||
proc_macro_error2::emit_error!(
|
||||
@@ -190,7 +190,7 @@ pub(crate) fn slot_to_tokens(
|
||||
|
||||
let slot = quote_spanned! {node.span()=>
|
||||
{
|
||||
let slot = #component_name::builder()
|
||||
let slot = #component_path::builder()
|
||||
#(#props)*
|
||||
#(#slots)*
|
||||
#children
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_graph"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -209,6 +209,25 @@ impl Owner {
|
||||
this
|
||||
}
|
||||
|
||||
/// Returns the parent of this `Owner`, if any.
|
||||
///
|
||||
/// None when:
|
||||
/// - This is a root owner
|
||||
/// - The parent has been dropped
|
||||
pub fn parent(&self) -> Option<Owner> {
|
||||
self.inner
|
||||
.read()
|
||||
.or_poisoned()
|
||||
.parent
|
||||
.as_ref()
|
||||
.and_then(|p| p.upgrade())
|
||||
.map(|inner| Owner {
|
||||
inner,
|
||||
#[cfg(feature = "hydration")]
|
||||
shared_context: self.shared_context.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `Owner` that is the child of the current `Owner`, if any.
|
||||
pub fn child(&self) -> Self {
|
||||
let parent = Some(Arc::downgrade(&self.inner));
|
||||
|
||||
@@ -1542,7 +1542,6 @@ pub mod read {
|
||||
|
||||
impl<T, S> ReadUntracked for MaybeProp<T, S>
|
||||
where
|
||||
T: Clone,
|
||||
S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
|
||||
{
|
||||
type Value = ReadGuard<Option<T>, SignalReadGuard<Option<T>, S>>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -364,6 +364,12 @@ where
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MatchedRoute(pub String, pub AnyView);
|
||||
|
||||
impl MatchedRoute {
|
||||
fn branch_name(&self) -> String {
|
||||
format!("{:?}", self.1.as_type_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for MatchedRoute {
|
||||
type State = <AnyView as Render>::State;
|
||||
|
||||
@@ -414,8 +420,9 @@ impl RenderHtml for MatchedRoute {
|
||||
mark_branches: bool,
|
||||
extra_attrs: Vec<AnyAttribute>,
|
||||
) {
|
||||
if mark_branches && escape {
|
||||
buf.open_branch(&self.0);
|
||||
let branch_name = (mark_branches && escape).then(|| self.branch_name());
|
||||
if let Some(bn) = &branch_name {
|
||||
buf.open_branch(bn);
|
||||
}
|
||||
self.1.to_html_with_buf(
|
||||
buf,
|
||||
@@ -424,8 +431,8 @@ impl RenderHtml for MatchedRoute {
|
||||
mark_branches,
|
||||
extra_attrs,
|
||||
);
|
||||
if mark_branches && escape {
|
||||
buf.close_branch(&self.0);
|
||||
if let Some(bn) = &branch_name {
|
||||
buf.close_branch(bn);
|
||||
if *position == Position::NextChildAfterText {
|
||||
*position = Position::NextChild;
|
||||
}
|
||||
@@ -442,8 +449,9 @@ impl RenderHtml for MatchedRoute {
|
||||
) where
|
||||
Self: Sized,
|
||||
{
|
||||
if mark_branches && escape {
|
||||
buf.open_branch(&self.0);
|
||||
let branch_name = (mark_branches && escape).then(|| self.branch_name());
|
||||
if let Some(bn) = &branch_name {
|
||||
buf.open_branch(bn);
|
||||
}
|
||||
self.1.to_html_async_with_buf::<OUT_OF_ORDER>(
|
||||
buf,
|
||||
@@ -452,8 +460,8 @@ impl RenderHtml for MatchedRoute {
|
||||
mark_branches,
|
||||
extra_attrs,
|
||||
);
|
||||
if mark_branches && escape {
|
||||
buf.close_branch(&self.0);
|
||||
if let Some(bn) = &branch_name {
|
||||
buf.close_branch(bn);
|
||||
if *position == Position::NextChildAfterText {
|
||||
*position = Position::NextChild;
|
||||
}
|
||||
|
||||
@@ -185,11 +185,15 @@ impl LocationProvider for BrowserUrl {
|
||||
let is_back = self.is_back.clone();
|
||||
move || match Self::current() {
|
||||
Ok(new_url) => {
|
||||
let stack = path_stack.read_value();
|
||||
let mut stack = path_stack.write_value();
|
||||
let is_navigating_back = stack.len() == 1
|
||||
|| (stack.len() >= 2
|
||||
&& stack.get(stack.len() - 2) == Some(&new_url));
|
||||
|
||||
if is_navigating_back {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
is_back.set(is_navigating_back);
|
||||
|
||||
url.set(new_url);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tachys"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -205,6 +205,14 @@ where
|
||||
self.add_any_attr(enterkeyhint(value))
|
||||
}
|
||||
|
||||
/// The `exportparts` attribute enables the sharing of parts of an element's shadow DOM with a containing document.
|
||||
fn exportparts(
|
||||
self,
|
||||
value: V,
|
||||
) -> <Self as AddAnyAttr>::Output<Attr<Exportparts, V>> {
|
||||
self.add_any_attr(exportparts(value))
|
||||
}
|
||||
|
||||
/// The `hidden` global attribute is a Boolean attribute indicating that the element is not yet, or is no longer, relevant.
|
||||
fn hidden(self, value: V) -> <Self as AddAnyAttr>::Output<Attr<Hidden, V>> {
|
||||
self.add_any_attr(hidden(value))
|
||||
|
||||
@@ -212,7 +212,7 @@ html_self_closing_elements! {
|
||||
/// The `<img>` HTML element embeds an image into the document.
|
||||
img HtmlImageElement [alt, attributionsrc, crossorigin, decoding, elementtiming, fetchpriority, height, ismap, loading, referrerpolicy, sizes, src, srcset, usemap, width] true,
|
||||
/// The `<input>` HTML element is used to create interactive controls for web-based forms in order to accept data from the user; a wide variety of types of input data and control widgets are available, depending on the device and user agent. The `<input>` element is one of the most powerful and complex in all of HTML due to the sheer number of combinations of input types and attributes.
|
||||
input HtmlInputElement [accept, alt, autocomplete, capture, checked, disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, height, list, max, maxlength, min, minlength, multiple, name, pattern, placeholder, popovertarget, popovertargetaction, readonly, required, size, src, step, r#type, value, width] true,
|
||||
input HtmlInputElement [accept, alt, autocomplete, capture, checked, dirname, disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, height, list, max, maxlength, min, minlength, multiple, name, pattern, placeholder, popovertarget, popovertargetaction, readonly, required, size, src, step, r#type, value, width] true,
|
||||
/// The `<link>` HTML element specifies relationships between the current document and an external resource. This element is most commonly used to link to CSS, but is also used to establish site icons (both "favicon" style icons and icons for the home screen and apps on mobile devices) among other things.
|
||||
link HtmlLinkElement [r#as, blocking, crossorigin, fetchpriority, href, hreflang, imagesizes, imagesrcset, integrity, media, rel, referrerpolicy, sizes, r#type] true,
|
||||
/// The `<meta>` HTML element represents Metadata that cannot be represented by other HTML meta-related elements, like base, link, script, style or title.
|
||||
|
||||
@@ -323,7 +323,9 @@ where
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
let (el, prev_cleanup) = state;
|
||||
if let Some(prev) = prev_cleanup.take() {
|
||||
(prev.into_inner())(el);
|
||||
if let Some(remove) = prev.into_inner() {
|
||||
remove();
|
||||
}
|
||||
}
|
||||
*prev_cleanup = Some(if E::CAPTURE {
|
||||
self.attach_capture(el)
|
||||
|
||||
@@ -258,7 +258,9 @@ where
|
||||
prop(self.key(), signal).rebuild(attr_state);
|
||||
|
||||
if let Some(prev) = prev_cleanup.take() {
|
||||
(prev.into_inner())(el);
|
||||
if let Some(remove) = prev.into_inner() {
|
||||
remove();
|
||||
}
|
||||
}
|
||||
*prev_cleanup = Some(self.attach(el));
|
||||
}
|
||||
|
||||
@@ -296,19 +296,20 @@ impl Dom {
|
||||
// return the remover
|
||||
RemoveEventHandler::new({
|
||||
let name = name.to_owned();
|
||||
let el = el.clone();
|
||||
// safe to construct this here, because it will only run in the browser
|
||||
// so it will always be accessed or dropped from the main thread
|
||||
let cb = send_wrapper::SendWrapper::new(cb);
|
||||
move |el: &Element| {
|
||||
let cb = send_wrapper::SendWrapper::new(move || {
|
||||
or_debug!(
|
||||
el.remove_event_listener_with_callback(
|
||||
intern(&name),
|
||||
cb.as_ref().unchecked_ref()
|
||||
),
|
||||
el,
|
||||
&el,
|
||||
"removeEventListener"
|
||||
)
|
||||
}
|
||||
});
|
||||
move || cb()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -334,20 +335,21 @@ impl Dom {
|
||||
// return the remover
|
||||
RemoveEventHandler::new({
|
||||
let name = name.to_owned();
|
||||
let el = el.clone();
|
||||
// safe to construct this here, because it will only run in the browser
|
||||
// so it will always be accessed or dropped from the main thread
|
||||
let cb = send_wrapper::SendWrapper::new(cb);
|
||||
move |el: &Element| {
|
||||
let cb = send_wrapper::SendWrapper::new(move || {
|
||||
or_debug!(
|
||||
el.remove_event_listener_with_callback_and_bool(
|
||||
intern(&name),
|
||||
cb.as_ref().unchecked_ref(),
|
||||
true
|
||||
),
|
||||
el,
|
||||
&el,
|
||||
"removeEventListener"
|
||||
)
|
||||
}
|
||||
});
|
||||
move || cb()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -448,17 +450,19 @@ impl Dom {
|
||||
// return the remover
|
||||
RemoveEventHandler::new({
|
||||
let key = key.to_owned();
|
||||
let el = el.clone();
|
||||
// safe to construct this here, because it will only run in the browser
|
||||
// so it will always be accessed or dropped from the main thread
|
||||
let cb = send_wrapper::SendWrapper::new(cb);
|
||||
move |el: &Element| {
|
||||
drop(cb.take());
|
||||
let el_cb = send_wrapper::SendWrapper::new((el, cb));
|
||||
move || {
|
||||
let (el, cb) = el_cb.take();
|
||||
drop(cb);
|
||||
or_debug!(
|
||||
js_sys::Reflect::delete_property(
|
||||
el,
|
||||
&el,
|
||||
&JsValue::from_str(&key)
|
||||
),
|
||||
el,
|
||||
&el,
|
||||
"delete property"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::view::{Mountable, ToTemplate};
|
||||
use std::{borrow::Cow, fmt::Debug};
|
||||
use std::{borrow::Cow, fmt::Debug, marker::PhantomData};
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
/// A DOM renderer.
|
||||
@@ -120,16 +120,33 @@ pub trait Renderer: Send + Sized + Debug + 'static {
|
||||
should store it in some other data structure to clean it up \
|
||||
later to avoid dropping it immediately, or leak it with \
|
||||
std::mem::forget() to never drop it."]
|
||||
pub struct RemoveEventHandler<T>(Box<dyn FnOnce(&T) + Send + Sync>);
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub struct RemoveEventHandler<T>(
|
||||
Option<Box<dyn FnOnce() + Send + Sync>>,
|
||||
// only here to keep the generic, removing which would be a breaking change
|
||||
// TODO remove generic in 0.9
|
||||
PhantomData<fn() -> T>,
|
||||
);
|
||||
|
||||
impl<T> RemoveEventHandler<T> {
|
||||
/// Creates a new container with a function that will be called when it is dropped.
|
||||
pub(crate) fn new(remove: impl FnOnce(&T) + Send + Sync + 'static) -> Self {
|
||||
Self(Box::new(remove))
|
||||
pub(crate) fn new(remove: impl FnOnce() + Send + Sync + 'static) -> Self {
|
||||
Self(Some(Box::new(remove)), PhantomData)
|
||||
}
|
||||
|
||||
pub(crate) fn into_inner(self) -> Box<dyn FnOnce(&T) + Send + Sync> {
|
||||
self.0
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub(crate) fn into_inner(
|
||||
mut self,
|
||||
) -> Option<Box<dyn FnOnce() + Send + Sync>> {
|
||||
self.0.take()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for RemoveEventHandler<T> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(cb) = self.0.take() {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -378,83 +378,91 @@ impl Stream for StreamBuilder {
|
||||
let next_chunk = this.chunks.pop_front();
|
||||
match next_chunk {
|
||||
None => {
|
||||
// now, handle out-of-order chunks
|
||||
if let Some(mut pending) = this.pending_ooo.pop_front() {
|
||||
match pending.as_mut().poll(cx) {
|
||||
Poll::Ready(OooChunk {
|
||||
id,
|
||||
chunks,
|
||||
replace,
|
||||
nonce,
|
||||
}) => {
|
||||
let opening = format!("<!--s-{id}o-->");
|
||||
let placeholder_at =
|
||||
this.sync_buf.find(&opening);
|
||||
if let Some(start) = placeholder_at {
|
||||
let closing = format!("<!--s-{id}c-->");
|
||||
let end =
|
||||
this.sync_buf.find(&closing).unwrap();
|
||||
let chunks_iter = chunks.into_iter().rev();
|
||||
if this.pending_ooo.is_empty() {
|
||||
if this.sync_buf.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
Poll::Ready(Some(mem::take(&mut this.sync_buf)))
|
||||
}
|
||||
} else {
|
||||
// check if *any* pending out-of-order chunk is ready
|
||||
for mut chunk in mem::take(&mut this.pending_ooo) {
|
||||
match chunk.as_mut().poll(cx) {
|
||||
Poll::Ready(OooChunk {
|
||||
id,
|
||||
chunks,
|
||||
replace,
|
||||
nonce,
|
||||
}) => {
|
||||
let opening = format!("<!--s-{id}o-->");
|
||||
let placeholder_at =
|
||||
this.sync_buf.find(&opening);
|
||||
if let Some(start) = placeholder_at {
|
||||
let closing = format!("<!--s-{id}c-->");
|
||||
let end = this
|
||||
.sync_buf
|
||||
.find(&closing)
|
||||
.unwrap();
|
||||
let chunks_iter =
|
||||
chunks.into_iter().rev();
|
||||
|
||||
// TODO can probably make this more efficient
|
||||
let (before, replaced) =
|
||||
this.sync_buf.split_at(start);
|
||||
let (_, after) = replaced
|
||||
.split_at(end - start + closing.len());
|
||||
let mut buf = String::new();
|
||||
buf.push_str(before);
|
||||
// TODO can probably make this more efficient
|
||||
let (before, replaced) =
|
||||
this.sync_buf.split_at(start);
|
||||
let (_, after) = replaced.split_at(
|
||||
end - start + closing.len(),
|
||||
);
|
||||
let mut buf = String::new();
|
||||
buf.push_str(before);
|
||||
|
||||
let mut held_chunks = VecDeque::new();
|
||||
for chunk in chunks_iter {
|
||||
if let StreamChunk::Sync(ready) = chunk
|
||||
{
|
||||
buf.push_str(&ready);
|
||||
} else {
|
||||
held_chunks.push_front(chunk);
|
||||
let mut held_chunks = VecDeque::new();
|
||||
for chunk in chunks_iter {
|
||||
if let StreamChunk::Sync(ready) =
|
||||
chunk
|
||||
{
|
||||
buf.push_str(&ready);
|
||||
} else {
|
||||
held_chunks.push_front(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.push_str(after);
|
||||
this.sync_buf = buf;
|
||||
for chunk in held_chunks {
|
||||
this.chunks.push_front(chunk);
|
||||
}
|
||||
} else {
|
||||
OooChunk::push_start(
|
||||
&id,
|
||||
&mut this.sync_buf,
|
||||
);
|
||||
for chunk in chunks.into_iter().rev() {
|
||||
if let StreamChunk::Sync(ready) = chunk
|
||||
{
|
||||
this.sync_buf.push_str(&ready);
|
||||
} else {
|
||||
buf.push_str(after);
|
||||
this.sync_buf = buf;
|
||||
for chunk in held_chunks {
|
||||
this.chunks.push_front(chunk);
|
||||
}
|
||||
} else {
|
||||
OooChunk::push_start(
|
||||
&id,
|
||||
&mut this.sync_buf,
|
||||
);
|
||||
for chunk in chunks.into_iter().rev() {
|
||||
if let StreamChunk::Sync(ready) =
|
||||
chunk
|
||||
{
|
||||
this.sync_buf.push_str(&ready);
|
||||
} else {
|
||||
this.chunks.push_front(chunk);
|
||||
}
|
||||
}
|
||||
OooChunk::push_end_with_nonce(
|
||||
replace,
|
||||
&id,
|
||||
&mut this.sync_buf,
|
||||
nonce.as_deref(),
|
||||
);
|
||||
}
|
||||
OooChunk::push_end_with_nonce(
|
||||
replace,
|
||||
&id,
|
||||
&mut this.sync_buf,
|
||||
nonce.as_deref(),
|
||||
);
|
||||
}
|
||||
self.poll_next(cx)
|
||||
}
|
||||
Poll::Pending => {
|
||||
this.pending_ooo.push_back(pending);
|
||||
if this.sync_buf.is_empty() {
|
||||
Poll::Pending
|
||||
} else {
|
||||
Poll::Ready(Some(mem::take(
|
||||
&mut this.sync_buf,
|
||||
)))
|
||||
Poll::Pending => {
|
||||
this.pending_ooo.push_back(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if this.sync_buf.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
Poll::Ready(Some(mem::take(&mut this.sync_buf)))
|
||||
|
||||
if this.sync_buf.is_empty() {
|
||||
Poll::Pending
|
||||
} else {
|
||||
Poll::Ready(Some(mem::take(&mut this.sync_buf)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(StreamChunk::Sync(value)) => {
|
||||
|
||||
@@ -79,6 +79,13 @@ pub struct AnyView {
|
||||
) -> Pin<Box<dyn Future<Output = AnyViewState>>>,
|
||||
}
|
||||
|
||||
impl AnyView {
|
||||
#[doc(hidden)]
|
||||
pub fn as_type_id(&self) -> TypeId {
|
||||
self.type_id
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for AnyView {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("AnyView")
|
||||
|
||||
Reference in New Issue
Block a user