ソースを参照

refactor: merge createTextNode & setText

三咲智子 Kevin Deng 2 年 前
コミット
e67e6432f0

+ 7 - 11
packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap

@@ -120,7 +120,7 @@ export function render(_ctx) {
 `;
 
 exports[`compile > directives > v-pre > should not affect siblings after it 1`] = `
-"import { resolveComponent as _resolveComponent, createComponent as _createComponent, createTextNode as _createTextNode, insert as _insert, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
+"import { resolveComponent as _resolveComponent, createComponent as _createComponent, createTextNode as _createTextNode, insert as _insert, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
 const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>")
 const t1 = _template("<div></div>")
 
@@ -129,20 +129,18 @@ export function render(_ctx) {
   const n0 = t0()
   const n3 = t1()
   const n1 = _createComponent(_component_Comp)
-  const n2 = _createTextNode()
+  const n2 = _createTextNode(() => [_ctx.bar])
   _insert([n1, n2], n3)
-  _renderEffect(() => _setText(n2, _ctx.bar))
   _renderEffect(() => _setDynamicProp(n3, "id", _ctx.foo))
   return [n0, n3]
 }"
 `;
 
 exports[`compile > dynamic root 1`] = `
-"import { createTextNode as _createTextNode, setText as _setText } from 'vue/vapor';
+"import { createTextNode as _createTextNode } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createTextNode()
-  _setText(n0, 1, 2)
+  const n0 = _createTextNode([1, 2])
   return n0
 }"
 `;
@@ -163,8 +161,7 @@ export function render(_ctx) {
 
 exports[`compile > expression parsing > interpolation 1`] = `
 "(() => {
-  const n0 = _createTextNode()
-  _renderEffect(() => _setText(n0, a + b.value))
+  const n0 = _createTextNode(() => [a + b.value])
   return n0
 })()"
 `;
@@ -192,11 +189,10 @@ export function render(_ctx) {
 `;
 
 exports[`compile > static + dynamic root 1`] = `
-"import { createTextNode as _createTextNode, setText as _setText } from 'vue/vapor';
+"import { createTextNode as _createTextNode } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createTextNode()
-  _setText(n0, 1, 2, "3", 4, 5, "6", 7, 8, "9", 'A', 'B')
+  const n0 = _createTextNode([1, 2, "3", 4, 5, "6", 7, 8, "9", 'A', 'B'])
   return n0
 }"
 `;

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

