Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #88

Merged
merged 105 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
87a4792
feat: remove skip_diff and template method from Application and Compo…
ivanceras Mar 21, 2024
ad101f8
refactor: remove skip_diff and vdom_template from StatelessComponent …
ivanceras Mar 21, 2024
b03af8e
fix: map the TemplatedView variant of Leaf
ivanceras Mar 21, 2024
0377cf5
fix: remove template, skip_diff and vdom_template from AppContext as …
ivanceras Mar 21, 2024
b42aab2
cleanup: remove unused objects
ivanceras Mar 21, 2024
a03cce1
docs
ivanceras Mar 21, 2024
17bf494
doc: more TODO items
ivanceras Mar 21, 2024
8855b41
fix: examples
ivanceras Mar 21, 2024
6536786
fix: creating the initial view from the template should still fire mo…
ivanceras Mar 21, 2024
e4cee32
cargo fmt
ivanceras Mar 21, 2024
f42373d
fix:tests
ivanceras Mar 21, 2024
f9701e2
fix: remove deny warnings on tests
ivanceras Mar 21, 2024
8366eab
doc
ivanceras Mar 21, 2024
b135fda
fix: AddAttributes patch to merge the attributes first, so as not to …
ivanceras Mar 22, 2024
bf48417
change defaults
ivanceras Mar 22, 2024
cbcc8dc
fix: remove more debugs
ivanceras Mar 22, 2024
8bb8045
fix: stateless component should not have attributes or children
ivanceras Mar 22, 2024
68bf04a
feat: make a DomNode counterpart to vdom::Node to be able to customiz…
ivanceras Mar 22, 2024
ae4114d
feat: wrap the web_sys::Node into DomNode for better control on how t…
ivanceras Mar 23, 2024
8439759
feat: implement the methods of the DomNode which is a wrapper to the …
ivanceras Mar 25, 2024
f5504c4
fix: set the parent for appended elements
ivanceras Mar 25, 2024
4c57e26
fix: remove node_closures, as the the event listeners is now stored i…
ivanceras Mar 26, 2024
84a65ca
fix: Task now carries the associated event closures, convert add_wind…
ivanceras Mar 26, 2024
9a96949
fix: put back stateless component and stateful component
ivanceras Mar 26, 2024
d985209
fix: return the first_node on replace_node when patch_path is empty, …
ivanceras Mar 26, 2024
495aa2b
fix: don't use templating for stateless component for now
ivanceras Mar 27, 2024
88c62ad
fix: put a boolean flag whether to use template or not
ivanceras Mar 27, 2024
c0aa4f3
fix: remove closures and event_closures
ivanceras Mar 27, 2024
76569d7
fix: move SkipPath into SkipDiff
ivanceras Mar 27, 2024
68099ba
more cleanup and optimization
ivanceras Mar 27, 2024
c0c7cf3
fix: removing from the last_child is much faster than removing from t…
ivanceras Mar 27, 2024
165568c
cleanup: remove unused
ivanceras Mar 27, 2024
f4806ea
feat: add every_interval Task in Window
ivanceras Mar 27, 2024
d8b67ec
fix: experimentals example
ivanceras Mar 27, 2024
d37250c
fix: some examples
ivanceras Mar 27, 2024
9219e4f
remove not applicable tests
ivanceras Mar 27, 2024
43d4db3
cargo fmt
ivanceras Mar 27, 2024
a58f029
fix: remove the use of template view for now, as there are unsolved b…
ivanceras Mar 28, 2024
6f14ed9
feat: add outer_html to DomNode
ivanceras Mar 28, 2024
15e1ad0
add more test for inserting in the middle patches
ivanceras Mar 28, 2024
fb50ada
fix: insert_before and insert_after method when applying the patch
ivanceras Mar 28, 2024
c47df1e
fix: remove node, reverse the iteration first, so as the order will b…
ivanceras Mar 28, 2024
7e3707a
fix: remove inner_html and safe_html as it can break the dom-tree, th…
ivanceras Mar 28, 2024
ec6e6b7
implement popstate
ivanceras Mar 28, 2024
5ca97b2
doc: add TODO item for symbol html
ivanceras Mar 28, 2024
b6f408e
feat: batch appending of children so we can apply optimization in the…
ivanceras Mar 28, 2024
95e495f
simplify setting parent node
ivanceras Mar 28, 2024
2190dae
fix: examples
ivanceras Mar 28, 2024
0f3a06d
fix: DomNode methods wrapper dont need to return Result or Option
ivanceras Mar 28, 2024
cb542c2
cargo fmt
ivanceras Mar 28, 2024
e538d34
fix: remove unused code
ivanceras Mar 28, 2024
0bcd2cf
fix: use the cached window
ivanceras Mar 28, 2024
438b40e
remove unused
ivanceras Mar 28, 2024
1c30894
feat: add template module for using template for performance improvem…
ivanceras Mar 28, 2024
16462b2
fix: dont use template for now
ivanceras Mar 28, 2024
9c2ab78
feat: StatelessComponent returns the attributes and values of the top…
ivanceras Mar 28, 2024
b508e0d
fix: remove some logging
ivanceras Mar 28, 2024
a5c963b
fix: also add clear_children shortcut for the keyed nodes
ivanceras Mar 28, 2024
ace896e
fix: use a receiver in the for loop expr, so as to not require the us…
ivanceras Mar 28, 2024
9d8804b
cargo fmt
ivanceras Mar 28, 2024
07ba03f
feat: add symbol variant for html entities
ivanceras Mar 28, 2024
28dc42b
cargo fmt
ivanceras Mar 28, 2024
e871e64
fix: Symbol variant in template module
ivanceras Mar 28, 2024
22780f7
cargo fmt
ivanceras Mar 28, 2024
1760a51
fix: symbol variant
ivanceras Mar 28, 2024
fdb149f
doc: TODO items
ivanceras Mar 28, 2024
f1d4a3e
fix: optimize, one call only to is_self_closing
ivanceras Mar 29, 2024
936a8a7
doc: add more TODO
ivanceras Mar 29, 2024
a9466c8
fix: remove already fixed TODO item
ivanceras Mar 29, 2024
a390f96
refactor: use insert_adjacent_element for insert_before
ivanceras Mar 29, 2024
be80606
fix: add more assertions
ivanceras Mar 29, 2024
719eb0a
feat: prepare remove_child for remove_children
ivanceras Mar 29, 2024
380a268
fix: convert remove_child into remove_children for better batching an…
ivanceras Mar 29, 2024
cab084a
fix: early break
ivanceras Mar 29, 2024
ee8cca3
fix: convert insert_before and insert_after to accept a vec of DomNod…
ivanceras Mar 29, 2024
bd23782
fix: remove unused field Marker
ivanceras Mar 29, 2024
fb611d3
feat: improve SkipDiff with inclusion of specific index of attributes…
ivanceras Mar 29, 2024
a478884
fix: and simplify the is_subset_of function
ivanceras Mar 29, 2024
84fa5f8
cargo fmt
ivanceras Mar 29, 2024
33bb3b1
fix: add allow(unused_braced) in for loop
ivanceras Mar 29, 2024
7b4437e
fix: no need to track the selected_id
ivanceras Mar 29, 2024
d83577c
fix: deep_clone which fix the templating, fix setting parent node
ivanceras Mar 30, 2024
d49322c
refactor: set parent directly instead of borrowing and setting
ivanceras Mar 30, 2024
7bfb4aa
fix: set the root_node in the apply_dom_patch function instead of pas…
ivanceras Mar 30, 2024
0d61123
fix: parent need not to be mutable RefCell
ivanceras Mar 30, 2024
17d3ba1
fix: TextNode and Symbol dont need inner mutability
ivanceras Mar 30, 2024
366cb8c
feat: make applying dom patches as mutable methods
ivanceras Mar 30, 2024
cf0fcc5
fix edge case of replace node when root node is replaced with multipe…
ivanceras Mar 30, 2024
50a5b09
cleanup: replace_node patch
ivanceras Mar 30, 2024
53eb114
fix: dont use raf in test_fixture when updating dom with patches, rem…
ivanceras Mar 30, 2024
a0aceab
fix: disable the add_event test for now
ivanceras Mar 30, 2024
3180d09
use template
ivanceras Mar 30, 2024
6f45f23
fix: adding event by using inner mutability to the listeners of an el…
ivanceras Mar 30, 2024
5cd5c91
feat: put the usage of skipdiff behind use-skipdiff feature gate
ivanceras Mar 30, 2024
77eb2b2
feat: add PartialEq implementation for DomNode
ivanceras Mar 30, 2024
62d2d81
cargo fmt
ivanceras Mar 30, 2024
b06880c
fix: use partial eq checking for comparing children to be removed
ivanceras Mar 30, 2024
0895a25
fix: the parent_node passed should be Rc<Option<DomNode>> so it can b…
ivanceras Mar 30, 2024
7b8fac7
use-skipdiff but not template and its much faster
ivanceras Mar 30, 2024
6b3c362
fix: display the time_spent and clear afterwards
ivanceras Mar 30, 2024
0632d40
doc: update TODO with new rethink about Cmd and Task
ivanceras Mar 30, 2024
5c9ceaf
doc: more docs and TODO
ivanceras Mar 30, 2024
77da86c
doc: TODO
ivanceras Mar 30, 2024
2b2d365
fix: remove more logging
ivanceras Mar 31, 2024
06b335a
fix: only store the Event closures
ivanceras Mar 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ test-fixtures = ["sauron-core/test-fixtures"] #include the test-fixtures for upd
with-node-macro = ["sauron-macro"]
custom_element = ["sauron-macro","sauron-core/custom_element"]
html-parser = ["sauron-html-parser"]
use-template = ["sauron-core/use-template"]
use-skipdiff = ["sauron-core/use-skipdiff"]


