Skip to content

Commit 5db15cf

Browse files
authored
fix(compiler-vapor): enhance v-slot prop destructuring support (#14165)
1 parent 0ab7e1b commit 5db15cf

File tree

6 files changed

+395
-163
lines changed

6 files changed

+395
-163
lines changed

packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ export function render(_ctx) {
324324
const n1 = _createComponentWithFallback(_component_Comp, null, {
325325
"foo": _withVaporCtx((_slotProps0) => {
326326
const n0 = t0()
327-
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["a"] + _slotProps0["b"])))
327+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.a + _slotProps0.b)))
328328
return n0
329329
})
330330
}, true)

packages/compiler-vapor/__tests__/__snapshots__/scopeId.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function render(_ctx) {
5656
const n4 = _createComponentWithFallback(_component_Child, null, {
5757
"foo": _withVaporCtx((_slotProps0) => {
5858
const n0 = t0()
59-
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["msg"])))
59+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.msg)))
6060
return n0
6161
}),
6262
"bar": _withVaporCtx(() => {

packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap

Lines changed: 142 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function render(_ctx) {
3333
name: item,
3434
fn: _withVaporCtx((_slotProps0) => {
3535
const n0 = t0()
36-
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["bar"])))
36+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.bar)))
3737
return n0
3838
})
3939
})))
@@ -275,12 +275,12 @@ export function render(_ctx) {
275275
const n1 = _createComponentWithFallback(_component_Inner, null, {
276276
"default": _withVaporCtx((_slotProps1) => {
277277
const n0 = t0()
278-
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _slotProps1["bar"] + _ctx.baz)))
278+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.foo + _slotProps1.bar + _ctx.baz)))
279279
return n0
280280
})
281281
})
282282
const n3 = t0()
283-
_renderEffect(() => _setText(n3, " " + _toDisplayString(_slotProps0["foo"] + _ctx.bar + _ctx.baz)))
283+
_renderEffect(() => _setText(n3, " " + _toDisplayString(_slotProps0.foo + _ctx.bar + _ctx.baz)))
284284
return [n1, n3]
285285
})
286286
}, true)
@@ -300,7 +300,7 @@ export function render(_ctx) {
300300
name: _ctx.named,
301301
fn: _withVaporCtx((_slotProps0) => {
302302
const n0 = t0()
303-
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _ctx.bar)))
303+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.foo + _ctx.bar)))
304304
return n0
305305
})
306306
})
@@ -319,7 +319,7 @@ export function render(_ctx) {
319319
const n1 = _createComponentWithFallback(_component_Comp, null, {
320320
"named": _withVaporCtx((_slotProps0) => {
321321
const n0 = t0()
322-
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _ctx.bar)))
322+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.foo + _ctx.bar)))
323323
return n0
324324
})
325325
}, true)
@@ -336,7 +336,7 @@ export function render(_ctx) {
336336
const n1 = _createComponentWithFallback(_component_Comp, null, {
337337
"default": _withVaporCtx((_slotProps0) => {
338338
const n0 = t0()
339-
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _ctx.bar)))
339+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.foo + _ctx.bar)))
340340
return n0
341341
})
342342
}, true)
@@ -380,6 +380,142 @@ export function render(_ctx) {
380380
}"
381381
`;
382382
383+
exports[`compiler: transform slot > slot prop alias uses original key 1`] = `
384+
"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
385+
const t0 = _template(" ")
386+
387+
export function render(_ctx) {
388+
const _component_Comp = _resolveComponent("Comp")
389+
const n2 = _createComponentWithFallback(_component_Comp, null, {
390+
"default": _withVaporCtx((_slotProps0) => {
391+
const n0 = t0()
392+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.msg)))
393+
return n0
394+
})
395+
}, true)
396+
return n2
397+
}"
398+
`;
399+
400+
exports[`compiler: transform slot > slot prop array rest destructuring 1`] = `
401+
"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
402+
const t0 = _template(" ")
403+
404+
export function render(_ctx) {
405+
const _component_Comp = _resolveComponent("Comp")
406+
const n2 = _createComponentWithFallback(_component_Comp, null, {
407+
"default": _withVaporCtx((_slotProps0) => {
408+
const n0 = t0()
409+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.arr.slice(1)[0])))
410+
return n0
411+
})
412+
}, true)
413+
return n2
414+
}"
415+
`;
416+
417+
exports[`compiler: transform slot > slot prop computed key destructuring 1`] = `
418+
"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
419+
const t0 = _template(" ")
420+
421+
export function render(_ctx) {
422+
const _component_Comp = _resolveComponent("Comp")
423+
const n2 = _createComponentWithFallback(_component_Comp, null, {
424+
"default": _withVaporCtx((_slotProps0) => {
425+
const n0 = t0()
426+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0[_ctx.key])))
427+
return n0
428+
})
429+
}, true)
430+
return n2
431+
}"
432+
`;
433+
434+
exports[`compiler: transform slot > slot prop default value 1`] = `
435+
"import { resolveComponent as _resolveComponent, getDefaultValue as _getDefaultValue, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
436+
const t0 = _template(" ")
437+
438+
export function render(_ctx) {
439+
const _component_Comp = _resolveComponent("Comp")
440+
const n2 = _createComponentWithFallback(_component_Comp, null, {
441+
"default": _withVaporCtx((_slotProps0) => {
442+
const n0 = t0()
443+
_renderEffect(() => _setText(n0, _toDisplayString(_getDefaultValue(_slotProps0.foo, 1))))
444+
return n0
445+
})
446+
}, true)
447+
return n2
448+
}"
449+
`;
450+
451+
exports[`compiler: transform slot > slot prop nested default value 1`] = `
452+
"import { resolveComponent as _resolveComponent, getDefaultValue as _getDefaultValue, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
453+
const t0 = _template(" ")
454+
455+
export function render(_ctx) {
456+
const _component_Comp = _resolveComponent("Comp")
457+
const n2 = _createComponentWithFallback(_component_Comp, null, {
458+
"default": _withVaporCtx((_slotProps0) => {
459+
const n0 = t0()
460+
_renderEffect(() => _setText(n0, _toDisplayString(_getDefaultValue(_slotProps0.foo[0], 1) + _getDefaultValue(_slotProps0.baz.qux, 2))))
461+
return n0
462+
})
463+
}, true)
464+
return n2
465+
}"
466+
`;
467+
468+
exports[`compiler: transform slot > slot prop nested destructuring 1`] = `
469+
"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
470+
const t0 = _template(" ")
471+
472+
export function render(_ctx) {
473+
const _component_Comp = _resolveComponent("Comp")
474+
const n2 = _createComponentWithFallback(_component_Comp, null, {
475+
"default": _withVaporCtx((_slotProps0) => {
476+
const n0 = t0()
477+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.foo.bar)))
478+
return n0
479+
})
480+
}, true)
481+
return n2
482+
}"
483+
`;
484+
485+
exports[`compiler: transform slot > slot prop rest destructuring 1`] = `
486+
"import { resolveComponent as _resolveComponent, getRestElement as _getRestElement, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
487+
const t0 = _template(" ")
488+
489+
export function render(_ctx) {
490+
const _component_Comp = _resolveComponent("Comp")
491+
const n2 = _createComponentWithFallback(_component_Comp, null, {
492+
"default": _withVaporCtx((_slotProps0) => {
493+
const n0 = t0()
494+
_renderEffect(() => _setText(n0, _toDisplayString(_getRestElement(_slotProps0, ["foo"]).bar)))
495+
return n0
496+
})
497+
}, true)
498+
return n2
499+
}"
500+
`;
501+
502+
exports[`compiler: transform slot > slot prop rest with computed keys preserved 1`] = `
503+
"import { resolveComponent as _resolveComponent, getRestElement as _getRestElement, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
504+
const t0 = _template(" ")
505+
506+
export function render(_ctx) {
507+
const _component_Comp = _resolveComponent("Comp")
508+
const n2 = _createComponentWithFallback(_component_Comp, null, {
509+
"default": _withVaporCtx((_slotProps0) => {
510+
const n0 = t0()
511+
_renderEffect(() => _setText(n0, _toDisplayString(_slotProps0.foo + _getRestElement(_slotProps0, ["foo", _ctx.key]).other)))
512+
return n0
513+
})
514+
}, true)
515+
return n2
516+
}"
517+
`;
518+
383519
exports[`compiler: transform slot > with whitespace: 'preserve' > implicit default slot 1`] = `
384520
"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
385521
const t0 = _template(" Header ")

packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ describe('compiler: transform slot', () => {
6868
expect(code).toMatchSnapshot()
6969

7070
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
71-
expect(code).contains(`_slotProps0["foo"] + _ctx.bar`)
71+
expect(code).contains(`_slotProps0.foo + _ctx.bar`)
7272

7373
expect(ir.block.dynamic.children[0].operation).toMatchObject({
7474
type: IRNodeTypes.CREATE_COMPONENT_NODE,
@@ -102,7 +102,7 @@ describe('compiler: transform slot', () => {
102102
expect(code).toMatchSnapshot()
103103

104104
expect(code).contains(`"named": _withVaporCtx((_slotProps0) =>`)
105-
expect(code).contains(`_slotProps0["foo"] + _ctx.bar`)
105+
expect(code).contains(`_slotProps0.foo + _ctx.bar`)
106106

107107
expect(ir.block.dynamic.children[0].operation).toMatchObject({
108108
type: IRNodeTypes.CREATE_COMPONENT_NODE,
@@ -131,7 +131,7 @@ describe('compiler: transform slot', () => {
131131
expect(code).toMatchSnapshot()
132132

133133
expect(code).contains(`fn: _withVaporCtx((_slotProps0) =>`)
134-
expect(code).contains(`_slotProps0["foo"] + _ctx.bar`)
134+
expect(code).contains(`_slotProps0.foo + _ctx.bar`)
135135

136136
expect(ir.block.dynamic.children[0].operation).toMatchObject({
137137
type: IRNodeTypes.CREATE_COMPONENT_NODE,
@@ -165,6 +165,87 @@ describe('compiler: transform slot', () => {
165165
expect(code).toMatchSnapshot()
166166
})
167167

168+
test('slot prop alias uses original key', () => {
169+
const { code } = compileWithSlots(
170+
`<Comp><template #default="{ msg: msg1 }">{{ msg1 }}</template></Comp>`,
171+
)
172+
173+
expect(code).toMatchSnapshot()
174+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
175+
expect(code).contains(`_slotProps0.msg`)
176+
})
177+
178+
test('slot prop nested destructuring', () => {
179+
const { code } = compileWithSlots(
180+
`<Comp><template #default="{ foo: { bar: baz } }">{{ baz }}</template></Comp>`,
181+
)
182+
183+
expect(code).toMatchSnapshot()
184+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
185+
expect(code).contains(`_slotProps0.foo.bar`)
186+
})
187+
188+
test('slot prop computed key destructuring', () => {
189+
const { code } = compileWithSlots(
190+
`<Comp><template #default="{ [key]: val }">{{ val }}</template></Comp>`,
191+
)
192+
193+
expect(code).toMatchSnapshot()
194+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
195+
expect(code).contains(`_slotProps0[_ctx.key]`)
196+
})
197+
198+
test('slot prop rest destructuring', () => {
199+
const { code } = compileWithSlots(
200+
`<Comp><template #default="{ foo, ...rest }">{{ rest.bar }}</template></Comp>`,
201+
)
202+
203+
expect(code).toMatchSnapshot()
204+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
205+
expect(code).contains(`_getRestElement(_slotProps0`)
206+
})
207+
208+
test('slot prop array rest destructuring', () => {
209+
const { code } = compileWithSlots(
210+
`<Comp><template #default="{ arr: [first, ...rest] }">{{ rest[0] }}</template></Comp>`,
211+
)
212+
213+
expect(code).toMatchSnapshot()
214+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
215+
expect(code).contains(`_slotProps0.arr.slice(1)`)
216+
})
217+
218+
test('slot prop default value', () => {
219+
const { code } = compileWithSlots(
220+
`<Comp><template #default="{ foo = 1 }">{{ foo }}</template></Comp>`,
221+
)
222+
223+
expect(code).toMatchSnapshot()
224+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
225+
expect(code).contains(`_getDefaultValue(_slotProps0.foo, 1)`)
226+
})
227+
228+
test('slot prop nested default value', () => {
229+
const { code } = compileWithSlots(
230+
`<Comp><template #default="{ foo: [bar = 1], baz: { qux = 2 } }">{{ bar + qux }}</template></Comp>`,
231+
)
232+
233+
expect(code).toMatchSnapshot()
234+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
235+
expect(code).contains(`_getDefaultValue(_slotProps0.foo[0], 1)`)
236+
expect(code).contains(`_getDefaultValue(_slotProps0.baz.qux, 2)`)
237+
})
238+
239+
test('slot prop rest with computed keys preserved', () => {
240+
const { code } = compileWithSlots(
241+
`<Comp><template #default="{ foo, [key]: val, ...rest }">{{ foo + rest.other }}</template></Comp>`,
242+
)
243+
244+
expect(code).toMatchSnapshot()
245+
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
246+
expect(code).contains(`_getRestElement(_slotProps0, ["foo", _ctx.key])`)
247+
})
248+
168249
test('named slots w/ implicit default slot', () => {
169250
const { ir, code } = compileWithSlots(
170251
`<Comp>
@@ -216,8 +297,8 @@ describe('compiler: transform slot', () => {
216297

217298
expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
218299
expect(code).contains(`"default": _withVaporCtx((_slotProps1) =>`)
219-
expect(code).contains(`_slotProps0["foo"] + _slotProps1["bar"] + _ctx.baz`)
220-
expect(code).contains(`_slotProps0["foo"] + _ctx.bar + _ctx.baz`)
300+
expect(code).contains(`_slotProps0.foo + _slotProps1.bar + _ctx.baz`)
301+
expect(code).contains(`_slotProps0.foo + _ctx.bar + _ctx.baz`)
221302

222303
const outerOp = ir.block.dynamic.children[0].operation
223304
expect(outerOp).toMatchObject({
@@ -293,7 +374,7 @@ describe('compiler: transform slot', () => {
293374
expect(code).toMatchSnapshot()
294375

295376
expect(code).contains(`fn: _withVaporCtx((_slotProps0) =>`)
296-
expect(code).contains(`_setText(n0, _toDisplayString(_slotProps0["bar"]))`)
377+
expect(code).contains(`_setText(n0, _toDisplayString(_slotProps0.bar))`)
297378

298379
expect(ir.block.dynamic.children[0].operation).toMatchObject({
299380
type: IRNodeTypes.CREATE_COMPONENT_NODE,

0 commit comments

Comments
 (0)