@@ -52,16 +52,17 @@ export interface CodegenContext extends Required<CodegenOptions> {
52
52
loc ?: SourceLocation ,
53
53
name ?: string ,
54
54
) : void
55
- pushWithNewline (
55
+ pushNewline (
56
56
code : string ,
57
57
newlineIndex ?: number ,
58
58
loc ?: SourceLocation ,
59
59
name ?: string ,
60
60
) : void
61
61
pushMulti (
62
62
codes : [ left : string , right : string , segment ?: string ] ,
63
- ...fn : Array < false | ( ( ) => void ) >
63
+ ...fn : Array < false | string | ( ( ) => void ) >
64
64
) : void
65
+ pushFnCall ( name : string , ...args : Array < false | string | ( ( ) => void ) > ) : void
65
66
withIndent ( fn : ( ) => void ) : void
66
67
newline ( ) : void
67
68
@@ -169,33 +170,36 @@ function createCodegenContext(
169
170
}
170
171
}
171
172
} ,
172
- pushWithNewline ( code , newlineIndex , node ) {
173
+ pushNewline ( code , newlineIndex , node ) {
173
174
context . newline ( )
174
175
context . push ( code , newlineIndex , node )
175
176
} ,
176
177
pushMulti ( [ left , right , seg ] , ...fns ) {
177
178
fns = fns . filter ( Boolean )
178
179
context . push ( left )
179
180
for ( let i = 0 ; i < fns . length ; i ++ ) {
180
- ; ( fns [ i ] as ( ) => void ) ( )
181
+ const fn = fns [ i ] as string | ( ( ) => void )
182
+
183
+ if ( isString ( fn ) ) context . push ( fn )
184
+ else fn ( )
181
185
if ( seg && i < fns . length - 1 ) context . push ( seg )
182
186
}
183
187
context . push ( right )
184
188
} ,
189
+ pushFnCall ( name , ...args ) {
190
+ context . push ( name )
191
+ context . pushMulti ( [ '(' , ')' , ', ' ] , ...args )
192
+ } ,
185
193
withIndent ( fn ) {
186
194
++ context . indentLevel
187
195
fn ( )
188
196
-- context . indentLevel
189
197
} ,
190
198
newline ( ) {
191
- newline ( context . indentLevel )
199
+ context . push ( `\n ${ ` ` . repeat ( context . indentLevel ) } ` , NewlineType . Start )
192
200
} ,
193
201
}
194
202
195
- function newline ( n : number ) {
196
- context . push ( `\n${ ` ` . repeat ( n ) } ` , NewlineType . Start )
197
- }
198
-
199
203
function addMapping ( loc : Position , name : string | null = null ) {
200
204
// we use the private property to directly add the mapping
201
205
// because the addMapping() implementation in source-map-js has a bunch of
@@ -231,7 +235,7 @@ export function generate(
231
235
const ctx = createCodegenContext ( ir , options )
232
236
const {
233
237
push,
234
- pushWithNewline ,
238
+ pushNewline ,
235
239
withIndent,
236
240
newline,
237
241
helpers,
@@ -246,33 +250,33 @@ export function generate(
246
250
} else {
247
251
// placeholder for preamble
248
252
newline ( )
249
- pushWithNewline ( `export function ${ functionName } (_ctx) {` )
253
+ pushNewline ( `export function ${ functionName } (_ctx) {` )
250
254
}
251
255
252
256
withIndent ( ( ) => {
253
257
ir . template . forEach ( ( template , i ) => {
254
258
if ( template . type === IRNodeTypes . TEMPLATE_FACTORY ) {
255
259
// TODO source map?
256
- pushWithNewline (
260
+ pushNewline (
257
261
`const t${ i } = ${ vaporHelper ( 'template' ) } (${ JSON . stringify (
258
262
template . template ,
259
263
) } )`,
260
264
)
261
265
} else {
262
266
// fragment
263
- pushWithNewline (
267
+ pushNewline (
264
268
`const t0 = ${ vaporHelper ( 'fragment' ) } ()\n` ,
265
269
NewlineType . End ,
266
270
)
267
271
}
268
272
} )
269
273
270
274
{
271
- pushWithNewline ( `const n${ ir . dynamic . id } = t0()` )
275
+ pushNewline ( `const n${ ir . dynamic . id } = t0()` )
272
276
273
277
const children = genChildren ( ir . dynamic . children )
274
278
if ( children ) {
275
- pushWithNewline (
279
+ pushNewline (
276
280
`const ${ children } = ${ vaporHelper ( 'children' ) } (n${ ir . dynamic . id } )` ,
277
281
)
278
282
}
@@ -289,18 +293,18 @@ export function generate(
289
293
}
290
294
291
295
for ( const { operations } of ir . effect ) {
292
- pushWithNewline ( `${ vaporHelper ( 'effect' ) } (() => {` )
296
+ pushNewline ( `${ vaporHelper ( 'effect' ) } (() => {` )
293
297
withIndent ( ( ) => {
294
298
for ( const operation of operations ) {
295
299
genOperation ( operation , ctx )
296
300
}
297
301
} )
298
- pushWithNewline ( '})' )
302
+ pushNewline ( '})' )
299
303
}
300
304
301
305
// TODO multiple-template
302
306
// TODO return statement in IR
303
- pushWithNewline ( `return n${ ir . dynamic . id } ` )
307
+ pushNewline ( `return n${ ir . dynamic . id } ` )
304
308
}
305
309
} )
306
310
@@ -336,7 +340,6 @@ export function generate(
336
340
337
341
function genChildren ( children : IRDynamicChildren ) {
338
342
let code = ''
339
- // TODO
340
343
let offset = 0
341
344
for ( const [ index , child ] of Object . entries ( children ) ) {
342
345
const childrenLength = Object . keys ( child . children ) . length
@@ -388,77 +391,93 @@ function genOperation(oper: OperationNode, context: CodegenContext) {
388
391
}
389
392
390
393
function genSetProp ( oper : SetPropIRNode , context : CodegenContext ) {
391
- const { push, pushWithNewline, vaporHelper, helper } = context
392
- pushWithNewline ( `${ vaporHelper ( 'setAttr' ) } (n${ oper . element } , ` )
393
- if ( oper . runtimeCamelize ) push ( `${ helper ( 'camelize' ) } (` )
394
- genExpression ( oper . key , context )
395
- if ( oper . runtimeCamelize ) push ( `)` )
396
- push ( `, undefined, ` )
397
- genExpression ( oper . value , context )
398
- push ( ')' )
394
+ const { pushFnCall, newline, vaporHelper, helper } = context
395
+
396
+ newline ( )
397
+ pushFnCall (
398
+ vaporHelper ( 'setAttr' ) ,
399
+ `n${ oper . element } ` ,
400
+ // 2. key name
401
+ ( ) => {
402
+ if ( oper . runtimeCamelize ) {
403
+ pushFnCall ( helper ( 'camelize' ) , ( ) => genExpression ( oper . key , context ) )
404
+ } else {
405
+ genExpression ( oper . key , context )
406
+ }
407
+ } ,
408
+ 'undefined' ,
409
+ ( ) => genExpression ( oper . value , context ) ,
410
+ )
399
411
}
400
412
401
413
function genSetText ( oper : SetTextIRNode , context : CodegenContext ) {
402
- const { push, pushWithNewline, vaporHelper } = context
403
- pushWithNewline ( `${ vaporHelper ( 'setText' ) } (n${ oper . element } , undefined, ` )
404
- genExpression ( oper . value , context )
405
- push ( ')' )
414
+ const { pushFnCall, newline, vaporHelper } = context
415
+ newline ( )
416
+ pushFnCall ( vaporHelper ( 'setText' ) , `n${ oper . element } ` , 'undefined' , ( ) =>
417
+ genExpression ( oper . value , context ) ,
418
+ )
406
419
}
407
420
408
421
function genSetHtml ( oper : SetHtmlIRNode , context : CodegenContext ) {
409
- const { push, pushWithNewline, vaporHelper } = context
410
- pushWithNewline ( `${ vaporHelper ( 'setHtml' ) } (n${ oper . element } , undefined, ` )
411
- genExpression ( oper . value , context )
412
- push ( ')' )
422
+ const { newline, pushFnCall, vaporHelper } = context
423
+ newline ( )
424
+ pushFnCall ( vaporHelper ( 'setHtml' ) , `n${ oper . element } ` , 'undefined' , ( ) =>
425
+ genExpression ( oper . value , context ) ,
426
+ )
413
427
}
414
428
415
429
function genCreateTextNode (
416
430
oper : CreateTextNodeIRNode ,
417
431
context : CodegenContext ,
418
432
) {
419
- const { push, pushWithNewline, vaporHelper } = context
420
- pushWithNewline ( `const n${ oper . id } = ${ vaporHelper ( 'createTextNode' ) } (` )
421
- genExpression ( oper . value , context )
422
- push ( ')' )
433
+ const { pushNewline, pushFnCall, vaporHelper } = context
434
+ pushNewline ( `const n${ oper . id } = ` )
435
+ pushFnCall ( vaporHelper ( 'createTextNode' ) , ( ) =>
436
+ genExpression ( oper . value , context ) ,
437
+ )
423
438
}
424
439
425
440
function genInsertNode ( oper : InsertNodeIRNode , context : CodegenContext ) {
426
- const { pushWithNewline , vaporHelper } = context
441
+ const { newline , pushFnCall , vaporHelper } = context
427
442
const elements = ( [ ] as number [ ] ) . concat ( oper . element )
428
443
let element = elements . map ( ( el ) => `n${ el } ` ) . join ( ', ' )
429
444
if ( elements . length > 1 ) element = `[${ element } ]`
430
- pushWithNewline (
431
- `${ vaporHelper ( 'insert' ) } (${ element } , n${
432
- oper . parent
433
- } ${ `, n${ oper . anchor } ` } )`,
445
+ newline ( )
446
+ pushFnCall (
447
+ vaporHelper ( 'insert' ) ,
448
+ element ,
449
+ `n${ oper . parent } ` ,
450
+ `n${ oper . anchor } ` ,
434
451
)
435
452
}
436
453
437
454
function genPrependNode ( oper : PrependNodeIRNode , context : CodegenContext ) {
438
- const { pushWithNewline, vaporHelper } = context
439
- pushWithNewline (
440
- `${ vaporHelper ( 'prepend' ) } (n${ oper . parent } , ${ oper . elements
441
- . map ( ( el ) => `n${ el } ` )
442
- . join ( ', ' ) } )`,
455
+ const { newline, pushFnCall, vaporHelper } = context
456
+ newline ( )
457
+ pushFnCall (
458
+ vaporHelper ( 'prepend' ) ,
459
+ `n${ oper . parent } ` ,
460
+ oper . elements . map ( ( el ) => `n${ el } ` ) . join ( ', ' ) ,
443
461
)
444
462
}
445
463
446
464
function genAppendNode ( oper : AppendNodeIRNode , context : CodegenContext ) {
447
- const { pushWithNewline, vaporHelper } = context
448
- pushWithNewline (
449
- `${ vaporHelper ( 'append' ) } (n${ oper . parent } , ${ oper . elements
450
- . map ( ( el ) => `n${ el } ` )
451
- . join ( ', ' ) } )`,
465
+ const { newline, pushFnCall, vaporHelper } = context
466
+ newline ( )
467
+ pushFnCall (
468
+ vaporHelper ( 'append' ) ,
469
+ `n${ oper . parent } ` ,
470
+ oper . elements . map ( ( el ) => `n${ el } ` ) . join ( ', ' ) ,
452
471
)
453
472
}
454
473
455
474
function genSetEvent ( oper : SetEventIRNode , context : CodegenContext ) {
456
- const { vaporHelper, push, pushWithNewline , pushMulti : pushMulti } = context
475
+ const { vaporHelper, push, newline , pushMulti, pushFnCall } = context
457
476
const { keys, nonKeys, options } = oper . modifiers
458
477
459
- pushWithNewline ( vaporHelper ( 'on' ) )
460
- pushMulti (
461
- [ '(' , ')' , ', ' ] ,
478
+ newline ( )
479
+ pushFnCall (
480
+ vaporHelper ( 'on' ) ,
462
481
// 1st arg: event name
463
482
( ) => push ( `n${ oper . element } ` ) ,
464
483
// 2nd arg: event name
@@ -508,46 +527,58 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) {
508
527
}
509
528
510
529
function genWithDirective ( oper : WithDirectiveIRNode , context : CodegenContext ) {
511
- const { push, pushWithNewline, vaporHelper, bindingMetadata } = context
530
+ const { push, newline, pushFnCall, pushMulti, vaporHelper, bindingMetadata } =
531
+ context
512
532
const { dir } = oper
513
533
514
534
// TODO merge directive for the same node
515
- pushWithNewline ( `${ vaporHelper ( 'withDirectives' ) } (n${ oper . element } , [[` )
516
-
517
- if ( dir . name === 'show' ) {
518
- push ( vaporHelper ( 'vShow' ) )
519
- } else {
520
- const directiveReference = camelize ( `v-${ dir . name } ` )
521
- // TODO resolve directive
522
- if ( bindingMetadata [ directiveReference ] ) {
523
- const directiveExpression = createSimpleExpression ( directiveReference )
524
- directiveExpression . ast = null
525
- genExpression ( directiveExpression , context )
526
- }
527
- }
535
+ newline ( )
536
+ pushFnCall (
537
+ vaporHelper ( 'withDirectives' ) ,
538
+ // 1st arg: node
539
+ `n${ oper . element } ` ,
540
+ // 2nd arg: directives
541
+ ( ) => {
542
+ push ( '[' )
543
+ // directive
544
+ pushMulti ( [ '[' , ']' , ', ' ] , ( ) => {
545
+ if ( dir . name === 'show' ) {
546
+ push ( vaporHelper ( 'vShow' ) )
547
+ } else {
548
+ const directiveReference = camelize ( `v-${ dir . name } ` )
549
+ // TODO resolve directive
550
+ if ( bindingMetadata [ directiveReference ] ) {
551
+ const directiveExpression =
552
+ createSimpleExpression ( directiveReference )
553
+ directiveExpression . ast = null
554
+ genExpression ( directiveExpression , context )
555
+ }
556
+ }
528
557
529
- if ( dir . exp ) {
530
- push ( ', () => ' )
531
- genExpression ( dir . exp , context )
532
- } else if ( dir . arg || dir . modifiers . length ) {
533
- push ( ', void 0' )
534
- }
558
+ if ( dir . exp ) {
559
+ push ( ', () => ' )
560
+ genExpression ( dir . exp , context )
561
+ } else if ( dir . arg || dir . modifiers . length ) {
562
+ push ( ', void 0' )
563
+ }
535
564
536
- if ( dir . arg ) {
537
- push ( ', ' )
538
- genExpression ( dir . arg , context )
539
- } else if ( dir . modifiers . length ) {
540
- push ( ', void 0' )
541
- }
565
+ if ( dir . arg ) {
566
+ push ( ', ' )
567
+ genExpression ( dir . arg , context )
568
+ } else if ( dir . modifiers . length ) {
569
+ push ( ', void 0' )
570
+ }
542
571
543
- if ( dir . modifiers . length ) {
544
- push ( ', ' )
545
- push ( '{ ' )
546
- push ( genDirectiveModifiers ( dir . modifiers ) )
547
- push ( ' }' )
548
- }
549
- push ( ']])' )
550
- return
572
+ if ( dir . modifiers . length ) {
573
+ push ( ', ' )
574
+ push ( '{ ' )
575
+ push ( genDirectiveModifiers ( dir . modifiers ) )
576
+ push ( ' }' )
577
+ }
578
+ } )
579
+ push ( ']' )
580
+ } ,
581
+ )
551
582
}
552
583
553
584
// TODO: other types (not only string)
0 commit comments