[dev-dependencies]
Expand All @@ -48,7 +50,7 @@ wasm-bindgen-test = "0.3"
wasm-bindgen-futures = "0.4.31"
regex = "1"
sauron-html-parser = { path = "crates/html-parser" }
sauron = { path = ".", features = ["test-fixtures"] }
sauron = { path = ".", features = ["test-fixtures", "html-parser", "log-patches"] }

[dev-dependencies.web-sys]
version = "0.3"
Expand Down
32 changes: 31 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@
}
```
- [ ] Make the compilation error in `jss!`, `style!`, more informative
- [ ] Optimize handling of style by diffing each style properties
- Update only specific stype instead of setting the whole style attributes


## Internal
Expand Down Expand Up @@ -225,6 +227,7 @@
add these events:
- `on_interval(|i32|{})` for attaching interval in the Window
Http can be done with task
- [ ] Make Http functions return a Task
- [ ] Make `Sub` as counterpart to `Cmd`
- We can use `Sub` in the `Component`
```rust
Expand Down Expand Up @@ -254,14 +257,37 @@
- This is anchored as next to the last sibling
- This can not just be backtrack to the parent, as it defeats the purpose of
doing as little diff as possible.
- [ ] Make a TemplateView struct and a variant of Leat
- [X] Make a TemplateView struct and a variant of Leaf
```rust
struct TemplatedView<MSG>{
template: Box<dyn Fn() -> Node<MSG>>,
skip_diff: Box<dyn Fn() -> SkipDiff>,
view: Node<MSG> ,
}
```
- [X] remove `SafeHtml` variant in leaf, instead provide a safe_html which is parsed and converted into node
- using safe html alters the dom tree
- [X] add `symbol_html` for html entities such as `&nbsp;` `&gt`, `&lt` etc.
- this should be safe to be inserted
- [X] remove `innerHTML` func in AttributeValue as it could alter the DOM node tree
- [X] Keep track of which attributes to be skipped in `SkipDiff{shall:false}`
```rust
enum SkipStrat{
SkipAll,
SkippIndex(Vec<usize>),
}
```
- [X] Maybe disable the template usage for now
- [ ] Make `Cmd` to be used internally as it needs reference to the `Program<APP>`
- [ ] Use `Task` for returning from `Application` init and `update`.
- The `Recurring Task` is actually just a Sub in elm
- Issue with recurring task, how to store the closures which has different multiple types for the in arguments
- Store the closures with `Closure<dyn Fn(IN)->MSG>`
- Then task becomes `Task<IN,MSG>`
- The `SingleTask` is a Cmd in sauron
- Rename `Cmd` to `Command` alternative: `Action`, `Operation`, `Instruction`, `Effects`, `Dispatch`
- This is effects in elm
- Sauron just consilidate them into one enum struct for simplicity

