]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(compiler-vapor): group directives by same element
author三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sat, 27 Jan 2024 12:49:43 +0000 (20:49 +0800)
committer三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sat, 27 Jan 2024 12:49:43 +0000 (20:49 +0800)
packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
packages/compiler-vapor/__tests__/compile.spec.ts
packages/compiler-vapor/src/generate.ts
packages/compiler-vapor/src/generators/directive.ts

index 2ce2fddd02e11c7a34e38b4a2144f00080d8d4e1..8de407e750aec702204eb5680f58c211cc14ae5d 100644 (file)
@@ -16,6 +16,18 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`compile > custom directive > basic 1`] = `
+"import { template as _template, children as _children, withDirectives as _withDirectives, resolveDirective("vTest") as _resolveDirective("vTest"), resolveDirective("vHello") as _resolveDirective("vHello") } from 'vue/vapor';
+
+export function render(_ctx) {
+  const t0 = _template("<div></div>")
+  const n0 = t0()
+  const { 0: [n1],} = _children(n0)
+  _withDirectives(n1, [[_resolveDirective("vTest")], [_resolveDirective("vHello"), void 0, void 0, { world: true }]])
+  return n0
+}"
+`;
+
 exports[`compile > directives > custom directive > basic 1`] = `
 "import { template as _template, children as _children, withDirectives as _withDirectives } from 'vue/vapor';
 
index a16b816552cc107e3ad786d5b0ebefb954ec0f66..23ba9888286dd9421ba9c819a72dc0dfeeec8f66 100644 (file)
@@ -207,4 +207,11 @@ describe('compile', () => {
 
     // TODO: add more test for expression parsing (v-on, v-slot, v-for)
   })
+
+  describe('custom directive', () => {
+    test('basic', () => {
+      const code = compile(`<div v-test v-hello.world />`)
+      expect(code).matchSnapshot()
+    })
+  })
 })
index bba27e32541edb236e582da8b533ef0831832756..4022c5a6c556409be948260db5c33e5f048d6563 100644 (file)
@@ -281,11 +281,12 @@ export function generate(
         )
       }
 
-      for (const oper of ir.operation.filter(
+      const directiveOps = ir.operation.filter(
         (oper): oper is WithDirectiveIRNode =>
           oper.type === IRNodeTypes.WITH_DIRECTIVE,
-      )) {
-        genWithDirective(oper, ctx)
+      )
+      for (const directives of groupDirective(directiveOps)) {
+        genWithDirective(directives, ctx)
       }
 
       for (const operation of ir.operation) {
@@ -393,3 +394,12 @@ function genOperation(oper: OperationNode, context: CodegenContext) {
       return checkNever(oper)
   }
 }
+
+function groupDirective(ops: WithDirectiveIRNode[]): WithDirectiveIRNode[][] {
+  const directiveMap: Record<number, WithDirectiveIRNode[]> = {}
+  for (const oper of ops) {
+    if (!directiveMap[oper.element]) directiveMap[oper.element] = []
+    directiveMap[oper.element].push(oper)
+  }
+  return Object.values(directiveMap)
+}
index 4b54bc5b79a6f8104c08782bed1b98023fe7f217..0092f9ed182a96417e5b566d979644fe6e3f65cc 100644 (file)
@@ -5,61 +5,67 @@ import type { CodegenContext } from '../generate'
 import type { WithDirectiveIRNode } from '../ir'
 
 export function genWithDirective(
-  oper: WithDirectiveIRNode,
+  opers: WithDirectiveIRNode[],
   context: CodegenContext,
 ) {
   const { push, newline, pushFnCall, pushMulti, vaporHelper, bindingMetadata } =
     context
-  const { dir, builtin } = oper
 
-  // TODO merge directive for the same node
   newline()
   pushFnCall(
     vaporHelper('withDirectives'),
     // 1st arg: node
-    `n${oper.element}`,
+    `n${opers[0].element}`,
     // 2nd arg: directives
     () => {
-      push('[')
       // directive
-      pushMulti(['[', ']', ', '], () => {
-        if (dir.name === 'show') {
-          push(vaporHelper('vShow'))
-        } else if (builtin) {
-          push(vaporHelper(builtin))
-        } else {
-          const directiveReference = camelize(`v-${dir.name}`)
-          // TODO resolve directive
-          if (bindingMetadata[directiveReference]) {
-            const directiveExpression =
-              createSimpleExpression(directiveReference)
-            directiveExpression.ast = null
-            genExpression(directiveExpression, context)
+      pushMulti(
+        ['[', ']', ', '],
+        ...opers.map((oper) => () => {
+          push('[')
+
+          const { dir, builtin } = oper
+          if (dir.name === 'show') {
+            push(vaporHelper('vShow'))
+          } else if (builtin) {
+            push(vaporHelper(builtin))
+          } else {
+            const directiveReference = camelize(`v-${dir.name}`)
+            // TODO resolve directive
+            if (bindingMetadata[directiveReference]) {
+              const directiveExpression =
+                createSimpleExpression(directiveReference)
+              directiveExpression.ast = null
+              genExpression(directiveExpression, context)
+            } else {
+              push(vaporHelper(`resolveDirective("${directiveReference}")`))
+            }
           }
-        }
 
-        if (dir.exp) {
-          push(', () => ')
-          genExpression(dir.exp, context)
-        } else if (dir.arg || dir.modifiers.length) {
-          push(', void 0')
-        }
+          if (dir.exp) {
+            push(', () => ')
+            genExpression(dir.exp, context)
+          } else if (dir.arg || dir.modifiers.length) {
+            push(', void 0')
+          }
 
-        if (dir.arg) {
-          push(', ')
-          genExpression(dir.arg, context)
-        } else if (dir.modifiers.length) {
-          push(', void 0')
-        }
+          if (dir.arg) {
+            push(', ')
+            genExpression(dir.arg, context)
+          } else if (dir.modifiers.length) {
+            push(', void 0')
+          }
+
+          if (dir.modifiers.length) {
+            push(', ')
+            push('{ ')
+            push(genDirectiveModifiers(dir.modifiers))
+            push(' }')
+          }
 
-        if (dir.modifiers.length) {
-          push(', ')
-          push('{ ')
-          push(genDirectiveModifiers(dir.modifiers))
-          push(' }')
-        }
-      })
-      push(']')
+          push(']')
+        }),
+      )
     },
   )
 }