mirror of https://github.com/sveltejs/svelte
parent
dab1f6a0fa
commit
a2d09c2136
@ -1,92 +1,78 @@
|
||||
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) {
|
||||
var last = null;
|
||||
var expected = head;
|
||||
export function destroyIteration(iteration, lookup) {
|
||||
var first = iteration.first
|
||||
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 mounts = {};
|
||||
var next_iteration = null;
|
||||
|
||||
for (i = 0; i < each_block_value.length; i += 1) {
|
||||
var key = each_block_value[i][block_key];
|
||||
var i = list.length;
|
||||
while (i--) {
|
||||
var key = list[i][key_prop];
|
||||
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 (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;
|
||||
if (iteration) {
|
||||
if (dynamic) iteration.p(changed, get_context(i));
|
||||
} else {
|
||||
// key is being inserted
|
||||
iteration = lookup[key] = create_each_block(component, key, get_context(i));
|
||||
iteration.c();
|
||||
mounts[key] = iteration;
|
||||
}
|
||||
|
||||
lookup[key] = iteration;
|
||||
keep[iteration.key] = iteration;
|
||||
last = iteration;
|
||||
keep[key] = 1;
|
||||
}
|
||||
|
||||
var destroy = hasOutroMethod
|
||||
? function(iteration) {
|
||||
iteration.o(function() {
|
||||
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;
|
||||
}
|
||||
? outroAndDestroyIteration
|
||||
: destroyIteration;
|
||||
|
||||
iteration = head;
|
||||
while(iteration) {
|
||||
if (!keep[iteration.key]) {
|
||||
destroy(iteration);
|
||||
}
|
||||
while (iteration) {
|
||||
if (!keep[iteration.key]) destroy(iteration, lookup);
|
||||
iteration = iteration.next;
|
||||
}
|
||||
|
||||
// Work backwards due to DOM api having insertBefore
|
||||
for (i = each_block_value.length - 1; i >= 0; i -= 1) {
|
||||
var data = each_block_value[i];
|
||||
var key = data[block_key];
|
||||
var next = null;
|
||||
|
||||
i = list.length;
|
||||
while (i--) {
|
||||
key = list[i][key_prop];
|
||||
iteration = lookup[key];
|
||||
|
||||
var block = mounts[key];
|
||||
if (block) {
|
||||
var anchor;
|
||||
var anchor;
|
||||
|
||||
if (hasOutroMethod) {
|
||||
var key_next_iteration = next_iteration && next_iteration.key;
|
||||
var iteration_anchor = iteration.next;
|
||||
var key_anchor;
|
||||
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;
|
||||
}
|
||||
if (hasOutroMethod) {
|
||||
var next_key = next && next.key;
|
||||
var neighbour = iteration.next;
|
||||
var anchor_key;
|
||||
|
||||
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;
|
||||
next_iteration = iteration;
|
||||
|
||||
iteration[iteration.i ? 'i' : 'm'](updateMountNode, anchor);
|
||||
|
||||
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 ) {
|
||||
return array.split( '' ).map( x => ({ id: x }) );
|
||||
function toObjects(array) {
|
||||
return array.split('').map(x => ({ id: x }));
|
||||
}
|
||||
|
||||
function permute () {
|
||||
function permute() {
|
||||
const values = VALUES.slice();
|
||||
const number = Math.floor(Math.random() * VALUES.length);
|
||||
const permuted = [];
|
||||
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 {
|
||||
data: {
|
||||
values: toObjects( 'abc' )
|
||||
values: toObjects('abc'),
|
||||
},
|
||||
|
||||
html: `(a)(b)(c)`,
|
||||
|
||||
test ( assert, component, target ) {
|
||||
function test ( sequence ) {
|
||||
component.set({ values: toObjects( sequence ) });
|
||||
assert.htmlEqual( target.innerHTML, sequence.split( '' ).map( x => `(${x})` ).join( '' ) );
|
||||
test(assert, component, target) {
|
||||
function test(sequence) {
|
||||
const previous = target.textContent;
|
||||
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
|
||||
test( 'abc' );
|
||||
test( 'abcd' );
|
||||
test( 'abecd' );
|
||||
test( 'fabecd' );
|
||||
test( 'fabed' );
|
||||
test( 'beadf' );
|
||||
test( 'ghbeadf' );
|
||||
test( 'gf' );
|
||||
test( 'gc' );
|
||||
test( 'g' );
|
||||
test( '' );
|
||||
test( 'abc' );
|
||||
test( 'duqbmineapjhtlofrskcg' );
|
||||
test( 'hdnkjougmrvftewsqpailcb' );
|
||||
test('abc');
|
||||
test('abcd');
|
||||
test('abecd');
|
||||
test('fabecd');
|
||||
test('fabed');
|
||||
test('beadf');
|
||||
test('ghbeadf');
|
||||
test('gf');
|
||||
test('gc');
|
||||
test('g');
|
||||
test('');
|
||||
test('abc');
|
||||
test('duqbmineapjhtlofrskcg');
|
||||
test('hdnkjougmrvftewsqpailcb');
|
||||
test('bidhfacge');
|
||||
test('kgjnempcboaflidh');
|
||||
|
||||
// then, we party
|
||||
for ( let i = 0; i < 100; i += 1 ) test( permute() );
|
||||
for (let i = 0; i < 100; i += 1) test(permute());
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in new issue