Convert src/runtime/internal/keyed_each.ts to JavaScript

pull/8569/head
S. Elliott Johnson 3 years ago
parent 78e8d8467c
commit 17c0c67747

@ -1,75 +1,58 @@
import { transition_in, transition_out } from './transitions'; import { transition_in, transition_out } from './transitions';
import { run_all } from './utils'; import { run_all } from './utils';
/** @returns {void} */
export function destroy_block(block, lookup) { export function destroy_block(block, lookup) {
block.d(1); block.d(1);
lookup.delete(block.key); lookup.delete(block.key);
} }
/** @returns {void} */
export function outro_and_destroy_block(block, lookup) { export function outro_and_destroy_block(block, lookup) {
transition_out(block, 1, 1, () => { transition_out(block, 1, 1, () => {
lookup.delete(block.key); lookup.delete(block.key);
}); });
} }
/** @returns {void} */
export function fix_and_destroy_block(block, lookup) { export function fix_and_destroy_block(block, lookup) {
block.f(); block.f();
destroy_block(block, lookup); destroy_block(block, lookup);
} }
/** @returns {void} */
export function fix_and_outro_and_destroy_block(block, lookup) { export function fix_and_outro_and_destroy_block(block, lookup) {
block.f(); block.f();
outro_and_destroy_block(block, lookup); outro_and_destroy_block(block, lookup);
} }
/** @returns {any[]} */
export function update_keyed_each( export function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) {
old_blocks,
dirty,
get_key,
dynamic,
ctx,
list,
lookup,
node,
destroy,
create_each_block,
next,
get_context
) {
let o = old_blocks.length; let o = old_blocks.length;
let n = list.length; let n = list.length;
let i = o; let i = o;
const old_indexes = {}; const old_indexes = {};
while (i--) old_indexes[old_blocks[i].key] = i; while (i--)
old_indexes[old_blocks[i].key] = i;
const new_blocks = []; const new_blocks = [];
const new_lookup = new Map(); const new_lookup = new Map();
const deltas = new Map(); const deltas = new Map();
const updates = []; const updates = [];
i = n; i = n;
while (i--) { while (i--) {
const child_ctx = get_context(ctx, list, i); const child_ctx = get_context(ctx, list, i);
const key = get_key(child_ctx); const key = get_key(child_ctx);
let block = lookup.get(key); let block = lookup.get(key);
if (!block) { if (!block) {
block = create_each_block(key, child_ctx); block = create_each_block(key, child_ctx);
block.c(); block.c();
} else if (dynamic) { }
else if (dynamic) {
// defer updates until all the DOM shuffling is done // defer updates until all the DOM shuffling is done
updates.push(() => block.p(child_ctx, dirty)); updates.push(() => block.p(child_ctx, dirty));
} }
new_lookup.set(key, (new_blocks[i] = block)); new_lookup.set(key, (new_blocks[i] = block));
if (key in old_indexes)
if (key in old_indexes) deltas.set(key, Math.abs(i - old_indexes[key])); deltas.set(key, Math.abs(i - old_indexes[key]));
} }
const will_move = new Set(); const will_move = new Set();
const did_move = new Set(); const did_move = new Set();
/** @returns {void} */
function insert(block) { function insert(block) {
transition_in(block, 1); transition_in(block, 1);
block.m(node, next); block.m(node, next);
@ -77,47 +60,48 @@ export function update_keyed_each(
next = block.first; next = block.first;
n--; n--;
} }
while (o && n) { while (o && n) {
const new_block = new_blocks[n - 1]; const new_block = new_blocks[n - 1];
const old_block = old_blocks[o - 1]; const old_block = old_blocks[o - 1];
const new_key = new_block.key; const new_key = new_block.key;
const old_key = old_block.key; const old_key = old_block.key;
if (new_block === old_block) { if (new_block === old_block) {
// do nothing // do nothing
next = new_block.first; next = new_block.first;
o--; o--;
n--; n--;
} else if (!new_lookup.has(old_key)) { }
else if (!new_lookup.has(old_key)) {
// remove old block // remove old block
destroy(old_block, lookup); destroy(old_block, lookup);
o--; o--;
} else if (!lookup.has(new_key) || will_move.has(new_key)) { }
else if (!lookup.has(new_key) || will_move.has(new_key)) {
insert(new_block); insert(new_block);
} else if (did_move.has(old_key)) { }
else if (did_move.has(old_key)) {
o--; o--;
} else if (deltas.get(new_key) > deltas.get(old_key)) { }
else if (deltas.get(new_key) > deltas.get(old_key)) {
did_move.add(new_key); did_move.add(new_key);
insert(new_block); insert(new_block);
} else { }
else {
will_move.add(old_key); will_move.add(old_key);
o--; o--;
} }
} }
while (o--) { while (o--) {
const old_block = old_blocks[o]; const old_block = old_blocks[o];
if (!new_lookup.has(old_block.key)) destroy(old_block, lookup); if (!new_lookup.has(old_block.key))
destroy(old_block, lookup);
} }
while (n)
while (n) insert(new_blocks[n - 1]); insert(new_blocks[n - 1]);
run_all(updates); run_all(updates);
return new_blocks; return new_blocks;
} }
/** @returns {void} */
export function validate_each_keys(ctx, list, get_context, get_key) { export function validate_each_keys(ctx, list, get_context, get_key) {
const keys = new Map(); const keys = new Map();
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
@ -126,15 +110,16 @@ export function validate_each_keys(ctx, list, get_context, get_key) {
let value = ''; let value = '';
try { try {
value = `with value '${String(key)}' `; value = `with value '${String(key)}' `;
} catch (e) { }
catch (e) {
// can't stringify // can't stringify
} }
throw new Error( throw new Error(`Cannot have duplicate keys in a keyed each: Keys at index ${keys.get(key)} and ${i} ${value}are duplicates`);
`Cannot have duplicate keys in a keyed each: Keys at index ${keys.get(
key
)} and ${i} ${value}are duplicates`
);
} }
keys.set(key, i); keys.set(key, i);
} }
} }

Loading…
Cancel
Save