mirror of https://github.com/sveltejs/svelte
Merge pull request #1274 from sveltejs/fix-perf-regression
A new list diffing algorithmpull/1279/head
commit
89c0864c81
@ -1,80 +1,99 @@
|
||||
import { assign } from './utils.js';
|
||||
|
||||
export function destroyIteration(iteration, lookup) {
|
||||
var first = iteration.first
|
||||
if (first && first.parentNode) {
|
||||
iteration.u();
|
||||
}
|
||||
iteration.d();
|
||||
lookup[iteration.key] = null;
|
||||
export function destroyBlock(block, lookup) {
|
||||
block.u();
|
||||
block.d();
|
||||
lookup[block.key] = null;
|
||||
}
|
||||
|
||||
export function outroAndDestroyIteration(iteration, lookup) {
|
||||
iteration.o(function() {
|
||||
iteration.u();
|
||||
iteration.d();
|
||||
lookup[iteration.key] = null;
|
||||
export function outroAndDestroyBlock(block, lookup) {
|
||||
block.o(function() {
|
||||
destroyBlock(block, lookup);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO is it possible to avoid mounting iterations that are
|
||||
// already in the right place?
|
||||
export function updateKeyedEach(component, key, changed, key_prop, dynamic, list, head, lookup, node, has_outro, create_each_block, intro_method, get_context) {
|
||||
var keep = {};
|
||||
export function updateKeyedEach(old_blocks, component, changed, key_prop, dynamic, list, lookup, node, has_outro, create_each_block, intro_method, get_context) {
|
||||
var o = old_blocks.length;
|
||||
var n = list.length;
|
||||
|
||||
var i = o;
|
||||
var old_indexes = {};
|
||||
while (i--) old_indexes[old_blocks[i].key] = i;
|
||||
|
||||
var i = list.length;
|
||||
var new_blocks = [];
|
||||
var new_lookup = {};
|
||||
var deltas = {};
|
||||
|
||||
var i = n;
|
||||
while (i--) {
|
||||
var key = list[i][key_prop];
|
||||
var iteration = lookup[key];
|
||||
var block = lookup[key];
|
||||
|
||||
if (iteration) {
|
||||
if (dynamic) iteration.p(changed, get_context(i));
|
||||
} else {
|
||||
iteration = lookup[key] = create_each_block(component, key, get_context(i));
|
||||
iteration.c();
|
||||
if (!block) {
|
||||
block = create_each_block(component, key, get_context(i));
|
||||
block.c();
|
||||
} else if (dynamic) {
|
||||
block.p(changed, get_context(i));
|
||||
}
|
||||
|
||||
lookup[key] = iteration;
|
||||
keep[key] = 1;
|
||||
new_blocks[i] = new_lookup[key] = block;
|
||||
|
||||
if (key in old_indexes) deltas[key] = Math.abs(i - old_indexes[key]);
|
||||
}
|
||||
|
||||
var destroy = has_outro
|
||||
? outroAndDestroyIteration
|
||||
: destroyIteration;
|
||||
var next = null;
|
||||
|
||||
var will_move = {};
|
||||
var did_move = {};
|
||||
|
||||
iteration = head;
|
||||
while (iteration) {
|
||||
if (!keep[iteration.key]) destroy(iteration, lookup);
|
||||
iteration = iteration.next;
|
||||
var destroy = has_outro ? outroAndDestroyBlock : destroyBlock;
|
||||
|
||||
function insert(block) {
|
||||
block[intro_method](node, next && next.first);
|
||||
next = lookup[block.key] = block;
|
||||
n--;
|
||||
}
|
||||
|
||||
var next = null;
|
||||
while (o && n) {
|
||||
var new_block = new_blocks[n - 1];
|
||||
var old_block = old_blocks[o - 1];
|
||||
var new_key = new_block.key;
|
||||
var old_key = old_block.key;
|
||||
|
||||
i = list.length;
|
||||
while (i--) {
|
||||
key = list[i][key_prop];
|
||||
iteration = lookup[key];
|
||||
if (new_block === old_block) {
|
||||
// do nothing
|
||||
next = new_block;
|
||||
o--;
|
||||
n--;
|
||||
}
|
||||
|
||||
else if (!new_lookup[old_key]) {
|
||||
// remove old block
|
||||
destroy(old_block, lookup);
|
||||
o--;
|
||||
}
|
||||
|
||||
else if (!lookup[new_key] || will_move[new_key]) {
|
||||
insert(new_block);
|
||||
}
|
||||
|
||||
var anchor;
|
||||
else if (did_move[old_key]) {
|
||||
o--;
|
||||
|
||||
if (has_outro) {
|
||||
var next_key = next && next.key;
|
||||
var neighbour = iteration.next;
|
||||
var anchor_key;
|
||||
} else if (deltas[new_key] > deltas[old_key]) {
|
||||
did_move[new_key] = true;
|
||||
insert(new_block);
|
||||
|
||||
while (neighbour && anchor_key != next_key && !keep[anchor_key]) {
|
||||
anchor = neighbour && neighbour.first;
|
||||
neighbour = neighbour.next;
|
||||
anchor_key = neighbour && neighbour.key;
|
||||
}
|
||||
} else {
|
||||
anchor = next && next.first;
|
||||
will_move[old_key] = true;
|
||||
o--;
|
||||
}
|
||||
}
|
||||
|
||||
iteration[intro_method](node, anchor);
|
||||
|
||||
iteration.next = next;
|
||||
if (next) next.last = iteration;
|
||||
next = iteration;
|
||||
while (o--) {
|
||||
var old_block = old_blocks[o];
|
||||
if (!new_lookup[old_block.key]) destroy(old_block, lookup);
|
||||
}
|
||||
|
||||
while (n) insert(new_blocks[n - 1]);
|
||||
|
||||
return new_blocks;
|
||||
}
|
Loading…
Reference in new issue