@@ -52,16 +52,17 @@ export interface CodegenContext extends Required<CodegenOptions> {
5252 loc ?: SourceLocation ,
5353 name ?: string ,
5454 ) : void
55- pushWithNewline (
55+ pushNewline (
5656 code : string ,
5757 newlineIndex ?: number ,
5858 loc ?: SourceLocation ,
5959 name ?: string ,
6060 ) : void
6161 pushMulti (
6262 codes : [ left : string , right : string , segment ?: string ] ,
63- ...fn : Array < false | ( ( ) => void ) >
63+ ...fn : Array < false | string | ( ( ) => void ) >
6464 ) : void
65+ pushFnCall ( name : string , ...args : Array < false | string | ( ( ) => void ) > ) : void
6566 withIndent ( fn : ( ) => void ) : void
6667 newline ( ) : void
6768
@@ -169,33 +170,36 @@ function createCodegenContext(
169170 }
170171 }
171172 } ,
172- pushWithNewline ( code , newlineIndex , node ) {
173+ pushNewline ( code , newlineIndex , node ) {
173174 context . newline ( )
174175 context . push ( code , newlineIndex , node )
175176 } ,
176177 pushMulti ( [ left , right , seg ] , ...fns ) {
177178 fns = fns . filter ( Boolean )
178179 context . push ( left )
179180 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 ( )
181185 if ( seg && i < fns . length - 1 ) context . push ( seg )
182186 }
183187 context . push ( right )
184188 } ,
189+ pushFnCall ( name , ...args ) {
190+ context . push ( name )
191+ context . pushMulti ( [ '(' , ')' , ', ' ] , ...args )
192+ } ,
185193 withIndent ( fn ) {
186194 ++ context . indentLevel
187195 fn ( )
188196 -- context . indentLevel
189197 } ,
190198 newline ( ) {
191- newline ( context . indentLevel )
199+ context . push ( `\n ${ ` ` . repeat ( context . indentLevel ) } ` , NewlineType . Start )
192200 } ,
193201 }
194202
195- function newline ( n : number ) {
196- context . push ( `\n${ ` ` . repeat ( n ) } ` , NewlineType . Start )
197- }
198-
199203 function addMapping ( loc : Position , name : string | null = null ) {
200204 // we use the private property to directly add the mapping
201205 // because the addMapping() implementation in source-map-js has a bunch of
@@ -231,7 +235,7 @@ export function generate(
231235 const ctx = createCodegenContext ( ir , options )
232236 const {
233237 push,
234- pushWithNewline ,
238+ pushNewline ,
235239 withIndent,
236240 newline,
237241 helpers,
@@ -246,33 +250,33 @@ export function generate(
246250 } else {
247251 // placeholder for preamble
248252 newline ( )
249- pushWithNewline ( `export function ${ functionName } (_ctx) {` )
253+ pushNewline ( `export function ${ functionName } (_ctx) {` )
250254 }
251255
252256 withIndent ( ( ) => {
253257 ir . template . forEach ( ( template , i ) => {
254258 if ( template . type === IRNodeTypes . TEMPLATE_FACTORY ) {
255259 // TODO source map?
256- pushWithNewline (
260+ pushNewline (
257261 `const t${ i } = ${ vaporHelper ( 'template' ) } (${ JSON . stringify (
258262 template . template ,
259263 ) } )`,
260264 )
261265 } else {
262266 // fragment
263- pushWithNewline (
267+ pushNewline (
264268 `const t0 = ${ vaporHelper ( 'fragment' ) } ()\n` ,
265269 NewlineType . End ,
266270 )
267271 }
268272 } )
269273
270274 {
271- pushWithNewline ( `const n${ ir . dynamic . id } = t0()` )
275+ pushNewline ( `const n${ ir . dynamic . id } = t0()` )
272276
273277 const children = genChildren ( ir . dynamic . children )
274278 if ( children ) {
275- pushWithNewline (
279+ pushNewline (
276280 `const ${ children } = ${ vaporHelper ( 'children' ) } (n${ ir . dynamic . id } )` ,
277281 )
278282 }
@@ -289,18 +293,18 @@ export function generate(
289293 }
290294
291295 for ( const { operations } of ir . effect ) {
292- pushWithNewline ( `${ vaporHelper ( 'effect' ) } (() => {` )
296+ pushNewline ( `${ vaporHelper ( 'effect' ) } (() => {` )
293297 withIndent ( ( ) => {
294298 for ( const operation of operations ) {
295299 genOperation ( operation , ctx )
296300 }
297301 } )
298- pushWithNewline ( '})' )
302+ pushNewline ( '})' )
299303 }
300304
301305 // TODO multiple-template
302306 // TODO return statement in IR
303- pushWithNewline ( `return n${ ir . dynamic . id } ` )
307+ pushNewline ( `return n${ ir . dynamic . id } ` )
304308 }
305309 } )
306310
@@ -336,7 +340,6 @@ export function generate(
336340
337341function genChildren ( children : IRDynamicChildren ) {
338342 let code = ''
339- // TODO
340343 let offset = 0
341344 for ( const [ index , child ] of Object . entries ( children ) ) {
342345 const childrenLength = Object . keys ( child . children ) . length
@@ -388,77 +391,93 @@ function genOperation(oper: OperationNode, context: CodegenContext) {
388391}
389392
390393function 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+ )
399411}
400412
401413function 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+ )
406419}
407420
408421function 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+ )
413427}
414428
415429function genCreateTextNode (
416430 oper : CreateTextNodeIRNode ,
417431 context : CodegenContext ,
418432) {
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+ )
423438}
424439
425440function genInsertNode ( oper : InsertNodeIRNode , context : CodegenContext ) {
426- const { pushWithNewline , vaporHelper } = context
441+ const { newline , pushFnCall , vaporHelper } = context
427442 const elements = ( [ ] as number [ ] ) . concat ( oper . element )
428443 let element = elements . map ( ( el ) => `n${ el } ` ) . join ( ', ' )
429444 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 } ` ,
434451 )
435452}
436453
437454function 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 ( ', ' ) ,
443461 )
444462}
445463
446464function 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 ( ', ' ) ,
452471 )
453472}
454473
455474function genSetEvent ( oper : SetEventIRNode , context : CodegenContext ) {
456- const { vaporHelper, push, pushWithNewline , pushMulti : pushMulti } = context
475+ const { vaporHelper, push, newline , pushMulti, pushFnCall } = context
457476 const { keys, nonKeys, options } = oper . modifiers
458477
459- pushWithNewline ( vaporHelper ( 'on' ) )
460- pushMulti (
461- [ '(' , ')' , ', ' ] ,
478+ newline ( )
479+ pushFnCall (
480+ vaporHelper ( 'on' ) ,
462481 // 1st arg: event name
463482 ( ) => push ( `n${ oper . element } ` ) ,
464483 // 2nd arg: event name
@@ -508,46 +527,58 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) {
508527}
509528
510529function genWithDirective ( oper : WithDirectiveIRNode , context : CodegenContext ) {
511- const { push, pushWithNewline, vaporHelper, bindingMetadata } = context
530+ const { push, newline, pushFnCall, pushMulti, vaporHelper, bindingMetadata } =
531+ context
512532 const { dir } = oper
513533
514534 // 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+ }
528557
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+ }
535564
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+ }
542571
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+ )
551582}
552583
553584// TODO: other types (not only string)
0 commit comments