@@ -200,6 +200,16 @@ export type ComponentPublicInstance<
200
200
201
201
type PublicPropertiesMap = Record < string , ( i : ComponentInternalInstance ) => any >
202
202
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
+
203
213
const publicPropertiesMap : PublicPropertiesMap = extend ( Object . create ( null ) , {
204
214
$ : i => i ,
205
215
$el : i => i . vnode . el ,
@@ -208,7 +218,7 @@ const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
208
218
$attrs : i => ( __DEV__ ? shallowReadonly ( i . attrs ) : i . attrs ) ,
209
219
$slots : i => ( __DEV__ ? shallowReadonly ( i . slots ) : i . slots ) ,
210
220
$refs : i => ( __DEV__ ? shallowReadonly ( i . refs ) : i . refs ) ,
211
- $parent : i => i . parent && i . parent . proxy ,
221
+ $parent : i => getPublicInstance ( i . parent ) ,
212
222
$root : i => i . root && i . root . proxy ,
213
223
$emit : i => i . emit ,
214
224
$options : i => ( __FEATURE_OPTIONS_API__ ? resolveMergedOptions ( i ) : i . type ) ,
0 commit comments