Skip to content

Commit

Permalink
Merge pull request #3518 from sveltejs/gh-3505
Browse files Browse the repository at this point in the history
fix code generation for if-else with static conditions
  • Loading branch information
Rich-Harris authored Sep 8, 2019
2 parents 686aa0b + 1ef9575 commit c9cf65c
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 89 deletions.
218 changes: 129 additions & 89 deletions src/compiler/compile/render_dom/wrappers/IfBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class IfBlockBranch extends Wrapper {
export default class IfBlockWrapper extends Wrapper {
node: IfBlock;
branches: IfBlockBranch[];
needs_update = false;

var = 'if_block';

Expand Down Expand Up @@ -112,10 +113,16 @@ export default class IfBlockWrapper extends Wrapper {
block.add_dependencies(node.expression.dependencies);

if (branch.block.dependencies.size > 0) {
// the condition, or its contents, is dynamic
is_dynamic = true;
block.add_dependencies(branch.block.dependencies);
}

if (branch.dependencies && branch.dependencies.length > 0) {
// the condition itself is dynamic
this.needs_update = true;
}

if (branch.block.has_intros) has_intros = true;
if (branch.block.has_outros) has_outros = true;

Expand Down Expand Up @@ -239,15 +246,29 @@ export default class IfBlockWrapper extends Wrapper {
const current_block_type_and = has_else ? '' : `${current_block_type} && `;

/* eslint-disable @typescript-eslint/indent,indent */
block.builders.init.add_block(deindent`
function ${select_block_type}(changed, ctx) {
${this.branches.map(({ dependencies, condition, snippet, block }) => condition
? deindent`
${snippet && `if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})`}
if (${condition}) return ${block.name};`
: `return ${block.name};`)}
}
`);
if (this.needs_update) {
block.builders.init.add_block(deindent`
function ${select_block_type}(changed, ctx) {
${this.branches.map(({ dependencies, condition, snippet, block }) => condition
? deindent`
${snippet && (
dependencies.length > 0
? `if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})`
: `if (${condition} == null) ${condition} = !!(${snippet})`
)}
if (${condition}) return ${block.name};`
: `return ${block.name};`)}
}
`);
} else {
block.builders.init.add_block(deindent`
function ${select_block_type}(changed, ctx) {
${this.branches.map(({ condition, snippet, block }) => condition
? `if (${snippet || condition}) return ${block.name};`
: `return ${block.name};`)}
}
`);
}
/* eslint-enable @typescript-eslint/indent,indent */

block.builders.init.add_block(deindent`
Expand All @@ -261,32 +282,36 @@ export default class IfBlockWrapper extends Wrapper {
`${if_name}${name}.m(${initial_mount_node}, ${anchor_node});`
);

const update_mount_node = this.get_update_mount_node(anchor);
if (this.needs_update) {
const update_mount_node = this.get_update_mount_node(anchor);

const change_block = deindent`
${if_name}${name}.d(1);
${name} = ${current_block_type_and}${current_block_type}(ctx);
if (${name}) {
${name}.c();
${has_transitions && `@transition_in(${name}, 1);`}
${name}.m(${update_mount_node}, ${anchor});
}
`;

if (dynamic) {
block.builders.update.add_block(deindent`
if (${current_block_type} === (${current_block_type} = ${select_block_type}(changed, ctx)) && ${name}) {
${name}.p(changed, ctx);
} else {
${change_block}
}
`);
} else {
block.builders.update.add_block(deindent`
if (${current_block_type} !== (${current_block_type} = ${select_block_type}(changed, ctx))) {
${change_block}
const change_block = deindent`
${if_name}${name}.d(1);
${name} = ${current_block_type_and}${current_block_type}(ctx);
if (${name}) {
${name}.c();
${has_transitions && `@transition_in(${name}, 1);`}
${name}.m(${update_mount_node}, ${anchor});
}
`);
`;

if (dynamic) {
block.builders.update.add_block(deindent`
if (${current_block_type} === (${current_block_type} = ${select_block_type}(changed, ctx)) && ${name}) {
${name}.p(changed, ctx);
} else {
${change_block}
}
`);
} else {
block.builders.update.add_block(deindent`
if (${current_block_type} !== (${current_block_type} = ${select_block_type}(changed, ctx))) {
${change_block}
}
`);
}
} else if (dynamic) {
block.builders.update.add_line(`${name}.p(changed, ctx);`);
}

block.builders.destroy.add_line(`${if_name}${name}.d(${detaching});`);
Expand Down Expand Up @@ -323,14 +348,25 @@ export default class IfBlockWrapper extends Wrapper {
var ${if_blocks} = [];
function ${select_block_type}(changed, ctx) {
${this.branches.map(({ dependencies, condition, snippet }, i) => condition
${this.needs_update
? deindent`
${snippet && `if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})`}
if (${condition}) return ${String(i)};`
: `return ${i};`)}
${!has_else && `return -1;`}
}
function ${select_block_type}(changed, ctx) {
${this.branches.map(({ dependencies, condition, snippet }, i) => condition
? deindent`
${snippet && `if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})`}
if (${condition}) return ${String(i)};`
: `return ${i};`)}
${!has_else && `return -1;`}
}
`
: deindent`
function ${select_block_type}(changed, ctx) {
${this.branches.map(({ condition, snippet }, i) => condition
? `if (${snippet || condition}) return ${String(i)};`
: `return ${i};`)}
${!has_else && `return -1;`}
}
`}
`);
/* eslint-enable @typescript-eslint/indent,indent */

Expand All @@ -354,62 +390,66 @@ export default class IfBlockWrapper extends Wrapper {
`${if_current_block_type_index}${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`
);

const update_mount_node = this.get_update_mount_node(anchor);

const destroy_old_block = deindent`
@group_outros();
@transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
${if_blocks}[${previous_block_index}] = null;
});
@check_outros();
`;
if (this.needs_update) {
const update_mount_node = this.get_update_mount_node(anchor);

const create_new_block = deindent`
${name} = ${if_blocks}[${current_block_type_index}];
if (!${name}) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](ctx);
${name}.c();
}
${has_transitions && `@transition_in(${name}, 1);`}
${name}.m(${update_mount_node}, ${anchor});
`;
const destroy_old_block = deindent`
@group_outros();
@transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
${if_blocks}[${previous_block_index}] = null;
});
@check_outros();
`;

const change_block = has_else
? deindent`
${destroy_old_block}
const create_new_block = deindent`
${name} = ${if_blocks}[${current_block_type_index}];
if (!${name}) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](ctx);
${name}.c();
}
${has_transitions && `@transition_in(${name}, 1);`}
${name}.m(${update_mount_node}, ${anchor});
`;

