Improving the performance of children_signal_vec
This commit is contained in:
parent
3062359534
commit
08864347f4
|
@ -57,7 +57,6 @@ use crate::cache::intern;
|
||||||
elem.style.setProperty(name, value, (important ? \"important\" : \"\"));
|
elem.style.setProperty(name, value, (important ? \"important\" : \"\"));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_at(parent, index) { return parent.childNodes[index]; }
|
|
||||||
export function insert_child_before(parent, child, other) { parent.insertBefore(child, other); }
|
export function insert_child_before(parent, child, other) { parent.insertBefore(child, other); }
|
||||||
export function replace_child(parent, child, other) { parent.replaceChild(child, other); }
|
export function replace_child(parent, child, other) { parent.replaceChild(child, other); }
|
||||||
export function append_child(parent, child) { parent.appendChild(child); }
|
export function append_child(parent, child) { parent.appendChild(child); }
|
||||||
|
@ -135,7 +134,6 @@ extern "C" {
|
||||||
pub(crate) fn remove_style(elem: &JsValue, name: &JsString);
|
pub(crate) fn remove_style(elem: &JsValue, name: &JsString);
|
||||||
pub(crate) fn set_style(elem: &JsValue, name: &JsString, value: &JsString, important: bool);
|
pub(crate) fn set_style(elem: &JsValue, name: &JsString, value: &JsString, important: bool);
|
||||||
|
|
||||||
pub(crate) fn get_at(parent: &Node, index: u32) -> Node;
|
|
||||||
pub(crate) fn insert_child_before(parent: &Node, child: &Node, other: &Node);
|
pub(crate) fn insert_child_before(parent: &Node, child: &Node, other: &Node);
|
||||||
pub(crate) fn replace_child(parent: &Node, child: &Node, other: &Node);
|
pub(crate) fn replace_child(parent: &Node, child: &Node, other: &Node);
|
||||||
pub(crate) fn append_child(parent: &Node, child: &Node);
|
pub(crate) fn append_child(parent: &Node, child: &Node);
|
||||||
|
@ -158,21 +156,3 @@ extern "C" {
|
||||||
pub(crate) fn remove_all_children(node: &Node) {
|
pub(crate) fn remove_all_children(node: &Node) {
|
||||||
set_text_content(node, &intern(""));
|
set_text_content(node, &intern(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO make this more efficient
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn insert_at(parent: &Node, index: u32, child: &Node) {
|
|
||||||
insert_child_before(parent, child, &get_at(parent, index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO make this more efficient
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn update_at(parent: &Node, index: u32, child: &Node) {
|
|
||||||
replace_child(parent, child, &get_at(parent, index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO make this more efficient
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn remove_at(parent: &Node, index: u32) {
|
|
||||||
remove_child(parent, &get_at(parent, index));
|
|
||||||
}
|
|
||||||
|
|
|
@ -95,9 +95,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_change(state: &mut State, element: &Node, change: VecDiff<Dom>) {
|
fn clear(state: &mut State, element: &Node) {
|
||||||
match change {
|
|
||||||
VecDiff::Replace { values } => {
|
|
||||||
// TODO is this correct ?
|
// TODO is this correct ?
|
||||||
if state.children.len() > 0 {
|
if state.children.len() > 0 {
|
||||||
bindings::remove_all_children(element);
|
bindings::remove_all_children(element);
|
||||||
|
@ -106,31 +104,45 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
||||||
dom.callbacks.discard();
|
dom.callbacks.discard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_at(state: &mut State, element: &Node, new_index: usize, child: &Node) {
|
||||||
|
if let Some(dom) = state.children.get(new_index) {
|
||||||
|
bindings::insert_child_before(element, child, &dom.element);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
bindings::append_child(element, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn after_insert(is_inserted: bool, callbacks: &mut Callbacks) {
|
||||||
|
callbacks.leak();
|
||||||
|
|
||||||
|
if is_inserted {
|
||||||
|
callbacks.trigger_after_insert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_change(state: &mut State, element: &Node, change: VecDiff<Dom>) {
|
||||||
|
match change {
|
||||||
|
VecDiff::Replace { values } => {
|
||||||
|
clear(state, element);
|
||||||
|
|
||||||
state.children = values;
|
state.children = values;
|
||||||
|
|
||||||
let is_inserted = state.is_inserted;
|
let is_inserted = state.is_inserted;
|
||||||
|
|
||||||
for dom in state.children.iter_mut() {
|
for dom in state.children.iter_mut() {
|
||||||
dom.callbacks.leak();
|
|
||||||
|
|
||||||
bindings::append_child(element, &dom.element);
|
bindings::append_child(element, &dom.element);
|
||||||
|
|
||||||
if is_inserted {
|
after_insert(is_inserted, &mut dom.callbacks);
|
||||||
dom.callbacks.trigger_after_insert();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
VecDiff::InsertAt { index, mut value } => {
|
VecDiff::InsertAt { index, mut value } => {
|
||||||
// TODO better usize -> u32 conversion
|
insert_at(state, element, index, &value.element);
|
||||||
bindings::insert_at(element, index as u32, &value.element);
|
|
||||||
|
|
||||||
value.callbacks.leak();
|
after_insert(state.is_inserted, &mut value.callbacks);
|
||||||
|
|
||||||
if state.is_inserted {
|
|
||||||
value.callbacks.trigger_after_insert();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO figure out a way to move this to the top
|
// TODO figure out a way to move this to the top
|
||||||
state.children.insert(index, value);
|
state.children.insert(index, value);
|
||||||
|
@ -139,29 +151,22 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
||||||
VecDiff::Push { mut value } => {
|
VecDiff::Push { mut value } => {
|
||||||
bindings::append_child(element, &value.element);
|
bindings::append_child(element, &value.element);
|
||||||
|
|
||||||
value.callbacks.leak();
|
after_insert(state.is_inserted, &mut value.callbacks);
|
||||||
|
|
||||||
if state.is_inserted {
|
|
||||||
value.callbacks.trigger_after_insert();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO figure out a way to move this to the top
|
// TODO figure out a way to move this to the top
|
||||||
state.children.push(value);
|
state.children.push(value);
|
||||||
},
|
},
|
||||||
|
|
||||||
VecDiff::UpdateAt { index, mut value } => {
|
VecDiff::UpdateAt { index, mut value } => {
|
||||||
// TODO better usize -> u32 conversion
|
let dom = &mut state.children[index];
|
||||||
bindings::update_at(element, index as u32, &value.element);
|
|
||||||
|
|
||||||
value.callbacks.leak();
|
bindings::replace_child(element, &value.element, &dom.element);
|
||||||
|
|
||||||
if state.is_inserted {
|
after_insert(state.is_inserted, &mut value.callbacks);
|
||||||
value.callbacks.trigger_after_insert();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO figure out a way to move this to the top
|
// TODO figure out a way to move this to the top
|
||||||
// TODO test this
|
// TODO test this
|
||||||
::std::mem::swap(&mut state.children[index], &mut value);
|
::std::mem::swap(dom, &mut value);
|
||||||
|
|
||||||
value.callbacks.discard();
|
value.callbacks.discard();
|
||||||
},
|
},
|
||||||
|
@ -169,44 +174,34 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
||||||
VecDiff::Move { old_index, new_index } => {
|
VecDiff::Move { old_index, new_index } => {
|
||||||
let value = state.children.remove(old_index);
|
let value = state.children.remove(old_index);
|
||||||
|
|
||||||
bindings::remove_child(element, &value.element);
|
insert_at(state, element, new_index, &value.element);
|
||||||
// TODO better usize -> u32 conversion
|
|
||||||
bindings::insert_at(element, new_index as u32, &value.element);
|
|
||||||
|
|
||||||
state.children.insert(new_index, value);
|
state.children.insert(new_index, value);
|
||||||
},
|
},
|
||||||
|
|
||||||
VecDiff::RemoveAt { index } => {
|
VecDiff::RemoveAt { index } => {
|
||||||
// TODO better usize -> u32 conversion
|
let dom = state.children.remove(index);
|
||||||
bindings::remove_at(element, index as u32);
|
|
||||||
|
|
||||||
state.children.remove(index).callbacks.discard();
|
bindings::remove_child(element, &dom.element);
|
||||||
|
|
||||||
|
dom.callbacks.discard();
|
||||||
},
|
},
|
||||||
|
|
||||||
VecDiff::Pop {} => {
|
VecDiff::Pop {} => {
|
||||||
let index = state.children.len() - 1;
|
let dom = state.children.pop().unwrap_throw();
|
||||||
|
|
||||||
// TODO create remove_last_child function ?
|
bindings::remove_child(element, &dom.element);
|
||||||
// TODO better usize -> u32 conversion
|
|
||||||
bindings::remove_at(element, index as u32);
|
|
||||||
|
|
||||||
state.children.pop().unwrap_throw().callbacks.discard();
|
dom.callbacks.discard();
|
||||||
},
|
},
|
||||||
|
|
||||||
VecDiff::Clear {} => {
|
VecDiff::Clear {} => {
|
||||||
// TODO is this correct ?
|
clear(state, element);
|
||||||
// TODO is this needed, or is it guaranteed by VecDiff ?
|
|
||||||
if state.children.len() > 0 {
|
|
||||||
bindings::remove_all_children(element);
|
|
||||||
|
|
||||||
for dom in state.children.drain(..) {
|
|
||||||
dom.callbacks.discard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO maybe move this into the after_insert callback and remove State
|
||||||
// TODO verify that this will drop `children`
|
// TODO verify that this will drop `children`
|
||||||
callbacks.after_remove(for_each_vec(signal, move |change| {
|
callbacks.after_remove(for_each_vec(signal, move |change| {
|
||||||
let mut state = state.lock().unwrap_throw();
|
let mut state = state.lock().unwrap_throw();
|
||||||
|
|
Loading…
Reference in New Issue