Ver código fonte

refactor(compiler-vapor): add placeholder for optional argument

三咲智子 Kevin Deng 1 ano atrás
pai
commit
30f98942db

+ 2 - 2
packages/compiler-vapor/src/generate.ts

@@ -13,8 +13,8 @@ import {
   LF,
   NEWLINE,
   buildCodeFragment,
+  codeFragmentToString,
   genCall,
-  genCodeFragment,
 } from './generators/utils'
 
 export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
@@ -132,7 +132,7 @@ export function generate(
     frag.unshift(...new Array<CodeFragment>(newlineCount).fill(LF))
   }
 
-  let [code, map] = genCodeFragment(frag, context)
+  let [code, map] = codeFragmentToString(frag, context)
   if (!inline) {
     code = preamble + code
   }

+ 2 - 2
packages/compiler-vapor/src/generators/block.ts

@@ -1,10 +1,10 @@
 import type { BlockIRNode } from '../ir'
 import {
   type CodeFragment,
+  DELIMITERS_ARRAY,
   INDENT_END,
   INDENT_START,
   NEWLINE,
-  SEGMENTS_ARRAY,
   buildCodeFragment,
   genCall,
   genMulti,
@@ -71,7 +71,7 @@ export function genBlockContent(
   const returnNodes = returns.map(n => `n${n}`)
   const returnsCode: CodeFragment[] =
     returnNodes.length > 1
-      ? genMulti(SEGMENTS_ARRAY, ...returnNodes)
+      ? genMulti(DELIMITERS_ARRAY, ...returnNodes)
       : [returnNodes[0] || 'null']
   push(...(customReturns ? customReturns(returnsCode) : returnsCode))
 

+ 13 - 17
packages/compiler-vapor/src/generators/component.ts

@@ -11,11 +11,11 @@ import {
 } from '../ir'
 import {
   type CodeFragment,
+  DELIMITERS_ARRAY,
+  DELIMITERS_ARRAY_NEWLINE,
+  DELIMITERS_OBJECT,
+  DELIMITERS_OBJECT_NEWLINE,
   NEWLINE,
-  SEGMENTS_ARRAY,
-  SEGMENTS_ARRAY_NEWLINE,
-  SEGMENTS_OBJECT,
-  SEGMENTS_OBJECT_NEWLINE,
   genCall,
   genMulti,
 } from './utils'
@@ -43,13 +43,9 @@ export function genCreateComponent(
     ...genCall(
       vaporHelper('createComponent'),
       tag,
-      rawProps || (slots || dynamicSlots || root ? 'null' : false),
-      slots ? genSlots(slots, context) : dynamicSlots || root ? 'null' : false,
-      dynamicSlots
-        ? genDynamicSlots(dynamicSlots, context)
-        : root
-          ? 'null'
-          : false,
+      rawProps,
+      slots && genSlots(slots, context),
+      dynamicSlots && genDynamicSlots(dynamicSlots, context),
       root && 'true',
     ),
     ...genDirectivesForElement(oper.id, context),
@@ -77,7 +73,7 @@ export function genRawProps(props: IRProps[], context: CodegenContext) {
       } else {
         let expr: CodeFragment[]
         if (props.kind === IRDynamicPropsKind.ATTRIBUTE)
-          expr = genMulti(SEGMENTS_OBJECT, genProp(props, context))
+          expr = genMulti(DELIMITERS_OBJECT, genProp(props, context))
         else {
           expr = genExpression(props.value, context)
           if (props.handler) expr = genCall(vaporHelper('toHandlers'), expr)
@@ -89,7 +85,7 @@ export function genRawProps(props: IRProps[], context: CodegenContext) {
       Boolean as any as (v: CodeFragment[] | undefined) => v is CodeFragment[],
     )
   if (frag.length) {
-    return genMulti(SEGMENTS_ARRAY_NEWLINE, ...frag)
+    return genMulti(DELIMITERS_ARRAY_NEWLINE, ...frag)
   }
 }
 
@@ -98,7 +94,7 @@ function genStaticProps(
   context: CodegenContext,
 ): CodeFragment[] {
   return genMulti(
-    props.length > 1 ? SEGMENTS_OBJECT_NEWLINE : SEGMENTS_OBJECT,
+    props.length > 1 ? DELIMITERS_OBJECT_NEWLINE : DELIMITERS_OBJECT,
     ...props.map(prop => genProp(prop, context, true)),
   )
 }
@@ -147,7 +143,7 @@ function genModelModifiers(
 function genSlots(slots: ComponentSlots, context: CodegenContext) {
   const slotList = Object.entries(slots)
   return genMulti(
-    slotList.length > 1 ? SEGMENTS_OBJECT_NEWLINE : SEGMENTS_OBJECT,
+    slotList.length > 1 ? DELIMITERS_OBJECT_NEWLINE : DELIMITERS_OBJECT,
     ...slotList.map(([name, slot]) => [name, ': ', ...genBlock(slot, context)]),
   )
 }
@@ -157,10 +153,10 @@ function genDynamicSlots(
   context: CodegenContext,
 ) {
   const slotsExpr = genMulti(
-    dynamicSlots.length > 1 ? SEGMENTS_ARRAY_NEWLINE : SEGMENTS_ARRAY,
+    dynamicSlots.length > 1 ? DELIMITERS_ARRAY_NEWLINE : DELIMITERS_ARRAY,
     ...dynamicSlots.map(({ name, fn }) =>
       genMulti(
-        SEGMENTS_OBJECT_NEWLINE,
+        DELIMITERS_OBJECT_NEWLINE,
         ['name: ', ...genExpression(name, context)],
         ['fn: ', ...genBlock(fn, context)],
       ),

+ 17 - 18
packages/compiler-vapor/src/generators/directive.ts

@@ -4,8 +4,9 @@ import { genExpression } from './expression'
 import type { CodegenContext } from '../generate'
 import {
   type CodeFragment,
+  type CodeFragmentDelimiters,
+  DELIMITERS_ARRAY,
   NEWLINE,
-  SEGMENTS_ARRAY,
   genCall,
   genMulti,
 } from './utils'
@@ -28,7 +29,7 @@ export function genWithDirective(
 
   const element = `n${opers[0].element}`
   const directiveItems = opers.map(genDirective)
-  const directives = genMulti(SEGMENTS_ARRAY, ...directiveItems)
+  const directives = genMulti(DELIMITERS_ARRAY, ...directiveItems)
 
   return [
     NEWLINE,
@@ -36,24 +37,22 @@ export function genWithDirective(
   ]
 
   function genDirective({ dir, builtin }: WithDirectiveIRNode): CodeFragment[] {
-    const NULL = 'void 0'
-
     const directive = genDirective()
-    const value = dir.exp
-      ? ['() => ', ...genExpression(dir.exp, context)]
-      : dir.arg || dir.modifiers.length
-        ? NULL
-        : false
-    const argument = dir.arg
-      ? genExpression(dir.arg, context)
-      : dir.modifiers.length
-        ? NULL
-        : false
-    const modifiers = dir.modifiers.length
-      ? ['{ ', genDirectiveModifiers(dir.modifiers), ' }']
-      : false
+    const value = dir.exp && ['() => ', ...genExpression(dir.exp, context)]
+    const argument = dir.arg && genExpression(dir.arg, context)
+    const modifiers = !!dir.modifiers.length && [
+      '{ ',
+      genDirectiveModifiers(dir.modifiers),
+      ' }',
+    ]
 
-    return genMulti(SEGMENTS_ARRAY, directive, value, argument, modifiers)
+    return genMulti(
+      DELIMITERS_ARRAY.concat('void 0') as CodeFragmentDelimiters,
+      directive,
+      value,
+      argument,
+      modifiers,
+    )
 
     function genDirective() {
       const {

+ 2 - 2
packages/compiler-vapor/src/generators/event.ts

@@ -8,8 +8,8 @@ import type { SetDynamicEventsIRNode, SetEventIRNode } from '../ir'
 import { genExpression } from './expression'
 import {
   type CodeFragment,
+  DELIMITERS_OBJECT_NEWLINE,
   NEWLINE,
-  SEGMENTS_OBJECT_NEWLINE,
   genCall,
   genMulti,
 } from './utils'
@@ -59,7 +59,7 @@ export function genSetEvent(
     if (!options.length && !nonKeys.length && !keys.length && !effect) return
 
     return genMulti(
-      SEGMENTS_OBJECT_NEWLINE,
+      DELIMITERS_OBJECT_NEWLINE,
       !!nonKeys.length && ['modifiers: ', genArrayExpression(nonKeys)],
       !!keys.length && ['keys: ', genArrayExpression(keys)],
       effect && ['effect: true'],

+ 1 - 1
packages/compiler-vapor/src/generators/if.ts

@@ -36,7 +36,7 @@ export function genIf(
       vaporHelper('createIf'),
       conditionExpr,
       positiveArg,
-      negativeArg || (once ? 'null' : false),
+      negativeArg,
       once && 'true',
     ),
   )

+ 5 - 5
packages/compiler-vapor/src/generators/prop.ts

@@ -14,9 +14,9 @@ import {
 import { genExpression } from './expression'
 import {
   type CodeFragment,
+  DELIMITERS_ARRAY,
+  DELIMITERS_OBJECT,
   NEWLINE,
-  SEGMENTS_ARRAY,
-  SEGMENTS_OBJECT,
   genCall,
   genMulti,
 } from './utils'
@@ -51,7 +51,7 @@ export function genSetProp(
   return [
     NEWLINE,
     ...genCall(
-      vaporHelper(helperName),
+      [vaporHelper(helperName), null],
       `n${oper.element}`,
       omitKey ? false : genExpression(key, context),
       genPropValue(values, context),
@@ -87,7 +87,7 @@ function genLiteralObjectProps(
   context: CodegenContext,
 ): CodeFragment[] {
   return genMulti(
-    SEGMENTS_OBJECT,
+    DELIMITERS_OBJECT,
     ...props.map(prop => [
       ...genPropKey(prop, context),
       `: `,
@@ -130,7 +130,7 @@ function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) {
     return genExpression(values[0], context)
   }
   return genMulti(
-    SEGMENTS_ARRAY,
+    DELIMITERS_ARRAY,
     ...values.map(expr => genExpression(expr, context)),
   )
 }

+ 2 - 2
packages/compiler-vapor/src/generators/text.ts

@@ -3,8 +3,8 @@ import type { CreateTextNodeIRNode, SetTextIRNode } from '../ir'
 import { genExpression } from './expression'
 import {
   type CodeFragment,
+  DELIMITERS_ARRAY,
   NEWLINE,
-  SEGMENTS_ARRAY,
   genCall,
   genMulti,
 } from './utils'
@@ -37,7 +37,7 @@ export function genCreateTextNode(
     ...genCall(vaporHelper('createTextNode'), [
       effect && '() => ',
       ...genMulti(
-        SEGMENTS_ARRAY,
+        DELIMITERS_ARRAY,
         ...values.map(value => genExpression(value, context)),
       ),
     ]),

+ 28 - 13
packages/compiler-vapor/src/generators/utils.ts

@@ -27,22 +27,34 @@ export type CodeFragment =
   | FalsyValue
 export type CodeFragments = Exclude<CodeFragment, any[]> | CodeFragment[]
 
-export function buildCodeFragment(...frag: CodeFragment[]) {
+export function buildCodeFragment(
+  ...frag: CodeFragment[]
+): [CodeFragment[], (...items: CodeFragment[]) => number] {
   const push = frag.push.bind(frag)
-  return [frag, push] as const
+  return [frag, push]
 }
 
-type Segments = [
+export type CodeFragmentDelimiters = [
   left: CodeFragments,
   right: CodeFragments,
-  segment: CodeFragments,
+  delimiter: CodeFragments,
+  placeholder?: CodeFragments,
 ]
+
 export function genMulti(
-  [left, right, seg]: Segments,
+  [left, right, seg, placeholder]: CodeFragmentDelimiters,
   ...frags: CodeFragments[]
 ): CodeFragment[] {
+  if (placeholder) {
+    while (!frags[frags.length - 1]) {
+      frags.pop()
+    }
+    frags = frags.map(frag => frag || placeholder)
+  } else {
+    frags = frags.filter(Boolean)
+  }
+
   const frag: CodeFragment[] = []
-  frags = frags.filter(Boolean)
   push(left)
   for (let [i, fn] of (
     frags as Array<Exclude<CodeFragments, FalsyValue>>
@@ -58,27 +70,30 @@ export function genMulti(
     frag.push(...fn)
   }
 }
-export const SEGMENTS_ARRAY: Segments = ['[', ']', ', ']
-export const SEGMENTS_ARRAY_NEWLINE: Segments = [
+export const DELIMITERS_ARRAY: CodeFragmentDelimiters = ['[', ']', ', ']
+export const DELIMITERS_ARRAY_NEWLINE: CodeFragmentDelimiters = [
   ['[', INDENT_START, NEWLINE],
   [INDENT_END, NEWLINE, ']'],
   [', ', NEWLINE],
 ]
-export const SEGMENTS_OBJECT: Segments = ['{ ', ' }', ', ']
-export const SEGMENTS_OBJECT_NEWLINE: Segments = [
+export const DELIMITERS_OBJECT: CodeFragmentDelimiters = ['{ ', ' }', ', ']
+export const DELIMITERS_OBJECT_NEWLINE: CodeFragmentDelimiters = [
   ['{', INDENT_START, NEWLINE],
   [INDENT_END, NEWLINE, '}'],
   [', ', NEWLINE],
 ]
 
 export function genCall(
-  name: string,
+  name: string | [name: string, placeholder?: CodeFragments],
   ...frags: CodeFragments[]
 ): CodeFragment[] {
-  return [name, ...genMulti(['(', ')', ', '], ...frags)]
+  const hasPlaceholder = isArray(name)
+  const fnName = hasPlaceholder ? name[0] : name
+  const placeholder = hasPlaceholder ? name[1] : 'null'
+  return [fnName, ...genMulti(['(', ')', ', ', placeholder], ...frags)]
 }
 
-export function genCodeFragment(
+export function codeFragmentToString(
   code: CodeFragment[],
   context: CodegenContext,
 ): [code: string, map: CodegenSourceMapGenerator | undefined] {

+ 1 - 1
packages/compiler-vapor/src/index.ts

@@ -17,7 +17,7 @@ export {
   genCall,
   genMulti,
   buildCodeFragment,
-  genCodeFragment,
+  codeFragmentToString,
   type CodeFragment,
 } from './generators/utils'
 export {