${create_new_block}
`
: deindent`
if (${name}) {
const change_block = has_else
? deindent`
${destroy_old_block}
}
if (~${current_block_type_index}) {
${create_new_block}
} else {
${name} = null;
}
`;
`
: deindent`
if (${name}) {
${destroy_old_block}
}
if (dynamic) {
block.builders.update.add_block(deindent`
var ${previous_block_index} = ${current_block_type_index};
${current_block_type_index} = ${select_block_type}(changed, ctx);
if (${current_block_type_index} === ${previous_block_index}) {
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].p(changed, ctx);
} else {
${change_block}
}
`);
} else {
block.builders.update.add_block(deindent`
var ${previous_block_index} = ${current_block_type_index};
${current_block_type_index} = ${select_block_type}(changed, ctx);
if (${current_block_type_index} !== ${previous_block_index}) {
${change_block}
}
`);
if (~${current_block_type_index}) {
${create_new_block}
} else {
${name} = null;
}
`;

if (dynamic) {
block.builders.update.add_block(deindent`
var ${previous_block_index} = ${current_block_type_index};
${current_block_type_index} = ${select_block_type}(changed, ctx);
if (${current_block_type_index} === ${previous_block_index}) {
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].p(changed, ctx);
} else {
${change_block}
}
`);
} else {
block.builders.update.add_block(deindent`
var ${previous_block_index} = ${current_block_type_index};
${current_block_type_index} = ${select_block_type}(changed, ctx);
if (${current_block_type_index} !== ${previous_block_index}) {
${change_block}
}
`);
}
} else if (dynamic) {
block.builders.update.add_line(`${name}.p(changed, ctx);`);
}

block.builders.destroy.add_line(deindent`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eee
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rrr
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
html: 'eee'
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
import EEE from './EEE.svelte';
import RRR from './RRR.svelte';
</script>

{#if "Eva".startsWith('E')}
<EEE/>
{:else}
<RRR/>
{/if}
3 changes: 3 additions & 0 deletions test/runtime/samples/if-block-static-with-else/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
html: 'eee'
};
5 changes: 5 additions & 0 deletions test/runtime/samples/if-block-static-with-else/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{#if "Eva".startsWith('E')}
eee
{:else}
rrr
{/if}

0 comments on commit c9cf65c

Please sign in to comment.