bugs: fix web list issue

This commit is contained in:
Jonathan Kelley committed 2021-10-10 22:27:08 -04:00
1 parent 4a0bb8cf84
commit da4423c141
8 files changed
+112 -48

No files matched your search

+67 -10
View File
@@ -330,9 +330,6 @@ impl<'bump> DiffMachine<'bump> {
}
if !children.is_empty() {
// self.stack.element_id_stack.push(real_id);
// push our element_id onto the stack
// drop our element off the stack
self.stack.create_children(children, MountType::Append);
}
}
@@ -543,11 +540,15 @@ impl<'bump> DiffMachine<'bump> {
}
}
if has_comitted {
self.mutations.pop();
if old.children.len() == 0 && new.children.len() != 0 {
please_commit(&mut self.mutations.edits);
self.stack.create_children(new.children, MountType::Append);
} else {
self.diff_children(old.children, new.children);
if has_comitted {
self.mutations.pop();
}
}
self.diff_children(old.children, new.children);
}
fn diff_component_nodes(
@@ -601,6 +602,9 @@ impl<'bump> DiffMachine<'bump> {
return;
}
debug_assert!(old.children.len() != 0);
debug_assert!(new.children.len() != 0);
self.diff_children(old.children, new.children);
}
@@ -633,6 +637,7 @@ impl<'bump> DiffMachine<'bump> {
match (old, new) {
([], []) => {}
([], _) => {
// we need to push the
self.stack.create_children(new, MountType::Append);
}
(_, []) => {
@@ -761,13 +766,57 @@ impl<'bump> DiffMachine<'bump> {
right_offset,
);
log::debug!("stack before lo is {:#?}", self.stack.instructions);
// Ok, we now hopefully have a smaller range of children in the middle
// within which to re-order nodes with the same keys, remove old nodes with
// now-unused keys, and create new nodes with fresh keys.
self.diff_keyed_middle(
&old[left_offset..(old.len() - right_offset)],
&new[left_offset..(new.len() - right_offset)],
let old_middle = &old[left_offset..(old.len() - right_offset)];
let new_middle = &new[left_offset..(new.len() - right_offset)];
debug_assert!(
!((old_middle.len() == new_middle.len()) && old_middle.len() == 0),
"keyed children must have the same number of children"
);
if new_middle.len() == 0 {
// remove the old elements
self.remove_nodes(old_middle);
} else if old_middle.len() == 0 {
// there were no old elements, so just create the new elements
// we need to find the right "foothold" though - we shouldnt use the "append" at all
if left_offset == 0 {
// insert at the beginning of the old list
let foothold = &old[old.len() - right_offset];
self.stack.create_children(
new_middle,
MountType::InsertBefore {
other_node: foothold,
},
);
} else if right_offset == 0 {
// insert at the end the old list
let foothold = old.last().unwrap();
self.stack.create_children(
new_middle,
MountType::InsertAfter {
other_node: foothold,
},
);
} else {
// inserting in the middle
let foothold = &old[left_offset - 1];
self.stack.create_children(
new_middle,
MountType::InsertAfter {
other_node: foothold,
},
);
}
} else {
self.diff_keyed_middle(old_middle, new_middle);
}
log::debug!("stack after km is {:#?}", self.stack.instructions);
}
/// Diff both ends of the children that share keys.
@@ -893,6 +942,14 @@ impl<'bump> DiffMachine<'bump> {
// If none of the old keys are reused by the new children, then we remove all the remaining old children and
// create the new children afresh.
if shared_keys.is_empty() {
log::debug!(
"no shared keys, replacing and creating many with many, {:#?}, {:#?}",
old,
new
);
log::debug!("old_key_to_old_index, {:#?}", old_key_to_old_index);
log::debug!("new_index_to_old_index, {:#?}", new_index_to_old_index);
log::debug!("shared_keys, {:#?}", shared_keys);
self.replace_and_create_many_with_many(old, new);
return;
}
+1 -1
View File
@@ -36,7 +36,7 @@ pub enum MountType<'a> {
}
pub(crate) struct DiffStack<'bump> {
instructions: Vec<DiffInstruction<'bump>>,
pub(crate) instructions: Vec<DiffInstruction<'bump>>,
nodes_created_stack: SmallVec<[usize; 10]>,
pub scope_stack: SmallVec<[ScopeId; 5]>,
}
+15 -2
View File
@@ -107,8 +107,6 @@ pub enum SchedulerMsg {
}
pub enum TaskMsg {
// SubmitTask(FiberTask, u64),
// SubmitTask(FiberTask, u64),
ToggleTask(u64),
PauseTask(u64),
ResumeTask(u64),
@@ -322,6 +320,9 @@ impl Scheduler {
unsafe fn load_work(&mut self) -> SavedDiffWork<'static> {
self.saved_state.take().unwrap().extend()
}
pub fn handle_task(&mut self, evt: TaskMsg) {
//
}
pub fn handle_channel_msg(&mut self, msg: SchedulerMsg) {
match msg {
@@ -480,6 +481,18 @@ impl Scheduler {
let mut committed_mutations = Vec::<Mutations<'static>>::new();
while self.has_any_work() {
while let Ok(Some(msg)) = self.receiver.try_next() {
match msg {
SchedulerMsg::Task(t) => todo!(),
SchedulerMsg::Immediate(im) => {
self.dirty_scopes.insert(im);
}
SchedulerMsg::UiEvent(evt) => {
self.ui_events.push_back(evt);
}
}
}
// switch our priority, pop off any work
while let Some(event) = self.ui_events.pop_front() {
if let Some(scope) = self.pool.get_scope_mut(event.scope) {
+4 -20
View File
@@ -360,25 +360,21 @@ impl VirtualDom {
/// Waits for the scheduler to have work
/// This lets us poll async tasks during idle periods without blocking the main thread.
pub async fn wait_for_work(&mut self) {
// todo: poll the events once even if there is work to do to prevent starvation
if self.scheduler.has_any_work() {
log::debug!("No need to wait for work, we already have some");
return;
}
log::debug!("No active work.... waiting for some...");
use futures_util::StreamExt;
// right now this won't poll events if there is ongoing work
// in the future we want to prioritize some events over ongoing work
// this is coming in the "priorities" PR
// Wait for any new events if we have nothing to do
// todo: poll the events once even if there is work to do to prevent starvation
futures_util::select! {
_ = self.scheduler.async_tasks.next() => {}
msg = self.scheduler.receiver.next() => {
match msg.unwrap() {
SchedulerMsg::Task(t) => todo!(),
SchedulerMsg::Task(t) => {
self.scheduler.handle_task(t);
},
SchedulerMsg::Immediate(im) => {
self.scheduler.dirty_scopes.insert(im);
}
@@ -388,18 +384,6 @@ impl VirtualDom {
}
},
}
while let Ok(Some(msg)) = self.scheduler.receiver.try_next() {
match msg {
SchedulerMsg::Task(t) => todo!(),
SchedulerMsg::Immediate(im) => {
self.scheduler.dirty_scopes.insert(im);
}
SchedulerMsg::UiEvent(evt) => {
self.scheduler.ui_events.push_back(evt);
}
}
}
}
}