Skip to content

fix: make scoped slots rendering consistent for stubs #2068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions packages/create-instance/create-component-stubs.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,8 @@ function getScopedSlotRenderFunctions(ctx: any): Array<string> {
// In Vue 2.6+ a new v-slot syntax was introduced
// scopedSlots are now saved in parent._vnode.data.scopedSlots
// We filter out _normalized, $stable and $key keys
if (
ctx &&
ctx.$options &&
ctx.$options.parent &&
ctx.$options.parent._vnode &&
ctx.$options.parent._vnode.data &&
ctx.$options.parent._vnode.data.scopedSlots
) {
const slotKeys: Array<string> = ctx.$options.parent._vnode.data.scopedSlots
return keys(slotKeys).filter(
if (ctx.$vnode.data.scopedSlots) {
return keys(ctx.$vnode.data.scopedSlots).filter(
x => x !== '_normalized' && x !== '$stable' && x !== '$key'
)
}
Expand Down Expand Up @@ -130,9 +122,15 @@ export function createStubFromComponent(
context
? context.children
: this.$options._renderChildren ||
getScopedSlotRenderFunctions(this).map(x =>
this.$options.parent._vnode.data.scopedSlots[x]({})
)
getScopedSlotRenderFunctions(this)
.map(x => {
let result = null
try {
Copy link
Contributor Author

@xanf xanf Apr 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This try catch is best-effort attempt to mitigate migration from existing state. Since we're now rendering more scoped slots on stubs than previously there is higher chance of blow up.

While it might create some confusion (hey, some my slots are rendering, some are not) considering close EOL of Vue.js 2 I'm thinking of this one as acceptable trade-off

For example at GitLab codebase, without try - catch this MR entirely blows over 700 tests, with try catch - less than 100, however I'm open for discussion on removing it

result = this.$vnode.data.scopedSlots[x]({})
} catch (e) {}
return result
})
.filter(Boolean)
)
}
}
Expand Down
32 changes: 32 additions & 0 deletions test/specs/shallow-mount.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,38 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => {
)
})

it('renders named slots with v-slot syntax when they are wrapped', () => {
const localVue = createLocalVue()
localVue.component('Foo', {
template: '<div><slot name="newSyntax" /></div>'
})
const TestComponent = {
template: `
<div>
<Foo>
<template v-slot:newSyntax>
<p class="new-example">text</p>
</template>
</Foo>
</div>
`
}
const wrapper = shallowMount(TestComponent, {
localVue
})
expect(wrapper.find({ name: 'Foo' }).exists()).toEqual(true)
expect(wrapper.find('.new-example').exists()).toEqual(true)
expect(wrapper.html()).toEqual(
[
'<div>',
' <foo-stub>',
' <p class="new-example">text</p>',
' </foo-stub>',
'</div>'
].join('\n')
)
})

it('renders named slots when they are located inside component with v-if', () => {
const localVue = createLocalVue()
localVue.component('Foo', {
Expand Down