Skip to content

Commit c1a1a01

Browse files
committed
generate less code for if-blocks with else-blocks (closes #540)
1 parent c712ad5 commit c1a1a01

File tree

2 files changed

+58
-25
lines changed

2 files changed

+58
-25
lines changed

src/generators/dom/visitors/IfBlock.js

+52-19
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ function isElseIf ( node ) {
55
return node && node.children.length === 1 && node.children[0].type === 'IfBlock';
66
}
77

8+
function isElseBranch ( branch ) {
9+
return branch.block && !branch.condition;
10+
}
11+
812
function getBranches ( generator, block, state, node ) {
913
const branches = [{
1014
condition: block.contextualise( node.expression ).snippet,
@@ -48,18 +52,22 @@ export default function visitIfBlock ( generator, block, state, node ) {
4852
const anchor = node.needsAnchor ? block.getUniqueName( `${name}_anchor` ) : ( node.next && node.next._state.name ) || 'null';
4953
const params = block.params.join( ', ' );
5054

51-
const vars = { name, anchor, params };
52-
5355
if ( node.needsAnchor ) {
5456
block.addElement( anchor, `${generator.helper( 'createComment' )}()`, state.parentNode, true );
5557
} else if ( node.next ) {
5658
node.next.usedAsAnchor = true;
5759
}
5860

5961
const branches = getBranches( generator, block, state, node, generator.getUniqueName( `create_if_block` ) );
62+
63+
const hasElse = isElseBranch( branches[ branches.length - 1 ] );
64+
const if_name = hasElse ? '' : `if ( ${name} ) `;
65+
6066
const dynamic = branches[0].hasUpdateMethod; // can use [0] as proxy for all, since they necessarily have the same value
6167
const hasOutros = branches[0].hasOutroMethod;
6268

69+
const vars = { name, anchor, params, if_name, hasElse };
70+
6371
if ( node.else ) {
6472
if ( hasOutros ) {
6573
compoundWithOutros( generator, block, state, node, branches, dynamic, vars );
@@ -71,7 +79,7 @@ export default function visitIfBlock ( generator, block, state, node ) {
7179
}
7280

7381
block.builders.destroy.addLine(
74-
`if ( ${name} ) ${name}.destroy( ${state.parentNode ? 'false' : 'detach'} );`
82+
`${if_name}${name}.destroy( ${state.parentNode ? 'false' : 'detach'} );`
7583
);
7684
}
7785

@@ -145,9 +153,10 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
145153
` );
146154
}
147155

148-
function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) {
156+
function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params, hasElse, if_name } ) {
149157
const get_block = block.getUniqueName( `get_block` );
150158
const current_block = block.getUniqueName( `current_block` );
159+
const current_block_and = hasElse ? '' : `${current_block} && `;
151160

152161
block.builders.create.addBlock( deindent`
153162
function ${get_block} ( ${params} ) {
@@ -157,24 +166,24 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
157166
}
158167
159168
var ${current_block} = ${get_block}( ${params} );
160-
var ${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
169+
var ${name} = ${current_block_and}${current_block}( ${params}, ${block.component} );
161170
` );
162171

163172
const isToplevel = !state.parentNode;
164173
const mountOrIntro = branches[0].hasIntroMethod ? 'intro' : 'mount';
165174

166175
if ( isToplevel ) {
167-
block.builders.mount.addLine( `if ( ${name} ) ${name}.${mountOrIntro}( ${block.target}, null );` );
176+
block.builders.mount.addLine( `${if_name}${name}.${mountOrIntro}( ${block.target}, null );` );
168177
} else {
169-
block.builders.create.addLine( `if ( ${name} ) ${name}.${mountOrIntro}( ${state.parentNode}, null );` );
178+
block.builders.create.addLine( `${if_name}${name}.${mountOrIntro}( ${state.parentNode}, null );` );
170179
}
171180

172181
const parentNode = state.parentNode || `${anchor}.parentNode`;
173182

174183
const changeBlock = deindent`
175-
if ( ${name} ) ${name}.destroy( true );
176-
${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
177-
if ( ${name} ) ${name}.${mountOrIntro}( ${parentNode}, ${anchor} );
184+
${if_name}${name}.destroy( true );
185+
${name} = ${current_block_and}${current_block}( ${params}, ${block.component} );
186+
${if_name}${name}.${mountOrIntro}( ${parentNode}, ${anchor} );
178187
`;
179188

180189
if ( dynamic ) {
@@ -196,13 +205,15 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
196205

197206
// if any of the siblings have outros, we need to keep references to the blocks
198207
// (TODO does this only apply to bidi transitions?)
199-
function compoundWithOutros ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) {
208+
function compoundWithOutros ( generator, block, state, node, branches, dynamic, { name, anchor, params, hasElse } ) {
200209
const get_block = block.getUniqueName( `get_block` );
201210
const current_block_index = block.getUniqueName( `current_block_index` );
202211
const previous_block_index = block.getUniqueName( `previous_block_index` );
203212
const if_block_creators = block.getUniqueName( `if_block_creators` );
204213
const if_blocks = block.getUniqueName( `if_blocks` );
205214

215+
const if_current_block_index = hasElse ? '' : `if ( ~${current_block_index} ) `;
216+
206217
block.addVariable( current_block_index );
207218

208219
block.builders.create.addBlock( deindent`
@@ -217,18 +228,27 @@ function compoundWithOutros ( generator, block, state, node, branches, dynamic,
217228
return `${condition ? `if ( ${condition} ) ` : ''}return ${block ? i : -1};`;
218229
} ).join( '\n' )}
219230
}
231+
` );
220232

221-
if ( ~( ${current_block_index} = ${get_block}( ${params} ) ) ) {
233+
if ( hasElse ) {
234+
block.builders.create.addBlock( deindent`
235+
${current_block_index} = ${get_block}( ${params} );
222236
${if_blocks}[ ${current_block_index} ] = ${if_block_creators}[ ${current_block_index} ]( ${params}, ${block.component} );
223-
}
224-
` );
237+
` );
238+
} else {
239+
block.builders.create.addBlock( deindent`
240+
if ( ~( ${current_block_index} = ${get_block}( ${params} ) ) ) {
241+
${if_blocks}[ ${current_block_index} ] = ${if_block_creators}[ ${current_block_index} ]( ${params}, ${block.component} );
242+
}
243+
` );
244+
}
225245

226246
const isToplevel = !state.parentNode;
227247
const mountOrIntro = branches[0].hasIntroMethod ? 'intro' : 'mount';
228248
const initialTarget = isToplevel ? block.target : state.parentNode;
229249

230250
( isToplevel ? block.builders.mount : block.builders.create ).addBlock(
231-
`if ( ~${current_block_index} ) ${if_blocks}[ ${current_block_index} ].${mountOrIntro}( ${initialTarget}, null );`
251+
`${if_current_block_index}${if_blocks}[ ${current_block_index} ].${mountOrIntro}( ${initialTarget}, null );`
232252
);
233253

234254
const parentNode = state.parentNode || `${anchor}.parentNode`;
@@ -241,23 +261,36 @@ function compoundWithOutros ( generator, block, state, node, branches, dynamic,
241261
${if_blocks}[ ${previous_block_index} ] = null;
242262
});
243263
}
264+
`;
244265

245-
if ( ~${current_block_index} ) {
266+
if ( hasElse ) {
267+
block.builders.create.addBlock( deindent`
246268
${name} = ${if_blocks}[ ${current_block_index} ];
247269
if ( !${name} ) {
248270
${name} = ${if_blocks}[ ${current_block_index} ] = ${if_block_creators}[ ${current_block_index} ]( ${params}, ${block.component} );
249271
}
250272
251273
${name}.${mountOrIntro}( ${parentNode}, ${anchor} );
252-
}
253-
`;
274+
` );
275+
} else {
276+
block.builders.create.addBlock( deindent`
277+
if ( ~${current_block_index} ) {
278+
${name} = ${if_blocks}[ ${current_block_index} ];
279+
if ( !${name} ) {
280+
${name} = ${if_blocks}[ ${current_block_index} ] = ${if_block_creators}[ ${current_block_index} ]( ${params}, ${block.component} );
281+
}
282+
283+
${name}.${mountOrIntro}( ${parentNode}, ${anchor} );
284+
}
285+
` );
286+
}
254287

