Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix VList Stream in SSR #2801

Merged
merged 12 commits into from Aug 7, 2022
49 changes: 32 additions & 17 deletions packages/yew/src/virtual_dom/vlist.rs
Expand Up @@ -156,7 +156,8 @@ mod test {

#[cfg(feature = "ssr")]
mod feat_ssr {
use futures::stream::{FuturesOrdered, StreamExt};
use futures::future;
use futures::stream::{FuturesUnordered, StreamExt};

use super::*;
use crate::html::AnyScope;
Expand All @@ -174,28 +175,42 @@ mod feat_ssr {
[child] => {
child.render_into_stream(w, parent_scope, hydratable).await;
}
_ => {
[first_child, rest_children @ ..] => {
let buf_capacity = w.capacity();
let mut child_streams = Vec::with_capacity(self.children.len() - 1);
let mut child_furs = FuturesUnordered::new();

// Concurrently render all children.
let mut children: FuturesOrdered<_> = self
.children
.iter()
.map(|m| async move {
let (mut w, r) = io::buffer(buf_capacity);
// Concurrently render rest children into a separate buffer.
for child in rest_children {
let (mut w, r) = io::buffer(buf_capacity);

m.render_into_stream(&mut w, parent_scope, hydratable).await;
drop(w);
child_furs.push(async move {
child
.render_into_stream(&mut w, parent_scope, hydratable)
.await;
});

r
})
.collect();
child_streams.push(r);
}

// Concurrently resolve all child futures.
let resolve_fur = async move { while child_furs.next().await.is_some() {} };

// Transfer results to parent writer.
let transfer_fur = async move {
// Render first child to parent buffer directly.
first_child
.render_into_stream(w, parent_scope, hydratable)
.await;

while let Some(mut r) = children.next().await {
while let Some(next_chunk) = r.next().await {
w.write(next_chunk.into());
for mut r in child_streams {
while let Some(next_chunk) = r.next().await {
w.write(next_chunk.into());
}
}
}
};

future::join(resolve_fur, transfer_fur).await;
}
}
}
Expand Down