Update other packages to handle new thread-local reactives
This commit is contained in:
parent
739e7db49d
commit
6c521226e3
|
@ -50,8 +50,8 @@ pub fn handle_server_fns() -> Route {
|
|||
if let Some(server_fn) = server_fn_by_path(path.as_str()) {
|
||||
let body: &[u8] = &body;
|
||||
|
||||
// TODO this leaks a runtime once per invocation
|
||||
let (cx, disposer) = raw_scope_and_disposer();
|
||||
let runtime = create_runtime();
|
||||
let (cx, disposer) = raw_scope_and_disposer(runtime);
|
||||
|
||||
// provide HttpRequest as context in server scope
|
||||
provide_context(cx, req.clone());
|
||||
|
@ -60,6 +60,7 @@ pub fn handle_server_fns() -> Route {
|
|||
Ok(serialized) => {
|
||||
// clean up the scope, which we only needed to run the server fn
|
||||
disposer.dispose();
|
||||
runtime.dispose();
|
||||
|
||||
// if this is Accept: application/json then send a serialized JSON response
|
||||
if let Some("application/json") = accept_header {
|
||||
|
|
|
@ -55,8 +55,8 @@ pub async fn handle_server_fns(
|
|||
let body: &[u8] = &body;
|
||||
|
||||
let res = if let Some(server_fn) = server_fn_by_path(path.as_str()) {
|
||||
// TODO this leaks a runtime once per invocation
|
||||
let (cx, disposer) = raw_scope_and_disposer();
|
||||
let runtime = create_runtime();
|
||||
let (cx, disposer) = raw_scope_and_disposer(runtime);
|
||||
|
||||
// provide request as context in server scope
|
||||
provide_context(cx, Arc::new(req));
|
||||
|
@ -65,6 +65,7 @@ pub async fn handle_server_fns(
|
|||
Ok(serialized) => {
|
||||
// clean up the scope, which we only needed to run the server fn
|
||||
disposer.dispose();
|
||||
runtime.dispose();
|
||||
|
||||
// if this is Accept: application/json then send a serialized JSON response
|
||||
let accept_header =
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
fn simple_ssr_test() {
|
||||
use leptos_dom::*;
|
||||
use leptos_macro::view;
|
||||
use leptos_reactive::{create_scope, create_signal};
|
||||
use leptos_reactive::{create_runtime, create_scope, create_signal};
|
||||
|
||||
_ = create_scope(|cx| {
|
||||
_ = create_scope(create_runtime(), |cx| {
|
||||
let (value, set_value) = create_signal(cx, 0);
|
||||
let rendered = view! {
|
||||
cx,
|
||||
|
@ -45,7 +45,7 @@ fn ssr_test_with_components() {
|
|||
}
|
||||
}
|
||||
|
||||
_ = create_scope(|cx| {
|
||||
_ = create_scope(create_runtime(), |cx| {
|
||||
let rendered = view! {
|
||||
cx,
|
||||
<div class="counters">
|
||||
|
@ -66,9 +66,9 @@ fn ssr_test_with_components() {
|
|||
fn test_classes() {
|
||||
use leptos_dom::*;
|
||||
use leptos_macro::view;
|
||||
use leptos_reactive::{create_scope, create_signal};
|
||||
use leptos_reactive::{create_runtime, create_scope, create_signal};
|
||||
|
||||
_ = create_scope(|cx| {
|
||||
_ = create_scope(create_runtime(), |cx| {
|
||||
let (value, set_value) = create_signal(cx, 5);
|
||||
let rendered = view! {
|
||||
cx,
|
||||
|
|
|
@ -71,11 +71,11 @@ where
|
|||
F: Fn(Scope) -> T + 'static,
|
||||
T: Mountable,
|
||||
{
|
||||
use leptos_reactive::create_scope;
|
||||
use leptos_reactive::{create_runtime, create_scope};
|
||||
|
||||
// running "mount" intentionally leaks the memory,
|
||||
// as the "mount" has no parent that can clean it up
|
||||
let _ = create_scope(move |cx| {
|
||||
// this is not a leak
|
||||
// CSR and hydrate mode define a single, thread-local Runtime
|
||||
let _ = create_scope(create_runtime(), move |cx| {
|
||||
(f(cx)).mount(&parent);
|
||||
});
|
||||
}
|
||||
|
@ -100,9 +100,11 @@ where
|
|||
F: Fn(Scope) -> T + 'static,
|
||||
T: Mountable,
|
||||
{
|
||||
// running "hydrate" intentionally leaks the memory,
|
||||
// as the "hydrate" has no parent that can clean it up
|
||||
let _ = leptos_reactive::create_scope(move |cx| {
|
||||
use leptos_reactive::create_runtime;
|
||||
|
||||
// this is not a leak
|
||||
// CSR and hydrate mode define a single, thread-local Runtime
|
||||
let _ = leptos_reactive::create_scope(create_runtime(), move |cx| {
|
||||
cx.start_hydration(&parent);
|
||||
(f(cx));
|
||||
cx.end_hydration();
|
||||
|
|
|
@ -31,8 +31,11 @@ cfg_if! {
|
|||
/// 3) HTML fragments to replace each `<Suspense/>` fallback with its actual data as the resources
|
||||
/// read under that `<Suspense/>` resolve.
|
||||
pub fn render_to_stream(view: impl Fn(Scope) -> Element + 'static) -> impl Stream<Item = String> {
|
||||
// create the runtime
|
||||
let runtime = create_runtime();
|
||||
|
||||
let ((shell, pending_resources, pending_fragments, serializers), _, disposer) =
|
||||
run_scope_undisposed({
|
||||
run_scope_undisposed(runtime, {
|
||||
move |cx| {
|
||||
// the actual app body/template code
|
||||
// this does NOT contain any of the data being loaded asynchronously in resources
|
||||
|
@ -55,6 +58,39 @@ cfg_if! {
|
|||
fragments.push(async move { (fragment_id, fut.await) })
|
||||
}
|
||||
|
||||
// resources and fragments
|
||||
let resources_and_fragments = futures::stream::select(
|
||||
// stream data for each Resource as it resolves
|
||||
serializers.map(|(id, json)| {
|
||||
let id = serde_json::to_string(&id).unwrap();
|
||||
format!(
|
||||
r#"<script>
|
||||
if(__LEPTOS_RESOURCE_RESOLVERS.get({id})) {{
|
||||
console.log("(create_resource) calling resolver");
|
||||
__LEPTOS_RESOURCE_RESOLVERS.get({id})({json:?})
|
||||
}} else {{
|
||||
console.log("(create_resource) saving data for resource creation");
|
||||
__LEPTOS_RESOLVED_RESOURCES.set({id}, {json:?});
|
||||
}}
|
||||
</script>"#,
|
||||
)
|
||||
}),
|
||||
// stream HTML for each <Suspense/> as it resolves
|
||||
fragments.map(|(fragment_id, html)| {
|
||||
format!(
|
||||
r#"
|
||||
<template id="{fragment_id}">{html}</template>
|
||||
<script>
|
||||
var frag = document.querySelector(`[data-fragment-id="{fragment_id}"]`);
|
||||
var tpl = document.getElementById("{fragment_id}");
|
||||
console.log("replace", frag, "with", tpl.content.cloneNode(true));
|
||||
frag.replaceWith(tpl.content.cloneNode(true));
|
||||
</script>
|
||||
"#
|
||||
)
|
||||
})
|
||||
);
|
||||
|
||||
// HTML for the view function and script to store resources
|
||||
futures::stream::once(async move {
|
||||
format!(
|
||||
|
@ -68,42 +104,11 @@ cfg_if! {
|
|||
"#
|
||||
)
|
||||
})
|
||||
|
||||
// TODO this is wrong: it should merge the next two streams, not chain them
|
||||
// you may well need to resolve some fragments before some of the resources are resolved
|
||||
|
||||
// stream data for each Resource as it resolves
|
||||
.chain(serializers.map(|(id, json)| {
|
||||
let id = serde_json::to_string(&id).unwrap();
|
||||
format!(
|
||||
r#"<script>
|
||||
if(__LEPTOS_RESOURCE_RESOLVERS.get({id})) {{
|
||||
console.log("(create_resource) calling resolver");
|
||||
__LEPTOS_RESOURCE_RESOLVERS.get({id})({json:?})
|
||||
}} else {{
|
||||
console.log("(create_resource) saving data for resource creation");
|
||||
__LEPTOS_RESOLVED_RESOURCES.set({id}, {json:?});
|
||||
}}
|
||||
</script>"#,
|
||||
)
|
||||
}))
|
||||
// stream HTML for each <Suspense/> as it resolves
|
||||
.chain(fragments.map(|(fragment_id, html)| {
|
||||
format!(
|
||||
r#"
|
||||
<template id="{fragment_id}">{html}</template>
|
||||
<script>
|
||||
var frag = document.querySelector(`[data-fragment-id="{fragment_id}"]`);
|
||||
var tpl = document.getElementById("{fragment_id}");
|
||||
console.log("replace", frag, "with", tpl.content.cloneNode(true));
|
||||
frag.replaceWith(tpl.content.cloneNode(true));
|
||||
</script>
|
||||
"#
|
||||
)
|
||||
}))
|
||||
// dispose of Scope
|
||||
.chain(futures::stream::once(async {
|
||||
.chain(resources_and_fragments)
|
||||
// dispose of Scope and Runtime
|
||||
.chain(futures::stream::once(async move {
|
||||
disposer.dispose();
|
||||
runtime.dispose();
|
||||
Default::default()
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) type PinnedFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
|||
cfg_if! {
|
||||
if #[cfg(any(feature = "csr", feature = "hydrate"))] {
|
||||
thread_local! {
|
||||
pub(crate) static RUNTIME: Runtime = Default::default();
|
||||
pub(crate) static RUNTIME: Runtime = Runtime::new();
|
||||
}
|
||||
} else {
|
||||
thread_local! {
|
||||
|
|
Loading…
Reference in New Issue