]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: v-skip
authordaiwei <daiwei521@126.com>
Wed, 22 Jan 2025 04:05:53 +0000 (12:05 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 22 Jan 2025 04:05:53 +0000 (12:05 +0800)
packages/compiler-core/src/ast.ts
packages/compiler-core/src/compile.ts
packages/compiler-core/src/errors.ts
packages/compiler-core/src/transforms/vIf.ts
packages/compiler-core/src/transforms/vSkip.ts [new file with mode: 0644]
packages/shared/src/general.ts

index 2d6df9d90106941708f3398cda3daf64c667ba55..2956a4b3dc337aaad11e08f1303d8fd53948f3be 100644 (file)
@@ -144,6 +144,7 @@ export interface PlainElementNode extends BaseElementNode {
     | SimpleExpressionNode // when hoisted
     | CacheExpression // when cached by v-once
     | MemoExpression // when cached by v-memo
+    | ConditionalExpression
     | undefined
   ssrCodegenNode?: TemplateLiteral
 }
index a697c9d22e679a8d0c7726aa8faa1933feb41026..637d31c5191dc406f6896a97d1d60f15672ab8ca 100644 (file)
@@ -22,6 +22,7 @@ import { transformModel } from './transforms/vModel'
 import { transformFilter } from './compat/transformFilter'
 import { ErrorCodes, createCompilerError, defaultOnError } from './errors'
 import { transformMemo } from './transforms/vMemo'
+import { transformSkip } from './transforms/vSkip'
 
 export type TransformPreset = [
   NodeTransform[],
@@ -35,6 +36,7 @@ export function getBaseTransformPreset(
     [
       transformOnce,
       transformIf,
+      transformSkip,
       transformMemo,
       transformFor,
       ...(__COMPAT__ ? [transformFilter] : []),
index 58e113ab19eef2d27e3e3e950d5651592748c443..42466168e98d7f26f2f2cdc156083b2544476103 100644 (file)
@@ -90,6 +90,8 @@ export enum ErrorCodes {
   X_V_MODEL_ON_PROPS,
   X_INVALID_EXPRESSION,
   X_KEEP_ALIVE_INVALID_CHILDREN,
+  X_V_SKIP_NO_EXPRESSION,
+  X_V_SKIP_ON_TEMPLATE,
 
   // generic errors
   X_PREFIX_ID_NOT_SUPPORTED,
@@ -179,6 +181,8 @@ export const errorMessages: Record<ErrorCodes, string> = {
   [ErrorCodes.X_INVALID_EXPRESSION]: `Error parsing JavaScript expression: `,
   [ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: `<KeepAlive> expects exactly one child component.`,
   [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.`,
 
   // generic errors
   [ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED]: `"prefixIdentifiers" option is not supported in this build of compiler.`,
index 54c505407a363783a66753dd187278139e3ec388..f2e1fd5e848456b2cb7f1dae28445ed79811204a 100644 (file)
@@ -217,7 +217,7 @@ function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
   }
 }
 
-function createCodegenNodeForBranch(
+export function createCodegenNodeForBranch(
   branch: IfBranchNode,
   keyIndex: number,
   context: TransformContext,
diff --git a/packages/compiler-core/src/transforms/vSkip.ts b/packages/compiler-core/src/transforms/vSkip.ts
new file mode 100644 (file)
index 0000000..ac96f8e
--- /dev/null
@@ -0,0 +1,70 @@
+import {
+  type IfBranchNode,
+  NodeTypes,
+  type SimpleExpressionNode,
+  createConditionalExpression,
+  createSimpleExpression,
+} from '../ast'
+import {
+  type NodeTransform,
+  createStructuralDirectiveTransform,
+} from '../transform'
+import {
+  ErrorCodes,
+  createCompilerError,
+  findProp,
+  isSlotOutlet,
+  isTemplateNode,
+  processExpression,
+} from '@vue/compiler-core'
+import { createCodegenNodeForBranch } from './vIf'
+import { validateBrowserExpression } from '../validateExpression'
+
+export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
+  'skip',
+  (node, dir, context) => {
+    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),
+      )
+      dir.exp = createSimpleExpression(`true`, false, loc)
+    }
+
+    if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {
+      dir.exp = processExpression(dir.exp as SimpleExpressionNode, context)
+    }
+
+    if (__DEV__ && __BROWSER__ && dir.exp) {
+      validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
+    }
+
+    return () => {
+      const consequent: IfBranchNode = {
+        type: NodeTypes.IF_BRANCH,
+        loc: node.loc,
+        condition: undefined,
+        children: node.children,
+        userKey: findProp(node, `key`),
+      }
+      const alternate: IfBranchNode = {
+        type: NodeTypes.IF_BRANCH,
+        loc: node.loc,
+        condition: undefined,
+        children: [node],
+        userKey: findProp(node, `key`),
+      }
+      node.codegenNode = createConditionalExpression(
+        dir.exp!,
+        createCodegenNodeForBranch(consequent, 0, context),
+        createCodegenNodeForBranch(alternate, 1, context),
+      )
+    }
+  },
+)
index 9c6a23132404d8c6bd54dacc8b073a2b18e837a7..d5b5e0b942d691da65872cec8f63ccdd62d68f5f 100644 (file)
@@ -90,7 +90,7 @@ export const isReservedProp: (key: string) => boolean = /*@__PURE__*/ makeMap(
 
 export const isBuiltInDirective: (key: string) => boolean =
   /*@__PURE__*/ makeMap(
-    'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo',
+    'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo,skip',
   )
 
 const cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {