@@ -3,6 +3,7 @@ import CodeBuilder from '../../../utils/CodeBuilder';
3
3
import visit from '../visit' ;
4
4
import { DomGenerator } from '../index' ;
5
5
import Block from '../Block' ;
6
+ import isDomNode from './shared/isDomNode' ;
6
7
import getTailSnippet from '../../../utils/getTailSnippet' ;
7
8
import getObject from '../../../utils/getObject' ;
8
9
import getExpressionPrecedence from '../../../utils/getExpressionPrecedence' ;
@@ -67,6 +68,9 @@ export default function visitComponent(
67
68
. filter ( ( a : Node ) => a . type === 'Binding' )
68
69
. map ( ( a : Node ) => mungeBinding ( a , block ) ) ;
69
70
71
+ const ref = node . attributes . find ( ( a : Node ) => a . type === 'Ref' ) ;
72
+ if ( ref ) generator . usesRefs = true ;
73
+
70
74
if ( attributes . length || bindings . length ) {
71
75
const initialProps = attributes
72
76
. map ( ( attribute : Attribute ) => `${ attribute . name } : ${ attribute . value } ` ) ;
@@ -205,30 +209,122 @@ export default function visitComponent(
205
209
}
206
210
}
207
211
208
- const expression = node . name === ':Self' ? generator . name : `%components- ${ node . name } ` ;
212
+ const isSwitch = node . name === ':Switch' ;
209
213
210
- block . builders . init . addBlock ( deindent `
211
- ${ statements . join ( '\n' ) }
212
- var ${ name } = new ${ expression } ({
213
- ${ componentInitProperties . join ( ',\n' ) }
214
- });
214
+ const switch_vars = isSwitch && {
215
+ value : block . getUniqueName ( 'switch_value' ) ,
216
+ props : block . getUniqueName ( 'switch_props' )
217
+ } ;
215
218
216
- ${ beforecreate }
217
- ` ) ;
219
+ const expression = (
220
+ node . name === ':Self' ? generator . name :
221
+ isSwitch ? switch_vars . value :
222
+ `%components-${ node . name } `
223
+ ) ;
218
224
219
- block . builders . create . addLine ( `${ name } ._fragment.c();` ) ;
225
+ if ( isSwitch ) {
226
+ block . contextualise ( node . expression ) ;
227
+ const { dependencies, snippet } = node . metadata ;
228
+
229
+ const needsAnchor = node . next ? ! isDomNode ( node . next , generator ) : ! state . parentNode || ! isDomNode ( node . parent , generator ) ;
230
+ const anchor = needsAnchor
231
+ ? block . getUniqueName ( `${ name } _anchor` )
232
+ : ( node . next && node . next . var ) || 'null' ;
233
+
234
+ if ( needsAnchor ) {
235
+ block . addElement (
236
+ anchor ,
237
+ `@createComment()` ,
238
+ `@createComment()` ,
239
+ state . parentNode
240
+ ) ;
241
+ }
220
242
221
- block . builders . claim . addLine (
222
- `${ name } ._fragment.l(${ state . parentNodes } );`
223
- ) ;
243
+ const params = block . params . join ( ', ' ) ;
224
244
225
- block . builders . mount . addLine (
226
- ` ${ name } ._mount( ${ state . parentNode || '#target' } , ${ state . parentNode ? 'null' : 'anchor' } );`
227
- ) ;
245
+ block . builders . init . addBlock ( deindent `
246
+ var ${ switch_vars . value } = ${ snippet } ;
247
+ ` ) ;
228
248
229
- if ( ! state . parentNode ) block . builders . unmount . addLine ( `${ name } ._unmount();` ) ;
249
+ block . builders . init . addBlock ( deindent `
250
+ function ${ switch_vars . props } (${ params } ) {
251
+ return {
252
+ ${ componentInitProperties . join ( ',\n' ) }
253
+ };
254
+ }
255
+
256
+ if (${ switch_vars . value } ) {
257
+ ${ statements . length > 0 && statements . join ( '\n' ) }
258
+ var ${ name } = new ${ expression } (${ switch_vars . props } (${ params } ));
259
+
260
+ ${ beforecreate }
261
+ }
262
+ ` ) ;
263
+
264
+ block . builders . create . addLine (
265
+ `if (${ name } ) ${ name } ._fragment.c();`
266
+ ) ;
267
+
268
+ block . builders . claim . addLine (
269
+ `if (${ name } ) ${ name } ._fragment.l(${ state . parentNodes } );`
270
+ ) ;
271
+
272
+ block . builders . mount . addLine (
273
+ `if (${ name } ) ${ name } ._mount(${ state . parentNode || '#target' } , ${ state . parentNode ? 'null' : 'anchor' } );`
274
+ ) ;
275
+
276
+ block . builders . update . addBlock ( deindent `
277
+ if (${ switch_vars . value } !== (${ switch_vars . value } = ${ snippet } )) {
278
+ if (${ name } ) ${ name } .destroy();
230
279
231
- block . builders . destroy . addLine ( `${ name } .destroy(false);` ) ;
280
+ if (${ switch_vars . value } ) {
281
+ ${ name } = new ${ switch_vars . value } (${ switch_vars . props } (${ params } ));
282
+ ${ name } ._fragment.c();
283
+ ${ name } ._mount(${ anchor } .parentNode, ${ anchor } );
284
+ ${ ref && `#component.refs.${ ref . name } = ${ name } ;` }
285
+ }
286
+
287
+ ${ ref && deindent `
288
+ else if (#component.refs.${ ref . name } === ${ name } ) {
289
+ #component.refs.${ ref . name } = null;
290
+ }` }
291
+ } else {
292
+ // normal update
293
+ }
294
+ ` ) ;
295
+
296
+ if ( ! state . parentNode ) block . builders . unmount . addLine ( `if (${ name } ) ${ name } ._unmount();` ) ;
297
+
298
+ block . builders . destroy . addLine ( `if (${ name } ) ${ name } .destroy(false);` ) ;
299
+ } else {
300
+ block . builders . init . addBlock ( deindent `
301
+ ${ statements . join ( '\n' ) }
302
+ var ${ name } = new ${ expression } ({
303
+ ${ componentInitProperties . join ( ',\n' ) }
304
+ });
305
+
306
+ ${ beforecreate }
307
+
308
+ ${ ref && `#component.refs.${ ref . name } = ${ name } ;` }
309
+ ` ) ;
310
+
311
+ block . builders . create . addLine ( `${ name } ._fragment.c();` ) ;
312
+
313
+ block . builders . claim . addLine (
314
+ `${ name } ._fragment.l(${ state . parentNodes } );`
315
+ ) ;
316
+
317
+ block . builders . mount . addLine (
318
+ `${ name } ._mount(${ state . parentNode || '#target' } , ${ state . parentNode ? 'null' : 'anchor' } );`
319
+ ) ;
320
+
321
+ if ( ! state . parentNode ) block . builders . unmount . addLine ( `${ name } ._unmount();` ) ;
322
+
323
+ block . builders . destroy . addLine ( deindent `
324
+ ${ name } .destroy(false);
325
+ ${ ref && `if (#component.refs.${ ref . name } === ${ name } ) #component.refs.${ ref . name } = null;` }
326
+ ` ) ;
327
+ }
232
328
233
329
// event handlers
234
330
node . attributes . filter ( ( a : Node ) => a . type === 'EventHandler' ) . forEach ( ( handler : Node ) => {
@@ -274,17 +370,6 @@ export default function visitComponent(
274
370
` ) ;
275
371
} ) ;
276
372
277
- // refs
278
- node . attributes . filter ( ( a : Node ) => a . type === 'Ref' ) . forEach ( ( ref : Node ) => {
279
- generator . usesRefs = true ;
280
-
281
- block . builders . init . addLine ( `#component.refs.${ ref . name } = ${ name } ;` ) ;
282
-
283
- block . builders . destroy . addLine ( deindent `
284
- if (#component.refs.${ ref . name } === ${ name } ) #component.refs.${ ref . name } = null;
285
- ` ) ;
286
- } ) ;
287
-
288
373
// maintain component context
289
374
if ( allContexts . size ) {
290
375
const contexts = Array . from ( allContexts ) ;
0 commit comments