Skip to content

Commit 53f4885

Browse files
committed
fix(runtime-core): skip functional components in public $parent chain traversal
fix #2437
1 parent 7cd85be commit 53f4885

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

packages/runtime-core/src/componentPublicInstance.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ export type ComponentPublicInstance<
200200

201201
type PublicPropertiesMap = Record<string, (i: ComponentInternalInstance) => any>
202202

203+
/**
204+
* #2437 In Vue 3, functional components do not have a public instance proxy but
205+
* they exist in the internal parent chain. For code that relies on traversing
206+
* public $parent chains, skip functional ones and go to the parent instead.
207+
*/
208+
const getPublicInstance = (
209+
i: ComponentInternalInstance | null
210+
): ComponentPublicInstance | null =>
211+
i && (i.proxy ? i.proxy : getPublicInstance(i.parent))
212+
203213
const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
204214
$: i => i,
205215
$el: i => i.vnode.el,
@@ -208,7 +218,7 @@ const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
208218
$attrs: i => (__DEV__ ? shallowReadonly(i.attrs) : i.attrs),
209219
$slots: i => (__DEV__ ? shallowReadonly(i.slots) : i.slots),
210220
$refs: i => (__DEV__ ? shallowReadonly(i.refs) : i.refs),
211-
$parent: i => i.parent && i.parent.proxy,
221+
$parent: i => getPublicInstance(i.parent),
212222
$root: i => i.root && i.root.proxy,
213223
$emit: i => i.emit,
214224
$options: i => (__FEATURE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),

0 commit comments

Comments
 (0)