diff --git a/src/compile/render-dom/Block.ts b/src/compile/render-dom/Block.ts index 012fd30015..f976f2cf29 100644 --- a/src/compile/render-dom/Block.ts +++ b/src/compile/render-dom/Block.ts @@ -220,10 +220,9 @@ export default class Block { if (this.hasIntroMethod || this.hasOutroMethod) { this.addVariable('#current'); - this.addVariable('#mounted'); if (!this.builders.mount.isEmpty()) { - this.builders.mount.addLine(`#current = #mounted = true;`); + this.builders.mount.addLine(`#current = true;`); } if (!this.builders.outro.isEmpty()) { @@ -348,13 +347,12 @@ export default class Block { } if (this.hasIntroMethod || this.hasOutroMethod) { - if (this.builders.mount.isEmpty()) { + if (this.builders.intro.isEmpty()) { properties.addLine(`i: @noop,`); } else { properties.addBlock(deindent` - ${dev ? 'i: function intro' : 'i'}(#target, anchor) { + ${dev ? 'i: function intro' : 'i'}() { ${this.builders.intro} - if (!#mounted) this.m(#target, anchor); }, `); } diff --git a/src/compile/render-dom/wrappers/AwaitBlock.ts b/src/compile/render-dom/wrappers/AwaitBlock.ts index 3d0c0be7a2..b987dd7fa9 100644 --- a/src/compile/render-dom/wrappers/AwaitBlock.ts +++ b/src/compile/render-dom/wrappers/AwaitBlock.ts @@ -172,11 +172,15 @@ export default class AwaitBlockWrapper extends Wrapper { const hasTransitions = this.pending.block.hasIntroMethod || this.pending.block.hasOutroMethod; block.builders.mount.addBlock(deindent` - ${info}.block.${hasTransitions ? 'i' : 'm'}(${initialMountNode}, ${info}.anchor = ${anchorNode}); + ${info}.block.m(${initialMountNode}, ${info}.anchor = ${anchorNode}); ${info}.mount = () => ${updateMountNode}; ${info}.anchor = ${anchor}; `); + if (hasTransitions) { + block.builders.intro.addLine(`${info}.block.i();`); + } + const conditions = []; if (this.node.expression.dependencies.size > 0) { conditions.push( diff --git a/src/compile/render-dom/wrappers/EachBlock.ts b/src/compile/render-dom/wrappers/EachBlock.ts index fe248696d0..ba266bd36c 100644 --- a/src/compile/render-dom/wrappers/EachBlock.ts +++ b/src/compile/render-dom/wrappers/EachBlock.ts @@ -60,7 +60,6 @@ export default class EachBlockWrapper extends Wrapper { get_each_context: string; iterations: string; length: string; - mountOrIntro: string; } contextProps: string[]; @@ -102,7 +101,6 @@ export default class EachBlockWrapper extends Wrapper { let c = this.node.start + 2; while (renderer.component.source[c] !== 'e') c += 1; renderer.component.code.overwrite(c, c + 4, 'length'); - const length = `[✂${c}-${c+4}✂]`; this.vars = { create_each_block: this.block.name, @@ -112,8 +110,7 @@ export default class EachBlockWrapper extends Wrapper { length: `[✂${c}-${c+4}✂]`, // filled out later - anchor: null, - mountOrIntro: null + anchor: null }; node.contexts.forEach(prop => { @@ -173,8 +170,6 @@ export default class EachBlockWrapper extends Wrapper { ? block.getUniqueName(`${this.var}_anchor`) : (this.next && this.next.var) || 'null'; - this.vars.mountOrIntro = (this.block.hasIntroMethod || this.block.hasOutroMethod) ? 'i' : 'm'; - this.contextProps = this.node.contexts.map(prop => `child_ctx.${prop.key.name} = list[i]${prop.tail};`); if (this.hasBinding) this.contextProps.push(`child_ctx.${this.vars.each_block_value} = list;`); @@ -198,6 +193,12 @@ export default class EachBlockWrapper extends Wrapper { this.renderUnkeyed(block, parentNode, parentNodes, snippet); } + if (this.block.hasIntroMethod || this.block.hasOutroMethod) { + block.builders.intro.addBlock(deindent` + for (var #i = 0; #i < ${this.vars.each_block_value}.${this.vars.length}; #i += 1) ${this.vars.iterations}[#i].i(); + `); + } + if (needsAnchor) { block.addElement( this.vars.anchor, @@ -209,7 +210,6 @@ export default class EachBlockWrapper extends Wrapper { if (this.else) { const each_block_else = component.getUniqueName(`${this.var}_else`); - const mountOrIntro = (this.else.block.hasIntroMethod || this.else.block.hasOutroMethod) ? 'i' : 'm'; block.builders.init.addLine(`var ${each_block_else} = null;`); @@ -223,7 +223,7 @@ export default class EachBlockWrapper extends Wrapper { block.builders.mount.addBlock(deindent` if (${each_block_else}) { - ${each_block_else}.${mountOrIntro}(${parentNode || '#target'}, null); + ${each_block_else}.m(${parentNode || '#target'}, null); } `); @@ -236,7 +236,7 @@ export default class EachBlockWrapper extends Wrapper { } else if (!${this.vars.each_block_value}.${this.vars.length}) { ${each_block_else} = ${this.else.block.name}($$, ctx); ${each_block_else}.c(); - ${each_block_else}.${mountOrIntro}(${initialMountNode}, ${this.vars.anchor}); + ${each_block_else}.m(${initialMountNode}, ${this.vars.anchor}); } else if (${each_block_else}) { ${each_block_else}.d(1); ${each_block_else} = null; @@ -252,7 +252,7 @@ export default class EachBlockWrapper extends Wrapper { } else if (!${each_block_else}) { ${each_block_else} = ${this.else.block.name}($$, ctx); ${each_block_else}.c(); - ${each_block_else}.${mountOrIntro}(${initialMountNode}, ${this.vars.anchor}); + ${each_block_else}.m(${initialMountNode}, ${this.vars.anchor}); } `); } @@ -279,14 +279,13 @@ export default class EachBlockWrapper extends Wrapper { create_each_block, length, anchor, - mountOrIntro, + iterations } = this.vars; const get_key = block.getUniqueName('get_key'); - const blocks = block.getUniqueName(`${this.var}_blocks`); const lookup = block.getUniqueName(`${this.var}_lookup`); - block.addVariable(blocks, '[]'); + block.addVariable(iterations, '[]'); block.addVariable(lookup, `@blankObject()`); if (this.fragment.nodes[0].isDomNode()) { @@ -307,7 +306,7 @@ export default class EachBlockWrapper extends Wrapper { for (var #i = 0; #i < ${this.vars.each_block_value}.${length}; #i += 1) { let child_ctx = ${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i); let key = ${get_key}(child_ctx); - ${blocks}[#i] = ${lookup}[key] = ${create_each_block}($$, key, child_ctx); + ${iterations}[#i] = ${lookup}[key] = ${create_each_block}($$, key, child_ctx); } `); @@ -316,17 +315,17 @@ export default class EachBlockWrapper extends Wrapper { const anchorNode = parentNode ? 'null' : 'anchor'; block.builders.create.addBlock(deindent` - for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].c(); + for (#i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].c(); `); if (parentNodes && this.renderer.options.hydratable) { block.builders.claim.addBlock(deindent` - for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].l(${parentNodes}); + for (#i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].l(${parentNodes}); `); } block.builders.mount.addBlock(deindent` - for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode}); + for (#i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].m(${initialMountNode}, ${anchorNode}); `); const dynamic = this.block.hasUpdateMethod; @@ -342,21 +341,20 @@ export default class EachBlockWrapper extends Wrapper { const ${this.vars.each_block_value} = ${snippet}; ${this.block.hasOutros && `@group_outros();`} - ${this.node.hasAnimation && `for (let #i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].r();`} - ${blocks} = @updateKeyedEach(${blocks}, $$, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.vars.each_block_value}, ${lookup}, ${updateMountNode}, ${destroy}, ${create_each_block}, "${mountOrIntro}", ${anchor}, ${this.vars.get_each_context}); - ${this.node.hasAnimation && `for (let #i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].a();`} + ${this.node.hasAnimation && `for (let #i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].r();`} + ${iterations} = @updateKeyedEach(${iterations}, $$, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.vars.each_block_value}, ${lookup}, ${updateMountNode}, ${destroy}, ${create_each_block}, ${anchor}, ${this.vars.get_each_context}); + ${this.node.hasAnimation && `for (let #i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].a();`} ${this.block.hasOutros && `@check_outros();`} `); if (this.block.hasOutros) { - const countdown = block.getUniqueName('countdown'); block.builders.outro.addBlock(deindent` - for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].o(); + for (#i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].o(); `); } block.builders.destroy.addBlock(deindent` - for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].d(${parentNode ? '' : 'detach'}); + for (#i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].d(${parentNode ? '' : 'detach'}); `); } @@ -370,8 +368,7 @@ export default class EachBlockWrapper extends Wrapper { create_each_block, length, iterations, - anchor, - mountOrIntro, + anchor } = this.vars; block.builders.init.addBlock(deindent` @@ -402,7 +399,7 @@ export default class EachBlockWrapper extends Wrapper { block.builders.mount.addBlock(deindent` for (var #i = 0; #i < ${iterations}.length; #i += 1) { - ${iterations}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode}); + ${iterations}[#i].m(${initialMountNode}, ${anchorNode}); } `); @@ -434,31 +431,25 @@ export default class EachBlockWrapper extends Wrapper { .map(dependency => `changed.${dependency}`) .join(' || '); + const has_transitions = !!(this.block.hasIntroMethod || this.block.hasOutroMethod); + if (condition !== '') { const forLoopBody = this.block.hasUpdateMethod - ? (this.block.hasIntros || this.block.hasOutros) - ? deindent` - if (${iterations}[#i]) { - ${iterations}[#i].p(changed, child_ctx); - } else { - ${iterations}[#i] = ${create_each_block}($$, child_ctx); - ${iterations}[#i].c(); - } - ${iterations}[#i].i(${updateMountNode}, ${anchor}); - ` - : deindent` - if (${iterations}[#i]) { - ${iterations}[#i].p(changed, child_ctx); - } else { - ${iterations}[#i] = ${create_each_block}($$, child_ctx); - ${iterations}[#i].c(); - ${iterations}[#i].m(${updateMountNode}, ${anchor}); - } - ` + ? deindent` + if (${iterations}[#i]) { + ${iterations}[#i].p(changed, child_ctx); + } else { + ${iterations}[#i] = ${create_each_block}($$, child_ctx); + ${iterations}[#i].c(); + ${iterations}[#i].m(${updateMountNode}, ${anchor}); + ${has_transitions && `${iterations}[#i].i();`} + } + ` : deindent` ${iterations}[#i] = ${create_each_block}($$, child_ctx); ${iterations}[#i].c(); - ${iterations}[#i].${mountOrIntro}(${updateMountNode}, ${anchor}); + ${iterations}[#i].m(${updateMountNode}, ${anchor}); + ${has_transitions && `${iterations}[#i].i();`} `; const start = this.block.hasUpdateMethod ? '0' : `${iterations}.length`; @@ -500,7 +491,6 @@ export default class EachBlockWrapper extends Wrapper { } if (outroBlock) { - const countdown = block.getUniqueName('countdown'); block.builders.outro.addBlock(deindent` ${iterations} = ${iterations}.filter(Boolean); for (let #i = 0; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 0);` diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts index 31c8b1ca49..615297123f 100644 --- a/src/compile/render-dom/wrappers/Element/index.ts +++ b/src/compile/render-dom/wrappers/Element/index.ts @@ -592,7 +592,7 @@ export default class ElementWrapper extends Wrapper { const fn = component.qualify(intro.name); - block.builders.intro.addConditional(`@intros.enabled`, deindent` + block.builders.intro.addBlock(deindent` @add_render_callback(() => { if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true); ${name}.run(1); @@ -620,14 +620,14 @@ export default class ElementWrapper extends Wrapper { const fn = component.qualify(intro.name); if (outro) { - block.builders.intro.addConditional(`@intros.enabled`, deindent` + block.builders.intro.addBlock(deindent` @add_render_callback(() => { if (${introName}) ${introName}.end(); ${introName} = @create_in_transition(${this.var}, ${fn}, ${snippet}); }); `); } else { - block.builders.intro.addConditional(`@intros.enabled`, deindent` + block.builders.intro.addBlock(deindent` if (!${introName}) { @add_render_callback(() => { ${introName} = @create_in_transition(${this.var}, ${fn}, ${snippet}); diff --git a/src/compile/render-dom/wrappers/IfBlock.ts b/src/compile/render-dom/wrappers/IfBlock.ts index a50b905a3c..bf4f2a7a44 100644 --- a/src/compile/render-dom/wrappers/IfBlock.ts +++ b/src/compile/render-dom/wrappers/IfBlock.ts @@ -219,12 +219,10 @@ export default class IfBlockWrapper extends Wrapper { var ${name} = ${current_block_type_and}${current_block_type}($$, ctx); `); - const mountOrIntro = this.branches[0].block.hasIntroMethod ? 'i' : 'm'; - const initialMountNode = parentNode || '#target'; const anchorNode = parentNode ? 'null' : 'anchor'; block.builders.mount.addLine( - `${if_name}${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});` + `${if_name}${name}.m(${initialMountNode}, ${anchorNode});` ); const updateMountNode = this.getUpdateMountNode(anchor); @@ -233,7 +231,7 @@ export default class IfBlockWrapper extends Wrapper { ${if_name}${name}.d(1); ${name} = ${current_block_type_and}${current_block_type}($$, ctx); ${if_name}${name}.c(); - ${if_name}${name}.${mountOrIntro}(${updateMountNode}, ${anchor}); + ${if_name}${name}.m(${updateMountNode}, ${anchor}); `; if (dynamic) { @@ -305,12 +303,11 @@ export default class IfBlockWrapper extends Wrapper { `); } - const mountOrIntro = this.branches[0].block.hasIntroMethod ? 'i' : 'm'; const initialMountNode = parentNode || '#target'; const anchorNode = parentNode ? 'null' : 'anchor'; block.builders.mount.addLine( - `${if_current_block_type_index}${if_blocks}[${current_block_type_index}].${mountOrIntro}(${initialMountNode}, ${anchorNode});` + `${if_current_block_type_index}${if_blocks}[${current_block_type_index}].m(${initialMountNode}, ${anchorNode});` ); const updateMountNode = this.getUpdateMountNode(anchor); @@ -331,7 +328,7 @@ export default class IfBlockWrapper extends Wrapper { ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}]($$, ctx); ${name}.c(); } - ${name}.${mountOrIntro}(${updateMountNode}, ${anchor}); + ${name}.m(${updateMountNode}, ${anchor}); `; const changeBlock = hasElse @@ -390,52 +387,35 @@ export default class IfBlockWrapper extends Wrapper { var ${name} = (${branch.condition}) && ${branch.block.name}($$, ctx); `); - const mountOrIntro = branch.block.hasIntroMethod ? 'i' : 'm'; const initialMountNode = parentNode || '#target'; const anchorNode = parentNode ? 'null' : 'anchor'; block.builders.mount.addLine( - `if (${name}) ${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});` + `if (${name}) ${name}.m(${initialMountNode}, ${anchorNode});` ); const updateMountNode = this.getUpdateMountNode(anchor); + const has_transitions = !!(branch.block.hasIntroMethod || branch.block.hasOutroMethod); const enter = dynamic - ? (branch.block.hasIntroMethod || branch.block.hasOutroMethod) - ? deindent` - if (${name}) { - ${name}.p(changed, ctx); - } else { - ${name} = ${branch.block.name}($$, ctx); - if (${name}) ${name}.c(); - } - - ${name}.i(${updateMountNode}, ${anchor}); - ` - : deindent` - if (${name}) { - ${name}.p(changed, ctx); - } else { - ${name} = ${branch.block.name}($$, ctx); - ${name}.c(); - ${name}.m(${updateMountNode}, ${anchor}); - } - ` - : (branch.block.hasIntroMethod || branch.block.hasOutroMethod) - ? deindent` - if (!${name}) { - ${name} = ${branch.block.name}($$, ctx); - ${name}.c(); - } - ${name}.i(${updateMountNode}, ${anchor}); - ` - : deindent` - if (!${name}) { - ${name} = ${branch.block.name}($$, ctx); - ${name}.c(); - ${name}.m(${updateMountNode}, ${anchor}); - } - `; + ? deindent` + if (${name}) { + ${name}.p(changed, ctx); + } else { + ${name} = ${branch.block.name}($$, ctx); + ${name}.c(); + ${name}.m(${updateMountNode}, ${anchor}); + } + ${has_transitions && `${name}.i();`} + ` + : deindent` + if (!${name}) { + ${name} = ${branch.block.name}($$, ctx); + ${name}.c(); + ${name}.m(${updateMountNode}, ${anchor}); + } + ${has_transitions && `${name}.i();`} + `; // no `p()` here — we don't want to update outroing nodes, // as that will typically result in glitching @@ -455,6 +435,10 @@ export default class IfBlockWrapper extends Wrapper { ${name} = null; `; + if (has_transitions) { + block.builders.intro.addLine(`if (${name}) ${name}.i();`); + } + block.builders.update.addBlock(deindent` if (${branch.condition}) { ${enter} diff --git a/src/compile/render-dom/wrappers/InlineComponent/index.ts b/src/compile/render-dom/wrappers/InlineComponent/index.ts index 254e8b592c..435f03e3b4 100644 --- a/src/compile/render-dom/wrappers/InlineComponent/index.ts +++ b/src/compile/render-dom/wrappers/InlineComponent/index.ts @@ -380,6 +380,7 @@ export default class InlineComponentWrapper extends Wrapper { ${this.fragment && this.fragment.nodes.map(child => child.remount(name))} ${name}.$$.fragment.c(); @mount_component(${name}, ${updateMountNode}, ${anchor}); + ${name}.$$.fragment.i(); ${this.node.handlers.map(handler => deindent` ${name}.$on("${handler.name}", ${handler.var}); @@ -390,6 +391,10 @@ export default class InlineComponentWrapper extends Wrapper { } `); + block.builders.intro.addBlock(deindent` + if (${name}) ${name}.$$.fragment.i(); + `); + if (updates.length) { block.builders.update.addBlock(deindent` else if (${switch_value}) { @@ -428,6 +433,10 @@ export default class InlineComponentWrapper extends Wrapper { `@mount_component(${name}, ${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'});` ); + block.builders.intro.addBlock(deindent` + ${name}.$$.fragment.i(); + `); + if (updates.length) { block.builders.update.addBlock(deindent` ${updates} diff --git a/src/internal/Component.js b/src/internal/Component.js index a1607f0b30..8df1d7aee5 100644 --- a/src/internal/Component.js +++ b/src/internal/Component.js @@ -12,7 +12,7 @@ export function bind(component, name, callback) { export function mount_component(component, target, anchor) { const { fragment, on_mount, on_destroy, after_render } = component.$$; - fragment[fragment.i ? 'i' : 'm'](target, anchor); + fragment.m(target, anchor); // onMount happens after the initial afterUpdate. Because // afterUpdate callbacks happen in reverse order (inner first) @@ -101,8 +101,6 @@ export function init(component, options, instance, create_fragment, not_equal) { $$.fragment = create_fragment($$, $$.ctx); if (options.target) { - intros.enabled = !!options.intro; - if (options.hydrate) { $$.fragment.l(children(options.target)); } else { @@ -110,8 +108,8 @@ export function init(component, options, instance, create_fragment, not_equal) { } mount_component(component, options.target, options.anchor); + if (options.intro && component.$$.fragment.i) component.$$.fragment.i(); flush(); - intros.enabled = true; } set_current_component(previous_component); diff --git a/src/internal/await-block.js b/src/internal/await-block.js index 9f49c13e55..3d8be35edc 100644 --- a/src/internal/await-block.js +++ b/src/internal/await-block.js @@ -29,7 +29,8 @@ export function handlePromise(promise, info) { } block.c(); - block[block.i ? 'i' : 'm'](info.mount(), info.anchor); + block.m(info.mount(), info.anchor); + if (block.i) block.i(); flush(); } diff --git a/src/internal/keyed-each.js b/src/internal/keyed-each.js index 8429e2961d..ad5eb243d2 100644 --- a/src/internal/keyed-each.js +++ b/src/internal/keyed-each.js @@ -18,7 +18,7 @@ export function fixAndOutroAndDestroyBlock(block, lookup) { outroAndDestroyBlock(block, lookup); } -export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, intro_method, next, get_context) { +export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) { var o = old_blocks.length; var n = list.length; @@ -52,7 +52,8 @@ export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic var did_move = {}; function insert(block) { - block[intro_method](node, next); + block.m(node, next); + if (block.i) block.i(); lookup[block.key] = block; next = block.first; n--; diff --git a/test/runtime/samples/transition-js-aborted-outro-in-each/_config.js b/test/runtime/samples/transition-js-aborted-outro-in-each/_config.js index 75242d21af..e78862e86c 100644 --- a/test/runtime/samples/transition-js-aborted-outro-in-each/_config.js +++ b/test/runtime/samples/transition-js-aborted-outro-in-each/_config.js @@ -7,7 +7,7 @@ export default { ] }, - test({ assert, component, target, window, raf }) { + test({ assert, component, target, raf }) { const { things } = component; component.things = []; diff --git a/test/runtime/samples/transition-js-await-block/_config.js b/test/runtime/samples/transition-js-await-block/_config.js index 5cddc8a95c..2e01dd7f76 100644 --- a/test/runtime/samples/transition-js-await-block/_config.js +++ b/test/runtime/samples/transition-js-await-block/_config.js @@ -13,7 +13,7 @@ export default { intro: true, - test({ assert, component, target, window, raf }) { + test({ assert, target, raf }) { let p = target.querySelector('p'); assert.equal(p.className, 'pending'); diff --git a/test/runtime/samples/transition-js-if-block-in-each-block-bidi-3/_config.js b/test/runtime/samples/transition-js-if-block-in-each-block-bidi-3/_config.js index 261731c700..04df38a09c 100644 --- a/test/runtime/samples/transition-js-if-block-in-each-block-bidi-3/_config.js +++ b/test/runtime/samples/transition-js-if-block-in-each-block-bidi-3/_config.js @@ -12,9 +12,7 @@ export default {