simplify updateKeyedEach

pull/1256/head
Rich Harris 7 years ago
parent dab1f6a0fa
commit a2d09c2136

@ -1,92 +1,78 @@
import { assign } from './utils.js'; import { assign } from './utils.js';
export function updateKeyedEach(component, key, changed, block_key, dynamic, each_block_value, head, lookup, updateMountNode, hasOutroMethod, create_each_block, get_context) { export function destroyIteration(iteration, lookup) {
var last = null; var first = iteration.first
var expected = head; if (first && first.parentNode) {
iteration.u();
}
iteration.d();
lookup[iteration.key] = null;
}
export function outroAndDestroyIteration(iteration, lookup) {
iteration.o(function() {
iteration.u();
iteration.d();
lookup[iteration.key] = null;
});
}
export function updateKeyedEach(component, key, changed, key_prop, dynamic, list, head, lookup, updateMountNode, hasOutroMethod, create_each_block, get_context) {
var keep = {}; var keep = {};
var mounts = {};
var next_iteration = null;
for (i = 0; i < each_block_value.length; i += 1) { var i = list.length;
var key = each_block_value[i][block_key]; while (i--) {
var key = list[i][key_prop];
var iteration = lookup[key]; var iteration = lookup[key];
var next_data = each_block_value[i+1];
var next = next_data && lookup[next_data[block_key]];
if (dynamic && iteration) iteration.p(changed, get_context(i)); // TODO should this be deferred? could it be redundant? if (iteration) {
if (dynamic) iteration.p(changed, get_context(i));
if (expected && (key === expected.key)) {
var first = iteration && iteration.first;
var parentNode = first && first.parentNode
if (!parentNode || (iteration && iteration.next) != next) mounts[key] = iteration;
expected = iteration.next;
} else if (iteration) {
mounts[key] = iteration;
expected = iteration.next;
} else { } else {
// key is being inserted
iteration = lookup[key] = create_each_block(component, key, get_context(i)); iteration = lookup[key] = create_each_block(component, key, get_context(i));
iteration.c(); iteration.c();
mounts[key] = iteration;
} }
lookup[key] = iteration; lookup[key] = iteration;
keep[iteration.key] = iteration; keep[key] = 1;
last = iteration;
} }
var destroy = hasOutroMethod var destroy = hasOutroMethod
? function(iteration) { ? outroAndDestroyIteration
iteration.o(function() { : destroyIteration;
iteration.u();
iteration.d();
lookup[iteration.key] = null;
});
}
: function(iteration) {
var first = iteration.first
if (first && first.parentNode) {
iteration.u();
}
iteration.d();
lookup[iteration.key] = null;
}
iteration = head; iteration = head;
while(iteration) { while (iteration) {
if (!keep[iteration.key]) { if (!keep[iteration.key]) destroy(iteration, lookup);
destroy(iteration);
}
iteration = iteration.next; iteration = iteration.next;
} }
// Work backwards due to DOM api having insertBefore var next = null;
for (i = each_block_value.length - 1; i >= 0; i -= 1) {
var data = each_block_value[i]; i = list.length;
var key = data[block_key]; while (i--) {
key = list[i][key_prop];
iteration = lookup[key]; iteration = lookup[key];
var block = mounts[key]; var anchor;
if (block) {
var anchor;
if (hasOutroMethod) { if (hasOutroMethod) {
var key_next_iteration = next_iteration && next_iteration.key; var next_key = next && next.key;
var iteration_anchor = iteration.next; var neighbour = iteration.next;
var key_anchor; var anchor_key;
do {
anchor = iteration_anchor && iteration_anchor.first;
iteration_anchor = iteration_anchor && iteration_anchor.next;
key_anchor = iteration_anchor && iteration_anchor.key;
} while(iteration_anchor && key_anchor != key_next_iteration && !keep[key_anchor])
} else {
anchor = next_iteration && next_iteration.first;
}
block[block.i ? 'i' : 'm'](updateMountNode, anchor); 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;
} }
iteration.next = next_iteration;
if (next_iteration) next_iteration.last = iteration; iteration[iteration.i ? 'i' : 'm'](updateMountNode, anchor);
next_iteration = iteration;
iteration.next = next;
if (next) next.last = iteration;
next = iteration;
} }
} }

@ -1,50 +1,60 @@
const VALUES = Array.from( 'abcdefghijklmnopqrstuvwxyz' ); const VALUES = Array.from('abcdefghijklmnopqrstuvwxyz');
function toObjects ( array ) { function toObjects(array) {
return array.split( '' ).map( x => ({ id: x }) ); return array.split('').map(x => ({ id: x }));
} }
function permute () { function permute() {
const values = VALUES.slice(); const values = VALUES.slice();
const number = Math.floor(Math.random() * VALUES.length); const number = Math.floor(Math.random() * VALUES.length);
const permuted = []; const permuted = [];
for (let i = 0; i < number; i++) { for (let i = 0; i < number; i++) {
permuted.push( ...values.splice( Math.floor( Math.random() * ( number - i ) ), 1 ) ); permuted.push(
...values.splice(Math.floor(Math.random() * (number - i)), 1)
);
} }
return permuted.join( '' ); return permuted.join('');
} }
export default { export default {
data: { data: {
values: toObjects( 'abc' ) values: toObjects('abc'),
}, },
html: `(a)(b)(c)`, html: `(a)(b)(c)`,
test ( assert, component, target ) { test(assert, component, target) {
function test ( sequence ) { function test(sequence) {
component.set({ values: toObjects( sequence ) }); const previous = target.textContent;
assert.htmlEqual( target.innerHTML, sequence.split( '' ).map( x => `(${x})` ).join( '' ) ); const expected = sequence.split('').map(x => `(${x})`).join('');
component.set({ values: toObjects(sequence) });
assert.htmlEqual(
target.innerHTML,
expected,
`\n${previous} -> ${expected}\n${target.textContent}`
);
} }
// first, some fixed tests so that we can debug them // first, some fixed tests so that we can debug them
test( 'abc' ); test('abc');
test( 'abcd' ); test('abcd');
test( 'abecd' ); test('abecd');
test( 'fabecd' ); test('fabecd');
test( 'fabed' ); test('fabed');
test( 'beadf' ); test('beadf');
test( 'ghbeadf' ); test('ghbeadf');
test( 'gf' ); test('gf');
test( 'gc' ); test('gc');
test( 'g' ); test('g');
test( '' ); test('');
test( 'abc' ); test('abc');
test( 'duqbmineapjhtlofrskcg' ); test('duqbmineapjhtlofrskcg');
test( 'hdnkjougmrvftewsqpailcb' ); test('hdnkjougmrvftewsqpailcb');
test('bidhfacge');
test('kgjnempcboaflidh');
// then, we party // then, we party
for ( let i = 0; i < 100; i += 1 ) test( permute() ); for (let i = 0; i < 100; i += 1) test(permute());
} }
}; };

Loading…
Cancel
Save