refactor(compiler-vapor): inline literal value into template

This commit is contained in:
三咲智子 Kevin Deng 2024-05-29 16:17:10 +08:00
parent 107569b922
commit 00c6e6dc73
No known key found for this signature in database
6 changed files with 46 additions and 29 deletions

View File

@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: children transform > children & sibling references 1`] = ` exports[`compiler: children transform > children & sibling references 1`] = `
"import { next as _next, setText as _setText, createTextNode as _createTextNode, insert as _insert, template as _template } from 'vue/vapor'; "import { next as _next, createTextNode as _createTextNode, insert as _insert, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
const t0 = _template("<div><p></p> <!><p></p></div>") const t0 = _template("<div><p></p> <!><p></p></div>")
export function render(_ctx) { export function render(_ctx) {
@ -9,10 +9,10 @@ export function render(_ctx) {
const n0 = n4.firstChild const n0 = n4.firstChild
const n3 = _next(n0, 2) const n3 = _next(n0, 2)
const n2 = n3.nextSibling const n2 = n3.nextSibling
_setText(n0, 'first') const n1 = _createTextNode(() => [_ctx.second, " ", _ctx.third, " "])
const n1 = _createTextNode(['second', " ", 'third', " "])
_setText(n2, 'forth')
_insert(n1, n4, n3) _insert(n1, n4, n3)
_renderEffect(() => _setText(n0, _ctx.first))
_renderEffect(() => _setText(n2, _ctx.forth))
return n4 return n4
}" }"
`; `;

View File

@ -23,12 +23,11 @@ export function render(_ctx) {
`; `;
exports[`v-text > should raise error if has no expression 1`] = ` exports[`v-text > should raise error if has no expression 1`] = `
"import { setText as _setText, template as _template } from 'vue/vapor'; "import { template as _template } from 'vue/vapor';
const t0 = _template("<div></div>") const t0 = _template("<div></div>")
export function render(_ctx) { export function render(_ctx) {
const n0 = t0() const n0 = t0()
_setText(n0, "")
return n0 return n0
}" }"
`; `;

View File

@ -21,10 +21,10 @@ describe('compiler: children transform', () => {
test('children & sibling references', () => { test('children & sibling references', () => {
const { code, vaporHelpers } = compileWithElementTransform( const { code, vaporHelpers } = compileWithElementTransform(
`<div> `<div>
<p>{{'first'}}</p> <p>{{ first }}</p>
{{'second'}} {{ second }}
{{'third'}} {{ third }}
<p>{{'forth'}}</p> <p>{{ forth }}</p>
</div>`, </div>`,
) )
expect(code).toMatchSnapshot() expect(code).toMatchSnapshot()

View File

@ -11,7 +11,7 @@ import {
} from '@vue/compiler-dom' } from '@vue/compiler-dom'
import type { NodeTransform, TransformContext } from '../transform' import type { NodeTransform, TransformContext } from '../transform'
import { DynamicFlag, IRNodeTypes } from '../ir' import { DynamicFlag, IRNodeTypes } from '../ir'
import { isConstantExpression } from '../utils' import { getLiteralExpressionValue, isConstantExpression } from '../utils'
type TextLike = TextNode | InterpolationNode type TextLike = TextNode | InterpolationNode
const seen = new WeakMap< const seen = new WeakMap<
@ -65,11 +65,16 @@ function processTextLikeContainer(
context: TransformContext<ElementNode>, context: TransformContext<ElementNode>,
) { ) {
const values = children.map(child => createTextLikeExpression(child, context)) const values = children.map(child => createTextLikeExpression(child, context))
context.registerEffect(values, { const literals = values.map(getLiteralExpressionValue)
type: IRNodeTypes.SET_TEXT, if (literals.every(l => l != null)) {
element: context.reference(), context.childrenTemplate = literals.map(l => String(l))
values, } else {
}) context.registerEffect(values, {
type: IRNodeTypes.SET_TEXT,
element: context.reference(),
values,
})
}
} }
function createTextLikeExpression(node: TextLike, context: TransformContext) { function createTextLikeExpression(node: TextLike, context: TransformContext) {

View File

@ -2,6 +2,7 @@ import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
import { IRNodeTypes } from '../ir' import { IRNodeTypes } from '../ir'
import { EMPTY_EXPRESSION } from './utils' import { EMPTY_EXPRESSION } from './utils'
import type { DirectiveTransform } from '../transform' import type { DirectiveTransform } from '../transform'
import { getLiteralExpressionValue } from '../utils'
export const transformVText: DirectiveTransform = (dir, node, context) => { export const transformVText: DirectiveTransform = (dir, node, context) => {
let { exp, loc } = dir let { exp, loc } = dir
@ -18,9 +19,14 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
context.childrenTemplate.length = 0 context.childrenTemplate.length = 0
} }
context.registerEffect([exp], { const literal = getLiteralExpressionValue(exp)
type: IRNodeTypes.SET_TEXT, if (literal != null) {
element: context.reference(), context.childrenTemplate = [String(literal)]
values: [exp], } else {
}) context.registerEffect([exp], {
type: IRNodeTypes.SET_TEXT,
element: context.reference(),
values: [exp],
})
}
} }

View File

@ -1,4 +1,4 @@
import type { NumericLiteral, StringLiteral } from '@babel/types' import type { BigIntLiteral, NumericLiteral, StringLiteral } from '@babel/types'
import { isGloballyAllowed } from '@vue/shared' import { isGloballyAllowed } from '@vue/shared'
import { import {
type AttributeNode, type AttributeNode,
@ -55,13 +55,20 @@ export function resolveExpression(exp: SimpleExpressionNode) {
export function getLiteralExpressionValue( export function getLiteralExpressionValue(
exp: SimpleExpressionNode, exp: SimpleExpressionNode,
): number | string | null { ): number | string | boolean | null {
if ( if (!__BROWSER__ && exp.ast) {
!__BROWSER__ && if (
exp.ast && ['StringLiteral', 'NumericLiteral', 'BigIntLiteral'].includes(
['StringLiteral', 'NumericLiteral'].includes(exp.ast.type) exp.ast.type,
) { )
return (exp.ast as StringLiteral | NumericLiteral).value ) {
return (exp.ast as StringLiteral | NumericLiteral | BigIntLiteral).value
} else if (
exp.ast.type === 'TemplateLiteral' &&
exp.ast.expressions.length === 0
) {
return exp.ast.quasis[0].value.cooked!
}
} }
return exp.isStatic ? exp.content : null return exp.isStatic ? exp.content : null
} }