ref,
render,
} from '@vue/runtime-test'
-import { normalizeVNode } from '../src/vnode'
+import { createBlock, normalizeVNode } from '../src/vnode'
import { createSlots } from '../src/helpers/createSlots'
describe('component: slots', () => {
}
test('initSlots: instance.slots should be set correctly', () => {
+ let instance: any
+ const Comp = {
+ render() {
+ instance = getCurrentInstance()
+ return h('div')
+ },
+ }
+ const slots = { foo: () => {}, _: 1 }
+ render(createBlock(Comp, null, slots), nodeOps.createElement('div'))
+ expect(instance.slots).toMatchObject(slots)
+ })
+
+ test('initSlots: instance.slots should remove compiler marker if parent is using manual render function', () => {
const { slots } = renderWithSlots({ _: 1 })
- expect(slots).toMatchObject({ _: 1 })
+ expect(slots).toMatchObject({})
})
test('initSlots: should normalize object slots (when value is null, string, array)', () => {
const App = {
setup() {
return () => {
- return createVNode(Comp, null, {
+ return createBlock(Comp, null, {
default: withCtx(() => [
createVNode('p', null, foo.value, PatchFlags.TEXT),
]),
const state = ref(0)
const CompA = {
+ name: 'A',
setup(props: any, { slots }: SetupContext) {
return () => {
return (
}
const Wrapper = {
+ name: 'Wrapper',
setup(props: any, { slots }: SetupContext) {
// use the manually written render function to rendering the optimized slots,
// which should make subsequent updates exit the optimized mode correctly
}
const app = createApp({
+ name: 'App',
setup() {
return () => {
return (
export function setupComponent(
instance: ComponentInternalInstance,
isSSR = false,
+ optimized = false,
) {
isSSR && setInSSRSetupState(isSSR)
const { props, children } = instance.vnode
const isStateful = isStatefulComponent(instance)
initProps(instance, props, isStateful, isSSR)
- initSlots(instance, children)
+ initSlots(instance, children, optimized)
const setupResult = isStateful
? setupStatefulComponent(instance, isSSR)
export const initSlots = (
instance: ComponentInternalInstance,
children: VNodeNormalizedChildren,
+ optimized: boolean,
) => {
const slots = (instance.slots = createInternalObject())
if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
if (type) {
extend(slots, children as InternalSlots)
// make compiler marker non-enumerable
- def(slots, '_', type, true)
+ if (optimized) {
+ def(slots, '_', type, true)
+ } else {
+ // #2893
+ // when rendering the optimized slots by manually written render function,
+ // we need to delete the `slots._` flag if necessary to make subsequent
+ // updates reliable, i.e. let the `renderSlot` create the bailed Fragment
+ delete slots._
+ }
} else {
normalizeObjectSlots(children as RawSlots, slots, instance)
}
// compiled but dynamic (v-if/v-for on slots) - update slots, but skip
// normalization.
extend(slots, children as Slots)
- // #2893
- // when rendering the optimized slots by manually written render function,
- // we need to delete the `slots._` flag if necessary to make subsequent updates reliable,
- // i.e. let the `renderSlot` create the bailed Fragment
- if (!optimized && type === SlotFlags.STABLE) {
- delete slots._
- }
}
} else {
needDeletionCheck = !(children as RawSlots).$stable
if (__DEV__) {
startMeasure(instance, `init`)
}
- setupComponent(instance)
+ setupComponent(instance, false, optimized)
if (__DEV__) {
endMeasure(instance, `init`)
}