]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): should pre-convert text nodes in all non-element cases
authorEvan You <yyx990803@gmail.com>
Mon, 2 Dec 2019 20:17:00 +0000 (15:17 -0500)
committerEvan You <yyx990803@gmail.com>
Mon, 2 Dec 2019 20:17:00 +0000 (15:17 -0500)
packages/compiler-core/src/transforms/transformText.ts

index 25bf22d482026277f22e35f14c4b8327bf392dec..91d5d5076ad40f3bcbe59af480030bb19b7ca476 100644 (file)
@@ -6,7 +6,8 @@ import {
   InterpolationNode,
   CompoundExpressionNode,
   createCallExpression,
-  CallExpression
+  CallExpression,
+  ElementTypes
 } from '../ast'
 import { CREATE_TEXT } from '../runtimeHelpers'
 import { PatchFlags, PatchFlagNames } from '@vue/shared'
@@ -53,33 +54,43 @@ export const transformText: NodeTransform = (node, context) => {
         }
       }
 
-      if (hasText && children.length > 1) {
-        // when an element has mixed text/element children, convert text nodes
-        // into createTextVNode(text) calls.
-        for (let i = 0; i < children.length; i++) {
-          const child = children[i]
-          if (isText(child) || child.type === NodeTypes.COMPOUND_EXPRESSION) {
-            const callArgs: CallExpression['arguments'] = []
-            // createTextVNode defaults to single whitespace, so if it is a
-            // single space the code could be an empty call to save bytes.
-            if (child.type !== NodeTypes.TEXT || child.content !== ' ') {
-              callArgs.push(child)
-            }
-            // mark dynamic text with flag so it gets patched inside a block
-            if (child.type !== NodeTypes.TEXT) {
-              callArgs.push(
-                `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
-              )
-            }
-            children[i] = {
-              type: NodeTypes.TEXT_CALL,
-              content: child,
-              loc: child.loc,
-              codegenNode: createCallExpression(
-                context.helper(CREATE_TEXT),
-                callArgs
-              )
-            }
+      if (
+        !hasText ||
+        // if this is a plain element with a single text child, leave it as-is
+        // since the runtime has dedicated fast path for this by directly
+        // setting textContent of the element.
+        (node.type === NodeTypes.ELEMENT &&
+          node.tagType === ElementTypes.ELEMENT &&
+          children.length === 1)
+      ) {
+        return
+      }
+
+      // pre-convert text nodes into createTextVNode(text) calls to avoid
+      // runtime normalization.
+      for (let i = 0; i < children.length; i++) {
+        const child = children[i]
+        if (isText(child) || child.type === NodeTypes.COMPOUND_EXPRESSION) {
+          const callArgs: CallExpression['arguments'] = []
+          // createTextVNode defaults to single whitespace, so if it is a
+          // single space the code could be an empty call to save bytes.
+          if (child.type !== NodeTypes.TEXT || child.content !== ' ') {
+            callArgs.push(child)
+          }
+          // mark dynamic text with flag so it gets patched inside a block
+          if (child.type !== NodeTypes.TEXT) {
+            callArgs.push(
+              `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
+            )
+          }
+          children[i] = {
+            type: NodeTypes.TEXT_CALL,
+            content: child,
+            loc: child.loc,
+            codegenNode: createCallExpression(
+              context.helper(CREATE_TEXT),
+              callArgs
+            )
           }
         }
       }