]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: v-skip
authordaiwei <daiwei521@126.com>
Wed, 22 Jan 2025 07:05:01 +0000 (15:05 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 22 Jan 2025 07:05:01 +0000 (15:05 +0800)
packages/compiler-core/src/errors.ts
packages/compiler-core/src/transforms/vSkip.ts

index 42466168e98d7f26f2f2cdc156083b2544476103..b5b5e8cd3e3ba29755be8e7be166c61b4ffef5c9 100644 (file)
@@ -92,6 +92,7 @@ export enum ErrorCodes {
   X_KEEP_ALIVE_INVALID_CHILDREN,
   X_V_SKIP_NO_EXPRESSION,
   X_V_SKIP_ON_TEMPLATE,
+  X_V_SKIP_UNEXPECTED_SLOT,
 
   // generic errors
   X_PREFIX_ID_NOT_SUPPORTED,
@@ -183,6 +184,7 @@ export const errorMessages: Record<ErrorCodes, string> = {
   [ErrorCodes.X_VNODE_HOOKS]: `@vnode-* hooks in templates are no longer supported. Use the vue: prefix instead. For example, @vnode-mounted should be changed to @vue:mounted. @vnode-* hooks support has been removed in 3.4.`,
   [ErrorCodes.X_V_SKIP_NO_EXPRESSION]: `v-skip is missing expression.`,
   [ErrorCodes.X_V_SKIP_ON_TEMPLATE]: `v-skip cannot be used on <template> or <slot> tags.`,
+  [ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT]: `v-skip directive requires the component to have a default slot without slot props`,
 
   // generic errors
   [ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED]: `"prefixIdentifiers" option is not supported in this build of compiler.`,
index ac96f8e3b255d8243b4481bbc714cb63328626ea..d1568ef6bee4ec652a1f1ff8d709a80a9750d201 100644 (file)
@@ -1,7 +1,10 @@
 import {
+  ElementTypes,
   type IfBranchNode,
   NodeTypes,
   type SimpleExpressionNode,
+  type SlotsExpression,
+  type TemplateChildNode,
   createConditionalExpression,
   createSimpleExpression,
 } from '../ast'
@@ -23,16 +26,15 @@ import { validateBrowserExpression } from '../validateExpression'
 export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
   'skip',
   (node, dir, context) => {
+    const loc = dir.exp ? dir.exp.loc : node.loc
     if (isTemplateNode(node) || isSlotOutlet(node)) {
-      const loc = dir.exp ? dir.exp.loc : node.loc
       context.onError(createCompilerError(ErrorCodes.X_V_SKIP_ON_TEMPLATE, loc))
       return
     }
 
     if (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim()) {
-      const loc = dir.exp ? dir.exp.loc : node.loc
       context.onError(
-        createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, dir.loc),
+        createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, loc),
       )
       dir.exp = createSimpleExpression(`true`, false, loc)
     }
@@ -46,13 +48,43 @@ export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
     }
 
     return () => {
+      let children: TemplateChildNode[] = []
+      // for components, extract default slot without props
+      // if not found, throw an error
+      if (node.tagType === ElementTypes.COMPONENT) {
+        const codegenNode = node.codegenNode!
+        if (codegenNode.type === NodeTypes.VNODE_CALL) {
+          const genChildren = codegenNode.children! as SlotsExpression
+          if (genChildren.type === NodeTypes.JS_OBJECT_EXPRESSION) {
+            const prop = genChildren.properties.find(
+              p =>
+                p.type === NodeTypes.JS_PROPERTY &&
+                p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
+                p.key.content === 'default' &&
+                p.value.params === undefined,
+            )
+            if (prop) {
+              children = prop.value.returns as TemplateChildNode[]
+            } else {
+              context.onError(
+                createCompilerError(ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT, loc),
+              )
+            }
+          }
+        }
+      }
+      // for plain elements, take all children
+      else {
+        children = node.children
+      }
       const consequent: IfBranchNode = {
         type: NodeTypes.IF_BRANCH,
         loc: node.loc,
         condition: undefined,
-        children: node.children,
+        children,
         userKey: findProp(node, `key`),
       }
+
       const alternate: IfBranchNode = {
         type: NodeTypes.IF_BRANCH,
         loc: node.loc,
@@ -60,6 +92,7 @@ export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
         children: [node],
         userKey: findProp(node, `key`),
       }
+
       node.codegenNode = createConditionalExpression(
         dir.exp!,
         createCodegenNodeForBranch(consequent, 0, context),