]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix: codegen
authordaiwei <daiwei521@126.com>
Mon, 27 Jan 2025 03:26:45 +0000 (11:26 +0800)
committerdaiwei <daiwei521@126.com>
Mon, 27 Jan 2025 03:26:45 +0000 (11:26 +0800)
packages/compiler-core/__tests__/transforms/__snapshots__/vSkip.spec.ts.snap
packages/compiler-core/__tests__/transforms/vSkip.spec.ts
packages/compiler-core/src/transform.ts
packages/compiler-core/src/transforms/vSkip.ts
packages/compiler-core/src/transforms/vSlot.ts
packages/compiler-core/src/utils.ts
packages/compiler-ssr/__tests__/ssrVSkip.spec.ts

index 15887f6d80ab7f4f2197c6697ce2f114955354a9..79ddaa94d2cc8138db153c49a1b3e5d1456f82b2 100644 (file)
@@ -19,7 +19,7 @@ exports[`compiler: v-skip > transform > nested v-skip 1`] = `
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { createCommentVNode: _createCommentVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode, Fragment: _Fragment } = _Vue
+    const { createCommentVNode: _createCommentVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, Fragment: _Fragment } = _Vue
 
     return (_ctx.ok)
       ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
@@ -95,12 +95,12 @@ exports[`compiler: v-skip > transform > on component with dynamic slot 1`] = `
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { withCtx: _withCtx, resolveComponent: _resolveComponent, resolveSkipComponent: _resolveSkipComponent, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+    const { withCtx: _withCtx, toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, resolveSkipComponent: _resolveSkipComponent, openBlock: _openBlock, createBlock: _createBlock } = _Vue
 
     const _component_Comp = _resolveComponent("Comp")
 
     return (_openBlock(), _createBlock(_resolveSkipComponent(_ctx.ok, _component_Comp), null, {
-      [_ctx.foo]: _withCtx(() => ["foo"]),
+      [_ctx.foo]: _withCtx(() => [_toDisplayString(_ctx.foo)]),
       _: 2 /* DYNAMIC */
     }, 1024 /* DYNAMIC_SLOTS */))
   }
