Skip to content

Commit 6250046

Browse files
authoredFeb 15, 2020
perform dirty check before updating keyed each blocks (#4413)
1 parent 7fdae5f commit 6250046

File tree

7 files changed

+74
-17
lines changed

7 files changed

+74
-17
lines changed
 

‎CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
* Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680))
6+
* Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373))
67

78
## 3.18.2
89

‎src/compiler/compile/render_dom/wrappers/EachBlock.ts

+18-9
Original file line numberDiff line numberDiff line change
@@ -412,16 +412,25 @@ export default class EachBlockWrapper extends Wrapper {
412412
? `@outro_and_destroy_block`
413413
: `@destroy_block`;
414414

415-
block.chunks.update.push(b`
416-
const ${this.vars.each_block_value} = ${snippet};
415+
const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
416+
this.node.expression.dynamic_dependencies().forEach((dependency: string) => {
417+
all_dependencies.add(dependency);
418+
});
417419

418-
${this.block.has_outros && b`@group_outros();`}
419-
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
420-
${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
421-
${iterations} = @update_keyed_each(${iterations}, #dirty, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context});
422-
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
423-
${this.block.has_outros && b`@check_outros();`}
424-
`);
420+
if (all_dependencies.size) {
421+
block.chunks.update.push(b`
422+
if (${block.renderer.dirty(Array.from(all_dependencies))}) {
423+
const ${this.vars.each_block_value} = ${snippet};
424+
425+
${this.block.has_outros && b`@group_outros();`}
426+
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`}
427+
${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
428+
${iterations} = @update_keyed_each(${iterations}, #dirty, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context});
429+
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
430+
${this.block.has_outros && b`@check_outros();`}
431+
}
432+
`);
433+
}
425434

426435
if (this.block.has_outros) {
427436
block.chunks.outro.push(b`

‎test/js/samples/each-block-keyed-animated/expected.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,12 @@ function create_fragment(ctx) {
9292
insert(target, each_1_anchor, anchor);
9393
},
9494
p(ctx, [dirty]) {
95-
const each_value = /*things*/ ctx[0];
96-
for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].r();
97-
each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, fix_and_destroy_block, create_each_block, each_1_anchor, get_each_context);
98-
for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].a();
95+
if (dirty & /*things*/ 1) {
96+
const each_value = /*things*/ ctx[0];
97+
for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].r();
98+
each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, fix_and_destroy_block, create_each_block, each_1_anchor, get_each_context);
99+
for (let i = 0; i < each_blocks.length; i += 1) each_blocks[i].a();
100+
}
99101
},
100102
i: noop,
101103
o: noop,

‎test/js/samples/each-block-keyed/expected.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,10 @@ function create_fragment(ctx) {
7777
insert(target, each_1_anchor, anchor);
7878
},
7979
p(ctx, [dirty]) {
80-
const each_value = /*things*/ ctx[0];
81-
each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, destroy_block, create_each_block, each_1_anchor, get_each_context);
80+
if (dirty & /*things*/ 1) {
81+
const each_value = /*things*/ ctx[0];
82+
each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each_1_lookup, each_1_anchor.parentNode, destroy_block, create_each_block, each_1_anchor, get_each_context);
83+
}
8284
},
8385
i: noop,
8486
o: noop,

‎test/runtime/samples/component-binding-blowback-c/main.svelte

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
export let count;
55
export let idToValue = Object.create(null);
66
7-
function ids() {
7+
function ids(count) {
88
return new Array(count)
99
.fill(null)
1010
.map((_, i) => ({ id: 'id-' + i}))
@@ -15,7 +15,7 @@
1515
<input type='number' bind:value={count}>
1616

1717
<ol>
18-
{#each ids() as object (object.id)}
18+
{#each ids(count) as object (object.id)}
1919
<Nested bind:value={idToValue[object.id]} id={object.id}>
2020
{object.id}: value is {idToValue[object.id]}
2121
</Nested>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export default {
2+
html: `
3+
<button>Click Me</button>
4+
0
5+
<ul></ul>
6+
`,
7+
8+
async test({ assert, component, target, window }) {
9+
const button = target.querySelector("button");
10+
11+
const event = new window.MouseEvent("click");
12+
await button.dispatchEvent(event);
13+
14+
assert.htmlEqual(
15+
target.innerHTML,
16+
`
17+
<button>Click Me</button>
18+
1
19+
<ul></ul>
20+
`
21+
);
22+
}
23+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<script>
2+
let num = 0;
3+
let cards = [];
4+
5+
function click() {
6+
// updating cards via push should have no effect to the ul,
7+
// since its being mutated instead of reassigned
8+
cards.push(num++);
9+
}
10+
</script>
11+
<button on:click={click}>
12+
Click Me
13+
</button>
14+
15+
{num}
16+
<ul>
17+
{#each cards as c, i (i)}
18+
<li>{c}</li>
19+
{/each}
20+
</ul>

0 commit comments

Comments
 (0)