wip: prep to fix bug in create
This commit is contained in:
1 parent
e09b6bf813
commit
04bc635ac5
14 files changed
+539
-57
No files matched your search
@@ -16,15 +16,17 @@ fn main() {
|
||||
}
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
let nf = NodeFactory::new(&cx);
|
||||
// let nf = NodeFactory::new(&cx);
|
||||
|
||||
let mut attrs = dioxus::core::exports::bumpalo::collections::Vec::new_in(nf.bump());
|
||||
// let mut attrs = dioxus::core::exports::bumpalo::collections::Vec::new_in(nf.bump());
|
||||
|
||||
attrs.push(nf.attr("client-id", format_args!("abc123"), None, false));
|
||||
// attrs.push(nf.attr("client-id", format_args!("abc123"), None, false));
|
||||
|
||||
attrs.push(nf.attr("name", format_args!("bob"), None, false));
|
||||
// attrs.push(nf.attr("name", format_args!("bob"), None, false));
|
||||
|
||||
attrs.push(nf.attr("age", format_args!("47"), None, false));
|
||||
// attrs.push(nf.attr("age", format_args!("47"), None, false));
|
||||
|
||||
Some(nf.raw_element("my-element", None, &[], attrs.into_bump_slice(), &[], None))
|
||||
// Some(nf.raw_element("my-element", None, &[], attrs.into_bump_slice(), &[], None))
|
||||
|
||||
todo!()
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@ fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx! {
|
||||
div { "hello {name}!" }
|
||||
Child {}
|
||||
ChildWithRef{}
|
||||
ChildWithRef {}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
//! It also proves that lifetimes work properly, especially when used with use_ref
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_ssr::config::SsrConfig;
|
||||
|
||||
fn main() {
|
||||
let mut vdom = VirtualDom::new(example);
|
||||
vdom.rebuild();
|
||||
|
||||
let out = dioxus_ssr::render_vdom_cfg(&vdom, |c| c.newline(true).indent(true));
|
||||
let out = dioxus_ssr::render_vdom_cfg(&vdom, SsrConfig::default().newline(true).indent(true));
|
||||
println!("{}", out);
|
||||
}
|
||||
|
||||
|
||||
+18
-10
@@ -6,15 +6,23 @@ fn main() {
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx!(
|
||||
// Use Map directly to lazily pull elements
|
||||
(0..10).map(|f| rsx! { "{f}" }),
|
||||
// Collect into an intermediate collection if necessary, and call into_iter
|
||||
["a", "b", "c"]
|
||||
.into_iter()
|
||||
.map(|f| rsx! { "{f}" })
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter(),
|
||||
// Use optionals
|
||||
Some(rsx! { "Some" }),
|
||||
div { id: "123123123",
|
||||
// Use Map directly to lazily pull elements
|
||||
// (0..3).map(|f| rsx! { "{f}" }),
|
||||
// Collect into an intermediate collection if necessary, and call into_iter
|
||||
["a", "b", "c", "x", "y", "z"]
|
||||
.into_iter()
|
||||
.map(|f| rsx! { "{f}" })
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter(),
|
||||
|
||||
["d", "e", "f"]
|
||||
.into_iter()
|
||||
.map(|f| rsx! { "{f}" })
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter(),
|
||||
// Use optionals
|
||||
// Some(rsx! { "Some" }),
|
||||
}
|
||||
))
|
||||
}
|
||||
+3
-2
@@ -5,6 +5,7 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_ssr::config::SsrConfig;
|
||||
|
||||
fn main() {
|
||||
// We can render VirtualDoms
|
||||
@@ -25,14 +26,14 @@ fn main() {
|
||||
// We can configure the SSR rendering to add ids for rehydration
|
||||
println!(
|
||||
"{}",
|
||||
dioxus_ssr::render_vdom_cfg(&vdom, |c| c.pre_render(true))
|
||||
dioxus_ssr::render_vdom_cfg(&vdom, SsrConfig::default().pre_render(true))
|
||||
);
|
||||
|
||||
// We can even render as a writer
|
||||
let mut file = String::new();
|
||||
let _ = file.write_fmt(format_args!(
|
||||
"{}",
|
||||
dioxus_ssr::TextRenderer::from_vdom(&vdom, Default::default())
|
||||
dioxus_ssr::SsrRender::default().render_vdom(&vdom)
|
||||
));
|
||||
println!("{}", file);
|
||||
}
|
||||
|
||||
@@ -96,3 +96,412 @@ set_node(el, [1,2,3,4])
|
||||
set_attribute("class", "foo")
|
||||
append_child(1)
|
||||
*/
|
||||
|
||||
|
||||
//! Instructions returned by the VirtualDOM on how to modify the Real DOM.
|
||||
//!
|
||||
//! This module contains an internal API to generate these instructions.
|
||||
//!
|
||||
//! Beware that changing code in this module will break compatibility with
|
||||
//! interpreters for these types of DomEdits.
|
||||
|
||||
use crate::innerlude::*;
|
||||
use std::{any::Any, fmt::Debug};
|
||||
|
||||
/// ## Mutations
|
||||
///
|
||||
/// This method returns "mutations" - IE the necessary changes to get the RealDOM to match the VirtualDOM. It also
|
||||
/// includes a list of NodeRefs that need to be applied and effects that need to be triggered after the RealDOM has
|
||||
/// applied the edits.
|
||||
///
|
||||
/// Mutations are the only link between the RealDOM and the VirtualDOM.
|
||||
pub struct Mutations<'a> {
|
||||
/// The list of edits that need to be applied for the RealDOM to match the VirtualDOM.
|
||||
pub edits: Vec<DomEdit<'a>>,
|
||||
|
||||
/// The list of Scopes that were diffed, created, and removed during the Diff process.
|
||||
pub dirty_scopes: FxHashSet<ScopeId>,
|
||||
|
||||
/// The list of nodes to connect to the RealDOM.
|
||||
pub refs: Vec<NodeRefMutation<'a>>,
|
||||
}
|
||||
|
||||
impl Debug for Mutations<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Mutations")
|
||||
.field("edits", &self.edits)
|
||||
.field("noderefs", &self.refs)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `DomEdit` represents a serialized form of the VirtualDom's trait-based API. This allows streaming edits across the
|
||||
/// network or through FFI boundaries.
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "serialize",
|
||||
derive(serde::Serialize, serde::Deserialize),
|
||||
serde(tag = "type")
|
||||
)]
|
||||
pub enum DomEdit<'bump> {
|
||||
/// Pop the topmost node from our stack and append them to the node
|
||||
/// at the top of the stack.
|
||||
AppendChildren {
|
||||
/// The parent to append nodes to.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The ids of the children to append.
|
||||
children: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Replace a given (single) node with a handful of nodes currently on the stack.
|
||||
ReplaceWith {
|
||||
/// The ID of the node to be replaced.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The ids of the nodes to replace the root with.
|
||||
nodes: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Insert a number of nodes after a given node.
|
||||
InsertAfter {
|
||||
/// The ID of the node to insert after.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The ids of the nodes to insert after the target node.
|
||||
nodes: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Insert a number of nodes before a given node.
|
||||
InsertBefore {
|
||||
/// The ID of the node to insert before.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The ids of the nodes to insert before the target node.
|
||||
nodes: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Remove a particular node from the DOM
|
||||
Remove {
|
||||
/// The ID of the node to remove.
|
||||
root: Option<u64>,
|
||||
},
|
||||
|
||||
/// Create a new purely-text node
|
||||
CreateTextNode {
|
||||
/// The ID the new node should have.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The textcontent of the node
|
||||
text: &'bump str,
|
||||
},
|
||||
|
||||
/// Create a new purely-element node
|
||||
CreateElement {
|
||||
/// The ID the new node should have.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The tagname of the node
|
||||
tag: &'bump str,
|
||||
|
||||
/// The number of children nodes that will follow this message.
|
||||
children: u32,
|
||||
},
|
||||
|
||||
/// Create a new purely-comment node with a given namespace
|
||||
CreateElementNs {
|
||||
/// The ID the new node should have.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The namespace of the node
|
||||
tag: &'bump str,
|
||||
|
||||
/// The namespace of the node (like `SVG`)
|
||||
ns: &'static str,
|
||||
|
||||
/// The number of children nodes that will follow this message.
|
||||
children: u32,
|
||||
},
|
||||
|
||||
/// Create a new placeholder node.
|
||||
/// In most implementations, this will either be a hidden div or a comment node.
|
||||
CreatePlaceholder {
|
||||
/// The ID the new node should have.
|
||||
root: Option<u64>,
|
||||
},
|
||||
|
||||
/// Create a new Event Listener.
|
||||
NewEventListener {
|
||||
/// The name of the event to listen for.
|
||||
event_name: &'static str,
|
||||
|
||||
/// The ID of the node to attach the listener to.
|
||||
scope: ScopeId,
|
||||
|
||||
/// The ID of the node to attach the listener to.
|
||||
root: Option<u64>,
|
||||
},
|
||||
|
||||
/// Remove an existing Event Listener.
|
||||
RemoveEventListener {
|
||||
/// The ID of the node to remove.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The name of the event to remove.
|
||||
event: &'static str,
|
||||
},
|
||||
|
||||
/// Set the textcontent of a node.
|
||||
SetText {
|
||||
/// The ID of the node to set the textcontent of.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The textcontent of the node
|
||||
text: &'bump str,
|
||||
},
|
||||
|
||||
/// Set the value of a node's attribute.
|
||||
SetAttribute {
|
||||
/// The ID of the node to set the attribute of.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The name of the attribute to set.
|
||||
field: &'static str,
|
||||
|
||||
/// The value of the attribute.
|
||||
value: AttributeValue<'bump>,
|
||||
|
||||
// value: &'bump str,
|
||||
/// The (optional) namespace of the attribute.
|
||||
/// For instance, "style" is in the "style" namespace.
|
||||
ns: Option<&'bump str>,
|
||||
},
|
||||
|
||||
/// Remove an attribute from a node.
|
||||
RemoveAttribute {
|
||||
/// The ID of the node to remove.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The name of the attribute to remove.
|
||||
name: &'static str,
|
||||
|
||||
/// The namespace of the attribute.
|
||||
ns: Option<&'bump str>,
|
||||
},
|
||||
|
||||
/// Clones a node.
|
||||
CloneNode {
|
||||
/// The ID of the node to clone.
|
||||
id: Option<u64>,
|
||||
|
||||
/// The ID of the new node.
|
||||
new_id: u64,
|
||||
},
|
||||
|
||||
/// Clones the children of a node. (allows cloning fragments)
|
||||
CloneNodeChildren {
|
||||
/// The ID of the node to clone.
|
||||
id: Option<u64>,
|
||||
|
||||
/// The ID of the new node.
|
||||
new_ids: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Navigates to the last node to the first child of the current node.
|
||||
FirstChild {},
|
||||
|
||||
/// Navigates to the last node to the last child of the current node.
|
||||
NextSibling {},
|
||||
|
||||
/// Navigates to the last node to the parent of the current node.
|
||||
ParentNode {},
|
||||
|
||||
/// Stores the last node with a new id.
|
||||
StoreWithId {
|
||||
/// The ID of the node to store.
|
||||
id: u64,
|
||||
},
|
||||
|
||||
/// Manually set the last node.
|
||||
SetLastNode {
|
||||
/// The ID to set the last node to.
|
||||
id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
use DomEdit::*;
|
||||
|
||||
#[allow(unused)]
|
||||
impl<'a> Mutations<'a> {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
edits: Vec::new(),
|
||||
refs: Vec::new(),
|
||||
dirty_scopes: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn replace_with(&mut self, root: Option<u64>, nodes: Vec<u64>) {
|
||||
self.edits.push(ReplaceWith { nodes, root });
|
||||
}
|
||||
|
||||
pub(crate) fn insert_after(&mut self, root: Option<u64>, nodes: Vec<u64>) {
|
||||
self.edits.push(InsertAfter { nodes, root });
|
||||
}
|
||||
|
||||
pub(crate) fn insert_before(&mut self, root: Option<u64>, nodes: Vec<u64>) {
|
||||
self.edits.push(InsertBefore { nodes, root });
|
||||
}
|
||||
|
||||
pub(crate) fn append_children(&mut self, root: Option<u64>, children: Vec<u64>) {
|
||||
self.edits.push(AppendChildren { root, children });
|
||||
}
|
||||
|
||||
// Remove Nodes from the dom
|
||||
pub(crate) fn remove(&mut self, id: Option<u64>) {
|
||||
self.edits.push(Remove { root: id });
|
||||
}
|
||||
|
||||
// Create
|
||||
pub(crate) fn create_text_node(&mut self, text: &'a str, id: Option<u64>) {
|
||||
self.edits.push(CreateTextNode { text, root: id });
|
||||
}
|
||||
|
||||
pub(crate) fn create_element(
|
||||
&mut self,
|
||||
tag: &'static str,
|
||||
ns: Option<&'static str>,
|
||||
id: Option<u64>,
|
||||
children: u32,
|
||||
) {
|
||||
match ns {
|
||||
Some(ns) => self.edits.push(CreateElementNs {
|
||||
root: id,
|
||||
ns,
|
||||
tag,
|
||||
children,
|
||||
}),
|
||||
None => self.edits.push(CreateElement {
|
||||
root: id,
|
||||
tag,
|
||||
children,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// placeholders are nodes that don't get rendered but still exist as an "anchor" in the real dom
|
||||
pub(crate) fn create_placeholder(&mut self, id: Option<u64>) {
|
||||
self.edits.push(CreatePlaceholder { root: id });
|
||||
}
|
||||
|
||||
// events
|
||||
pub(crate) fn new_event_listener(&mut self, listener: &Listener, scope: ScopeId) {
|
||||
let Listener {
|
||||
event,
|
||||
mounted_node,
|
||||
..
|
||||
} = listener;
|
||||
|
||||
let element_id = Some(mounted_node.get().unwrap().into());
|
||||
|
||||
self.edits.push(NewEventListener {
|
||||
scope,
|
||||
event_name: event,
|
||||
root: element_id,
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn remove_event_listener(&mut self, event: &'static str, root: Option<u64>) {
|
||||
self.edits.push(RemoveEventListener { event, root });
|
||||
}
|
||||
|
||||
// modify
|
||||
pub(crate) fn set_text(&mut self, text: &'a str, root: Option<u64>) {
|
||||
self.edits.push(SetText { text, root });
|
||||
}
|
||||
|
||||
pub(crate) fn set_attribute(&mut self, attribute: &'a Attribute<'a>, root: Option<u64>) {
|
||||
let Attribute {
|
||||
value, attribute, ..
|
||||
} = attribute;
|
||||
|
||||
self.edits.push(SetAttribute {
|
||||
field: attribute.name,
|
||||
value: value.clone(),
|
||||
ns: attribute.namespace,
|
||||
root,
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn remove_attribute(&mut self, attribute: &Attribute, root: Option<u64>) {
|
||||
let Attribute { attribute, .. } = attribute;
|
||||
|
||||
self.edits.push(RemoveAttribute {
|
||||
name: attribute.name,
|
||||
ns: attribute.namespace,
|
||||
root,
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn mark_dirty_scope(&mut self, scope: ScopeId) {
|
||||
self.dirty_scopes.insert(scope);
|
||||
}
|
||||
|
||||
pub(crate) fn clone_node(&mut self, id: Option<u64>, new_id: u64) {
|
||||
self.edits.push(CloneNode { id, new_id });
|
||||
}
|
||||
|
||||
pub(crate) fn clone_node_children(&mut self, id: Option<u64>, new_ids: Vec<u64>) {
|
||||
self.edits.push(CloneNodeChildren { id, new_ids });
|
||||
}
|
||||
|
||||
pub(crate) fn first_child(&mut self) {
|
||||
self.edits.push(FirstChild {});
|
||||
}
|
||||
|
||||
pub(crate) fn next_sibling(&mut self) {
|
||||
self.edits.push(NextSibling {});
|
||||
}
|
||||
|
||||
pub(crate) fn parent_node(&mut self) {
|
||||
self.edits.push(ParentNode {});
|
||||
}
|
||||
|
||||
pub(crate) fn store_with_id(&mut self, id: u64) {
|
||||
self.edits.push(StoreWithId { id });
|
||||
}
|
||||
|
||||
pub(crate) fn set_last_node(&mut self, id: u64) {
|
||||
self.edits.push(SetLastNode { id });
|
||||
}
|
||||
}
|
||||
|
||||
// refs are only assigned once
|
||||
pub struct NodeRefMutation<'a> {
|
||||
pub element: &'a mut Option<once_cell::sync::OnceCell<Box<dyn Any>>>,
|
||||
pub element_id: ElementId,
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Debug for NodeRefMutation<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("NodeRefMutation")
|
||||
.field("element_id", &self.element_id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> NodeRefMutation<'a> {
|
||||
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
|
||||
self.element
|
||||
.as_ref()
|
||||
.and_then(|f| f.get())
|
||||
.and_then(|f| f.downcast_ref::<T>())
|
||||
}
|
||||
pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
|
||||
self.element
|
||||
.as_mut()
|
||||
.and_then(|f| f.get_mut())
|
||||
.and_then(|f| f.downcast_mut::<T>())
|
||||
}
|
||||
}
|
||||
+16
-14
@@ -49,20 +49,19 @@ impl VirtualDom {
|
||||
let mut dynamic_nodes = template.template.node_paths.iter().enumerate().peekable();
|
||||
let cur_scope = self.scope_stack.last().copied().unwrap();
|
||||
|
||||
println!("creating template: {:#?}", template);
|
||||
|
||||
let mut on_stack = 0;
|
||||
for (root_idx, root) in template.template.roots.iter().enumerate() {
|
||||
on_stack += match root {
|
||||
TemplateNode::Element { .. }
|
||||
| TemplateNode::Text(_)
|
||||
| TemplateNode::DynamicText { .. } => {
|
||||
mutations.push(LoadTemplate {
|
||||
name: template.template.id,
|
||||
index: root_idx,
|
||||
});
|
||||
1
|
||||
}
|
||||
mutations.push(LoadTemplate {
|
||||
name: template.template.id,
|
||||
index: root_idx,
|
||||
});
|
||||
|
||||
TemplateNode::Dynamic(id) => {
|
||||
on_stack += match root {
|
||||
TemplateNode::Element { .. } | TemplateNode::Text(_) => 1,
|
||||
|
||||
TemplateNode::DynamicText(id) | TemplateNode::Dynamic(id) => {
|
||||
self.create_dynamic_node(mutations, template, &template.dynamic_nodes[*id], *id)
|
||||
}
|
||||
};
|
||||
@@ -268,9 +267,12 @@ impl VirtualDom {
|
||||
}
|
||||
}
|
||||
|
||||
DynamicNode::Fragment { nodes, .. } => nodes
|
||||
.iter()
|
||||
.fold(0, |acc, child| acc + self.create(mutations, child)),
|
||||
DynamicNode::Fragment { nodes, .. } => {
|
||||
//
|
||||
nodes
|
||||
.iter()
|
||||
.fold(0, |acc, child| acc + self.create(mutations, child))
|
||||
}
|
||||
|
||||
DynamicNode::Placeholder(_) => {
|
||||
let id = self.next_element(template);
|
||||
|
||||
@@ -160,8 +160,10 @@ impl<'a, 'b> IntoDynNode<'a> for VNode<'a> {
|
||||
|
||||
impl<'a, 'b, T: IntoDynNode<'a>> IntoDynNode<'a> for Option<T> {
|
||||
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
// DynamicNode::Fragment { nodes: cx., inner: () }
|
||||
todo!()
|
||||
match self {
|
||||
Some(val) => val.into_vnode(_cx),
|
||||
None => DynamicNode::Placeholder(Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use std::{
|
||||
pub type TemplateId = &'static str;
|
||||
|
||||
/// A reference to a template along with any context needed to hydrate it
|
||||
#[derive(Debug)]
|
||||
pub struct VNode<'a> {
|
||||
// The ID assigned for the root of this template
|
||||
pub node_id: Cell<ElementId>,
|
||||
@@ -106,6 +107,7 @@ pub enum TemplateNode<'a> {
|
||||
DynamicText(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DynamicNode<'a> {
|
||||
Component {
|
||||
name: &'static str,
|
||||
@@ -137,6 +139,7 @@ pub enum TemplateAttribute<'a> {
|
||||
Dynamic(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Attribute<'a> {
|
||||
pub name: &'a str,
|
||||
pub value: AttributeValue<'a>,
|
||||
|
||||
@@ -50,6 +50,8 @@ impl DesktopController {
|
||||
|
||||
let edits = dom.rebuild();
|
||||
|
||||
println!("got muts: {:#?}", edits);
|
||||
|
||||
{
|
||||
let mut queue = edit_queue.lock().unwrap();
|
||||
queue.push(serde_json::to_string(&edits.template_mutations).unwrap());
|
||||
|
||||
@@ -7,7 +7,7 @@ use wry::{
|
||||
const MODULE_LOADER: &str = r#"
|
||||
<script>
|
||||
import("./index.js").then(function (module) {
|
||||
module.main();
|
||||
module.main();
|
||||
});
|
||||
</script>
|
||||
"#;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
export function main() {
|
||||
let root = window.document.getElementById("main");
|
||||
console.log("loading!");
|
||||
if (root != null) {
|
||||
window.interpreter = new Interpreter(root);
|
||||
console.log("properly loaded!");
|
||||
window.ipc.postMessage(serializeIpcMessage("initialize"));
|
||||
}
|
||||
}
|
||||
@@ -62,13 +64,15 @@ class ListenerMap {
|
||||
|
||||
export class Interpreter {
|
||||
constructor(root) {
|
||||
console.log("interpreter created", root);
|
||||
this.root = root;
|
||||
this.stack = [root];
|
||||
this.listeners = new ListenerMap(root);
|
||||
this.nodes = [root];
|
||||
this.stack = [root];
|
||||
this.handlers = {};
|
||||
this.lastNodeWasText = false;
|
||||
this.nodes = [root];
|
||||
this.templates = {};
|
||||
console.log(this);
|
||||
}
|
||||
top() {
|
||||
return this.stack[this.stack.length - 1];
|
||||
@@ -208,14 +212,11 @@ export class Interpreter {
|
||||
}
|
||||
}
|
||||
handleEdits(edits) {
|
||||
console.log("handling edits", edits);
|
||||
console.log("handling edits", edits, this.stack.length);
|
||||
|
||||
for (let edit of edits) {
|
||||
this.handleEdit(edit);
|
||||
console.log(this.stack);
|
||||
}
|
||||
|
||||
console.log(this.stack);
|
||||
}
|
||||
AssignId(path, id) {
|
||||
this.nodes[id] = this.LoadChild(path);
|
||||
@@ -235,16 +236,20 @@ export class Interpreter {
|
||||
node.textContent = value;
|
||||
this.nodes[id] = node;
|
||||
}
|
||||
ReplacePlaceholder(path, m) {
|
||||
let els = this.stack.splice(this.stack.length - m);
|
||||
let node = this.LoadChild(path);
|
||||
node.replaceWith(...els);
|
||||
}
|
||||
LoadTemplate(name, index) {
|
||||
console.log("loading template", name, index);
|
||||
let node = this.templates[name][index].cloneNode(true);
|
||||
this.stack.push(node);
|
||||
}
|
||||
SaveTemplate(name, m) {
|
||||
this.templates[name] = this.stack.splice(-m);
|
||||
this.templates[name] = this.stack.splice(this.stack.length - m);
|
||||
}
|
||||
handleEdit(edit) {
|
||||
console.log("handling edit", edit);
|
||||
switch (edit.type) {
|
||||
case "AppendChildren":
|
||||
this.AppendChildren(edit.m);
|
||||
@@ -270,6 +275,9 @@ export class Interpreter {
|
||||
case "ReplaceWith":
|
||||
this.ReplaceWith(edit.id, edit.m);
|
||||
break;
|
||||
case "ReplacePlaceholder":
|
||||
this.ReplacePlaceholder(edit.path, edit.m);
|
||||
break;
|
||||
case "InsertAfter":
|
||||
this.InsertAfter(edit.id, edit.n);
|
||||
break;
|
||||
@@ -288,6 +296,15 @@ export class Interpreter {
|
||||
case "CreateElementNs":
|
||||
this.CreateElementNs(edit.tag, edit.id, edit.ns);
|
||||
break;
|
||||
case "SetText":
|
||||
this.SetText(edit.id, edit.text);
|
||||
break;
|
||||
case "SetAttribute":
|
||||
this.SetAttribute(edit.id, edit.name, edit.value, edit.ns);
|
||||
break;
|
||||
case "RemoveAttribute":
|
||||
this.RemoveAttribute(edit.id, edit.name, edit.ns);
|
||||
break;
|
||||
case "RemoveEventListener":
|
||||
this.RemoveEventListener(edit.id, edit.event_name);
|
||||
break;
|
||||
@@ -385,15 +402,6 @@ export class Interpreter {
|
||||
};
|
||||
this.NewEventListener(edit.event_name, edit.id, handler, event_bubbles(edit.event_name));
|
||||
|
||||
break;
|
||||
case "SetText":
|
||||
this.SetText(edit.id, edit.text);
|
||||
break;
|
||||
case "SetAttribute":
|
||||
this.SetAttribute(edit.id, edit.field, edit.value, edit.ns);
|
||||
break;
|
||||
case "RemoveAttribute":
|
||||
this.RemoveAttribute(edit.id, edit.name, edit.ns);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,11 +245,16 @@ impl<'a> DynamicContext<'a> {
|
||||
quote! { ::dioxus::core::TemplateNode::Text(#text) }
|
||||
}
|
||||
|
||||
BodyNode::RawExpr(_) | BodyNode::Text(_) | BodyNode::Component(_) => {
|
||||
BodyNode::Text(_) | BodyNode::RawExpr(_) | BodyNode::Component(_) => {
|
||||
let ct = self.dynamic_nodes.len();
|
||||
self.dynamic_nodes.push(root);
|
||||
self.node_paths.push(self.current_path.clone());
|
||||
quote! { ::dioxus::core::TemplateNode::Dynamic(#ct) }
|
||||
|
||||
if let BodyNode::Text(_) = root {
|
||||
quote! { ::dioxus::core::TemplateNode::DynamicText(#ct) }
|
||||
} else {
|
||||
quote! { ::dioxus::core::TemplateNode::Dynamic(#ct) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use dioxus_core::VirtualDom;
|
||||
use dioxus_core::{LazyNodes, ScopeId, VirtualDom};
|
||||
|
||||
use crate::config::SsrConfig;
|
||||
|
||||
pub fn pre_render(dom: &VirtualDom) -> String {
|
||||
todo!()
|
||||
@@ -9,3 +11,40 @@ pub fn pre_render(dom: &VirtualDom) -> String {
|
||||
pub fn pre_render_to(dom: &VirtualDom, write: impl Write) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn render_vdom(dom: &VirtualDom) -> String {
|
||||
todo!()
|
||||
// format!("{:}", TextRenderer::from_vdom(dom, SsrConfig::default()))
|
||||
}
|
||||
|
||||
pub fn pre_render_vdom(dom: &VirtualDom) -> String {
|
||||
todo!()
|
||||
// format!(
|
||||
// "{:}",
|
||||
// TextRenderer::from_vdom(dom, SsrConfig::default().pre_render(true))
|
||||
// )
|
||||
}
|
||||
|
||||
pub fn render_vdom_cfg(dom: &VirtualDom, cfg: SsrConfig) -> String {
|
||||
todo!()
|
||||
// format!(
|
||||
// "{:}",
|
||||
// TextRenderer::from_vdom(dom, cfg(SsrConfig::default()))
|
||||
// )
|
||||
}
|
||||
|
||||
pub fn render_vdom_scope(vdom: &VirtualDom, scope: ScopeId) -> Option<String> {
|
||||
todo!()
|
||||
// Some(format!(
|
||||
// "{:}",
|
||||
// TextRenderer {
|
||||
// cfg: SsrConfig::default(),
|
||||
// root: vdom.get_scope(scope).unwrap().root_node(),
|
||||
// vdom: Some(vdom),
|
||||
// }
|
||||
// ))
|
||||
}
|
||||
|
||||
pub fn render_lazy<'a, 'b>(f: LazyNodes<'a, 'b>) -> String {
|
||||
todo!()
|
||||
}
|
||||
Reference in new issue
Block a user