@@ -112,20 +112,20 @@ exports[`compiler: v-skip > transform > on component with implicit default slot
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { withCtx: _withCtx, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, resolveComponent: _resolveComponent, Fragment: _Fragment, createBlock: _createBlock } = _Vue
+    const { withCtx: _withCtx, toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, resolveComponent: _resolveComponent, Fragment: _Fragment, createBlock: _createBlock } = _Vue
 
     const _component_Comp = _resolveComponent("Comp")
 
     return (_ctx.ok)
       ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
           (_ctx.yes)
-            ? (_openBlock(), _createElementBlock("span", { key: 0 }, "default"))
+            ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.default), 1 /* TEXT */))
             : _createCommentVNode("v-if", true)
         ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
       : (_openBlock(), _createBlock(_component_Comp, { key: 1 }, {
           default: _withCtx(() => [
             (_ctx.yes)
-              ? (_openBlock(), _createElementBlock("span", { key: 0 }, "default"))
+              ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.default), 1 /* TEXT */))
               : _createCommentVNode("v-if", true)
           ]),
           _: 1 /* STABLE */
@@ -139,7 +139,7 @@ exports[`compiler: v-skip > transform > on component with multiple implicit defa
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { withCtx: _withCtx, createElementVNode: _createElementVNode, resolveComponent: _resolveComponent, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createBlock: _createBlock } = _Vue
+    const { withCtx: _withCtx, createElementVNode: _createElementVNode, toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createBlock: _createBlock } = _Vue
 
     const _component_Comp = _resolveComponent("Comp")
 
@@ -149,7 +149,7 @@ return function render(_ctx, _cache) {
           _createElementVNode("div")
         ], 64 /* STABLE_FRAGMENT */))
       : (_openBlock(), _createBlock(_component_Comp, { key: 1 }, {
-          foo: _withCtx(() => ["foo"]),
+          foo: _withCtx(() => [_toDisplayString(_ctx.foo)]),
           default: _withCtx(() => [
             _createElementVNode("span"),
             _createElementVNode("div")
@@ -185,7 +185,7 @@ exports[`compiler: v-skip > transform > on component with name default slot + v-
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { withCtx: _withCtx, createSlots: _createSlots, resolveComponent: _resolveComponent, resolveSkipComponent: _resolveSkipComponent, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+    const { withCtx: _withCtx, createSlots: _createSlots, toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, resolveSkipComponent: _resolveSkipComponent, openBlock: _openBlock, createBlock: _createBlock } = _Vue
 
     const _component_Comp = _resolveComponent("Comp")
 
@@ -193,7 +193,7 @@ return function render(_ctx, _cache) {
       (_ctx.yes)
         ? {
             name: "default",
-            fn: _withCtx(() => ["default"]),
+            fn: _withCtx(() => [_toDisplayString(_ctx.default)]),
             key: "0"
           }
         : undefined
@@ -325,7 +325,7 @@ exports[`compiler: v-skip > transform > with component children 1`] = `
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createElementBlock: _createElementBlock } = _Vue
+    const { resolveComponent: _resolveComponent, openBlock: _openBlock, createBlock: _createBlock, createElementBlock: _createElementBlock } = _Vue
 
     const _component_Comp = _resolveComponent("Comp")
 
@@ -343,7 +343,7 @@ exports[`compiler: v-skip > transform > with element children 1`] = `
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
+    const { openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return (_ctx.ok)
       ? (_openBlock(), _createElementBlock("span", { key: 0 }))
@@ -381,11 +381,11 @@ exports[`compiler: v-skip > transform > with text children 1`] = `
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
+    const { toDisplayString: _toDisplayString, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
 
     return (_ctx.ok)
-      ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, ["foo"], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
-      : (_openBlock(), _createElementBlock("div", { key: 1 }, "foo"))
+      ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [_toDisplayString(_ctx.foo)], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
+      : (_openBlock(), _createElementBlock("div", { key: 1 }, _toDisplayString(_ctx.foo), 1 /* TEXT */))
   }
 }"
 `;
@@ -395,7 +395,7 @@ exports[`compiler: v-skip > transform > with v-memo 1`] = `
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, withMemo: _withMemo } = _Vue
+    const { openBlock: _openBlock, createElementBlock: _createElementBlock, withMemo: _withMemo } = _Vue
 
     return (_ctx.ok)
       ? (_openBlock(), _createElementBlock("span", { key: 0 }))
index 33114486d734149ef626ed69aed2deaf266ff694..b352ecf3f461dc0311756303f5619de5d77376f6 100644 (file)
@@ -70,17 +70,20 @@ describe('compiler: v-skip', () => {
 
     test('with text children', () => {
       const { root, node } = parseWithSkipTransform(
-        `<div v-skip="ok">foo</div>`,
+        `<div v-skip="ok">{{foo}}</div>`,
       ) as { root: RootNode; node: SkipNode }
       expect(node.type).toBe(NodeTypes.SKIP)
       expect((node.test as SimpleExpressionNode).content).toBe(`_ctx.ok`)
       expect((node.consequent as IfBranchNode).children.length).toBe(1)
       expect((node.consequent as IfBranchNode).children[0].type).toBe(
-        NodeTypes.TEXT,
+        NodeTypes.INTERPOLATION,
       )
       expect(
-        ((node.consequent as IfBranchNode).children[0] as any).content,
-      ).toBe(`foo`)
+        (
+          ((node.consequent as IfBranchNode).children[0] as any)
+            .content as SimpleExpressionNode
+        ).content,
+      ).toBe(`_ctx.foo`)
       expect(node.alternate.children.length).toBe(1)
       expect(node.alternate.children[0].type).toBe(NodeTypes.ELEMENT)
       expect((node.alternate.children[0] as ElementNode).tag).toBe(`div`)
@@ -341,7 +344,7 @@ describe('compiler: v-skip', () => {
       const { root, node } = parseWithSkipTransform(
         `<Comp v-skip="ok">
           <span/>
-          <template #foo>foo</template>
+          <template #foo>{{foo}}</template>
           <div/>
         </Comp>`,
       ) as { root: RootNode; node: SkipNode }
@@ -371,7 +374,7 @@ describe('compiler: v-skip', () => {
     test('on component with name default slot + v-if', () => {
       const { root, node } = parseWithSkipTransform(
         `<Comp v-skip="ok">
-          <template v-if="yes" #default>default</template>
+          <template v-if="yes" #default>{{default}}</template>
         </Comp>`,
       ) as { root: RootNode; node: ComponentNode }
       expect(node.type).toBe(NodeTypes.ELEMENT)
@@ -390,7 +393,7 @@ describe('compiler: v-skip', () => {
     test('on component with implicit default slot + v-if', () => {
       const { root, node } = parseWithSkipTransform(
         `<Comp v-skip="ok">
-          <span v-if="yes">default</span>
+          <span v-if="yes">{{default}}</span>
         </Comp>`,
       ) as { root: RootNode; node: SkipNode }
       expect(node.type).toBe(NodeTypes.SKIP)
@@ -401,7 +404,7 @@ describe('compiler: v-skip', () => {
     test('on component with dynamic slot', () => {
       const { root, node } = parseWithSkipTransform(
         `<Comp v-skip="ok">
-          <template #[foo]>foo</template>
+          <template #[foo]>{{foo}}</template>
         </Comp>`,
       ) as { root: RootNode; node: ComponentNode }
       expect(node.type).toBe(NodeTypes.ELEMENT)
index bfdc5bb3cf409cb5d5e0ee48b8b0fe81f8107313..40755178def0cc20f7247f5d269c4623ce176dd8 100644 (file)
@@ -467,9 +467,15 @@ export function traverseNode(
       }
       break
     case NodeTypes.SKIP:
-      const { consequent } = node
-      if (consequent.type === NodeTypes.IF_BRANCH)
-        traverseNode(consequent, context)
+      // in non-SSR mode, `alternate` already includes `consequent` content,
+      // so no need to traverse `consequent` node
+      // during `inSSR` transform, we need to traverse both since we use the cloned nodes,
+      // see `createBranchNode` in `vSkip.ts`
+      if (context.inSSR) {
+        const { consequent } = node
+        if (consequent.type === NodeTypes.IF_BRANCH)
+          traverseNode(consequent, context)
+      }
       traverseNode(node.alternate, context)
       break
     case NodeTypes.IF_BRANCH:
index d4436a38e101eafb351a7605fcba28d345ea8b3c..c2ef333f94552d4926801cd339adc9071ceb6f27 100644 (file)
@@ -132,8 +132,7 @@ export function processSkip(
     if (!hasDynamicSlots) {
       if (defaultSlot) {
         processAsSkipNode = true
-        // using the cloned node for ssr VNode-based slot
-        children = context.inSSR ? clone(defaultSlot) : defaultSlot
+        children = defaultSlot
       } else {
         context.onError(
           createCompilerError(ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT, loc),
@@ -147,7 +146,7 @@ export function processSkip(
     // if children is empty, create comment node
     const consequent =
       children.length !== 0
-        ? createBranchNode(node, node.loc, children)
+        ? createBranchNode(context, node, node.loc, children)
         : createCallExpression(context.helper(CREATE_COMMENT), [
             __DEV__ ? '"v-skip"' : '""',
             'true',
@@ -158,7 +157,7 @@ export function processSkip(
       loc: cloneLoc(node.loc),
       test: dir.exp,
       consequent,
-      alternate: createBranchNode(node, node.loc, [node]),
+      alternate: createBranchNode(context, node, node.loc, [node]),
       newline: true,
       codegenNode: undefined,
     }
@@ -189,6 +188,7 @@ function resolveDefaultSlot(node: ComponentNode, context: TransformContext) {
 }
 
 function createBranchNode(
+  context: TransformContext,
   node: ElementNode,
   loc: SourceLocation,
   children: TemplateChildNode[],
@@ -197,7 +197,8 @@ function createBranchNode(
     type: NodeTypes.IF_BRANCH,
     loc,
     condition: undefined,
-    children,
+    // using cloned node during `inSSR` transform
+    children: context.inSSR ? clone(children) : children,
     userKey: findProp(node, `key`),
   }
 }
index 4ebb24ba05b029213ecf3bddc0aa7f4d53c248a5..0f795fcce9cb9e7d7172fafabe0cdd3b453f7f2c 100644 (file)
@@ -413,13 +413,8 @@ function hasForwardedSlots(children: TemplateChildNode[]): boolean {
         if (hasForwardedSlots(child.branches)) return true
         break
       case NodeTypes.SKIP:
-        const { consequent } = child
-        if (
-          (consequent.type === NodeTypes.IF_BRANCH &&
-            hasForwardedSlots(consequent.children)) ||
-          hasForwardedSlots(child.alternate.children)
-        )
-          return true
+        // only check `alternate` branch since it contains the `consequent` node
+        if (hasForwardedSlots(child.alternate.children)) return true
         break
       case NodeTypes.IF_BRANCH:
       case NodeTypes.FOR:
index faaddb2b2c08aec1f361ce01dc93010e9a446eda..093b6bba81668f32f43c8130ec19afbe84f13105 100644 (file)
@@ -529,11 +529,9 @@ export function hasScopeRef(
     case NodeTypes.IF:
       return node.branches.some(b => hasScopeRef(b, ids))
     case NodeTypes.SKIP:
-      const { consequent } = node
       return (
         hasScopeRef(node.test, ids) ||
-        (consequent.type === NodeTypes.IF_BRANCH &&
-          consequent.children.some(c => hasScopeRef(c, ids))) ||
+        // only check `alternate` branch since it contains the `consequent` node
         node.alternate.children.some(c => hasScopeRef(c, ids))
       )
     case NodeTypes.IF_BRANCH:
index 2a177711bbc74f3f7684d62bd1f5cbc50d4c9c70..3b228b349df66c7a1dc399bc3d2304be46b17969 100644 (file)
@@ -17,15 +17,19 @@ describe('ssr: v-skip', () => {
   })
 
   test('with text children', () => {
-    expect(compile(`<div v-skip="foo">hello</div>`).code)
+    expect(compile(`<div v-skip="foo">{{hello}}</div>`).code)
       .toMatchInlineSnapshot(`
-        "const { ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
+        "const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
         return function ssrRender(_ctx, _push, _parent, _attrs) {
           if (_ctx.foo) {
-            _push(\`<!--[-->hello<!--]-->\`)
+            _push(\`<!--[-->\${_ssrInterpolate(_ctx.hello)}<!--]-->\`)
           } else {
-            _push(\`<div\${_ssrRenderAttrs(_attrs)}>hello</div>\`)
+            _push(\`<div\${
+              _ssrRenderAttrs(_attrs)
+            }>\${
+              _ssrInterpolate(_ctx.hello)
+            }</div>\`)
           }
         }"
       `)
@@ -212,67 +216,68 @@ describe('ssr: v-skip', () => {
   })
 
   test('on component with default slot', () => {
-    expect(compile(`<Comp v-skip="ok">foo</Comp>`).code).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, createTextVNode: _createTextVNode } = require("vue")
-      const { ssrRenderComponent: _ssrRenderComponent } = require("vue/server-renderer")
+    expect(compile(`<Comp v-skip="ok">{{foo}}</Comp>`).code)
+      .toMatchInlineSnapshot(`
+        "const { withCtx: _withCtx, resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require("vue")
+        const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
-      return function ssrRender(_ctx, _push, _parent, _attrs) {
-        const _component_Comp = _resolveComponent("Comp")
+        return function ssrRender(_ctx, _push, _parent, _attrs) {
+          const _component_Comp = _resolveComponent("Comp")
 
-        if (_ctx.ok) {
-          _push(\`<!--[-->foo<!--]-->\`)
-        } else {
-          _push(_ssrRenderComponent(_component_Comp, _attrs, {
-            default: _withCtx((_, _push, _parent, _scopeId) => {
-              if (_push) {
-                _push(\`foo\`)
-              } else {
-                return [
-                  _createTextVNode("foo")
-                ]
-              }
-            }),
-            _: 1 /* STABLE */
-          }, _parent))
-        }
-      }"
-    `)
+          if (_ctx.ok) {
+            _push(\`<!--[-->\${_ssrInterpolate(_ctx.foo)}<!--]-->\`)
+          } else {
+            _push(_ssrRenderComponent(_component_Comp, _attrs, {
+              default: _withCtx((_, _push, _parent, _scopeId) => {
+                if (_push) {
+                  _push(\`\${_ssrInterpolate(_ctx.foo)}\`)
+                } else {
+                  return [
+                    _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
+                  ]
+                }
+              }),
+              _: 1 /* STABLE */
+            }, _parent))
+          }
+        }"
+      `)
   })
 
   test('on component with multiple named slot', () => {
     expect(
       compile(
         `<Comp v-skip="ok">
-          <template #default>default</template>
-          <template #foo>foo</template>
+          <template #default>{{default}}</template>
+          <template #foo>{{foo}}</template>
         </Comp>`,
       ).code,
     ).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, createTextVNode: _createTextVNode } = require("vue")
-      const { ssrRenderComponent: _ssrRenderComponent } = require("vue/server-renderer")
+      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require("vue")
+      const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         const _component_Comp = _resolveComponent("Comp")
 
         if (_ctx.ok) {
-          _push(\`<!--[-->default<!--]-->\`)
+          _push(\`<!--[-->\${_ssrInterpolate(_ctx.default)}<!--]-->\`)
         } else {
           _push(_ssrRenderComponent(_component_Comp, _attrs, {
             default: _withCtx((_, _push, _parent, _scopeId) => {
               if (_push) {
-                _push(\`default\`)
+                _push(\`\${_ssrInterpolate(_ctx.default)}\`)
               } else {
                 return [
-                  _createTextVNode("default")
+                  _createTextVNode(_toDisplayString(_ctx.default), 1 /* TEXT */)
                 ]
               }
             }),
             foo: _withCtx((_, _push, _parent, _scopeId) => {
               if (_push) {
-                _push(\`foo\`)
+                _push(\`\${_ssrInterpolate(_ctx.foo)}\`)
               } else {
                 return [
-                  _createTextVNode("foo")
+                  _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
                 ]
               }
             }),
@@ -288,13 +293,13 @@ describe('ssr: v-skip', () => {
       compile(
         `<Comp v-skip="ok">
           <span/>
-          <template #foo>foo</template>
+          <template #foo>{{foo}}</template>
           <div/>
         </Comp>`,
       ).code,
     ).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, createTextVNode: _createTextVNode, createVNode: _createVNode } = require("vue")
-      const { ssrRenderComponent: _ssrRenderComponent } = require("vue/server-renderer")
+      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, createVNode: _createVNode } = require("vue")
+      const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         const _component_Comp = _resolveComponent("Comp")
@@ -305,10 +310,10 @@ describe('ssr: v-skip', () => {
           _push(_ssrRenderComponent(_component_Comp, _attrs, {
             foo: _withCtx((_, _push, _parent, _scopeId) => {
               if (_push) {
-                _push(\`foo\`)
+                _push(\`\${_ssrInterpolate(_ctx.foo)}\`)
               } else {
                 return [
-                  _createTextVNode("foo")
+                  _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
                 ]
               }
             }),
@@ -337,12 +342,12 @@ describe('ssr: v-skip', () => {
     expect(
       compile(
         `<Comp v-skip="ok">
-          <template v-if="yes" #default>default</template>
+          <template v-if="yes" #default>{{default}}</template>
         </Comp>`,
       ).code,
     ).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, createSlots: _createSlots, resolveComponent: _resolveComponent, createTextVNode: _createTextVNode } = require("vue")
-      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSkipComponent: _ssrRenderSkipComponent } = require("vue/server-renderer")
+      "const { withCtx: _withCtx, createSlots: _createSlots, resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require("vue")
+      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSkipComponent: _ssrRenderSkipComponent, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         const _component_Comp = _resolveComponent("Comp")
@@ -353,10 +358,10 @@ describe('ssr: v-skip', () => {
                 name: "default",
                 fn: _withCtx((_, _push, _parent, _scopeId) => {
                   if (_push) {
-                    _push(\`default\`)
+                    _push(\`\${_ssrInterpolate(_ctx.default)}\`)
                   } else {
                     return [
-                      _createTextVNode("default")
+                      _createTextVNode(_toDisplayString(_ctx.default), 1 /* TEXT */)
                     ]
                   }
                 }),
@@ -372,12 +377,12 @@ describe('ssr: v-skip', () => {
     expect(
       compile(
         `<Comp v-skip="ok">
-          <span v-if="yes">default</span>
+          <span v-if="yes">{{default}}</span>
         </Comp>`,
       ).code,
     ).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = require("vue")
-      const { ssrRenderComponent: _ssrRenderComponent } = require("vue/server-renderer")
+      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = require("vue")
+      const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         const _component_Comp = _resolveComponent("Comp")
@@ -385,7 +390,7 @@ describe('ssr: v-skip', () => {
         if (_ctx.ok) {
           _push(\`<!--[-->\`)
           if (_ctx.yes) {
-            _push(\`<span>default</span>\`)
+            _push(\`<span>\${_ssrInterpolate(_ctx.default)}</span>\`)
           } else {
             _push(\`<!---->\`)
           }
@@ -395,14 +400,18 @@ describe('ssr: v-skip', () => {
             default: _withCtx((_, _push, _parent, _scopeId) => {
               if (_push) {
                 if (_ctx.yes) {
-                  _push(\`<span\${_scopeId}>default</span>\`)
+                  _push(\`<span\${
+                    _scopeId
+                  }>\${
+                    _ssrInterpolate(_ctx.default)
+                  }</span>\`)
                 } else {
                   _push(\`<!---->\`)
                 }
               } else {
                 return [
                   (_ctx.yes)
-                    ? (_openBlock(), _createBlock("span", { key: 0 }, "default"))
+                    ? (_openBlock(), _createBlock("span", { key: 0 }, _toDisplayString(_ctx.default), 1 /* TEXT */))
                     : _createCommentVNode("v-if", true)
                 ]
               }
@@ -418,12 +427,12 @@ describe('ssr: v-skip', () => {
     expect(
       compile(
         `<Comp v-skip="ok">
-          <template #[foo]>foo</template>
+          <template #[foo]>{{foo}}</template>
         </Comp>`,
       ).code,
     ).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, createTextVNode: _createTextVNode } = require("vue")
-      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSkipComponent: _ssrRenderSkipComponent } = require("vue/server-renderer")
+      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require("vue")
+      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSkipComponent: _ssrRenderSkipComponent, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         const _component_Comp = _resolveComponent("Comp")
@@ -431,10 +440,10 @@ describe('ssr: v-skip', () => {
         _push(_ssrRenderSkipComponent(_push, _ctx.ok, _component_Comp, _attrs, {
           [_ctx.foo]: _withCtx((_, _push, _parent, _scopeId) => {
             if (_push) {
-              _push(\`foo\`)
+              _push(\`\${_ssrInterpolate(_ctx.foo)}\`)
             } else {
               return [
-                _createTextVNode("foo")
+                _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
               ]
             }
           }),
@@ -448,13 +457,13 @@ describe('ssr: v-skip', () => {
     expect(
       compile(
         `<Comp v-skip="ok">
-          <template #[foo]>foo</template>
-          <template #default>default</template>
+          <template #[foo]>{{foo}}</template>
+          <template #default>{{default}}</template>
         </Comp>`,
       ).code,
     ).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, createTextVNode: _createTextVNode } = require("vue")
-      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSkipComponent: _ssrRenderSkipComponent } = require("vue/server-renderer")
+      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require("vue")
+      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSkipComponent: _ssrRenderSkipComponent, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         const _component_Comp = _resolveComponent("Comp")
@@ -462,19 +471,19 @@ describe('ssr: v-skip', () => {
         _push(_ssrRenderSkipComponent(_push, _ctx.ok, _component_Comp, _attrs, {
           [_ctx.foo]: _withCtx((_, _push, _parent, _scopeId) => {
             if (_push) {
-              _push(\`foo\`)
+              _push(\`\${_ssrInterpolate(_ctx.foo)}\`)
             } else {
               return [
-                _createTextVNode("foo")
+                _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
               ]
             }
           }),
           default: _withCtx((_, _push, _parent, _scopeId) => {
             if (_push) {
-              _push(\`default\`)
+              _push(\`\${_ssrInterpolate(_ctx.default)}\`)
             } else {
               return [
-                _createTextVNode("default")
+                _createTextVNode(_toDisplayString(_ctx.default), 1 /* TEXT */)
               ]
             }
           }),
@@ -485,51 +494,52 @@ describe('ssr: v-skip', () => {
   })
 
   test('on dynamic component with default slot', () => {
-    expect(compile(`<component :is="Comp" v-skip="ok">foo</component>`).code)
-      .toMatchInlineSnapshot(`
-        "const { withCtx: _withCtx, resolveDynamicComponent: _resolveDynamicComponent, createTextVNode: _createTextVNode, createVNode: _createVNode } = require("vue")
-        const { ssrRenderVNode: _ssrRenderVNode } = require("vue/server-renderer")
+    expect(
+      compile(`<component :is="Comp" v-skip="ok">{{foo}}</component>`).code,
+    ).toMatchInlineSnapshot(`
+      "const { withCtx: _withCtx, resolveDynamicComponent: _resolveDynamicComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, createVNode: _createVNode } = require("vue")
+      const { ssrRenderVNode: _ssrRenderVNode, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
-        return function ssrRender(_ctx, _push, _parent, _attrs) {
-          if (_ctx.ok) {
-            _push(\`<!--[-->foo<!--]-->\`)
-          } else {
-            _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent(_ctx.Comp), _attrs, {
-              default: _withCtx((_, _push, _parent, _scopeId) => {
-                if (_push) {
-                  _push(\`foo\`)
-                } else {
-                  return [
-                    _createTextVNode("foo")
-                  ]
-                }
-              }),
-              _: 1 /* STABLE */
-            }), _parent)
-          }
-        }"
-      `)
+      return function ssrRender(_ctx, _push, _parent, _attrs) {
+        if (_ctx.ok) {
+          _push(\`<!--[-->\${_ssrInterpolate(_ctx.foo)}<!--]-->\`)
+        } else {
+          _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent(_ctx.Comp), _attrs, {
+            default: _withCtx((_, _push, _parent, _scopeId) => {
+              if (_push) {
+                _push(\`\${_ssrInterpolate(_ctx.foo)}\`)
+              } else {
+                return [
+                  _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
+                ]
+              }
+            }),
+            _: 1 /* STABLE */
+          }), _parent)
+        }
+      }"
+    `)
   })
 
   test('on dynamic component with dynamic slot', () => {
     expect(
       compile(`
-      <component :is="Comp" v-skip="ok">
-          <template #[foo]>foo</template>
+        <component :is="Comp" v-skip="ok">
+          <template #[foo]>{{foo}}</template>
         </component>
       `).code,
     ).toMatchInlineSnapshot(`
-      "const { withCtx: _withCtx, resolveDynamicComponent: _resolveDynamicComponent, createTextVNode: _createTextVNode, createVNode: _createVNode } = require("vue")
-      const { ssrRenderVNode: _ssrRenderVNode, ssrRenderSkipVNode: _ssrRenderSkipVNode } = require("vue/server-renderer")
+      "const { withCtx: _withCtx, resolveDynamicComponent: _resolveDynamicComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, createVNode: _createVNode } = require("vue")
+      const { ssrRenderVNode: _ssrRenderVNode, ssrRenderSkipVNode: _ssrRenderSkipVNode, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         _ssrRenderSkipVNode(_ctx.ok, _push, _createVNode(_resolveDynamicComponent(_ctx.Comp), _attrs, {
           [_ctx.foo]: _withCtx((_, _push, _parent, _scopeId) => {
             if (_push) {
-              _push(\`foo\`)
+              _push(\`\${_ssrInterpolate(_ctx.foo)}\`)
             } else {
               return [
-                _createTextVNode("foo")
+                _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
               ]
             }
           }),
@@ -541,19 +551,20 @@ describe('ssr: v-skip', () => {
 
   test('on Teleport', () => {
     expect(
-      compile(`<teleport to="target" v-skip="ok">
-          <div>foo</div>
+      compile(`
+        <teleport to="target" v-skip="ok">
+          <div>{{foo}}</div>
         </teleport>`).code,
     ).toMatchInlineSnapshot(`
       "const { withCtx: _withCtx } = require("vue")
-      const { ssrRenderTeleport: _ssrRenderTeleport } = require("vue/server-renderer")
+      const { ssrInterpolate: _ssrInterpolate, ssrRenderTeleport: _ssrRenderTeleport } = require("vue/server-renderer")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
         if (_ctx.ok) {
-          _push(\`<div>foo</div>\`)
+          _push(\`<div>\${_ssrInterpolate(_ctx.foo)}</div>\`)
         } else {
           _ssrRenderTeleport(_push, (_push) => {
-            _push(\`<div>foo</div>\`)
+            _push(\`<div>\${_ssrInterpolate(_ctx.foo)}</div>\`)
           }, "target", false, _parent)
         }
       }"