From 1cc835f7fff88aebe10d594e79acc9196691a058 Mon Sep 17 00:00:00 2001
From: zhiyuanzmj <260480378@qq.com>
Date: Thu, 2 Oct 2025 15:18:28 +0800
Subject: [PATCH 1/3] fix(compiler-vapor): handle numbers as static text
---
.../__snapshots__/transformText.spec.ts.snap | 11 +++++
.../__snapshots__/vBind.spec.ts.snap | 4 +-
.../transforms/transformText.spec.ts | 14 +++++++
.../compiler-vapor/src/generators/text.ts | 2 +-
.../src/transforms/transformText.ts | 40 ++++++-------------
.../compiler-vapor/src/transforms/vBind.ts | 4 +-
packages/compiler-vapor/src/utils.ts | 16 +++++---
7 files changed, 53 insertions(+), 38 deletions(-)
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
index f18f8520353..1898cce3bff 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
@@ -11,6 +11,17 @@ export function render(_ctx) {
}"
`;
+exports[`compiler: text transform > constant text 1`] = `
+"import { child as _child, template as _template } from 'vue';
+const t0 = _template("
2 foo1 1 1
", true)
+
+export function render(_ctx) {
+ const n1 = t0()
+ const n0 = _child(n1)
+ return n1
+}"
+`;
+
exports[`compiler: text transform > no consecutive text 1`] = `
"import { setText as _setText, template as _template } from 'vue';
const t0 = _template(" ")
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap
index 4ea0db55fe5..4bbf1884d94 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap
@@ -633,7 +633,7 @@ export function render(_ctx) {
exports[`compiler v-bind > with constant value 1`] = `
"import { setProp as _setProp, template as _template } from 'vue';
-const t0 = _template("", true)
+const t0 = _template("", true)
export function render(_ctx, $props, $emit, $attrs, $slots) {
const n0 = t0()
@@ -641,8 +641,6 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
_setProp(n0, "b", 1 > 2)
_setProp(n0, "c", 1 + 2)
_setProp(n0, "d", 1 ? 2 : 3)
- _setProp(n0, "e", (2))
- _setProp(n0, "g", 1)
_setProp(n0, "i", true)
_setProp(n0, "j", null)
_setProp(n0, "k", _ctx.x)
diff --git a/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
index dbff56f2a42..747be50b428 100644
--- a/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
@@ -54,4 +54,18 @@ describe('compiler: text transform', () => {
expect(ir.template).toContain('<script>')
expect(ir.template).not.toContain('')
})
+
+ test('constant text', () => {
+ const { code } = compileWithTextTransform(
+ `
+
+ {{ (2) }}
+ {{ \`foo\` }}
+ {{ 1 }}
+ {{ '1' }}
+
`,
+ )
+ expect(code).includes(`_template("2 foo1 1 1
", true)`)
+ expect(code).toMatchSnapshot()
+ })
})
diff --git a/packages/compiler-vapor/src/generators/text.ts b/packages/compiler-vapor/src/generators/text.ts
index 89e3167c664..69728179bd1 100644
--- a/packages/compiler-vapor/src/generators/text.ts
+++ b/packages/compiler-vapor/src/generators/text.ts
@@ -25,7 +25,7 @@ function combineValues(
): CodeFragment[] {
return values.flatMap((value, i) => {
let exp = genExpression(value, context)
- if (!jsx && getLiteralExpressionValue(value) == null) {
+ if (!jsx && getLiteralExpressionValue(value, true) == null) {
// dynamic, wrap with toDisplayString
exp = genCall(context.helper('toDisplayString'), exp)
}
diff --git a/packages/compiler-vapor/src/transforms/transformText.ts b/packages/compiler-vapor/src/transforms/transformText.ts
index dd81bec1e80..b2295630542 100644
--- a/packages/compiler-vapor/src/transforms/transformText.ts
+++ b/packages/compiler-vapor/src/transforms/transformText.ts
@@ -11,11 +11,7 @@ import {
} from '@vue/compiler-dom'
import type { NodeTransform, TransformContext } from '../transform'
import { DynamicFlag, IRNodeTypes } from '../ir'
-import {
- getLiteralExpressionValue,
- isConstantExpression,
- isStaticExpression,
-} from '../utils'
+import { getLiteralExpressionValue } from '../utils'
import { escapeHtml } from '@vue/shared'
type TextLike = TextNode | InterpolationNode
@@ -108,31 +104,19 @@ function processInterpolation(context: TransformContext) {
context.template += ' '
const id = context.reference()
- if (values.length === 0) {
+ if (
+ values.length === 0 ||
+ (values.every(v => getLiteralExpressionValue(v) != null) &&
+ parentNode.type !== NodeTypes.ROOT)
+ ) {
return
}
- const nonConstantExps = values.filter(v => !isConstantExpression(v))
- const isStatic =
- !nonConstantExps.length ||
- nonConstantExps.every(e =>
- isStaticExpression(e, context.options.bindingMetadata),
- ) ||
- context.inVOnce
-
- if (isStatic) {
- context.registerOperation({
- type: IRNodeTypes.SET_TEXT,
- element: id,
- values,
- })
- } else {
- context.registerEffect(values, {
- type: IRNodeTypes.SET_TEXT,
- element: id,
- values,
- })
- }
+ context.registerEffect(values, {
+ type: IRNodeTypes.SET_TEXT,
+ element: id,
+ values,
+ })
}
function processTextContainer(
@@ -141,7 +125,7 @@ function processTextContainer(
) {
const values = processTextLikeChildren(children, context)
- const literals = values.map(getLiteralExpressionValue)
+ const literals = values.map(value => getLiteralExpressionValue(value))
if (literals.every(l => l != null)) {
context.childrenTemplate = literals.map(l => escapeHtml(String(l)))
diff --git a/packages/compiler-vapor/src/transforms/vBind.ts b/packages/compiler-vapor/src/transforms/vBind.ts
index dc56eb34b4e..86efa866977 100644
--- a/packages/compiler-vapor/src/transforms/vBind.ts
+++ b/packages/compiler-vapor/src/transforms/vBind.ts
@@ -1,4 +1,5 @@
import {
+ ElementTypes,
ErrorCodes,
NodeTypes,
type SimpleExpressionNode,
@@ -46,7 +47,8 @@ export const transformVBind: DirectiveTransform = (dir, node, context) => {
exp = createSimpleExpression('', true, loc)
}
- exp = resolveExpression(exp)
+ const isComponent = node.tagType === ElementTypes.COMPONENT
+ exp = resolveExpression(exp, isComponent)
arg = resolveExpression(arg)
if (arg.isStatic && isReservedProp(arg.content)) return
diff --git a/packages/compiler-vapor/src/utils.ts b/packages/compiler-vapor/src/utils.ts
index 728281914fd..47c3f15ef87 100644
--- a/packages/compiler-vapor/src/utils.ts
+++ b/packages/compiler-vapor/src/utils.ts
@@ -1,4 +1,3 @@
-import type { BigIntLiteral, NumericLiteral, StringLiteral } from '@babel/types'
import { isGloballyAllowed } from '@vue/shared'
import {
type AttributeNode,
@@ -63,11 +62,12 @@ export function isStaticExpression(
export function resolveExpression(
exp: SimpleExpressionNode,
+ isComponent?: boolean,
): SimpleExpressionNode {
if (!exp.isStatic) {
- const value = getLiteralExpressionValue(exp)
+ const value = getLiteralExpressionValue(exp, isComponent)
if (value !== null) {
- return createSimpleExpression('' + value, true, exp.loc)
+ return createSimpleExpression(value, true, exp.loc)
}
}
return exp
@@ -75,10 +75,16 @@ export function resolveExpression(
export function getLiteralExpressionValue(
exp: SimpleExpressionNode,
-): number | string | boolean | null {
+ excludeNumber?: boolean,
+): string | null {
if (exp.ast) {
if (exp.ast.type === 'StringLiteral') {
- return (exp.ast as StringLiteral | NumericLiteral | BigIntLiteral).value
+ return exp.ast.value
+ } else if (
+ !excludeNumber &&
+ (exp.ast.type === 'NumericLiteral' || exp.ast.type === 'BigIntLiteral')
+ ) {
+ return String(exp.ast.value)
} else if (
exp.ast.type === 'TemplateLiteral' &&
exp.ast.expressions.length === 0
From d80e25e6b4830401b46407a2ee904aa89bcca97f Mon Sep 17 00:00:00 2001
From: zhiyuanzmj <260480378@qq.com>
Date: Thu, 2 Oct 2025 15:39:19 +0800
Subject: [PATCH 2/3] chore: update
---
.../transforms/__snapshots__/transformText.spec.ts.snap | 2 +-
.../compiler-vapor/__tests__/transforms/transformText.spec.ts | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
index 1898cce3bff..d792e6cc828 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
@@ -13,7 +13,7 @@ export function render(_ctx) {
exports[`compiler: text transform > constant text 1`] = `
"import { child as _child, template as _template } from 'vue';
-const t0 = _template("2 foo1 1 1
", true)
+const t0 = _template("2 foo 1 1 1
", true)
export function render(_ctx) {
const n1 = t0()
diff --git a/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
index 747be50b428..756f7ad6ede 100644
--- a/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
@@ -62,10 +62,11 @@ describe('compiler: text transform', () => {
{{ (2) }}
{{ \`foo\` }}
{{ 1 }}
+ {{ 1n }}
{{ '1' }}
`,
)
- expect(code).includes(`_template("2 foo1 1 1
", true)`)
+ expect(code).includes(`_template("2 foo 1 1 1
", true)`)
expect(code).toMatchSnapshot()
})
})
From 0a7c7b052a64506405c1297234955e83faac24d0 Mon Sep 17 00:00:00 2001
From: zhiyuanzmj <260480378@qq.com>
Date: Thu, 16 Oct 2025 16:39:58 +0800
Subject: [PATCH 3/3] chore: TemplateLiteral
---
.../__snapshots__/transformText.spec.ts.snap | 2 +-
.../transforms/transformText.spec.ts | 4 ++--
.../__tests__/transforms/vBind.spec.ts | 12 +++++------
packages/compiler-vapor/src/utils.ts | 21 ++++++++++++++-----
4 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
index d792e6cc828..e1981aac172 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap
@@ -13,7 +13,7 @@ export function render(_ctx) {
exports[`compiler: text transform > constant text 1`] = `
"import { child as _child, template as _template } from 'vue';
-const t0 = _template("2 foo 1 1 1
", true)
+const t0 = _template("2 foo1 1 1 1
", true)
export function render(_ctx) {
const n1 = t0()
diff --git a/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
index 756f7ad6ede..1c929f0f206 100644
--- a/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
@@ -60,13 +60,13 @@ describe('compiler: text transform', () => {
`
{{ (2) }}
- {{ \`foo\` }}
+ {{ \`foo\${1}\` }}
{{ 1 }}
{{ 1n }}
{{ '1' }}
`,
)
- expect(code).includes(`_template("2 foo 1 1 1
", true)`)
+ expect(code).includes(`_template("2 foo1 1 1 1
", true)`)
expect(code).toMatchSnapshot()
})
})
diff --git a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
index e96186c275c..9c07b9de90b 100644
--- a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
@@ -666,12 +666,12 @@ describe('compiler v-bind', () => {
const { code } = compileWithVBind(
`