Feat: desktop app wired up
This commit is contained in:
1 parent
bcbb93b697
commit
b3e6886351
10 files changed
+744
-269
No files matched your search
@@ -19,6 +19,8 @@
|
|||||||
//!
|
//!
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
|
||||||
use crate::innerlude::{Listener, VirtualDom};
|
use crate::innerlude::{Listener, VirtualDom};
|
||||||
@@ -32,8 +34,9 @@ use crate::innerlude::{Listener, VirtualDom};
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
/// todo@ jon: allow serde to be optional
|
||||||
#[derive(Debug)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
pub enum Edit<'d> {
|
pub enum Edit<'d> {
|
||||||
SetText { text: &'d str },
|
SetText { text: &'d str },
|
||||||
RemoveSelfAndNextSiblings {},
|
RemoveSelfAndNextSiblings {},
|
||||||
@@ -59,20 +62,23 @@ pub enum Edit<'d> {
|
|||||||
SetClass { class_name: &'d str },
|
SetClass { class_name: &'d str },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EditList<'src> {
|
pub type EditList<'src> = Vec<Edit<'src>>;
|
||||||
|
|
||||||
|
pub struct EditMachine<'src> {
|
||||||
pub traversal: Traversal,
|
pub traversal: Traversal,
|
||||||
next_temporary: u32,
|
next_temporary: u32,
|
||||||
forcing_new_listeners: bool,
|
forcing_new_listeners: bool,
|
||||||
pub emitter: Vec<Edit<'src>>,
|
|
||||||
|
pub emitter: EditList<'src>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> EditList<'b> {
|
impl<'b> EditMachine<'b> {
|
||||||
pub fn new(bump: &'b Bump) -> Self {
|
pub fn new(bump: &'b Bump) -> Self {
|
||||||
Self {
|
Self {
|
||||||
traversal: Traversal::new(),
|
traversal: Traversal::new(),
|
||||||
next_temporary: 0,
|
next_temporary: 0,
|
||||||
forcing_new_listeners: false,
|
forcing_new_listeners: false,
|
||||||
emitter: Vec::new(),
|
emitter: EditList::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +159,7 @@ impl<'b> EditList<'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EditList<'a> {
|
impl<'a> EditMachine<'a> {
|
||||||
pub fn next_temporary(&self) -> u32 {
|
pub fn next_temporary(&self) -> u32 {
|
||||||
self.next_temporary
|
self.next_temporary
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ use fxhash::{FxHashMap, FxHashSet};
|
|||||||
use generational_arena::Index;
|
use generational_arena::Index;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
changelist::{Edit, EditList},
|
changelist::{Edit, EditList, EditMachine},
|
||||||
innerlude::{Attribute, Listener, Scope, VElement, VNode, VText},
|
innerlude::{Attribute, Listener, Scope, VElement, VNode, VText},
|
||||||
virtual_dom::LifecycleEvent,
|
virtual_dom::LifecycleEvent,
|
||||||
};
|
};
|
||||||
@@ -57,7 +57,7 @@ use std::cmp::Ordering;
|
|||||||
/// that were modified by the eventtrigger. This prevents doubly evaluating components if they wereboth updated via
|
/// that were modified by the eventtrigger. This prevents doubly evaluating components if they wereboth updated via
|
||||||
/// subscriptions and props changes.
|
/// subscriptions and props changes.
|
||||||
pub struct DiffMachine<'a> {
|
pub struct DiffMachine<'a> {
|
||||||
pub change_list: EditList<'a>,
|
pub change_list: EditMachine<'a>,
|
||||||
immediate_queue: Vec<Index>,
|
immediate_queue: Vec<Index>,
|
||||||
diffed: FxHashSet<Index>,
|
diffed: FxHashSet<Index>,
|
||||||
need_to_diff: FxHashSet<Index>,
|
need_to_diff: FxHashSet<Index>,
|
||||||
@@ -71,14 +71,14 @@ enum NeedToDiff {
|
|||||||
impl<'a> DiffMachine<'a> {
|
impl<'a> DiffMachine<'a> {
|
||||||
pub fn new(bump: &'a Bump) -> Self {
|
pub fn new(bump: &'a Bump) -> Self {
|
||||||
Self {
|
Self {
|
||||||
change_list: EditList::new(bump),
|
change_list: EditMachine::new(bump),
|
||||||
immediate_queue: Vec::new(),
|
immediate_queue: Vec::new(),
|
||||||
diffed: FxHashSet::default(),
|
diffed: FxHashSet::default(),
|
||||||
need_to_diff: FxHashSet::default(),
|
need_to_diff: FxHashSet::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn consume(self) -> Vec<Edit<'a>> {
|
pub fn consume(self) -> EditList<'a> {
|
||||||
self.change_list.emitter
|
self.change_list.emitter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ impl EventTrigger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum VirtualEvent {
|
pub enum VirtualEvent {
|
||||||
|
// the event to drain the current lifecycle queue
|
||||||
|
// Used to initate the dom
|
||||||
|
InitiateEvent,
|
||||||
|
|
||||||
|
// Real events
|
||||||
ClipboardEvent,
|
ClipboardEvent,
|
||||||
CompositionEvent,
|
CompositionEvent,
|
||||||
KeyboardEvent,
|
KeyboardEvent,
|
||||||
|
|||||||
+16
-20
@@ -21,7 +21,8 @@ use std::{
|
|||||||
///
|
///
|
||||||
/// Scopes are allocated in a generational arena. As components are mounted/unmounted, they will replace slots of dead components.
|
/// Scopes are allocated in a generational arena. As components are mounted/unmounted, they will replace slots of dead components.
|
||||||
/// The actual contents of the hooks, though, will be allocated with the standard allocator. These should not allocate as frequently.
|
/// The actual contents of the hooks, though, will be allocated with the standard allocator. These should not allocate as frequently.
|
||||||
pub(crate) struct Scope {
|
pub struct Scope {
|
||||||
|
// pub(crate) struct Scope {
|
||||||
// TODO @Jon
|
// TODO @Jon
|
||||||
// These hooks are actually references into the hook arena
|
// These hooks are actually references into the hook arena
|
||||||
// These two could be combined with "OwningRef" to remove unsafe usage
|
// These two could be combined with "OwningRef" to remove unsafe usage
|
||||||
@@ -50,23 +51,10 @@ pub(crate) struct Scope {
|
|||||||
pub caller: *const i32,
|
pub caller: *const i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub enum ActiveFrame {
|
|
||||||
// First,
|
|
||||||
// Second,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl ActiveFrame {
|
|
||||||
// fn next(&mut self) {
|
|
||||||
// match self {
|
|
||||||
// ActiveFrame::First => *self = ActiveFrame::Second,
|
|
||||||
// ActiveFrame::Second => *self = ActiveFrame::First,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
// create a new scope from a function
|
// create a new scope from a function
|
||||||
pub(crate) fn new<T: 'static>(
|
pub fn new<T: 'static>(
|
||||||
|
// pub(crate) fn new<T: 'static>(
|
||||||
f: FC<T>,
|
f: FC<T>,
|
||||||
props: impl Properties + 'static,
|
props: impl Properties + 'static,
|
||||||
parent: Option<Index>,
|
parent: Option<Index>,
|
||||||
@@ -120,7 +108,7 @@ impl Scope {
|
|||||||
/// This function downcasts the function pointer based on the stored props_type
|
/// This function downcasts the function pointer based on the stored props_type
|
||||||
///
|
///
|
||||||
/// Props is ?Sized because we borrow the props and don't need to know the size. P (sized) is used as a marker (unsized)
|
/// Props is ?Sized because we borrow the props and don't need to know the size. P (sized) is used as a marker (unsized)
|
||||||
pub(crate) fn run<'bump, P: Properties + Sized + 'static>(&'bump mut self) {
|
pub fn run<'bump, P: Properties + Sized + 'static>(&'bump mut self) {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame = self.frames.next();
|
let frame = self.frames.next();
|
||||||
frame.bump.reset();
|
frame.bump.reset();
|
||||||
@@ -164,14 +152,12 @@ impl Scope {
|
|||||||
|
|
||||||
let unsafe_node = unsafe { std::mem::transmute::<VNode<'bump>, VNode<'static>>(nodes) };
|
let unsafe_node = unsafe { std::mem::transmute::<VNode<'bump>, VNode<'static>>(nodes) };
|
||||||
frame.head_node = unsafe_node;
|
frame.head_node = unsafe_node;
|
||||||
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accessor to get the root node and its children (safely)\
|
/// Accessor to get the root node and its children (safely)\
|
||||||
/// Scope is self-referntial, so we are forced to use the 'static lifetime to cheat
|
/// Scope is self-referntial, so we are forced to use the 'static lifetime to cheat
|
||||||
pub fn current_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
pub fn current_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||||
todo!()
|
self.frames.current_head_node()
|
||||||
}
|
}
|
||||||
pub fn prev_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
pub fn prev_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||||
todo!()
|
todo!()
|
||||||
@@ -196,6 +182,16 @@ impl ActiveFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn current_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||||
|
let cur_idx = self.idx.borrow().load(std::sync::atomic::Ordering::Relaxed);
|
||||||
|
let raw_node = &self.frames[cur_idx];
|
||||||
|
unsafe {
|
||||||
|
let unsafe_head = &raw_node.head_node;
|
||||||
|
let safe_node = std::mem::transmute::<&VNode<'static>, &VNode<'b>>(unsafe_head);
|
||||||
|
safe_node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn next(&mut self) -> &mut BumpFrame {
|
fn next(&mut self) -> &mut BumpFrame {
|
||||||
self.idx.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
self.idx.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
let cur = self.idx.borrow().load(std::sync::atomic::Ordering::Relaxed);
|
let cur = self.idx.borrow().load(std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// use crate::{changelist::EditList, nodes::VNode};
|
// use crate::{changelist::EditList, nodes::VNode};
|
||||||
use crate::{dodriodiff::DiffMachine, nodes::VNode};
|
use crate::{changelist::{self, EditList}, dodriodiff::DiffMachine, nodes::VNode};
|
||||||
use crate::{events::EventTrigger, innerlude::*};
|
use crate::{events::EventTrigger, innerlude::*};
|
||||||
use any::Any;
|
use any::Any;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
use changelist::EditMachine;
|
||||||
use generational_arena::{Arena, Index};
|
use generational_arena::{Arena, Index};
|
||||||
use std::{
|
use std::{
|
||||||
any::{self, TypeId},
|
any::{self, TypeId},
|
||||||
@@ -105,6 +106,10 @@ impl VirtualDom {
|
|||||||
/// This lets services external to the virtual dom interact directly with the component and event system.
|
/// This lets services external to the virtual dom interact directly with the component and event system.
|
||||||
pub fn queue_update() {}
|
pub fn queue_update() {}
|
||||||
|
|
||||||
|
pub fn start(&mut self) -> Result<EditList> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
/// Pop an event off the event queue and process it
|
/// Pop an event off the event queue and process it
|
||||||
/// Update the root props, and progress
|
/// Update the root props, and progress
|
||||||
/// Takes a bump arena to allocate into, making the diff phase as fast as possible
|
/// Takes a bump arena to allocate into, making the diff phase as fast as possible
|
||||||
@@ -115,7 +120,7 @@ impl VirtualDom {
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.pop_front()
|
.pop_front()
|
||||||
.ok_or(Error::NoEvent)?;
|
.ok_or(Error::NoEvent)?;
|
||||||
self.process_event(event)
|
self.process_lifecycle(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method is the most sophisticated way of updating the virtual dom after an external event has been triggered.
|
/// This method is the most sophisticated way of updating the virtual dom after an external event has been triggered.
|
||||||
@@ -171,7 +176,7 @@ impl VirtualDom {
|
|||||||
new_evt
|
new_evt
|
||||||
} {
|
} {
|
||||||
affected_components.push(event.component_index);
|
affected_components.push(event.component_index);
|
||||||
self.process_event(event)?;
|
self.process_lifecycle(event)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let diff_bump = Bump::new();
|
let diff_bump = Bump::new();
|
||||||
@@ -180,9 +185,6 @@ impl VirtualDom {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn progress_completely(&mut self) -> Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
/// Using mutable access to the Virtual Dom, progress a given lifecycle event
|
/// Using mutable access to the Virtual Dom, progress a given lifecycle event
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -190,7 +192,7 @@ impl VirtualDom {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
fn process_event(
|
fn process_lifecycle(
|
||||||
&mut self,
|
&mut self,
|
||||||
LifecycleEvent {
|
LifecycleEvent {
|
||||||
component_index: index,
|
component_index: index,
|
||||||
|
|||||||
+223
-223
@@ -380,257 +380,257 @@ impl PatchMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0
|
// // 0
|
||||||
pub fn set_text(&mut self, text: &str) {
|
// pub fn set_text(&mut self, text: &str) {
|
||||||
self.stack.top().set_text_content(Some(text));
|
// self.stack.top().set_text_content(Some(text));
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 1
|
// // 1
|
||||||
pub fn remove_self_and_next_siblings(&mut self) {
|
// pub fn remove_self_and_next_siblings(&mut self) {
|
||||||
let node = self.stack.pop();
|
// let node = self.stack.pop();
|
||||||
let mut sibling = node.next_sibling();
|
// let mut sibling = node.next_sibling();
|
||||||
|
|
||||||
while let Some(inner) = sibling {
|
// while let Some(inner) = sibling {
|
||||||
let temp = inner.next_sibling();
|
// let temp = inner.next_sibling();
|
||||||
if let Some(sibling) = inner.dyn_ref::<Element>() {
|
// if let Some(sibling) = inner.dyn_ref::<Element>() {
|
||||||
sibling.remove();
|
// sibling.remove();
|
||||||
}
|
// }
|
||||||
sibling = temp;
|
// sibling = temp;
|
||||||
}
|
// }
|
||||||
if let Some(node) = node.dyn_ref::<Element>() {
|
// if let Some(node) = node.dyn_ref::<Element>() {
|
||||||
node.remove();
|
// node.remove();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 2
|
// // 2
|
||||||
pub fn replace_with(&mut self) {
|
// pub fn replace_with(&mut self) {
|
||||||
let new_node = self.stack.pop();
|
// let new_node = self.stack.pop();
|
||||||
let old_node = self.stack.pop();
|
// let old_node = self.stack.pop();
|
||||||
|
|
||||||
if old_node.has_type::<Element>() {
|
// if old_node.has_type::<Element>() {
|
||||||
old_node
|
// old_node
|
||||||
.dyn_ref::<Element>()
|
// .dyn_ref::<Element>()
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.replace_with_with_node_1(&new_node)
|
// .replace_with_with_node_1(&new_node)
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
} else if old_node.has_type::<web_sys::CharacterData>() {
|
// } else if old_node.has_type::<web_sys::CharacterData>() {
|
||||||
old_node
|
// old_node
|
||||||
.dyn_ref::<web_sys::CharacterData>()
|
// .dyn_ref::<web_sys::CharacterData>()
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.replace_with_with_node_1(&new_node)
|
// .replace_with_with_node_1(&new_node)
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
} else if old_node.has_type::<web_sys::DocumentType>() {
|
// } else if old_node.has_type::<web_sys::DocumentType>() {
|
||||||
old_node
|
// old_node
|
||||||
.dyn_ref::<web_sys::DocumentType>()
|
// .dyn_ref::<web_sys::DocumentType>()
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.replace_with_with_node_1(&new_node)
|
// .replace_with_with_node_1(&new_node)
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
} else {
|
// } else {
|
||||||
panic!("Cannot replace node: {:?}", old_node);
|
// panic!("Cannot replace node: {:?}", old_node);
|
||||||
}
|
// }
|
||||||
|
|
||||||
self.stack.push(new_node);
|
// self.stack.push(new_node);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 3
|
// // 3
|
||||||
pub fn set_attribute(&mut self, name: &str, value: &str) {
|
// pub fn set_attribute(&mut self, name: &str, value: &str) {
|
||||||
let node = self.stack.top();
|
// let node = self.stack.top();
|
||||||
|
|
||||||
if let Some(node) = node.dyn_ref::<Element>() {
|
// if let Some(node) = node.dyn_ref::<Element>() {
|
||||||
node.set_attribute(name, value).unwrap();
|
// node.set_attribute(name, value).unwrap();
|
||||||
|
|
||||||
// Some attributes are "volatile" and don't work through `setAttribute`.
|
// // Some attributes are "volatile" and don't work through `setAttribute`.
|
||||||
// TODO:
|
// // TODO:
|
||||||
// if name == "value" {
|
// // if name == "value" {
|
||||||
// node.set_value(value);
|
// // node.set_value(value);
|
||||||
// }
|
// // }
|
||||||
// if name == "checked" {
|
// // if name == "checked" {
|
||||||
// node.set_checked(true);
|
// // node.set_checked(true);
|
||||||
// }
|
// // }
|
||||||
// if name == "selected" {
|
// // if name == "selected" {
|
||||||
// node.set_selected(true);
|
// // node.set_selected(true);
|
||||||
// }
|
// // }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 4
|
// // 4
|
||||||
pub fn remove_attribute(&mut self, name: &str) {
|
// pub fn remove_attribute(&mut self, name: &str) {
|
||||||
let node = self.stack.top();
|
// let node = self.stack.top();
|
||||||
if let Some(node) = node.dyn_ref::<Element>() {
|
// if let Some(node) = node.dyn_ref::<Element>() {
|
||||||
node.remove_attribute(name).unwrap();
|
// node.remove_attribute(name).unwrap();
|
||||||
|
|
||||||
// Some attributes are "volatile" and don't work through `removeAttribute`.
|
// // Some attributes are "volatile" and don't work through `removeAttribute`.
|
||||||
// TODO:
|
// // TODO:
|
||||||
// if name == "value" {
|
// // if name == "value" {
|
||||||
// node.set_value("");
|
// // node.set_value("");
|
||||||
// }
|
// // }
|
||||||
// if name == "checked" {
|
// // if name == "checked" {
|
||||||
// node.set_checked(false);
|
// // node.set_checked(false);
|
||||||
// }
|
// // }
|
||||||
// if name == "selected" {
|
// // if name == "selected" {
|
||||||
// node.set_selected(false);
|
// // node.set_selected(false);
|
||||||
// }
|
// // }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 5
|
// // 5
|
||||||
pub fn push_reverse_child(&mut self, n: u32) {
|
// pub fn push_reverse_child(&mut self, n: u32) {
|
||||||
let parent = self.stack.top();
|
// let parent = self.stack.top();
|
||||||
let children = parent.child_nodes();
|
// let children = parent.child_nodes();
|
||||||
let child = children.get(children.length() - n - 1).unwrap();
|
// let child = children.get(children.length() - n - 1).unwrap();
|
||||||
self.stack.push(child);
|
// self.stack.push(child);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 6
|
// // 6
|
||||||
pub fn pop_push_child(&mut self, n: u32) {
|
// pub fn pop_push_child(&mut self, n: u32) {
|
||||||
self.stack.pop();
|
// self.stack.pop();
|
||||||
let parent = self.stack.top();
|
// let parent = self.stack.top();
|
||||||
let children = parent.child_nodes();
|
// let children = parent.child_nodes();
|
||||||
let child = children.get(n).unwrap();
|
// let child = children.get(n).unwrap();
|
||||||
self.stack.push(child);
|
// self.stack.push(child);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 7
|
// // 7
|
||||||
pub fn pop(&mut self) {
|
// pub fn pop(&mut self) {
|
||||||
self.stack.pop();
|
// self.stack.pop();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 8
|
// // 8
|
||||||
pub fn append_child(&mut self) {
|
// pub fn append_child(&mut self) {
|
||||||
let child = self.stack.pop();
|
// let child = self.stack.pop();
|
||||||
self.stack.top().append_child(&child).unwrap();
|
// self.stack.top().append_child(&child).unwrap();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 9
|
// // 9
|
||||||
pub fn create_text_node(&mut self, text: &str) {
|
// pub fn create_text_node(&mut self, text: &str) {
|
||||||
self.stack.push(
|
// self.stack.push(
|
||||||
self.document
|
// self.document
|
||||||
.create_text_node(text)
|
// .create_text_node(text)
|
||||||
.dyn_into::<Node>()
|
// .dyn_into::<Node>()
|
||||||
.unwrap(),
|
// .unwrap(),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 10
|
// // 10
|
||||||
pub fn create_element(&mut self, tag_name: &str) {
|
// pub fn create_element(&mut self, tag_name: &str) {
|
||||||
let el = self
|
// let el = self
|
||||||
.document
|
// .document
|
||||||
.create_element(tag_name)
|
// .create_element(tag_name)
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.dyn_into::<Node>()
|
// .dyn_into::<Node>()
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
self.stack.push(el);
|
// self.stack.push(el);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 11
|
// // 11
|
||||||
pub fn new_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
// pub fn new_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
||||||
let el = self.stack.top();
|
// let el = self.stack.top();
|
||||||
|
|
||||||
let el = el
|
// let el = el
|
||||||
.dyn_ref::<Element>()
|
// .dyn_ref::<Element>()
|
||||||
.expect(&format!("not an element: {:?}", el));
|
// .expect(&format!("not an element: {:?}", el));
|
||||||
el.add_event_listener_with_callback(
|
// el.add_event_listener_with_callback(
|
||||||
event_type,
|
// event_type,
|
||||||
self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
// self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
||||||
)
|
// )
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
debug!("adding attributes: {}, {}", a, b);
|
// debug!("adding attributes: {}, {}", a, b);
|
||||||
el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
// el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
// el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 12
|
// // 12
|
||||||
pub fn update_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
// pub fn update_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
||||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
// if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||||
el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
// el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
// el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 13
|
// // 13
|
||||||
pub fn remove_event_listener(&mut self, event_type: &str) {
|
// pub fn remove_event_listener(&mut self, event_type: &str) {
|
||||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
// if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||||
el.remove_event_listener_with_callback(
|
// el.remove_event_listener_with_callback(
|
||||||
event_type,
|
// event_type,
|
||||||
self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
// self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
||||||
)
|
// )
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 16
|
// // 16
|
||||||
pub fn create_element_ns(&mut self, tag_name: &str, ns: &str) {
|
// pub fn create_element_ns(&mut self, tag_name: &str, ns: &str) {
|
||||||
let el = self
|
// let el = self
|
||||||
.document
|
// .document
|
||||||
.create_element_ns(Some(ns), tag_name)
|
// .create_element_ns(Some(ns), tag_name)
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.dyn_into::<Node>()
|
// .dyn_into::<Node>()
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
self.stack.push(el);
|
// self.stack.push(el);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 17
|
// // 17
|
||||||
pub fn save_children_to_temporaries(&mut self, mut temp: u32, start: u32, end: u32) {
|
// pub fn save_children_to_temporaries(&mut self, mut temp: u32, start: u32, end: u32) {
|
||||||
let parent = self.stack.top();
|
// let parent = self.stack.top();
|
||||||
let children = parent.child_nodes();
|
// let children = parent.child_nodes();
|
||||||
for i in start..end {
|
// for i in start..end {
|
||||||
self.temporaries.insert(temp, children.get(i).unwrap());
|
// self.temporaries.insert(temp, children.get(i).unwrap());
|
||||||
temp += 1;
|
// temp += 1;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 18
|
// // 18
|
||||||
pub fn push_child(&mut self, n: u32) {
|
// pub fn push_child(&mut self, n: u32) {
|
||||||
let parent = self.stack.top();
|
// let parent = self.stack.top();
|
||||||
let child = parent.child_nodes().get(n).unwrap();
|
// let child = parent.child_nodes().get(n).unwrap();
|
||||||
self.stack.push(child);
|
// self.stack.push(child);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 19
|
// // 19
|
||||||
pub fn push_temporary(&mut self, temp: u32) {
|
// pub fn push_temporary(&mut self, temp: u32) {
|
||||||
let t = self.temporaries.get(&temp).unwrap().clone();
|
// let t = self.temporaries.get(&temp).unwrap().clone();
|
||||||
self.stack.push(t);
|
// self.stack.push(t);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 20
|
// // 20
|
||||||
pub fn insert_before(&mut self) {
|
// pub fn insert_before(&mut self) {
|
||||||
let before = self.stack.pop();
|
// let before = self.stack.pop();
|
||||||
let after = self.stack.pop();
|
// let after = self.stack.pop();
|
||||||
after
|
// after
|
||||||
.parent_node()
|
// .parent_node()
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.insert_before(&before, Some(&after))
|
// .insert_before(&before, Some(&after))
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
self.stack.push(before);
|
// self.stack.push(before);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 21
|
// // 21
|
||||||
pub fn pop_push_reverse_child(&mut self, n: u32) {
|
// pub fn pop_push_reverse_child(&mut self, n: u32) {
|
||||||
self.stack.pop();
|
// self.stack.pop();
|
||||||
let parent = self.stack.top();
|
// let parent = self.stack.top();
|
||||||
let children = parent.child_nodes();
|
// let children = parent.child_nodes();
|
||||||
let child = children.get(children.length() - n - 1).unwrap();
|
// let child = children.get(children.length() - n - 1).unwrap();
|
||||||
self.stack.push(child);
|
// self.stack.push(child);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 22
|
// // 22
|
||||||
pub fn remove_child(&mut self, n: u32) {
|
// pub fn remove_child(&mut self, n: u32) {
|
||||||
let parent = self.stack.top();
|
// let parent = self.stack.top();
|
||||||
if let Some(child) = parent.child_nodes().get(n).unwrap().dyn_ref::<Element>() {
|
// if let Some(child) = parent.child_nodes().get(n).unwrap().dyn_ref::<Element>() {
|
||||||
child.remove();
|
// child.remove();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 23
|
// // 23
|
||||||
pub fn set_class(&mut self, class_name: &str) {
|
// pub fn set_class(&mut self, class_name: &str) {
|
||||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
// if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||||
el.set_class_name(class_name);
|
// el.set_class_name(class_name);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 24
|
// 24
|
||||||
pub fn save_template(&mut self, id: CacheId) {
|
pub fn save_template(&mut self, id: CacheId) {
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
web-view = "0.7.2"
|
web-view = "0.7.2"
|
||||||
dioxus-core = { path = "../core" }
|
dioxus-core = { path = "../core" }
|
||||||
|
anyhow = "1.0.38"
|
||||||
|
argh = "0.1.4"
|
||||||
|
serde = "1.0.120"
|
||||||
|
serde_json = "1.0.61"
|
||||||
|
async-std = { version = "1.9.0", features = ["attributes"] }
|
||||||
|
thiserror = "1.0.23"
|
||||||
|
log = "0.4.13"
|
||||||
|
fern = { version = "0.6.0", features = ["colored"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// This file interperets incoming edit messages into the page and renders them.
|
||||||
|
// This is written in javascript to be slightly easier to work with (instead of having to pre-compile the wasm)
|
||||||
|
// One day, we'll probably using wasmbindgen for the inner, but a javascripty one is fine too.
|
||||||
@@ -1,20 +1,152 @@
|
|||||||
//! An example where the dioxus vdom is running in a native thread, interacting with webview
|
//! An example where the dioxus vdom is running in a native thread, interacting with webview
|
||||||
|
|
||||||
fn main() {
|
use std::{
|
||||||
let html_content = "<div>Hello world!</div>";
|
borrow::BorrowMut,
|
||||||
|
rc::Rc,
|
||||||
|
sync::{mpsc::channel, Arc},
|
||||||
|
};
|
||||||
|
|
||||||
web_view::builder()
|
// use async_std::{channel, task::block_on};
|
||||||
|
|
||||||
|
use dioxus_core::{dodriodiff::DiffMachine, prelude::bumpalo::Bump, prelude::*, scope};
|
||||||
|
use scope::Scope;
|
||||||
|
use web_view::Handle;
|
||||||
|
static HTML_CONTENT: &'static str = include_str!("./index.html");
|
||||||
|
|
||||||
|
enum InnerEvent {
|
||||||
|
Initiate(Handle<()>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// async_std::task::spawn(async {
|
||||||
|
// #[async_std::main]
|
||||||
|
fn main() -> anyhow::Result<()> {
|
||||||
|
let (sender, receiver) = channel::<InnerEvent>();
|
||||||
|
// let (sender, receiver) = channel::unbounded::<InnerEvent>();
|
||||||
|
|
||||||
|
// let task = async_std::task::spawn(async move {
|
||||||
|
let mut view = web_view::builder()
|
||||||
.title("My Project")
|
.title("My Project")
|
||||||
.content(web_view::Content::Html(html_content))
|
.content(web_view::Content::Html(HTML_CONTENT))
|
||||||
.size(320, 480)
|
.size(320, 480)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.debug(true)
|
.debug(true)
|
||||||
.user_data(())
|
.user_data(())
|
||||||
.invoke_handler(|view, arg| {
|
.invoke_handler(|view, arg| {
|
||||||
//
|
// todo: handle events here
|
||||||
|
println!("handling invoker");
|
||||||
|
let handle = view.handle();
|
||||||
|
sender.send(InnerEvent::Initiate(handle));
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.run()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
println!("building the diff");
|
||||||
|
let bump = Bump::new();
|
||||||
|
let mut diff_machine = DiffMachine::new(&bump);
|
||||||
|
let old = html! {<div> </div>}(&bump);
|
||||||
|
|
||||||
|
// let mut scope = Scope::new(TEST, (), None);
|
||||||
|
// scope.run::<()>();
|
||||||
|
let new = html! {
|
||||||
|
<div>
|
||||||
|
<div class="flex items-center justify-center flex-col">
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<div class="flex flex-col bg-white rounded p-4 w-full max-w-xs">
|
||||||
|
// Title
|
||||||
|
<div class="font-bold text-xl">
|
||||||
|
"Jon's awesome site!!11"
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// Subtext / description
|
||||||
|
<div class="text-sm text-gray-500">
|
||||||
|
"He worked so hard on it :)"
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row items-center justify-center mt-6">
|
||||||
|
// Main number
|
||||||
|
<div class="font-medium text-6xl">
|
||||||
|
"1337"
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// Try another
|
||||||
|
<div class="flex flex-row justify-between mt-6">
|
||||||
|
// <a href=format!("http://localhost:8080/fib/{}", other_fib_to_try) class="underline">
|
||||||
|
"Legit made my own React"
|
||||||
|
// </a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}(&bump);
|
||||||
|
|
||||||
|
diff_machine.diff_node(&old, &new);
|
||||||
|
|
||||||
|
let edits = diff_machine.consume();
|
||||||
|
let ready_edits = serde_json::to_string(&edits)?;
|
||||||
|
let ref_edits = Arc::new(ready_edits);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
view.step().expect("should not fail");
|
||||||
|
// if let Some(evt) = receiver.try_recv() {}
|
||||||
|
if let Ok(event) = receiver.try_recv() {
|
||||||
|
match event {
|
||||||
|
InnerEvent::Initiate(handle) => {
|
||||||
|
// println!("awesome, things worked");
|
||||||
|
let ediits = ref_edits.clone();
|
||||||
|
// println!("{}", ediits);
|
||||||
|
handle
|
||||||
|
.dispatch(move |view| {
|
||||||
|
view.eval(format!("EditListReceived(`{}`);", ediits).as_str())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.expect("Dispatch failed");
|
||||||
|
// let g = handle.();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// let event = receiver.try_recv();
|
||||||
|
|
||||||
|
// view.eval("alert('omg');")?;
|
||||||
|
// view.step().expect("webview should not fail")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static TEST: FC<()> = |ctx, props| {
|
||||||
|
// ctx.view(html! {
|
||||||
|
// <div>
|
||||||
|
// <div class="flex items-center justify-center flex-col">
|
||||||
|
// <div class="flex items-center justify-center">
|
||||||
|
// <div class="flex flex-col bg-white rounded p-4 w-full max-w-xs">
|
||||||
|
// // Title
|
||||||
|
// <div class="font-bold text-xl">
|
||||||
|
// "Jon's awesome site!!11"
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// // Subtext / description
|
||||||
|
// <div class="text-sm text-gray-500">
|
||||||
|
// "He worked so hard on it :)"
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// <div class="flex flex-row items-center justify-center mt-6">
|
||||||
|
// // Main number
|
||||||
|
// <div class="font-medium text-6xl">
|
||||||
|
// "1337"
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// // Try another
|
||||||
|
// <div class="flex flex-row justify-between mt-6">
|
||||||
|
// // <a href=format!("http://localhost:8080/fib/{}", other_fib_to_try) class="underline">
|
||||||
|
// "Legit made my own React"
|
||||||
|
// // </a>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// })
|
||||||
|
// };
|
||||||
@@ -0,0 +1,324 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link
|
||||||
|
href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
// #[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
// pub enum Edit<'d> {
|
||||||
|
// SetText { text: &'d str },
|
||||||
|
// RemoveSelfAndNextSiblings {},
|
||||||
|
// ReplaceWith,
|
||||||
|
// SetAttribute { name: &'d str, value: &'d str },
|
||||||
|
// RemoveAttribute { name: &'d str },
|
||||||
|
// PushReverseChild { n: u32 },
|
||||||
|
// PopPushChild { n: u32 },
|
||||||
|
// Pop,
|
||||||
|
// AppendChild,
|
||||||
|
// CreateTextNode { text: &'d str },
|
||||||
|
// CreateElement { tag_name: &'d str },
|
||||||
|
// NewEventListener { event_type: &'d str, a: u32, b: u32 },
|
||||||
|
// UpdateEventListener { event_type: &'d str, a: u32, b: u32 },
|
||||||
|
// RemoveEventListener { event_type: &'d str },
|
||||||
|
// CreateElementNs { tag_name: &'d str, ns: &'d str },
|
||||||
|
// SaveChildrenToTemporaries { temp: u32, start: u32, end: u32 },
|
||||||
|
// PushChild { n: u32 },
|
||||||
|
// PushTemporary { temp: u32 },
|
||||||
|
// InsertBefore,
|
||||||
|
// PopPushReverseChild { n: u32 },
|
||||||
|
// RemoveChild { n: u32 },
|
||||||
|
// SetClass { class_name: &'d str },
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const interpreter = new Interpreter();
|
||||||
|
|
||||||
|
class Interpreter {
|
||||||
|
constructor(root) {
|
||||||
|
this.stack = [root];
|
||||||
|
}
|
||||||
|
|
||||||
|
top() {
|
||||||
|
return this.stack[this.stack.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
pop() {
|
||||||
|
return this.stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OPTABLE {
|
||||||
|
// 0
|
||||||
|
SetText(edit, interp) {
|
||||||
|
interp.top(interp.stack).textContent = edit.text;
|
||||||
|
}
|
||||||
|
// 1
|
||||||
|
RemoveSelfAndNextSiblings(edit) {
|
||||||
|
const node = interp.pop();
|
||||||
|
let sibling = node.nextSibling;
|
||||||
|
while (sibling) {
|
||||||
|
const temp = sibling.nextSibling;
|
||||||
|
sibling.remove();
|
||||||
|
sibling = temp;
|
||||||
|
}
|
||||||
|
node.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2
|
||||||
|
ReplaceWith(edit, interp) {
|
||||||
|
const newNode = interp.pop();
|
||||||
|
const oldNode = interp.pop();
|
||||||
|
oldNode.replaceWith(newNode);
|
||||||
|
interp.stack.push(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3
|
||||||
|
SetAttribute(edit, interp) {
|
||||||
|
const name = edit.name;
|
||||||
|
const value = edit.value;
|
||||||
|
const node = interp.top(interp.stack);
|
||||||
|
node.setAttribute(name, value);
|
||||||
|
|
||||||
|
// Some attributes are "volatile" and don't work through `setAttribute`.
|
||||||
|
if ((name === "value", interp)) {
|
||||||
|
node.value = value;
|
||||||
|
}
|
||||||
|
if ((name === "checked", interp)) {
|
||||||
|
node.checked = true;
|
||||||
|
}
|
||||||
|
if ((name === "selected", interp)) {
|
||||||
|
node.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4
|
||||||
|
RemoveAttribute(edit, interp) {
|
||||||
|
const name = edit.name;
|
||||||
|
const node = interp.top(interp.stack);
|
||||||
|
node.removeAttribute(name);
|
||||||
|
|
||||||
|
// Some attributes are "volatile" and don't work through `removeAttribute`.
|
||||||
|
if ((name === "value", interp)) {
|
||||||
|
node.value = null;
|
||||||
|
}
|
||||||
|
if ((name === "checked", interp)) {
|
||||||
|
node.checked = false;
|
||||||
|
}
|
||||||
|
if ((name === "selected", interp)) {
|
||||||
|
node.selected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5
|
||||||
|
PushReverseChild(edit, interp) {
|
||||||
|
const n = edit.n;
|
||||||
|
const parent = interp.top(interp.stack);
|
||||||
|
const children = parent.childNodes;
|
||||||
|
const child = children[children.length - n - 1];
|
||||||
|
interp.stack.push(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6
|
||||||
|
PopPushChild(edit, interp) {
|
||||||
|
const n = edit.n;
|
||||||
|
interp.pop();
|
||||||
|
const parent = interp.top(interp.stack);
|
||||||
|
const children = parent.childNodes;
|
||||||
|
const child = children[n];
|
||||||
|
interp.stack.push(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7
|
||||||
|
Pop(edit, interp) {
|
||||||
|
interp.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8
|
||||||
|
AppendChild(edit, interp) {
|
||||||
|
console.log(interp.stack);
|
||||||
|
const child = interp.pop();
|
||||||
|
console.log(interp.stack);
|
||||||
|
interp.top().appendChild(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9
|
||||||
|
CreateTextNode(edit, interp) {
|
||||||
|
// interp.stack.push(document.createTextNode("asd"));
|
||||||
|
console.log(interp.stack);
|
||||||
|
|
||||||
|
interp.stack.push(document.createTextNode(edit.text));
|
||||||
|
console.log(interp.stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10
|
||||||
|
CreateElement(edit, interp) {
|
||||||
|
const tagName = edit.tag_name;
|
||||||
|
interp.stack.push(document.createElement(tagName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 11
|
||||||
|
NewEventListener(edit, interp) {
|
||||||
|
// todo!
|
||||||
|
const eventId = mem32[i++];
|
||||||
|
const eventType = interp.getCachedString(eventId);
|
||||||
|
const a = mem32[i++];
|
||||||
|
const b = mem32[i++];
|
||||||
|
const el = interp.top(interp.stack);
|
||||||
|
el.addEventListener(eventType, interp.eventHandler);
|
||||||
|
el[`dodrio-a-${eventType}`] = a;
|
||||||
|
el[`dodrio-b-${eventType}`] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 12
|
||||||
|
UpdateEventListener(edit, interp) {
|
||||||
|
// todo!
|
||||||
|
const eventId = mem32[i++];
|
||||||
|
const eventType = interp.getCachedString(eventId);
|
||||||
|
const el = interp.top(interp.stack);
|
||||||
|
el[`dodrio-a-${eventType}`] = mem32[i++];
|
||||||
|
el[`dodrio-b-${eventType}`] = mem32[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13
|
||||||
|
RemoveEventListener(edit, interp) {
|
||||||
|
// todo!
|
||||||
|
const eventId = mem32[i++];
|
||||||
|
const eventType = interp.getCachedString(eventId);
|
||||||
|
const el = interp.top(interp.stack);
|
||||||
|
el.removeEventListener(eventType, interp.eventHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 14
|
||||||
|
AddCachedString(edit, interp) {
|
||||||
|
// todo!
|
||||||
|
const pointer = mem32[i++];
|
||||||
|
const length = mem32[i++];
|
||||||
|
const id = mem32[i++];
|
||||||
|
const str = string(mem8, pointer, length);
|
||||||
|
interp.addCachedString(str, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 15
|
||||||
|
DropCachedString(edit, interp) {
|
||||||
|
// todo!
|
||||||
|
const id = mem32[i++];
|
||||||
|
interp.dropCachedString(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 16
|
||||||
|
CreateElementNS(edit, interp) {
|
||||||
|
// const tagNameId = mem32[i++];
|
||||||
|
// const tagName = interp.getCachedString(tagNameId);
|
||||||
|
// const nsId = mem32[i++];
|
||||||
|
// const ns = interp.getCachedString(nsId);
|
||||||
|
interp.stack.push(document.createElementNS(edit.ns, edit.tag_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 17
|
||||||
|
SaveChildrenToTemporaries(edit, interp) {
|
||||||
|
// let temp = mem32[i++];
|
||||||
|
// const start = mem32[i++];
|
||||||
|
// const end = mem32[i++];
|
||||||
|
let temp = edit.temp;
|
||||||
|
const start = edit.start;
|
||||||
|
const end = edit.end;
|
||||||
|
const parent = interp.top(interp.stack);
|
||||||
|
const children = parent.childNodes;
|
||||||
|
for (let i = start; i < end; i++, interp) {
|
||||||
|
interp.temporaries[temp++] = children[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 18
|
||||||
|
PushChild(edit, interp) {
|
||||||
|
const parent = interp.top(interp.stack);
|
||||||
|
// const n = mem32[i++];
|
||||||
|
const n = edit.n;
|
||||||
|
const child = parent.childNodes[n];
|
||||||
|
interp.stack.push(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 19
|
||||||
|
PushTemporary(edit, interp) {
|
||||||
|
// const temp = mem32[i++];
|
||||||
|
const temp = edit.temp;
|
||||||
|
interp.stack.push(interp.temporaries[temp]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 20
|
||||||
|
InsertBefore(edit, interp) {
|
||||||
|
const before = interp.pop();
|
||||||
|
const after = interp.pop();
|
||||||
|
after.parentNode.insertBefore(before, after);
|
||||||
|
interp.stack.push(before);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 21
|
||||||
|
PopPushReverseChild(edit, interp) {
|
||||||
|
// const n = mem32[i++];
|
||||||
|
const n = edit.n;
|
||||||
|
interp.pop();
|
||||||
|
const parent = interp.top(interp.stack);
|
||||||
|
const children = parent.childNodes;
|
||||||
|
const child = children[children.length - n - 1];
|
||||||
|
interp.stack.push(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 22
|
||||||
|
RemoveChild(edit, interp) {
|
||||||
|
// const n = mem32[i++];
|
||||||
|
const n = edit.n;
|
||||||
|
const parent = interp.top(interp.stack);
|
||||||
|
const child = parent.childNodes[n];
|
||||||
|
child.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 23
|
||||||
|
SetClass(edit, interp) {
|
||||||
|
// const classId = mem32[i++];
|
||||||
|
const className = edit.class_name;
|
||||||
|
interp.top(interp.stack).className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 24
|
||||||
|
SaveTemplate(edit, interp) {
|
||||||
|
const id = mem32[i++];
|
||||||
|
const template = interp.top(interp.stack);
|
||||||
|
interp.saveTemplate(id, template.cloneNode(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 25
|
||||||
|
PushTemplate(edit, interp) {
|
||||||
|
const id = mem32[i++];
|
||||||
|
const template = interp.getTemplate(id);
|
||||||
|
interp.stack.push(template.cloneNode(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let op = new OPTABLE();
|
||||||
|
const c = window.document.body.firstChild;
|
||||||
|
console.log("First child");
|
||||||
|
console.log(c);
|
||||||
|
const interpreter = new Interpreter(window.document.body);
|
||||||
|
function EditListReceived(rawEditList) {
|
||||||
|
let editList = JSON.parse(rawEditList);
|
||||||
|
console.log(editList);
|
||||||
|
editList.forEach(function (edit, index) {
|
||||||
|
// console.log("processing edit");
|
||||||
|
const name = edit.type;
|
||||||
|
console.log(name);
|
||||||
|
const f = op[name];
|
||||||
|
f(edit, interpreter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
external.invoke("initiate");
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
Reference in new issue
Block a user