@@ -10,8 +10,7 @@ export function render(_ctx) {
   const n3 = _next(n0, 2)
   const n2 = n3.nextSibling
   _setText(n0, 'first')
-  const n1 = _createTextNode()
-  _setText(n1, 'second', " ", 'third', " ")
+  const n1 = _createTextNode(['second', " ", 'third', " "])
   _setText(n2, 'forth')
   _insert(n1, n4, n3)
   return n4

+ 2 - 3
packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap

@@ -12,14 +12,13 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: v-once > basic 1`] = `
-"import { createTextNode as _createTextNode, setText as _setText, setClass as _setClass, prepend as _prepend, template as _template } from 'vue/vapor';
+"import { createTextNode as _createTextNode, setClass as _setClass, prepend as _prepend, template as _template } from 'vue/vapor';
 const t0 = _template("<div><span></span></div>")
 
 export function render(_ctx) {
   const n2 = t0()
   const n1 = n2.firstChild
-  const n0 = _createTextNode()
-  _setText(n0, _ctx.msg, " ")
+  const n0 = _createTextNode([_ctx.msg, " "])
   _setClass(n1, _ctx.clz)
   _prepend(n2, n0)
   return n2

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

@@ -31,10 +31,6 @@ describe('compiler: v-once', () => {
       {
         type: IRNodeTypes.CREATE_TEXT_NODE,
         id: 0,
-      },
-      {
-        element: 0,
-        type: IRNodeTypes.SET_TEXT,
         values: [
           {
             type: NodeTypes.SIMPLE_EXPRESSION,
@@ -47,6 +43,7 @@ describe('compiler: v-once', () => {
             isStatic: true,
           },
         ],
+        effect: false,
       },
       {
         element: 1,

+ 12 - 5
packages/compiler-vapor/src/generators/text.ts

@@ -1,19 +1,19 @@
 import type { CodegenContext } from '../generate'
 import type { CreateTextNodeIRNode, SetTextIRNode } from '../ir'
 import { genExpression } from './expression'
-import { type CodeFragment, NEWLINE, genCall } from './utils'
+import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
 
 export function genSetText(
   oper: SetTextIRNode,
   context: CodegenContext,
 ): CodeFragment[] {
   const { vaporHelper } = context
-  const { values } = oper
+  const { element, values } = oper
   return [
     NEWLINE,
     ...genCall(
       vaporHelper('setText'),
-      `n${oper.element}`,
+      `n${element}`,
       ...values.map(value => genExpression(value, context)),
     ),
   ]
@@ -24,9 +24,16 @@ export function genCreateTextNode(
   context: CodegenContext,
 ): CodeFragment[] {
   const { vaporHelper } = context
+  const { id, values, effect } = oper
   return [
     NEWLINE,
-    `const n${oper.id} = `,
-    ...genCall(vaporHelper('createTextNode')),
+    `const n${id} = `,
+    ...genCall(vaporHelper('createTextNode'), [
+      effect && '() => ',
+      ...genMulti(
+        ['[', ']', ', '],
+        ...values.map(value => genExpression(value, context)),
+      ),
+    ]),
   ]
 }

+ 2 - 0
packages/compiler-vapor/src/ir.ts

@@ -159,6 +159,8 @@ export interface SetModelValueIRNode extends BaseIRNode {
 export interface CreateTextNodeIRNode extends BaseIRNode {
   type: IRNodeTypes.CREATE_TEXT_NODE
   id: number
+  values: SimpleExpressionNode[]
+  effect: boolean
 }
 
 export interface InsertNodeIRNode extends BaseIRNode {

+ 4 - 7
packages/compiler-vapor/src/transforms/transformText.ts

@@ -11,6 +11,7 @@ import {
 } from '@vue/compiler-dom'
 import type { NodeTransform, TransformContext } from '../transform'
 import { DynamicFlag, IRNodeTypes } from '../ir'
+import { isConstantExpression } from '../utils'
 
 type TextLike = TextNode | InterpolationNode
 const seen = new WeakMap<
@@ -50,17 +51,13 @@ function processTextLike(context: TransformContext<InterpolationNode>) {
   const values = nodes.map(node => createTextLikeExpression(node, context))
 
   context.dynamic.flags |= DynamicFlag.INSERT | DynamicFlag.NON_TEMPLATE
+
   context.registerOperation({
     type: IRNodeTypes.CREATE_TEXT_NODE,
     id,
+    values,
+    effect: !values.some(isConstantExpression),
   })
-  context.registerEffect(values, [
-    {
-      type: IRNodeTypes.SET_TEXT,
-      element: id,
-      values,
-    },
-  ])
 }
 
 function processTextLikeContainer(

+ 12 - 4
packages/runtime-vapor/src/dom/element.ts

@@ -1,6 +1,8 @@
-import { isArray, toDisplayString } from '@vue/shared'
+import { isArray } from '@vue/shared'
 import type { Block } from '../apiRender'
 import { componentKey } from '../component'
+import { renderEffect } from '../renderEffect'
+import { setText } from './prop'
 
 /*! #__NO_SIDE_EFFECTS__ */
 export function normalizeBlock(block: Block): Node[] {
@@ -34,10 +36,16 @@ export function remove(block: Block, parent: ParentNode) {
   normalizeBlock(block).forEach(node => parent.removeChild(node))
 }
 
-/*! #__NO_SIDE_EFFECTS__ */
-export function createTextNode(val?: unknown): Text {
+export function createTextNode(values?: any[] | (() => any[])): Text {
   // eslint-disable-next-line no-restricted-globals
-  return document.createTextNode(val === undefined ? '' : toDisplayString(val))
+  const node = document.createTextNode('')
+  if (values)
+    if (isArray(values)) {
+      setText(node, ...values)
+    } else {
+      renderEffect(() => setText(node, ...values()))
+    }
+  return node
 }
 
 /*! #__NO_SIDE_EFFECTS__ */