]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: warp if/else-if/else node with a template node
authordaiwei <daiwei521@126.com>
Wed, 13 Aug 2025 03:07:17 +0000 (11:07 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 13 Aug 2025 03:07:17 +0000 (11:07 +0800)
packages/compiler-ssr/__tests__/ssrVaporAnchors.spec.ts
packages/compiler-ssr/src/transforms/ssrTransformComponent.ts

index 745bf65f42d698ceae6174657f54575b46655608..9b25d11231b4d22059d7bc8a578b942142e65374 100644 (file)
@@ -176,16 +176,19 @@ describe('insertion anchors', () => {
                   _createVNode("div", null, [
                     _createCommentVNode("[p"),
                     (_ctx.foo)
-                      ? (_openBlock(), _createBlock("span", { key: 0 }, [
+                      ? (_openBlock(), _createBlock(_Fragment, { key: 0 }, [
+                          _createVNode("span"),
                           _createCommentVNode("if")
-                        ]))
+                        ], 64 /* STABLE_FRAGMENT */))
                       : (_ctx.bar)
-                        ? (_openBlock(), _createBlock("span", { key: 1 }, [
+                        ? (_openBlock(), _createBlock(_Fragment, { key: 1 }, [
+                            _createVNode("span"),
                             _createCommentVNode("if--><!--if")
-                          ]))
-                        : (_openBlock(), _createBlock("span", { key: 2 }, [
+                          ], 64 /* STABLE_FRAGMENT */))
+                        : (_openBlock(), _createBlock(_Fragment, { key: 2 }, [
+                            _createVNode("span"),
                             _createCommentVNode("if--><!--if")
-                          ])),
+                          ], 64 /* STABLE_FRAGMENT */)),
                     _createCommentVNode("p]"),
                     _createVNode("span")
                   ])
@@ -322,37 +325,43 @@ describe('insertion anchors', () => {
                   _createVNode("div", null, [
                     _createCommentVNode("[p"),
                     (_ctx.foo)
-                      ? (_openBlock(), _createBlock("span", { key: 0 }, [
-                          _createCommentVNode("[p"),
-                          (_ctx.foo1)
-                            ? (_openBlock(), _createBlock("span", { key: 0 }))
-                            : _createCommentVNode("v-if", true),
-                          _createCommentVNode("if"),
-                          _createCommentVNode("p]"),
-                          _createVNode("span"),
-                          _createCommentVNode("if")
-                        ]))
-                      : (_ctx.bar)
-                        ? (_openBlock(), _createBlock("span", { key: 1 }, [
+                      ? (_openBlock(), _createBlock(_Fragment, { key: 0 }, [
+                          _createVNode("span", null, [
                             _createCommentVNode("[p"),
-                            (_ctx.bar1)
+                            (_ctx.foo1)
                               ? (_openBlock(), _createBlock("span", { key: 0 }))
                               : _createCommentVNode("v-if", true),
                             _createCommentVNode("if"),
                             _createCommentVNode("p]"),
-                            _createVNode("span"),
+                            _createVNode("span")
+                          ]),
+                          _createCommentVNode("if")
+                        ], 64 /* STABLE_FRAGMENT */))
+                      : (_ctx.bar)
+                        ? (_openBlock(), _createBlock(_Fragment, { key: 1 }, [
+                            _createVNode("span", null, [
+                              _createCommentVNode("[p"),
+                              (_ctx.bar1)
+                                ? (_openBlock(), _createBlock("span", { key: 0 }))
+                                : _createCommentVNode("v-if", true),
+                              _createCommentVNode("if"),
+                              _createCommentVNode("p]"),
+                              _createVNode("span")
+                            ]),
                             _createCommentVNode("if--><!--if")
-                          ]))
-                        : (_openBlock(), _createBlock("span", { key: 2 }, [
-                            _createCommentVNode("[p"),
-                            (_ctx.bar2)
-                              ? (_openBlock(), _createBlock("span", { key: 0 }))
-                              : _createCommentVNode("v-if", true),
-                            _createCommentVNode("if"),
-                            _createCommentVNode("p]"),
-                            _createVNode("span"),
+                          ], 64 /* STABLE_FRAGMENT */))
+                        : (_openBlock(), _createBlock(_Fragment, { key: 2 }, [
+                            _createVNode("span", null, [
+                              _createCommentVNode("[p"),
+                              (_ctx.bar2)
+                                ? (_openBlock(), _createBlock("span", { key: 0 }))
+                                : _createCommentVNode("v-if", true),
+                              _createCommentVNode("if"),
+                              _createCommentVNode("p]"),
+                              _createVNode("span")
+                            ]),
                             _createCommentVNode("if--><!--if")
-                          ])),
+                          ], 64 /* STABLE_FRAGMENT */)),
                     _createCommentVNode("p]"),
                     _createVNode("span")
                   ])
@@ -606,24 +615,86 @@ describe('block anchors', () => {
             } else {
               return [
                 (_ctx.count === 1)
-                  ? (_openBlock(), _createBlock("span", { key: 0 }, [
-                      _createTextVNode("1"),
+                  ? (_openBlock(), _createBlock(_Fragment, { key: 0 }, [
+                      _createVNode("span", null, "1"),
                       _createCommentVNode("if")
-                    ]))
+                    ], 64 /* STABLE_FRAGMENT */))
                   : (_ctx.count === 2)
-                    ? (_openBlock(), _createBlock("span", { key: 1 }, [
-                        _createTextVNode("2"),
+                    ? (_openBlock(), _createBlock(_Fragment, { key: 1 }, [
+                        _createVNode("span", null, "2"),
                         _createCommentVNode("if--><!--if")
-                      ]))
+                      ], 64 /* STABLE_FRAGMENT */))
                     : (_ctx.count === 3)
-                      ? (_openBlock(), _createBlock("span", { key: 2 }, [
-                          _createTextVNode("3"),
+                      ? (_openBlock(), _createBlock(_Fragment, { key: 2 }, [
+                          _createVNode("span", null, "3"),
                           _createCommentVNode("if--><!--if--><!--if")
-                        ]))
-                      : (_openBlock(), _createBlock("span", { key: 3 }, [
-                          _createTextVNode("4"),
+                        ], 64 /* STABLE_FRAGMENT */))
+                      : (_openBlock(), _createBlock(_Fragment, { key: 3 }, [
+                          _createVNode("span", null, "4"),
                           _createCommentVNode("if--><!--if--><!--if")
-                        ]))
+                        ], 64 /* STABLE_FRAGMENT */))
+              ]
+            }
+          }),
+          _: 1 /* STABLE */
+        }), _parent)
+        _push(\`<!--dynamic-component--><!--a]-->\`"
+    `)
+  })
+
+  test('if + v-html/v-text', () => {
+    expect(
+      getCompiledString(
+        `<component :is="tag">
+          <span v-if="count === 1" v-html="html"></span>
+          <span v-else-if="count === 2" v-text="txt"></span>
+          <span v-else>4</span>
+        </component>`,
+        {
+          vapor: true,
+        },
+      ),
+    ).toMatchInlineSnapshot(`
+      "\`<!--[a-->\`)
+        _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent(_ctx.tag), null, {
+          default: _withCtx((_, _push, _parent, _scopeId) => {
+            if (_push) {
+              if (_ctx.count === 1) {
+                _push(\`<span\${
+                  _scopeId
+                }>\${
+                  (_ctx.html) ?? ''
+                }</span>\`)
+                _push(\`<!--if-->\`)
+              } else if (_ctx.count === 2) {
+                _push(\`<span\${
+                  _scopeId
+                }>\${
+                  _ssrInterpolate(_ctx.txt)
+                }</span>\`)
+                _push(\`<!--if--><!--if-->\`)
+              } else {
+                _push(\`<span\${_scopeId}>4</span>\`)
+                _push(\`<!--if--><!--if-->\`)
+              }
+            } else {
+              return [
+                (_ctx.count === 1)
+                  ? (_openBlock(), _createBlock(_Fragment, { key: 0 }, [
+                      _createVNode("span", { innerHTML: _ctx.html }, null, 8 /* PROPS */, ["innerHTML"]),
+                      _createCommentVNode("if")
+                    ], 64 /* STABLE_FRAGMENT */))
+                  : (_ctx.count === 2)
+                    ? (_openBlock(), _createBlock(_Fragment, { key: 1 }, [
+                        _createVNode("span", {
+                          textContent: _toDisplayString(_ctx.txt)
+                        }, null, 8 /* PROPS */, ["textContent"]),
+                        _createCommentVNode("if--><!--if")
+                      ], 64 /* STABLE_FRAGMENT */))
+                    : (_openBlock(), _createBlock(_Fragment, { key: 2 }, [
+                        _createVNode("span", null, "4"),
+                        _createCommentVNode("if--><!--if")
+                      ], 64 /* STABLE_FRAGMENT */))
               ]
             }
           }),
index 53e6355fab9f01ad1468c6e16a0f98cf9c84b801..e3833a6ef966a3821d1b1d2a583b76af64ca1c64 100644 (file)
@@ -407,7 +407,6 @@ function injectVaporAnchors(
   }
 
   const newChildren: TemplateChildNode[] = []
-
   for (let i = 0; i < children.length; i++) {
     const child = children[i]
 
@@ -440,41 +439,15 @@ function injectVaporAnchors(
 
       if (hasIf) {
         insertionAnchor = (child as any as IfNode).anchor
-        // find sibling else-if/else branches
-        // inject anchor after else-if/else branch if founded
-        // otherwise inject after if node
         const lastBranchIndex = findLastIfBranchIndex(children, i)
         if (lastBranchIndex > i) {
-          // inject anchor before if node
-          if (insertionAnchor) {
-            newChildren.push(createAnchor(`[${insertionAnchor}`))
-          }
-
-          // copy branch nodes
-          for (let j = i; j <= lastBranchIndex; j++) {
-            const node = children[j] as PlainElementNode
-            newChildren.push(node)
-
-            // inject block anchor
-            const blockAnchorLabel = getBlockAnchorLabel(node)
-            if (blockAnchorLabel) {
-              const isElse = node.props.some(p => p.name === 'else')
-              const repeatCount = j - i - (isElse ? 1 : 0) + 1
-              node.children.push(
-                createAnchor(
-                  `<!--${blockAnchorLabel}-->`.repeat(repeatCount).slice(4, -3),
-                ),
-              )
-            }
-
-            node.children = injectVaporAnchors(node.children, node)
-          }
-
-          // inject anchor after branch nodes
-          if (insertionAnchor) {
-            newChildren.push(createAnchor(`${insertionAnchor}]`))
-          }
-
+          injectIfAnchors(
+            insertionAnchor,
+            newChildren,
+            i,
+            lastBranchIndex,
+            children,
+          )
           i = lastBranchIndex
           continue
         }
@@ -505,6 +478,71 @@ function injectVaporAnchors(
   return newChildren
 }
 
+function injectIfAnchors(
+  insertionAnchor: string | undefined,
+  newChildren: TemplateChildNode[],
+  i: number,
+  lastBranchIndex: number,
+  children: TemplateChildNode[],
+) {
+  // inject anchor before if node
+  if (insertionAnchor) {
+    newChildren.push(createAnchor(`[${insertionAnchor}`))
+  }
+
+  for (let j = i; j <= lastBranchIndex; j++) {
+    const node = children[j] as PlainElementNode
+    const blockAnchorLabel = getBlockAnchorLabel(node)
+    let isElse = false
+
+    const conditionalProps: typeof node.props = []
+    const restProps: typeof node.props = []
+
+    for (const prop of node.props) {
+      if (
+        prop.name === 'if' ||
+        prop.name === 'else-if' ||
+        prop.name === 'else'
+      ) {
+        conditionalProps.push(prop)
+        if (prop.name === 'else') isElse = true
+      } else {
+        restProps.push(prop)
+      }
+    }
+    node.props = restProps
+
+    // wrap the node with a template node
+    const wrapperNode: TemplateNode = {
+      type: NodeTypes.ELEMENT,
+      ns: Namespaces.HTML,
+      tag: 'template',
+      tagType: ElementTypes.TEMPLATE,
+      props: conditionalProps,
+      children: [node],
+      loc: node.loc,
+      codegenNode: undefined,
+    }
+    newChildren.push(wrapperNode)
+
+    // inject block anchor
+    if (blockAnchorLabel) {
+      const repeatCount = j - i - (isElse ? 1 : 0) + 1
+      wrapperNode.children.push(
+        createAnchor(
+          `<!--${blockAnchorLabel}-->`.repeat(repeatCount).slice(4, -3),
+        ),
+      )
+    }
+    node.children = injectVaporAnchors(node.children, node)
+  }
+
+  // inject anchor after branch nodes
+  if (insertionAnchor) {
+    newChildren.push(createAnchor(`${insertionAnchor}]`))
+  }
+}
+
 function createAnchor(content: string): CommentNode {
   return {
     type: NodeTypes.COMMENT,