diff --git a/packages/runtime-core/src/compat/instanceChildren.ts b/packages/runtime-core/src/compat/instanceChildren.ts index 415275342ab..2623e1ef1bb 100644 --- a/packages/runtime-core/src/compat/instanceChildren.ts +++ b/packages/runtime-core/src/compat/instanceChildren.ts @@ -18,7 +18,11 @@ export function getCompatChildren( function walk(vnode: VNode, children: ComponentPublicInstance[]) { if (vnode.component) { - children.push(vnode.component.proxy!) + // `proxy` is not available for functional components + children.push( + vnode.component.proxy || + (vnode.component.ctx as unknown as ComponentPublicInstance), + ) } else if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) { const vnodes = vnode.children as VNode[] for (let i = 0; i < vnodes.length; i++) { diff --git a/packages/vue-compat/__tests__/instance.spec.ts b/packages/vue-compat/__tests__/instance.spec.ts index 75f1ea1334c..57f78dcf846 100644 --- a/packages/vue-compat/__tests__/instance.spec.ts +++ b/packages/vue-compat/__tests__/instance.spec.ts @@ -209,25 +209,50 @@ describe('INSTANCE_EVENT_HOOKS', () => { }) }) -test('INSTANCE_EVENT_CHILDREN', () => { - const vm = new Vue({ - template: `
`, - components: { - child: { - template: 'foo', - data() { - return { n: 1 } +describe('INSTANCE_CHILDREN', () => { + test('$children', () => { + const vm = new Vue({ + template: `
`, + components: { + child: { + template: 'foo', + data() { + return { n: 1 } + }, }, }, - }, - }).$mount() - expect(vm.$children.length).toBe(4) - vm.$children.forEach((c: any) => { - expect(c.n).toBe(1) + }).$mount() + expect(vm.$children.length).toBe(4) + vm.$children.forEach((c: any) => { + expect(c.n).toBe(1) + }) + expect( + deprecationData[DeprecationTypes.INSTANCE_CHILDREN].message, + ).toHaveBeenWarned() + }) + + test('$children inside functional component', () => { + const vm = new Vue({ + template: `
`, + compatConfig: { COMPONENT_FUNCTIONAL: 'suppress-warning' }, + components: { + childFunc: { + functional: true, + render: (h: any) => h('div'), + }, + childNormal: { + template: 'foo', + }, + }, + }).$mount() + expect(vm.$children.length).toBe(5) + vm.$children.forEach((c: any) => { + expect(c).toBeTruthy() + }) + expect( + deprecationData[DeprecationTypes.INSTANCE_CHILDREN].message, + ).toHaveBeenWarned() }) - expect( - deprecationData[DeprecationTypes.INSTANCE_CHILDREN].message, - ).toHaveBeenWarned() }) test('INSTANCE_LISTENERS', () => {