diff --git a/src/compile/nodes/AwaitBlock.ts b/src/compile/nodes/AwaitBlock.ts index 882a27885f..4897adcd59 100644 --- a/src/compile/nodes/AwaitBlock.ts +++ b/src/compile/nodes/AwaitBlock.ts @@ -172,12 +172,13 @@ export default class AwaitBlock extends Node { } if (this.pending.block.hasOutroMethod && this.compiler.options.nestedTransitions) { + const countdown = block.getUniqueName('countdown'); block.builders.outro.addBlock(deindent` - #outrocallback = @callAfter(#outrocallback, 3); + const ${countdown} = @callAfter(#outrocallback, 3); for (let #i = 0; #i < 3; #i += 1) { const block = ${info}.blocks[#i]; - if (block) block.o(#outrocallback); - else #outrocallback(); + if (block) block.o(${countdown}); + else ${countdown}(); } `); } diff --git a/src/compile/nodes/EachBlock.ts b/src/compile/nodes/EachBlock.ts index 89953ca19a..adf23d85c9 100644 --- a/src/compile/nodes/EachBlock.ts +++ b/src/compile/nodes/EachBlock.ts @@ -331,9 +331,10 @@ export default class EachBlock extends Node { `); if (this.compiler.options.nestedTransitions) { + const countdown = block.getUniqueName('countdown'); block.builders.outro.addBlock(deindent` - #outrocallback = @callAfter(#outrocallback, ${blocks}.length); - for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].o(#outrocallback); + const ${countdown} = @callAfter(#outrocallback, ${blocks}.length); + for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].o(${countdown}); `); } @@ -476,9 +477,10 @@ export default class EachBlock extends Node { } if (outroBlock && this.compiler.options.nestedTransitions) { + const countdown = block.getUniqueName('countdown'); block.builders.outro.addBlock(deindent` - #outrocallback = @callAfter(#outrocallback, #i); - for (let #i = 0; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 0, #outrocallback);` + const ${countdown} = @callAfter(#outrocallback, ${iterations}.length); + for (let #i = 0; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 0, ${countdown});` ); } diff --git a/src/compile/nodes/IfBlock.ts b/src/compile/nodes/IfBlock.ts index 3ecab77f43..ee5cb41a83 100644 --- a/src/compile/nodes/IfBlock.ts +++ b/src/compile/nodes/IfBlock.ts @@ -147,9 +147,10 @@ export default class IfBlock extends Node { this.buildSimple(block, parentNode, parentNodes, branches[0], dynamic, vars); if (hasOutros && this.compiler.options.nestedTransitions) { - block.builders.outro.addLine( - `if (${name}) ${name}.o(#outrocallback);` - ); + block.builders.outro.addBlock(deindent` + if (${name}) ${name}.o(#outrocallback); + else #outrocallback(); + `); } } diff --git a/test/runtime/samples/nested-transition-detach-each/_config.js b/test/runtime/samples/nested-transition-detach-each/_config.js new file mode 100644 index 0000000000..523be65e97 --- /dev/null +++ b/test/runtime/samples/nested-transition-detach-each/_config.js @@ -0,0 +1,41 @@ +export default { + data: { + visible: false, + rows: [1, 2, 3], + cols: ['a', 'b', 'c'] + }, + + html: ``, + + compileOptions: { + dev: true + }, + nestedTransitions: true, + skipIntroByDefault: true, + + test(assert, component, target, window, raf) { + component.set({ visible: true }); + assert.htmlEqual(target.innerHTML, ` + <div class="row"> + <div class="cell">1, a</div> + <div class="cell">1, b</div> + <div class="cell">1, c</div> + </div> + <div class="row"> + <div class="cell">2, a</div> + <div class="cell">2, b</div> + <div class="cell">2, c</div> + </div> + <div class="row"> + <div class="cell">3, a</div> + <div class="cell">3, b</div> + <div class="cell">3, c</div> + </div> + `); + + component.set({ visible: false }); + raf.tick(0); + raf.tick(100); + assert.htmlEqual(target.innerHTML, ``); + }, +}; diff --git a/test/runtime/samples/nested-transition-detach-each/main.html b/test/runtime/samples/nested-transition-detach-each/main.html new file mode 100644 index 0000000000..c81fc3eb78 --- /dev/null +++ b/test/runtime/samples/nested-transition-detach-each/main.html @@ -0,0 +1,22 @@ +{#if visible} + {#each rows as row} + <div out:foo class="row"> + {#each cols as col} + <div out:foo class="cell">{row}, {col}</div> + {/each} + </div> + {/each} +{/if} + +<script> + export default { + transitions: { + foo(node) { + return { + duration: 100, + tick: t => node.foo = t + }; + } + } + }; +</script> \ No newline at end of file diff --git a/test/runtime/samples/nested-transition-detach-if-false/Folder.html b/test/runtime/samples/nested-transition-detach-if-false/Folder.html new file mode 100644 index 0000000000..cd3448a3f2 --- /dev/null +++ b/test/runtime/samples/nested-transition-detach-if-false/Folder.html @@ -0,0 +1,44 @@ +<li> + <span>{dir}</span> + + {#if open} + <ul> + {#each items as item (item.filename)} + {#if item.isDir} + <svelte:self dir={item.filename}/> + {:else} + <li>{item.filename}</li> + {/if} + {/each} + </ul> + {/if} +</li> + +<script> + export default { + data() { + return { + items: [], + open: true + }; + }, + + computed: { + items: ({ dir }) => { + return dir === 'a' + ? [ + { + filename: 'a/b', + isDir: true + } + ] + : [ + { + filename: 'a/b/c', + isDir: false + } + ]; + } + } + }; +</script> \ No newline at end of file diff --git a/test/runtime/samples/nested-transition-detach-if-false/_config.js b/test/runtime/samples/nested-transition-detach-if-false/_config.js new file mode 100644 index 0000000000..1e26a54787 --- /dev/null +++ b/test/runtime/samples/nested-transition-detach-if-false/_config.js @@ -0,0 +1,26 @@ +export default { + html: ` + <li> + <span>a</span> + <ul> + <li> + <span>a/b</span> + <ul> + <li>a/b/c</li> + </ul> + </li> + </ul> + </li> + `, + + nestedTransitions: true, + + test(assert, component, target, window, raf) { + component.refs.folder.set({ open: false }); + assert.htmlEqual(target.innerHTML, ` + <li> + <span>a</span> + </li> + `); + }, +}; diff --git a/test/runtime/samples/nested-transition-detach-if-false/main.html b/test/runtime/samples/nested-transition-detach-if-false/main.html new file mode 100644 index 0000000000..cf14773c9c --- /dev/null +++ b/test/runtime/samples/nested-transition-detach-if-false/main.html @@ -0,0 +1,9 @@ +<Folder ref:folder dir="a"/> + +<script> + export default { + components: { + Folder: './Folder.html' + } + }; +</script> \ No newline at end of file