diff --git a/packages/runtime-core/__tests__/componentProxy.spec.ts b/packages/runtime-core/__tests__/componentProxy.spec.ts index 0790f2246e1..8ea2ace2079 100644 --- a/packages/runtime-core/__tests__/componentProxy.spec.ts +++ b/packages/runtime-core/__tests__/componentProxy.spec.ts @@ -76,6 +76,20 @@ describe('component: proxy', () => { expect(`Attempting to mutate prop "foo"`).toHaveBeenWarned() }) + test('should not expose non-declared props', () => { + let instanceProxy: any + const Comp = { + setup() { + return () => null + }, + mounted() { + instanceProxy = this + } + } + render(h(Comp, { count: 1 }), nodeOps.createElement('div')) + expect('count' in instanceProxy).toBe(false) + }) + test('public properties', () => { let instance: ComponentInternalInstance let instanceProxy: any diff --git a/packages/runtime-core/src/componentProxy.ts b/packages/runtime-core/src/componentProxy.ts index dbdbe894060..1adad4aa056 100644 --- a/packages/runtime-core/src/componentProxy.ts +++ b/packages/runtime-core/src/componentProxy.ts @@ -69,7 +69,8 @@ const publicPropertiesMap: Record< const enum AccessTypes { DATA, CONTEXT, - PROPS + PROPS, + OTHER } export const PublicInstanceProxyHandlers: ProxyHandler = { @@ -104,6 +105,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler = { return renderContext[key] case AccessTypes.PROPS: return propsProxy![key] + // default: just fallthrough } } else if (data !== EMPTY_OBJ && hasOwn(data, key)) { accessCache![key] = AccessTypes.DATA @@ -111,13 +113,16 @@ export const PublicInstanceProxyHandlers: ProxyHandler = { } else if (hasOwn(renderContext, key)) { accessCache![key] = AccessTypes.CONTEXT return renderContext[key] - } else if (hasOwn(props, key)) { - // only cache props access if component has declared (thus stable) props - if (type.props != null) { + } else if (type.props != null) { + // only cache other properties when instance has declared (this stable) + // props + if (hasOwn(props, key)) { accessCache![key] = AccessTypes.PROPS + // return the value from propsProxy for ref unwrapping and readonly + return propsProxy![key] + } else { + accessCache![key] = AccessTypes.OTHER } - // return the value from propsProxy for ref unwrapping and readonly - return propsProxy![key] } }