Browse Source

fix(compiler-sfc): preserve vapor render args for template-only components (#14722)

edison 1 week ago
parent
commit
eef81d3e85

+ 13 - 0
packages/compiler-sfc/__tests__/compileTemplate.spec.ts

@@ -542,6 +542,19 @@ test('returns multiRoot metadata for a multi-root template when vapor is enabled
   expect(result.multiRoot).toBe(true)
   expect(result.multiRoot).toBe(true)
 })
 })
 
 
+test('template-only vapor compile keeps built-in render args for $slots', () => {
+  const result = compile({
+    filename: 'example.vue',
+    source: `<span v-if="$slots.default"><slot /></span>`,
+    vapor: true,
+  })
+
+  expect(result.code).toContain(
+    `export function render(_ctx, $props, $emit, $attrs, $slots)`,
+  )
+  expect(result.code).toContain(`_createIf(() => ($slots.default)`)
+})
+
 test('returns single-root metadata for root control flow when vapor is enabled', () => {
 test('returns single-root metadata for root control flow when vapor is enabled', () => {
   const result = compile({
   const result = compile({
     filename: 'example.vue',
     filename: 'example.vue',

+ 6 - 0
packages/compiler-sfc/src/compileTemplate.ts

@@ -255,6 +255,12 @@ function doCompileTemplate({
       slotted,
       slotted,
       sourceMap: true,
       sourceMap: true,
       ...compilerOptions,
       ...compilerOptions,
+      // Template-only vapor SFCs have no script analysis, but compiler-vapor
+      // still needs bindingMetadata to keep built-in render args like $slots.
+      bindingMetadata:
+        vapor && !ssr && compilerOptions.bindingMetadata == null
+          ? {}
+          : compilerOptions.bindingMetadata,
       hmr: !isProd,
       hmr: !isProd,
       nodeTransforms: nodeTransforms.concat(
       nodeTransforms: nodeTransforms.concat(
         compilerOptions.nodeTransforms || [],
         compilerOptions.nodeTransforms || [],

+ 10 - 10
packages/compiler-vapor/__tests__/transforms/__snapshots__/templateTransformAssetUrl.spec.ts.snap

@@ -4,7 +4,7 @@ exports[`compiler sfc: transform asset url > should allow for full base URLs, wi
 "import { template as _template } from 'vue';
 "import { template as _template } from 'vue';
 const t0 = _template("<img src=http://localhost:3000/src/logo.png>", true)
 const t0 = _template("<img src=http://localhost:3000/src/logo.png>", true)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   return n0
   return n0
 }"
 }"
@@ -14,7 +14,7 @@ exports[`compiler sfc: transform asset url > should allow for full base URLs, wi
 "import { template as _template } from 'vue';
 "import { template as _template } from 'vue';
 const t0 = _template("<img src=http://localhost:3000/logo.png>", true)
 const t0 = _template("<img src=http://localhost:3000/logo.png>", true)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   return n0
   return n0
 }"
 }"
@@ -24,7 +24,7 @@ exports[`compiler sfc: transform asset url > should allow for full base URLs, wi
 "import { template as _template } from 'vue';
 "import { template as _template } from 'vue';
 const t0 = _template("<img src=http://localhost/logo.png>", true)
 const t0 = _template("<img src=http://localhost/logo.png>", true)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   return n0
   return n0
 }"
 }"
@@ -34,7 +34,7 @@ exports[`compiler sfc: transform asset url > should allow for full base URLs, wi
 "import { template as _template } from 'vue';
 "import { template as _template } from 'vue';
 const t0 = _template("<img src=//localhost/logo.png>", true)
 const t0 = _template("<img src=//localhost/logo.png>", true)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   return n0
   return n0
 }"
 }"
@@ -45,7 +45,7 @@ exports[`compiler sfc: transform asset url > support uri fragment 1`] = `
 import _imports_0 from '@svg/file.svg';
 import _imports_0 from '@svg/file.svg';
 const t0 = _template("<use href=\\"" + _imports_0 + '#fragment' + "\\">", false, 1)
 const t0 = _template("<use href=\\"" + _imports_0 + '#fragment' + "\\">", false, 1)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t0()
   const n1 = t0()
   return [n0, n1]
   return [n0, n1]
@@ -56,7 +56,7 @@ exports[`compiler sfc: transform asset url > support uri is empty 1`] = `
 "import { template as _template } from 'vue';
 "import { template as _template } from 'vue';
 const t0 = _template("<use href>", true, 1)
 const t0 = _template("<use href>", true, 1)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   return n0
   return n0
 }"
 }"
@@ -74,7 +74,7 @@ const t3 = _template("<img src=//example.com/fixtures/logo.png>")
 const t4 = _template("<img src=\\"" + _imports_2 + "\\">")
 const t4 = _template("<img src=\\"" + _imports_2 + "\\">")
 const t5 = _template("<img src=data:image/png;base64,i>")
 const t5 = _template("<img src=data:image/png;base64,i>")
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t1()
   const n1 = t1()
   const n2 = t1()
   const n2 = t1()
@@ -92,7 +92,7 @@ import _imports_0 from './bar.png';
 import _imports_1 from '/bar.png';
 import _imports_1 from '/bar.png';
 const t0 = _template("<div><img src=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_1 + "\\"><img src=https://foo.bar/baz.png><img src=//foo.bar/baz.png><img src=\\"" + _imports_0 + "\\">", true)
 const t0 = _template("<div><img src=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_1 + "\\"><img src=https://foo.bar/baz.png><img src=//foo.bar/baz.png><img src=\\"" + _imports_0 + "\\">", true)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   return n0
   return n0
 }"
 }"
@@ -106,7 +106,7 @@ const t0 = _template("<img src=/foo/bar.png>")
 const t1 = _template("<img src=\\"" + _imports_0 + "\\">")
 const t1 = _template("<img src=\\"" + _imports_0 + "\\">")
 const t2 = _template("<img src=\\"" + _imports_1 + "\\">")
 const t2 = _template("<img src=\\"" + _imports_1 + "\\">")
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t1()
   const n1 = t1()
   const n2 = t1()
   const n2 = t1()
@@ -124,7 +124,7 @@ const t1 = _template("<img src=\\"" + _imports_1 + "\\">")
 const t2 = _template("<img src=https://foo.bar/baz.png>")
 const t2 = _template("<img src=https://foo.bar/baz.png>")
 const t3 = _template("<img src=//foo.bar/baz.png>")
 const t3 = _template("<img src=//foo.bar/baz.png>")
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t1()
   const n1 = t1()
   const n2 = t2()
   const n2 = t2()

+ 5 - 5
packages/compiler-vapor/__tests__/transforms/__snapshots__/templateTransformSrcset.spec.ts.snap

@@ -7,7 +7,7 @@ import _imports_1 from '/foo/logo.png';
 const t0 = _template("<img srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\">")
 const t0 = _template("<img srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\">")
 const t1 = _template("<img srcset=\\"" + _imports_0 + ' 1x, ' + _imports_1 + ' 2x' + "\\">")
 const t1 = _template("<img srcset=\\"" + _imports_0 + ' 1x, ' + _imports_1 + ' 2x' + "\\">")
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t1()
   const n1 = t1()
   return [n0, n1]
   return [n0, n1]
@@ -30,7 +30,7 @@ const t8 = _template("<img src=https://example.com/logo.png srcset=\\"https://ex
 const t9 = _template("<img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\">")
 const t9 = _template("<img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\">")
 const t10 = _template("<img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
 const t10 = _template("<img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t1()
   const n1 = t1()
   const n2 = t2()
   const n2 = t2()
@@ -63,7 +63,7 @@ const t8 = _template("<img src=https://example.com/logo.png srcset=\\"https://ex
 const t9 = _template("<img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ', ' + _imports_1 + ' 2x' + "\\">")
 const t9 = _template("<img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ', ' + _imports_1 + ' 2x' + "\\">")
 const t10 = _template("<img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
 const t10 = _template("<img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t1()
   const n1 = t1()
   const n2 = t2()
   const n2 = t2()
@@ -96,7 +96,7 @@ const t8 = _template("<img src=https://example.com/logo.png srcset=\\"https://ex
 const t9 = _template("<img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\">")
 const t9 = _template("<img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\">")
 const t10 = _template("<img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
 const t10 = _template("<img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   const n1 = t1()
   const n1 = t1()
   const n2 = t2()
   const n2 = t2()
@@ -119,7 +119,7 @@ import _imports_0 from './logo.png';
 import _imports_1 from '/logo.png';
 import _imports_1 from '/logo.png';
 const t0 = _template("<div><img src=\\"" + _imports_0 + "\\"srcset><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\"><img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_1 + ' 2x' + "\\"><img src=https://example.com/logo.png srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\"><img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\"><img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">", true)
 const t0 = _template("<div><img src=\\"" + _imports_0 + "\\"srcset><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\"><img src=\\"" + _imports_0 + "\\"srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\"><img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_1 + ' 2x' + "\\"><img src=https://example.com/logo.png srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\"><img src=\\"" + _imports_1 + "\\"srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\"><img src=data:image/png;base64,i srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">", true)
 
 
-export function render(_ctx) {
+export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n0 = t0()
   const n0 = t0()
   return n0
   return n0
 }"
 }"