feat: overhaul ssr

This commit is contained in:
Jonathan Kelley committed 2022-12-06 17:41:47 -08:00
1 parent e8ae1fb83e
commit 34d9aafe0e
16 files changed
+263 -561

No files matched your search

+2 -1
View File
@@ -307,7 +307,8 @@ impl<'b> VirtualDom {
let unbounded_props = unsafe { std::mem::transmute(props) };
let scope = self.new_scope(unbounded_props).id;
let scope = self.new_scope(unbounded_props, component.name);
let scope = scope.id;
component.scope.set(Some(scope));
let return_nodes = unsafe { self.run_scope(scope).extend_lifetime_ref() };
+6 -1
View File
@@ -17,7 +17,11 @@ use std::{
};
impl VirtualDom {
pub(super) fn new_scope(&mut self, props: Box<dyn AnyProps<'static>>) -> &ScopeState {
pub(super) fn new_scope(
&mut self,
props: Box<dyn AnyProps<'static>>,
name: &'static str,
) -> &ScopeState {
let parent = self.acquire_current_scope_raw();
let entry = self.scopes.vacant_entry();
let height = unsafe { parent.map(|f| (*f).height + 1).unwrap_or(0) };
@@ -28,6 +32,7 @@ impl VirtualDom {
id,
height,
props: Some(props),
name,
placeholder: Default::default(),
node_arena_1: BumpFrame::new(50),
node_arena_2: BumpFrame::new(50),
+6
View File
@@ -68,6 +68,7 @@ pub struct ScopeId(pub usize);
/// This struct exists to provide a common interface for all scopes without relying on generics.
pub struct ScopeState {
pub(crate) render_cnt: Cell<usize>,
pub(crate) name: &'static str,
pub(crate) node_arena_1: BumpFrame,
pub(crate) node_arena_2: BumpFrame,
@@ -115,6 +116,11 @@ impl<'src> ScopeState {
}
}
/// Get the name of this component
pub fn name(&self) -> &str {
self.name
}
/// Get the current render since the inception of this component
///
/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
+4 -5
View File
@@ -239,11 +239,10 @@ impl VirtualDom {
mutations: Mutations::default(),
};
let root = dom.new_scope(Box::new(VProps::new(
root,
|_, _| unreachable!(),
root_props,
)));
let root = dom.new_scope(
Box::new(VProps::new(root, |_, _| unreachable!(), root_props)),
"app",
);
// The root component is always a suspense boundary for any async children
// This could be unexpected, so we might rethink this behavior later
+2 -8
View File
@@ -29,17 +29,11 @@ fn state_shares() {
dom.mark_dirty(ScopeId(0));
_ = dom.render_immediate();
assert_eq!(
dom.base_scope().consume_context::<i32>().unwrap().as_ref(),
&1
);
assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 1);
dom.mark_dirty(ScopeId(0));
_ = dom.render_immediate();
assert_eq!(
dom.base_scope().consume_context::<i32>().unwrap().as_ref(),
&2
);
assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 2);
dom.mark_dirty(ScopeId(2));
assert_eq!(
+3 -1
View File
@@ -1,5 +1,7 @@
//! Tests related to safety of the library.
use std::rc::Rc;
use dioxus::prelude::*;
use dioxus_core::SuspenseContext;
@@ -18,5 +20,5 @@ fn root_node_isnt_null() {
// There should be a default suspense context
// todo: there should also be a default error boundary
assert!(scope.has_context::<SuspenseContext>().is_some());
assert!(scope.has_context::<Rc<SuspenseContext>>().is_some());
}
+3 -2
View File
@@ -2,6 +2,7 @@ use dioxus::core::ElementId;
use dioxus::core::{Mutation::*, SuspenseContext};
use dioxus::prelude::*;
use std::future::IntoFuture;
use std::rc::Rc;
use std::time::Duration;
#[tokio::test]
@@ -51,11 +52,11 @@ fn app(cx: Scope) -> Element {
fn suspense_boundary(cx: Scope) -> Element {
cx.use_hook(|| {
cx.provide_context(SuspenseContext::new(cx.scope_id()));
cx.provide_context(Rc::new(SuspenseContext::new(cx.scope_id())));
});
// Ensure the right types are found
cx.has_context::<SuspenseContext>().unwrap();
cx.has_context::<Rc<SuspenseContext>>().unwrap();
cx.render(rsx!(async_child {}))
}