255288
if ( dynamic ) {
256289
block.builders.update.addBlock( deindent`
257290
var ${previous_block_index} = ${current_block_index};
258291
${current_block_index} = ${get_block}( state );
259292
if ( ${current_block_index} === ${previous_block_index} ) {
260-
if ( ~${current_block_index} ) ${if_blocks}[ ${current_block_index} ].update( changed, ${params} );
293+
${if_current_block_index}${if_blocks}[ ${current_block_index} ].update( changed, ${params} );
261294
} else {
262295
${changeBlock}
263296
}

test/js/samples/if-block-no-update/expected.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,24 @@ function create_main_fragment ( state, component ) {
99
}
1010

1111
var current_block = get_block( state );
12-
var if_block = current_block && current_block( state, component );
12+
var if_block = current_block( state, component );
1313

1414
return {
1515
mount: function ( target, anchor ) {
1616
insertNode( if_block_anchor, target, anchor );
17-
if ( if_block ) if_block.mount( target, null );
17+
if_block.mount( target, null );
1818
},
1919

2020
update: function ( changed, state ) {
2121
if ( current_block !== ( current_block = get_block( state ) ) ) {
22-
if ( if_block ) if_block.destroy( true );
23-
if_block = current_block && current_block( state, component );
24-
if ( if_block ) if_block.mount( if_block_anchor.parentNode, if_block_anchor );
22+
if_block.destroy( true );
23+
if_block = current_block( state, component );
24+
if_block.mount( if_block_anchor.parentNode, if_block_anchor );
2525
}
2626
},
2727

2828
destroy: function ( detach ) {
29-
if ( if_block ) if_block.destroy( detach );
29+
if_block.destroy( detach );
3030

3131
if ( detach ) {
3232
detachNode( if_block_anchor );

0 commit comments

Comments
 (0)