## Features
- [X] Storage service (May not be needed since the user can directly use web-sys)
Expand Down Expand Up @@ -296,6 +322,10 @@
- Right now, it is triggered when the virtual Node is created into a real Node.
- [X] Maybe rename `#[web_component]` macro to `#[custom_element]`
- Also `WebComponent` to `CustomElementWrapper`
- [ ] Implement the `StatefulComponent`
- [ ] attributes and attribute value (key)
- [ ] removing children and setting attributes
- [ ] Make the fancy-ui example work


## Performance
Expand Down
10 changes: 6 additions & 4 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ edition = "2021"
maintenance = { status = "actively-developed" }

[features]
default = ["with-dom", "use-cached-elements","ensure-check", "ensure-attr-set"]
default = ["with-dom", "ensure-check", "ensure-attr-set"]
with-dom = ["wasm-bindgen", "js-sys", "web-sys", "wasm-bindgen-futures"] # for client-side usage
with-lookup = [] #enumerates html tags and attributes
with-measure = [] # log traces for measurements in various parts of the system where performance matters.
Expand All @@ -23,11 +23,12 @@ log-patches = [] # use in combination to with-debug to log the debug patches
with-ric = [] # use of request_idle_callback in javascript
with-raf = [] # use of request_animation_frame in javascript
with-interning = [] # use caching of strings when crossing rust to js, for faster transfer
use-cached-elements = [] # use caching of common elements
custom_element = [] # use of register_custom_element, adding this will add the js snippets
ensure-check = [] #do checking if pending msgs, patches, cmds, has been processed accordingly to ensure proper order and synchronized dom state
ensure-attr-set = [] #ensure attributes is reflected into the element by explicitly calling the element corresponding methods aside fro just setting its attribute by name
test-fixtures = [] #include the test-fixtures for updating the program with the supplied vdom
use-template = [] #use the templated view and building before hand
use-skipdiff = [] #use skipdiff to selectively skip attributes that can not change

