mirror of https://github.com/sveltejs/svelte
				
				
				
			Merge pull request #1256 from sveltejs/each-keyed-helper
	
		
	
				
					
				
			[WIP] move keyed each diffing into a shared helperpull/1261/head
						commit
						35a7fc6d32
					
				@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					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 outroAndDestroyIteration(iteration, lookup) {
 | 
				
			||||||
 | 
						iteration.o(function() {
 | 
				
			||||||
 | 
							iteration.u();
 | 
				
			||||||
 | 
							iteration.d();
 | 
				
			||||||
 | 
							lookup[iteration.key] = null;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var i = list.length;
 | 
				
			||||||
 | 
						while (i--) {
 | 
				
			||||||
 | 
							var key = list[i][key_prop];
 | 
				
			||||||
 | 
							var iteration = 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();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							lookup[key] = iteration;
 | 
				
			||||||
 | 
							keep[key] = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var destroy = has_outro
 | 
				
			||||||
 | 
							? outroAndDestroyIteration
 | 
				
			||||||
 | 
							: destroyIteration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iteration = head;
 | 
				
			||||||
 | 
						while (iteration) {
 | 
				
			||||||
 | 
							if (!keep[iteration.key]) destroy(iteration, lookup);
 | 
				
			||||||
 | 
							iteration = iteration.next;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var next = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						i = list.length;
 | 
				
			||||||
 | 
						while (i--) {
 | 
				
			||||||
 | 
							key = list[i][key_prop];
 | 
				
			||||||
 | 
							iteration = lookup[key];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var anchor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (has_outro) {
 | 
				
			||||||
 | 
								var next_key = next && next.key;
 | 
				
			||||||
 | 
								var neighbour = iteration.next;
 | 
				
			||||||
 | 
								var anchor_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								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[intro_method](node, 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 ) {
 | 
					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…
					
					
				
		Reference in new issue