]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(ssr): respect textContent/innerHTML from getSSRProps in optimized SSR output
authorEvan You <evan@vuejs.org>
Tue, 6 Aug 2024 10:14:47 +0000 (18:14 +0800)
committerEvan You <evan@vuejs.org>
Tue, 6 Aug 2024 10:14:59 +0000 (18:14 +0800)
close #8112

packages/compiler-ssr/__tests__/ssrElement.spec.ts
packages/compiler-ssr/src/transforms/ssrTransformElement.ts

index 4056b4c3c71a2e811a9752250ced422a849d9b49..723ef7b359284bfc43ae548db0eb60cc26ce0603 100644 (file)
@@ -288,12 +288,27 @@ describe('ssr: element', () => {
           }></div>\`"
       `)
     })
+  })
 
-    test('custom dir', () => {
+  describe('custom directives', () => {
+    // #8112 should respect textContent / innerHTML from directive getSSRProps
+    // if the element has no children
+    test('custom dir without children', () => {
       expect(getCompiledString(`<div v-xxx:x.y="z" />`)).toMatchInlineSnapshot(`
+        "\`<div\${
+            _ssrRenderAttrs(_temp0 = _ssrGetDirectiveProps(_ctx, _directive_xxx, _ctx.z, "x", { y: true }))
+          }>\${
+            ("textContent" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''
+          }</div>\`"
+      `)
+    })
+
+    test('custom dir with children', () => {
+      expect(getCompiledString(`<div v-xxx:x.y="z">hello</div>`))
+        .toMatchInlineSnapshot(`
         "\`<div\${
             _ssrRenderAttrs(_ssrGetDirectiveProps(_ctx, _directive_xxx, _ctx.z, "x", { y: true }))
-          }></div>\`"
+          }>hello</div>\`"
       `)
     })
 
@@ -301,30 +316,36 @@ describe('ssr: element', () => {
       expect(getCompiledString(`<div class="foo" v-xxx />`))
         .toMatchInlineSnapshot(`
           "\`<div\${
-              _ssrRenderAttrs(_mergeProps({ class: "foo" }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
-            }></div>\`"
+              _ssrRenderAttrs(_temp0 = _mergeProps({ class: "foo" }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
+            }>\${
+              ("textContent" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''
+            }</div>\`"
         `)
     })
 
     test('custom dir with v-bind', () => {
       expect(getCompiledString(`<div :title="foo" :class="bar" v-xxx />`))
         .toMatchInlineSnapshot(`
-        "\`<div\${
-            _ssrRenderAttrs(_mergeProps({
-              title: _ctx.foo,
-              class: _ctx.bar
-            }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
-          }></div>\`"
-      `)
+          "\`<div\${
+              _ssrRenderAttrs(_temp0 = _mergeProps({
+                title: _ctx.foo,
+                class: _ctx.bar
+              }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
+            }>\${
+              ("textContent" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''
+            }</div>\`"
+        `)
     })
 
     test('custom dir with object v-bind', () => {
       expect(getCompiledString(`<div v-bind="x" v-xxx />`))
         .toMatchInlineSnapshot(`
-        "\`<div\${
-            _ssrRenderAttrs(_mergeProps(_ctx.x, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
-          }></div>\`"
-      `)
+          "\`<div\${
+              _ssrRenderAttrs(_temp0 = _mergeProps(_ctx.x, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
+            }>\${
+              ("textContent" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''
+            }</div>\`"
+        `)
     })
 
     test('custom dir with object v-bind + normal bindings', () => {
@@ -332,11 +353,13 @@ describe('ssr: element', () => {
         getCompiledString(`<div v-bind="x" class="foo" v-xxx title="bar" />`),
       ).toMatchInlineSnapshot(`
         "\`<div\${
-            _ssrRenderAttrs(_mergeProps(_ctx.x, {
+            _ssrRenderAttrs(_temp0 = _mergeProps(_ctx.x, {
               class: "foo",
               title: "bar"
             }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))
-          }></div>\`"
+          }>\${
+            ("textContent" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''
+          }</div>\`"
       `)
     })
   })
index 7175b797d4817e694ec75d405bf6c197505b2813..45d4d76fe9ad6277c73aab56e7b27b1b7ef5627b 100644 (file)
@@ -163,6 +163,25 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
               ]),
             ]
           }
+        } else if (directives.length && !node.children.length) {
+          const tempId = `_temp${context.temps++}`
+          propsExp.arguments = [
+            createAssignmentExpression(
+              createSimpleExpression(tempId, false),
+              mergedProps,
+            ),
+          ]
+          rawChildrenMap.set(
+            node,
+            createConditionalExpression(
+              createSimpleExpression(`"textContent" in ${tempId}`, false),
+              createCallExpression(context.helper(SSR_INTERPOLATE), [
+                createSimpleExpression(`${tempId}.textContent`, false),
+              ]),
+              createSimpleExpression(`${tempId}.innerHTML ?? ''`, false),
+              false,
+            ),
+          )
         }
 
         if (needTagForRuntime) {