Просмотр исходного кода

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

三咲智子 Kevin Deng 2 лет назад
Родитель
Сommit
00c6e6dc73

+ 4 - 4
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap

@@ -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(['second', " ", 'third', " "])
-  _setText(n2, 'forth')
+  const n1 = _createTextNode(() => [_ctx.second, " ", _ctx.third, " "])
   _insert(n1, n4, n3)
   _insert(n1, n4, n3)
+  _renderEffect(() => _setText(n0, _ctx.first))
+  _renderEffect(() => _setText(n2, _ctx.forth))
   return n4
   return n4
 }"
 }"
 `;
 `;

+ 1 - 2
packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap

@@ -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
 }"
 }"
 `;
 `;

+ 4 - 4
packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts

@@ -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>
-        {{'second'}}
-        {{'third'}}
-        <p>{{'forth'}}</p>
+        <p>{{ first }}</p>
+        {{ second }}
+        {{ third }}
+        <p>{{ forth }}</p>
       </div>`,
       </div>`,
     )
     )
     expect(code).toMatchSnapshot()
     expect(code).toMatchSnapshot()

+ 11 - 6
packages/compiler-vapor/src/transforms/transformText.ts

@@ -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, {
-    type: IRNodeTypes.SET_TEXT,
-    element: context.reference(),
-    values,
-  })
+  const literals = values.map(getLiteralExpressionValue)
+  if (literals.every(l => l != null)) {
+    context.childrenTemplate = literals.map(l => String(l))
+  } else {
+    context.registerEffect(values, {
+      type: IRNodeTypes.SET_TEXT,
+      element: context.reference(),
+      values,
+    })
+  }
 }
 }
 
 
 function createTextLikeExpression(node: TextLike, context: TransformContext) {
 function createTextLikeExpression(node: TextLike, context: TransformContext) {

+ 11 - 5
packages/compiler-vapor/src/transforms/vText.ts

@@ -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], {
-    type: IRNodeTypes.SET_TEXT,
-    element: context.reference(),
-    values: [exp],
-  })
+  const literal = getLiteralExpressionValue(exp)
+  if (literal != null) {
+    context.childrenTemplate = [String(literal)]
+  } else {
+    context.registerEffect([exp], {
+      type: IRNodeTypes.SET_TEXT,
+      element: context.reference(),
+      values: [exp],
+    })
+  }
 }
 }

+ 15 - 8
packages/compiler-vapor/src/utils.ts

@@ -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 {
-  if (
-    !__BROWSER__ &&
-    exp.ast &&
-    ['StringLiteral', 'NumericLiteral'].includes(exp.ast.type)
-  ) {
-    return (exp.ast as StringLiteral | NumericLiteral).value
+): number | string | boolean | null {
+  if (!__BROWSER__ && exp.ast) {
+    if (
+      ['StringLiteral', 'NumericLiteral', 'BigIntLiteral'].includes(
+        exp.ast.type,
+      )
+    ) {
+      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
 }
 }