|
|
|
@ -7,6 +7,7 @@ import create_debugging_comment from './shared/create_debugging_comment';
|
|
|
|
|
import ElseBlock from '../../nodes/ElseBlock';
|
|
|
|
|
import FragmentWrapper from './Fragment';
|
|
|
|
|
import deindent from '../../utils/deindent';
|
|
|
|
|
import { walk } from 'estree-walker';
|
|
|
|
|
|
|
|
|
|
function is_else_if(node: ElseBlock) {
|
|
|
|
|
return (
|
|
|
|
@ -17,7 +18,9 @@ function is_else_if(node: ElseBlock) {
|
|
|
|
|
class IfBlockBranch extends Wrapper {
|
|
|
|
|
block: Block;
|
|
|
|
|
fragment: FragmentWrapper;
|
|
|
|
|
condition: string;
|
|
|
|
|
dependencies?: string[];
|
|
|
|
|
condition?: string;
|
|
|
|
|
snippet?: string;
|
|
|
|
|
is_dynamic: boolean;
|
|
|
|
|
|
|
|
|
|
var = null;
|
|
|
|
@ -32,13 +35,35 @@ class IfBlockBranch extends Wrapper {
|
|
|
|
|
) {
|
|
|
|
|
super(renderer, block, parent, node);
|
|
|
|
|
|
|
|
|
|
this.condition = (node as IfBlock).expression && (node as IfBlock).expression.render(block);
|
|
|
|
|
const { expression } = (node as IfBlock);
|
|
|
|
|
const is_else = !expression;
|
|
|
|
|
|
|
|
|
|
if (expression) {
|
|
|
|
|
const dependencies = expression.dynamic_dependencies();
|
|
|
|
|
|
|
|
|
|
// TODO is this the right rule? or should any non-reference count?
|
|
|
|
|
// const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
|
|
|
|
|
let should_cache = false;
|
|
|
|
|
walk(expression.node, {
|
|
|
|
|
enter(node) {
|
|
|
|
|
if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
|
|
|
|
should_cache = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (should_cache) {
|
|
|
|
|
this.condition = block.get_unique_name(`show_if`);
|
|
|
|
|
this.snippet = expression.render(block);
|
|
|
|
|
this.dependencies = dependencies;
|
|
|
|
|
} else {
|
|
|
|
|
this.condition = expression.render(block);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.block = block.child({
|
|
|
|
|
comment: create_debugging_comment(node, parent.renderer.component),
|
|
|
|
|
name: parent.renderer.component.get_unique_name(
|
|
|
|
|
(node as IfBlock).expression ? `create_if_block` : `create_else_block`
|
|
|
|
|
)
|
|
|
|
|
name: parent.renderer.component.get_unique_name(is_else ? `create_else_block` : `create_if_block`)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);
|
|
|
|
@ -157,6 +182,10 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
const detaching = (parent_node && parent_node !== '@_document.head') ? '' : 'detaching';
|
|
|
|
|
|
|
|
|
|
if (this.node.else) {
|
|
|
|
|
this.branches.forEach(branch => {
|
|
|
|
|
if (branch.snippet) block.add_variable(branch.condition);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (has_outros) {
|
|
|
|
|
this.render_compound_with_outros(block, parent_node, parent_nodes, dynamic, vars, detaching);
|
|
|
|
|
|
|
|
|
@ -212,16 +241,18 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
|
|
|
|
|
/* eslint-disable @typescript-eslint/indent,indent */
|
|
|
|
|
block.builders.init.add_block(deindent`
|
|
|
|
|
function ${select_block_type}(ctx) {
|
|
|
|
|
${this.branches
|
|
|
|
|
.map(({ condition, block }) => `${condition ? `if (${condition}) ` : ''}return ${block.name};`)
|
|
|
|
|
.join('\n')}
|
|
|
|
|
function ${select_block_type}(changed, ctx) {
|
|
|
|
|
${this.branches.map(({ dependencies, condition, snippet, block }) => condition
|
|
|
|
|
? deindent`
|
|
|
|
|
${dependencies && `if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})`}
|
|
|
|
|
if (${condition}) return ${block.name};`
|
|
|
|
|
: `return ${block.name};`)}
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
/* eslint-enable @typescript-eslint/indent,indent */
|
|
|
|
|
|
|
|
|
|
block.builders.init.add_block(deindent`
|
|
|
|
|
var ${current_block_type} = ${select_block_type}(ctx);
|
|
|
|
|
var ${current_block_type} = ${select_block_type}(null, ctx);
|
|
|
|
|
var ${name} = ${current_block_type_and}${current_block_type}(ctx);
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
@ -245,7 +276,7 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
|
|
|
|
|
if (dynamic) {
|
|
|
|
|
block.builders.update.add_block(deindent`
|
|
|
|
|
if (${current_block_type} === (${current_block_type} = ${select_block_type}(ctx)) && ${name}) {
|
|
|
|
|
if (${current_block_type} === (${current_block_type} = ${select_block_type}(changed, ctx)) && ${name}) {
|
|
|
|
|
${name}.p(changed, ctx);
|
|
|
|
|
} else {
|
|
|
|
|
${change_block}
|
|
|
|
@ -253,7 +284,7 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
`);
|
|
|
|
|
} else {
|
|
|
|
|
block.builders.update.add_block(deindent`
|
|
|
|
|
if (${current_block_type} !== (${current_block_type} = ${select_block_type}(ctx))) {
|
|
|
|
|
if (${current_block_type} !== (${current_block_type} = ${select_block_type}(changed, ctx))) {
|
|
|
|
|
${change_block}
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
@ -293,10 +324,12 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
|
|
|
|
|
var ${if_blocks} = [];
|
|
|
|
|
|
|
|
|
|
function ${select_block_type}(ctx) {
|
|
|
|
|
${this.branches
|
|
|
|
|
.map(({ condition }, i) => `${condition ? `if (${condition}) ` : ''}return ${i};`)
|
|
|
|
|
.join('\n')}
|
|
|
|
|
function ${select_block_type}(changed, ctx) {
|
|
|
|
|
${this.branches.map(({ dependencies, condition, snippet }, i) => condition
|
|
|
|
|
? deindent`
|
|
|
|
|
${dependencies && `if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})`}
|
|
|
|
|
if (${condition}) return ${String(i)};`
|
|
|
|
|
: `return ${i};`)}
|
|
|
|
|
${!has_else && `return -1;`}
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
@ -304,12 +337,12 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
|
|
|
|
|
if (has_else) {
|
|
|
|
|
block.builders.init.add_block(deindent`
|
|
|
|
|
${current_block_type_index} = ${select_block_type}(ctx);
|
|
|
|
|
${current_block_type_index} = ${select_block_type}(null, ctx);
|
|
|
|
|
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](ctx);
|
|
|
|
|
`);
|
|
|
|
|
} else {
|
|
|
|
|
block.builders.init.add_block(deindent`
|
|
|
|
|
if (~(${current_block_type_index} = ${select_block_type}(ctx))) {
|
|
|
|
|
if (~(${current_block_type_index} = ${select_block_type}(null, ctx))) {
|
|
|
|
|
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](ctx);
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
@ -363,7 +396,7 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
if (dynamic) {
|
|
|
|
|
block.builders.update.add_block(deindent`
|
|
|
|
|
var ${previous_block_index} = ${current_block_type_index};
|
|
|
|
|
${current_block_type_index} = ${select_block_type}(ctx);
|
|
|
|
|
${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 {
|
|
|
|
@ -373,7 +406,7 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
} else {
|
|
|
|
|
block.builders.update.add_block(deindent`
|
|
|
|
|
var ${previous_block_index} = ${current_block_type_index};
|
|
|
|
|
${current_block_type_index} = ${select_block_type}(ctx);
|
|
|
|
|
${current_block_type_index} = ${select_block_type}(changed, ctx);
|
|
|
|
|
if (${current_block_type_index} !== ${previous_block_index}) {
|
|
|
|
|
${change_block}
|
|
|
|
|
}
|
|
|
|
@ -395,6 +428,8 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
) {
|
|
|
|
|
const branch = this.branches[0];
|
|
|
|
|
|
|
|
|
|
if (branch.snippet) block.add_variable(branch.condition, branch.snippet);
|
|
|
|
|
|
|
|
|
|
block.builders.init.add_block(deindent`
|
|
|
|
|
var ${name} = (${branch.condition}) && ${branch.block.name}(ctx);
|
|
|
|
|
`);
|
|
|
|
@ -431,6 +466,10 @@ export default class IfBlockWrapper extends Wrapper {
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
if (branch.snippet) {
|
|
|
|
|
block.builders.update.add_block(`if (${branch.dependencies.map(n => `changed.${n}`).join(' || ')}) ${branch.condition} = ${branch.snippet}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// no `p()` here — we don't want to update outroing nodes,
|
|
|
|
|
// as that will typically result in glitching
|
|
|
|
|
if (branch.block.has_outro_method) {
|
|
|
|
|