feat: support cached ssr
This commit is contained in:
1 parent
4a31b29703
commit
b6c0bce89c
11 files changed
+433
-178
No files matched your search
@@ -3,6 +3,7 @@ use crate::mutations::Mutation::*;
|
||||
use crate::nodes::VNode;
|
||||
use crate::nodes::{DynamicNode, DynamicNodeKind, TemplateNode};
|
||||
use crate::virtualdom::VirtualDom;
|
||||
use crate::TemplateAttribute;
|
||||
|
||||
impl VirtualDom {
|
||||
/// Create this template and write its mutations
|
||||
@@ -112,10 +113,11 @@ impl VirtualDom {
|
||||
id,
|
||||
});
|
||||
|
||||
mutations.extend(attrs.into_iter().map(|attr| SetAttribute {
|
||||
name: attr.name,
|
||||
value: attr.value,
|
||||
id,
|
||||
mutations.extend(attrs.into_iter().filter_map(|attr| match attr {
|
||||
TemplateAttribute::Static { name, value, .. } => {
|
||||
Some(SetAttribute { name, value, id })
|
||||
}
|
||||
_ => None,
|
||||
}));
|
||||
|
||||
children
|
||||
|
||||
@@ -1,19 +1,36 @@
|
||||
use std::fmt::Arguments;
|
||||
use std::{cell::Cell, fmt::Arguments};
|
||||
|
||||
use crate::{innerlude::DynamicNode, LazyNodes, ScopeState, VNode};
|
||||
use crate::{
|
||||
arena::ElementId,
|
||||
innerlude::{DynamicNode, DynamicNodeKind},
|
||||
LazyNodes, ScopeState, VNode,
|
||||
};
|
||||
|
||||
impl ScopeState {
|
||||
/// Create some text that's allocated along with the other vnodes
|
||||
///
|
||||
pub fn text(&self, args: Arguments) -> DynamicNode {
|
||||
// let (text, _is_static) = self.raw_text(args);
|
||||
pub fn text<'a>(&'a self, args: Arguments) -> DynamicNode<'a> {
|
||||
let (text, _) = self.raw_text(args);
|
||||
|
||||
// VNode::Text(self.bump.alloc(VText {
|
||||
// text,
|
||||
// id: Default::default(),
|
||||
// }))
|
||||
DynamicNode {
|
||||
kind: DynamicNodeKind::Text {
|
||||
id: Cell::new(ElementId(0)),
|
||||
value: text,
|
||||
},
|
||||
path: &[0],
|
||||
}
|
||||
}
|
||||
|
||||
todo!()
|
||||
pub fn raw_text<'a>(&'a self, args: Arguments) -> (&'a str, bool) {
|
||||
match args.as_str() {
|
||||
Some(static_str) => (static_str, true),
|
||||
None => {
|
||||
use bumpalo::core_alloc::fmt::Write;
|
||||
let mut str_buf = bumpalo::collections::String::new_in(self.bump());
|
||||
str_buf.write_fmt(args).unwrap();
|
||||
(str_buf.into_bump_str(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fragment_from_iter<'a, I, F: IntoVnode<'a, I>>(
|
||||
|
||||
@@ -69,6 +69,8 @@ pub use crate::innerlude::{
|
||||
// AnyAttributeValue, AnyEvent, Attribute, AttributeValue, Component, Element, ElementId,
|
||||
Attribute,
|
||||
AttributeValue,
|
||||
DynamicNode,
|
||||
DynamicNodeKind,
|
||||
Element,
|
||||
EventPriority,
|
||||
LazyNodes,
|
||||
@@ -94,8 +96,9 @@ pub use crate::innerlude::{
|
||||
/// This includes types like [`Scope`], [`Element`], and [`Component`].
|
||||
pub mod prelude {
|
||||
pub use crate::innerlude::{
|
||||
Attribute, Element, EventPriority, LazyNodes, Listener, NodeFactory, Scope, ScopeId,
|
||||
ScopeState, TaskId, Template, TemplateAttribute, TemplateNode, UiEvent, VNode, VirtualDom,
|
||||
Attribute, DynamicNode, DynamicNodeKind, Element, EventPriority, LazyNodes, Listener,
|
||||
NodeFactory, Scope, ScopeId, ScopeState, TaskId, Template, TemplateAttribute, TemplateNode,
|
||||
UiEvent, VNode, VirtualDom,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ pub enum Mutation<'a> {
|
||||
},
|
||||
|
||||
ReplacePlaceholder {
|
||||
path: &'static [u8],
|
||||
m: usize,
|
||||
path: &'static [u8],
|
||||
},
|
||||
|
||||
AssignId {
|
||||
|
||||
+41
-16
@@ -1,9 +1,5 @@
|
||||
use crate::{any_props::AnyProps, arena::ElementId};
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::Cell,
|
||||
num::NonZeroUsize,
|
||||
};
|
||||
use std::{any::Any, cell::Cell, hash::Hasher};
|
||||
|
||||
pub type TemplateId = &'static str;
|
||||
|
||||
@@ -15,7 +11,7 @@ pub struct VNode<'a> {
|
||||
// When rendered, this template will be linked to its parent
|
||||
pub parent: Option<(*mut VNode<'static>, usize)>,
|
||||
|
||||
pub template: Template,
|
||||
pub template: Template<'static>,
|
||||
|
||||
pub root_ids: &'a [Cell<ElementId>],
|
||||
|
||||
@@ -26,15 +22,38 @@ pub struct VNode<'a> {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Template {
|
||||
pub id: &'static str,
|
||||
pub roots: &'static [TemplateNode<'static>],
|
||||
pub struct Template<'a> {
|
||||
pub id: &'a str,
|
||||
pub roots: &'a [TemplateNode<'a>],
|
||||
}
|
||||
|
||||
impl<'a> std::hash::Hash for Template<'a> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.id.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Template<'_> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Template<'_> {}
|
||||
impl PartialOrd for Template<'_> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.id.partial_cmp(other.id)
|
||||
}
|
||||
}
|
||||
impl Ord for Template<'_> {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.id.cmp(other.id)
|
||||
}
|
||||
}
|
||||
|
||||
/// A weird-ish variant of VNodes with way more limited types
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum TemplateNode<'a> {
|
||||
/// A simple element
|
||||
Element {
|
||||
tag: &'a str,
|
||||
namespace: Option<&'a str>,
|
||||
@@ -62,7 +81,7 @@ pub enum DynamicNodeKind<'a> {
|
||||
// Comes in with string interpolation or from format_args, include_str, etc
|
||||
Text {
|
||||
id: Cell<ElementId>,
|
||||
value: &'static str,
|
||||
value: &'a str,
|
||||
},
|
||||
|
||||
// Anything that's coming in as an iterator
|
||||
@@ -72,11 +91,17 @@ pub enum DynamicNodeKind<'a> {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TemplateAttribute<'a> {
|
||||
pub name: &'static str,
|
||||
pub value: &'a str,
|
||||
pub namespace: Option<&'static str>,
|
||||
pub volatile: bool,
|
||||
pub enum TemplateAttribute<'a> {
|
||||
Static {
|
||||
name: &'static str,
|
||||
value: &'a str,
|
||||
namespace: Option<&'static str>,
|
||||
volatile: bool,
|
||||
},
|
||||
Dynamic {
|
||||
name: &'static str,
|
||||
index: usize,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct AttributeLocation<'a> {
|
||||
|
||||
@@ -15,7 +15,7 @@ use slab::Slab;
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
|
||||
pub struct VirtualDom {
|
||||
pub(crate) templates: HashMap<TemplateId, Template>,
|
||||
pub(crate) templates: HashMap<TemplateId, Template<'static>>,
|
||||
pub(crate) elements: Slab<ElementPath>,
|
||||
pub(crate) scopes: Slab<ScopeState>,
|
||||
pub(crate) scope_stack: Vec<ScopeId>,
|
||||
@@ -82,6 +82,14 @@ impl VirtualDom {
|
||||
///
|
||||
/// This is cancel safe, so if the future is dropped, you can push events into the virtualdom
|
||||
pub async fn wait_for_work(&mut self) {}
|
||||
|
||||
pub fn get_scope(&self, id: ScopeId) -> Option<&ScopeState> {
|
||||
self.scopes.get(id.0)
|
||||
}
|
||||
|
||||
pub fn base_scope(&self) -> &ScopeState {
|
||||
self.scopes.get(0).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VirtualDom {
|
||||
|
||||
Reference in new issue
Block a user