Skip to content

Commit 4b9399a

Browse files
authored
fix(compiler-vapor): handle numbers as static text (#13957)
1 parent 60aba09 commit 4b9399a

File tree

8 files changed

+74
-47
lines changed

8 files changed

+74
-47
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/transformText.spec.ts.snap

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ export function render(_ctx) {
1111
}"
1212
`;
1313

14+
exports[`compiler: text transform > constant text 1`] = `
15+
"import { child as _child, template as _template } from 'vue';
16+
const t0 = _template("<div>2 foo1 1 1 1</div>", true)
17+
18+
export function render(_ctx) {
19+
const n1 = t0()
20+
const n0 = _child(n1)
21+
return n1
22+
}"
23+
`;
24+
1425
exports[`compiler: text transform > no consecutive text 1`] = `
1526
"import { setText as _setText, template as _template } from 'vue';
1627
const t0 = _template(" ")

packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -633,16 +633,14 @@ export function render(_ctx) {
633633
634634
exports[`compiler v-bind > with constant value 1`] = `
635635
"import { setProp as _setProp, template as _template } from 'vue';
636-
const t0 = _template("<div f=\\"foo1\\" h=\\"1\\"></div>", true)
636+
const t0 = _template("<div e=\\"2\\" f=\\"foo1\\" g=\\"1\\" h=\\"1\\"></div>", true)
637637
638638
export function render(_ctx, $props, $emit, $attrs, $slots) {
639639
const n0 = t0()
640640
_setProp(n0, "a", void 0)
641641
_setProp(n0, "b", 1 > 2)
642642
_setProp(n0, "c", 1 + 2)
643643
_setProp(n0, "d", 1 ? 2 : 3)
644-
_setProp(n0, "e", (2))
645-
_setProp(n0, "g", 1)
646644
_setProp(n0, "i", true)
647645
_setProp(n0, "j", null)
648646
_setProp(n0, "k", _ctx.x)

packages/compiler-vapor/__tests__/transforms/transformText.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,19 @@ describe('compiler: text transform', () => {
5454
expect(ir.template).toContain('<code>&lt;script&gt;</code>')
5555
expect(ir.template).not.toContain('<code><script></code>')
5656
})
57+
58+
test('constant text', () => {
59+
const { code } = compileWithTextTransform(
60+
`
61+
<div>
62+
{{ (2) }}
63+
{{ \`foo\${1}\` }}
64+
{{ 1 }}
65+
{{ 1n }}
66+
{{ '1' }}
67+
</div>`,
68+
)
69+
expect(code).includes(`_template("<div>2 foo1 1 1 1</div>", true)`)
70+
expect(code).toMatchSnapshot()
71+
})
5772
})