[dependencies]
js-sys = { version = "0.3", optional = true }
Expand Down Expand Up @@ -59,6 +60,7 @@ optional = true
features = [
"AnimationEvent",
"Attr",
"CharacterData",
"Comment",
"ClipboardEvent",
"console",
Expand Down Expand Up @@ -108,13 +110,13 @@ features = [
"NamedNodeMap",
"Node",
"NodeList",
"Performance",
"PopStateEvent",
"Text",
"TransitionEvent",
"Touch",
"TouchEvent",
"TouchList",
"CharacterData",
"Performance",
"Window",
"History",
"Response",
Expand Down
4 changes: 2 additions & 2 deletions crates/core/src/dom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod task;
use cfg_if::cfg_if;

cfg_if! {if #[cfg(feature = "with-dom")] {
pub use application::{Application, Measurements, SkipDiff, skip_if, skip_diff};
pub use application::{Application, Measurements, SkipDiff, skip_if, skip_diff, SkipPath};
#[cfg(feature = "custom_element")]
pub use component::{register_web_component, WebComponent, WebComponentWrapper};
pub use component::{component, stateful_component, StatefulComponent, StatefulModel, StatelessModel};
Expand Down Expand Up @@ -50,7 +50,7 @@ cfg_if! {if #[cfg(feature = "with-dom")] {


/// Map the Event to DomEvent, which are browser events
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone)]
pub enum Event {
/// native dome events web_sys::Events
WebEvent(web_sys::Event),
Expand Down
13 changes: 1 addition & 12 deletions crates/core/src/dom/application.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::dom::Cmd;
use crate::vdom::Node;
pub use skip_diff::{skip_if, SkipDiff};
pub use skip_diff::{skip_if, SkipDiff, SkipPath};

///
pub mod skip_diff;
Expand All @@ -26,17 +26,6 @@ pub trait Application: Sized + 'static {
/// Returns a node on how the component is presented.
fn view(&self) -> Node<Self::MSG>;

/// optional logical code when to skip diffing some particular node
/// by comparing field values of app and its old values
fn skip_diff(&self) -> Option<SkipDiff> {
None
}

///
fn template(&self) -> Option<Node<Self::MSG>> {
None
}

/// The css style for the application, will be mounted automatically by the program
fn stylesheet() -> Vec<String> {
vec![]
Expand Down
100 changes: 64 additions & 36 deletions crates/core/src/dom/application/skip_diff.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,55 @@
use crate::vdom::TreePath;

///
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Marker {
/// anything else in the valid block
Block,
/// specifies how attributes will be skipped
#[derive(Debug, PartialEq, Clone)]
pub enum SkipAttrs {
/// all attributes are skipped
All,
/// skip only the listed indices
Indices(Vec<usize>),
}

impl SkipAttrs {
/// dont skip anything
pub fn none() -> Self {
Self::Indices(vec![])
}
}

/// if the expression evaluates to true,
/// diffing at this node will be skipped entirely
#[derive(Debug, PartialEq, Clone)]
pub struct SkipDiff {
/// shall skip or not
pub shall: bool,
/// marker for template blocks
pub marker: Option<Marker>,
pub skip_attrs: SkipAttrs,
/// children skip diff
pub children: Vec<SkipDiff>,
}

impl SkipDiff {
/// new
pub fn new(shall: bool, children: impl IntoIterator<Item = Self>) -> Self {
Self {
shall,
marker: None,
children: children.into_iter().collect(),
}
}

/// the skip diff is a block
pub fn block() -> Self {
Self {
shall: false,
marker: Some(Marker::Block),
skip_attrs: SkipAttrs::none(),
children: vec![],
}
}


/// return SkipDiff in this path location
pub fn in_path(&self, path: &TreePath) -> Option<&Self> {
let mut path = path.clone();
if path.is_empty(){
if path.is_empty() {
Some(&self)
}else{
} else {
let idx = path.remove_first();
if let Some(child) = self.children.get(idx){
if let Some(child) = self.children.get(idx) {
child.in_path(&path)
}else{
} else {
None
}
}
}


/// get the skip diff at this child index
pub fn traverse(&self, idx: usize) -> Option<&Self> {
self.children.get(idx)
Expand All @@ -63,31 +58,28 @@ impl SkipDiff {
/// check if shall skip diffing attributes at this path
/// if the path does not coincide in this skip diff, then by default it is skipped
pub fn shall_skip_attributes(&self) -> bool {
self.shall
self.skip_attrs == SkipAttrs::All
}


/// return true if this skip diff and its children can be skipped
pub fn is_skippable_recursive(&self) -> bool {
self.shall && self.children.iter().all(Self::is_skippable_recursive)
self.shall_skip_attributes() && self.children.iter().all(Self::is_skippable_recursive)
}

///
///
pub fn shall_skip_node(&self) -> bool {
self.shall && self.children.is_empty()
self.shall_skip_attributes() && self.children.is_empty()
}

/// collapse into 1 skip_if if all the children is skippable
pub fn collapse_children(self) -> Self {
let Self {
shall,
skip_attrs,
children,
marker,
} = self;
let can_skip_children = children.iter().all(Self::is_skippable_recursive);
Self {
shall,
marker,
skip_attrs,
children: if can_skip_children {
vec![]
} else {
Expand All @@ -100,10 +92,46 @@ impl SkipDiff {
/// skip diffing the node is the val is true
pub fn skip_if(shall: bool, children: impl IntoIterator<Item = SkipDiff>) -> SkipDiff {
SkipDiff {
shall,
marker: None,
skip_attrs: if shall {
SkipAttrs::All
} else {
SkipAttrs::none()
},
children: children.into_iter().collect(),
}
}

/// combination of TreePath and SkipDiff
#[derive(Debug)]
pub struct SkipPath {
pub(crate) path: TreePath,
pub(crate) skip_diff: Option<SkipDiff>,
}

impl SkipPath {
pub(crate) fn new(path: TreePath, skip_diff: SkipDiff) -> Self {
Self {
path,
skip_diff: Some(skip_diff),
}
}

pub(crate) fn traverse(&self, idx: usize) -> Self {
Self {
path: self.path.traverse(idx),
skip_diff: if let Some(skip_diff) = self.skip_diff.as_ref() {
skip_diff.traverse(idx).cloned()
} else {
None
},
}
}

pub(crate) fn backtrack(&self) -> Self {
Self {
path: self.path.backtrack(),
//TODO: here the skip_diff can not back track as we lose that info already
skip_diff: None,
}
}
}
Loading
Loading