Skip to content

Commit ecf7da9

Browse files
committed
feat: pushFnCall
1 parent 0c26b0d commit ecf7da9

File tree

1 file changed

+123
-92
lines changed

1 file changed

+123
-92
lines changed

packages/compiler-vapor/src/generate.ts

+123-92
Original file line numberDiff line numberDiff line change
@@ -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

337341
function 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

390393
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+
)
399411
}
400412

401413
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+
)
406419
}
407420

408421
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+
)
413427
}
414428

415429
function 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

425440
function 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

437454
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(', '),
443461
)
444462
}
445463

446464
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(', '),
452471
)
453472
}
454473

455474
function 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

510529
function 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

Comments
 (0)