]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: adjust isConstantNode
authorEvan You <evan@vuejs.org>
Wed, 12 Feb 2025 03:57:16 +0000 (11:57 +0800)
committerEvan You <evan@vuejs.org>
Wed, 12 Feb 2025 03:57:16 +0000 (11:57 +0800)
packages/compiler-core/src/babelUtils.ts
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap
packages/compiler-vapor/src/transform.ts
packages/compiler-vapor/src/transforms/transformText.ts
packages/compiler-vapor/src/transforms/vFor.ts
packages/compiler-vapor/src/transforms/vIf.ts
packages/compiler-vapor/src/utils.ts

index f81f269157005dfdbccc22d0714461d316c51429..ccf123f7bb69ddfc1a4277841b352fd4a8b1e58b 100644 (file)
@@ -12,6 +12,7 @@ import type {
   Program,
 } from '@babel/types'
 import { walk } from 'estree-walker'
+import { type BindingMetadata, BindingTypes } from './options'
 
 /**
  * Return value indicates whether the AST walked can be a constant
@@ -543,34 +544,31 @@ export function isStaticNode(node: Node): boolean {
     case 'BooleanLiteral':
     case 'NullLiteral':
     case 'BigIntLiteral':
+    case 'RegExpLiteral':
       return true
   }
   return false
 }
 
-export function isConstantNode(
-  node: Node,
-  onIdentifier: (name: string) => boolean,
-): boolean {
+export function isConstantNode(node: Node, bindings: BindingMetadata): boolean {
   if (isStaticNode(node)) return true
 
   node = unwrapTSNode(node)
   switch (node.type) {
     case 'Identifier':
-      return onIdentifier(node.name)
-    case 'RegExpLiteral':
-      return true
+      const type = bindings[node.name]
+      return type === BindingTypes.LITERAL_CONST
     case 'ObjectExpression':
       return node.properties.every(prop => {
         // { bar() {} } object methods are not considered static nodes
         if (prop.type === 'ObjectMethod') return false
         // { ...{ foo: 1 } }
         if (prop.type === 'SpreadElement')
-          return isConstantNode(prop.argument, onIdentifier)
+          return isConstantNode(prop.argument, bindings)
         // { foo: 1 }
         return (
-          (!prop.computed || isConstantNode(prop.key, onIdentifier)) &&
-          isConstantNode(prop.value, onIdentifier)
+          (!prop.computed || isConstantNode(prop.key, bindings)) &&
+          isConstantNode(prop.value, bindings)
         )
       })
     case 'ArrayExpression':
@@ -579,9 +577,9 @@ export function isConstantNode(
         if (element === null) return true
         // [1, ...[2, 3]]
         if (element.type === 'SpreadElement')
-          return isConstantNode(element.argument, onIdentifier)
+          return isConstantNode(element.argument, bindings)
         // [1, 2]
-        return isConstantNode(element, onIdentifier)
+        return isConstantNode(element, bindings)
       })
   }
   return false
index 302e240ca50c31e02516dd1bef3954f691f04b0c..15da71ff4f320a1f4c60d4a15a91239f07f05df5 100644 (file)
@@ -23,7 +23,7 @@ export function render(_ctx) {
     const n2 = t0()
     _setTemplateRef(n2, "foo", void 0, true)
     return n2
-  })
+  }, null, null, true)
   return n0
 }"
 `;
index bf619b17dc29cc826b19aff0852fabd43948ffa7..76563899d2b770b19aae215805cded9c13ba85b5 100644 (file)
@@ -143,7 +143,9 @@ export class TransformContext<T extends AllNode = AllNode> {
     if (
       this.inVOnce ||
       expressions.length === 0 ||
-      isStaticExpression(this.root, expressions)
+      expressions.every(e =>
+        isStaticExpression(e, this.root.options.bindingMetadata),
+      )
     ) {
       return this.registerOperation(...operations)
     }
index 852cfd463ed4d791ef67e4cb334ff9e3e9039288..12f072818d1315ac86f0ca544bd27f7f37db018c 100644 (file)
@@ -59,7 +59,9 @@ function processTextLike(context: TransformContext<InterpolationNode>) {
   const nonConstantExps = values.filter(v => !isConstantExpression(v))
   const isStatic =
     !nonConstantExps.length ||
-    isStaticExpression(context, nonConstantExps) ||
+    nonConstantExps.every(e =>
+      isStaticExpression(e, context.options.bindingMetadata),
+    ) ||
     context.inVOnce
 
   context.registerOperation({
index 83bda630672af52886762395fe0a38f2977f4a14..69480672a99112a236e68a6428255bdf0e2be2ec 100644 (file)
@@ -16,7 +16,7 @@ import {
   IRNodeTypes,
   type VaporDirectiveNode,
 } from '../ir'
-import { findProp, propToExpression } from '../utils'
+import { findProp, isStaticExpression, propToExpression } from '../utils'
 import { newBlock, wrapTemplate } from './utils'
 
 export const transformVFor: NodeTransform = createStructuralDirectiveTransform(
@@ -76,7 +76,12 @@ export function processFor(
       index: index as SimpleExpressionNode | undefined,
       keyProp: keyProperty,
       render,
-      once: context.inVOnce,
+      once:
+        context.inVOnce ||
+        isStaticExpression(
+          source as SimpleExpressionNode,
+          context.options.bindingMetadata,
+        ),
       component: isComponent,
       onlyChild: !!isOnlyChild,
     })
index f59abe9e2f90321e5c701649b01ef36bee6d55ff..8fad9c3146ec1df75bffd7ea404f454a9078be5a 100644 (file)
@@ -18,6 +18,7 @@ import {
 import { extend } from '@vue/shared'
 import { newBlock, wrapTemplate } from './utils'
 import { getSiblingIf } from './transformComment'
+import { isStaticExpression } from '../utils'
 
 export const transformVIf: NodeTransform = createStructuralDirectiveTransform(
   ['if', 'else', 'else-if'],
@@ -50,7 +51,9 @@ export function processIf(
         id,
         condition: dir.exp!,
         positive: branch,
-        once: context.inVOnce,
+        once:
+          context.inVOnce ||
+          isStaticExpression(dir.exp!, context.options.bindingMetadata),
       })
     }
   } else {
index b20bd3ef16165dc22109cda7a031a594d75bb320..728281914fd786f67aee7e73d6e4edd38c0ef2b7 100644 (file)
@@ -2,6 +2,7 @@ import type { BigIntLiteral, NumericLiteral, StringLiteral } from '@babel/types'
 import { isGloballyAllowed } from '@vue/shared'
 import {
   type AttributeNode,
+  type BindingMetadata,
   BindingTypes,
   type ElementNode,
   NodeTypes,
@@ -14,7 +15,6 @@ import {
 } from '@vue/compiler-dom'
 import type { VaporDirectiveNode } from './ir'
 import { EMPTY_EXPRESSION } from './transforms/utils'
-import type { TransformContext } from './transform'
 
 export const findProp = _findProp as (
   node: ElementNode,
@@ -49,21 +49,16 @@ export function isConstantExpression(exp: SimpleExpressionNode): boolean {
 }
 
 export function isStaticExpression(
-  context: TransformContext,
-  expressions: SimpleExpressionNode[],
+  node: SimpleExpressionNode,
+  bindings: BindingMetadata,
 ): boolean {
-  const {
-    options: { bindingMetadata },
-  } = context
-  const isLiteralConst = (name: string) =>
-    bindingMetadata[name] === BindingTypes.LITERAL_CONST
-  return expressions.every(node => {
-    if (node.ast) {
-      return isConstantNode(node.ast, isLiteralConst)
-    } else if (node.ast === null) {
-      return isLiteralConst(node.content)
-    }
-  })
+  if (node.ast) {
+    return isConstantNode(node.ast, bindings)
+  } else if (node.ast === null) {
+    const type = bindings[node.content]
+    return type === BindingTypes.LITERAL_CONST
+  }
+  return false
 }
 
 export function resolveExpression(