packages/compiler-vapor/__tests__/transforms/vBind.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -666,12 +666,12 @@ describe('compiler v-bind', () => {
666666
const { code } = compileWithVBind(
667667
`
668668
<div
669-
:a="void 0"
670-
:b="1 > 2"
671-
:c="1 + 2"
672-
:d="1 ? 2 : 3"
673-
:e="(2)"
674-
:f="\`foo${1}\`"
669+
:a="void 0"
670+
:b="1 > 2"
671+
:c="1 + 2"
672+
:d="1 ? 2 : 3"
673+
:e="(2)"
674+
:f="\`foo\${1}\`"
675675
:g="1"
676676
:h="'1'"
677677
:i="true"

packages/compiler-vapor/src/generators/text.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function combineValues(
3030
): CodeFragment[] {
3131
return values.flatMap((value, i) => {
3232
let exp = genExpression(value, context)
33-
if (!jsx && getLiteralExpressionValue(value) == null) {
33+
if (!jsx && getLiteralExpressionValue(value, true) == null) {
3434
// dynamic, wrap with toDisplayString
3535
exp = genCall(context.helper('toDisplayString'), exp)
3636
}

packages/compiler-vapor/src/transforms/transformText.ts

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ import {
1111
} from '@vue/compiler-dom'
1212
import type { NodeTransform, TransformContext } from '../transform'
1313
import { DynamicFlag, IRNodeTypes } from '../ir'
14-
import {
15-
getLiteralExpressionValue,
16-
isConstantExpression,
17-
isStaticExpression,
18-
} from '../utils'
14+
import { getLiteralExpressionValue } from '../utils'
1915
import { escapeHtml } from '@vue/shared'
2016

2117
type TextLike = TextNode | InterpolationNode
@@ -108,31 +104,19 @@ function processInterpolation(context: TransformContext<InterpolationNode>) {
108104
context.template += ' '
109105
const id = context.reference()
110106

111-
if (values.length === 0) {
107+
if (
108+
values.length === 0 ||
109+
(values.every(v => getLiteralExpressionValue(v) != null) &&
110+
parentNode.type !== NodeTypes.ROOT)
111+
) {
112112
return
113113
}
114114

115-
const nonConstantExps = values.filter(v => !isConstantExpression(v))
116-
const isStatic =
117-
!nonConstantExps.length ||
118-
nonConstantExps.every(e =>
119-
isStaticExpression(e, context.options.bindingMetadata),
120-
) ||
121-
context.inVOnce
122-
123-
if (isStatic) {
124-
context.registerOperation({
125-
type: IRNodeTypes.SET_TEXT,
126-
element: id,
127-
values,
128-
})
129-
} else {
130-
context.registerEffect(values, {
131-
type: IRNodeTypes.SET_TEXT,
132-
element: id,
133-
values,
134-
})
135-
}
115+
context.registerEffect(values, {
116+
type: IRNodeTypes.SET_TEXT,
117+
element: id,
118+
values,
119+
})
136120
}
137121

138122
function processTextContainer(
@@ -141,7 +125,7 @@ function processTextContainer(
141125
) {
142126
const values = processTextLikeChildren(children, context)
143127

144-
const literals = values.map(getLiteralExpressionValue)
128+
const literals = values.map(value => getLiteralExpressionValue(value))
145129

146130
if (literals.every(l => l != null)) {
147131
context.childrenTemplate = literals.map(l => escapeHtml(String(l)))

packages/compiler-vapor/src/transforms/vBind.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
ElementTypes,
23
ErrorCodes,
34
NodeTypes,
45
type SimpleExpressionNode,
@@ -46,7 +47,8 @@ export const transformVBind: DirectiveTransform = (dir, node, context) => {
4647
exp = createSimpleExpression('', true, loc)
4748
}
4849

49-
exp = resolveExpression(exp)
50+
const isComponent = node.tagType === ElementTypes.COMPONENT
51+
exp = resolveExpression(exp, isComponent)
5052
arg = resolveExpression(arg)
5153

5254
if (arg.isStatic && isReservedProp(arg.content)) return

packages/compiler-vapor/src/utils.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { BigIntLiteral, NumericLiteral, StringLiteral } from '@babel/types'
21
import { isGloballyAllowed } from '@vue/shared'
32
import {
43
type AttributeNode,
@@ -64,27 +63,45 @@ export function isStaticExpression(
6463

6564
export function resolveExpression(
6665
exp: SimpleExpressionNode,
66+
isComponent?: boolean,
6767
): SimpleExpressionNode {
6868
if (!exp.isStatic) {
69-
const value = getLiteralExpressionValue(exp)
69+
const value = getLiteralExpressionValue(exp, isComponent)
7070
if (value !== null) {
71-
return createSimpleExpression('' + value, true, exp.loc)
71+
return createSimpleExpression(value, true, exp.loc)
7272
}
7373
}
7474
return exp
7575
}
7676

7777
export function getLiteralExpressionValue(
7878
exp: SimpleExpressionNode,
79-
): number | string | boolean | null {
79+
excludeNumber?: boolean,
80+
): string | null {
8081
if (exp.ast) {
8182
if (exp.ast.type === 'StringLiteral') {
82-
return (exp.ast as StringLiteral | NumericLiteral | BigIntLiteral).value
83+
return exp.ast.value
8384
} else if (
84-
exp.ast.type === 'TemplateLiteral' &&
85-
exp.ast.expressions.length === 0
85+
!excludeNumber &&
86+
(exp.ast.type === 'NumericLiteral' || exp.ast.type === 'BigIntLiteral')
8687
) {
87-
return exp.ast.quasis[0].value.cooked!
88+
return String(exp.ast.value)
89+
} else if (exp.ast.type === 'TemplateLiteral') {
90+
let result = ''
91+
for (const [index, quasi] of exp.ast.quasis.entries()) {
92+
result += quasi.value.cooked!
93+
if (exp.ast.expressions[index]) {
94+
let expressionValue = getLiteralExpressionValue({
95+
ast: exp.ast.expressions[index],
96+
} as SimpleExpressionNode)
97+
if (expressionValue == null) {
98+
return null
99+
} else {
100+
result += expressionValue
101+
}
102+
}
103+
}
104+
return result
88105
}
89106
}
90107
return exp.isStatic ? exp.content : null

0 commit comments

Comments
 (0)