}"
`;
+exports[`compiler: text transform > constant text 1`] = `
+"import { child as _child, template as _template } from 'vue';
+const t0 = _template("<div>2 foo1 1 1 1</div>", 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(" ")
exports[`compiler v-bind > with constant value 1`] = `
"import { setProp as _setProp, template as _template } from 'vue';
-const t0 = _template("<div f=\\"foo1\\" h=\\"1\\"></div>", true)
+const t0 = _template("<div e=\\"2\\" f=\\"foo1\\" g=\\"1\\" h=\\"1\\"></div>", true)
export function render(_ctx, $props, $emit, $attrs, $slots) {
const n0 = t0()
_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)
expect(ir.template).toContain('<code><script></code>')
expect(ir.template).not.toContain('<code><script></code>')
})
+
+ test('constant text', () => {
+ const { code } = compileWithTextTransform(
+ `
+ <div>
+ {{ (2) }}
+ {{ \`foo\${1}\` }}
+ {{ 1 }}
+ {{ 1n }}
+ {{ '1' }}
+ </div>`,
+ )
+ expect(code).includes(`_template("<div>2 foo1 1 1 1</div>", true)`)
+ expect(code).toMatchSnapshot()
+ })
})
const { code } = compileWithVBind(
`
<div
- :a="void 0"
- :b="1 > 2"
- :c="1 + 2"
- :d="1 ? 2 : 3"
- :e="(2)"
- :f="\`foo${1}\`"
+ :a="void 0"
+ :b="1 > 2"
+ :c="1 + 2"
+ :d="1 ? 2 : 3"
+ :e="(2)"
+ :f="\`foo\${1}\`"
:g="1"
:h="'1'"
:i="true"
): 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)
}
} 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
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(
) {
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)))
import {
+ ElementTypes,
ErrorCodes,
NodeTypes,
type SimpleExpressionNode,
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
-import type { BigIntLiteral, NumericLiteral, StringLiteral } from '@babel/types'
import { isGloballyAllowed } from '@vue/shared'
import {
type AttributeNode,
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
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 (
- exp.ast.type === 'TemplateLiteral' &&
- exp.ast.expressions.length === 0
+ !excludeNumber &&
+ (exp.ast.type === 'NumericLiteral' || exp.ast.type === 'BigIntLiteral')
) {
- return exp.ast.quasis[0].value.cooked!
+ return String(exp.ast.value)
+ } else if (exp.ast.type === 'TemplateLiteral') {
+ let result = ''
+ for (const [index, quasi] of exp.ast.quasis.entries()) {
+ result += quasi.value.cooked!
+ if (exp.ast.expressions[index]) {
+ let expressionValue = getLiteralExpressionValue({
+ ast: exp.ast.expressions[index],
+ } as SimpleExpressionNode)
+ if (expressionValue == null) {
+ return null
+ } else {
+ result += expressionValue
+ }
+ }
+ }
+ return result
}
}
return exp.isStatic ? exp.content : null