Skip to content

Commit b3890a9

Browse files
committed
fix(runtime-core): fix component proxy props presence check
fix #864
1 parent c3bb316 commit b3890a9

File tree

3 files changed

+22
-14
lines changed

3 files changed

+22
-14
lines changed

packages/runtime-core/__tests__/componentProxy.spec.ts

+14
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,18 @@ describe('component: proxy', () => {
175175
instanceProxy.baz = 1
176176
expect('baz' in instanceProxy).toBe(true)
177177
})
178+
179+
// #864
180+
test('should not warn declared but absent props', () => {
181+
const Comp = {
182+
props: ['test'],
183+
render(this: any) {
184+
return this.test
185+
}
186+
}
187+
render(h(Comp), nodeOps.createElement('div'))
188+
expect(
189+
`was accessed during render but is not defined`
190+
).not.toHaveBeenWarned()
191+
})
178192
})

packages/runtime-core/src/componentProps.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {
1212
toRawType,
1313
PatchFlags,
1414
makeMap,
15-
isReservedProp
15+
isReservedProp,
16+
EMPTY_ARR
1617
} from '@vue/shared'
1718
import { warn } from './warning'
1819
import { Data, ComponentInternalInstance } from './component'
@@ -216,11 +217,11 @@ function validatePropName(key: string) {
216217
return false
217218
}
218219

219-
function normalizePropsOptions(
220+
export function normalizePropsOptions(
220221
raw: ComponentPropsOptions | void
221222
): NormalizedPropsOptions {
222223
if (!raw) {
223-
return [] as any
224+
return EMPTY_ARR as any
224225
}
225226
if (normalizationMap.has(raw)) {
226227
return normalizationMap.get(raw)!

packages/runtime-core/src/componentProxy.ts

+4-11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
currentRenderingInstance,
1616
markAttrsAccessed
1717
} from './componentRenderUtils'
18+
import { normalizePropsOptions } from './componentProps'
1819

1920
// public properties exposed on the proxy, which is used as the render context
2021
// in templates (as `this` in the render option)
@@ -75,15 +76,7 @@ const enum AccessTypes {
7576

7677
export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
7778
get(target: ComponentInternalInstance, key: string) {
78-
const {
79-
renderContext,
80-
data,
81-
props,
82-
propsProxy,
83-
accessCache,
84-
type,
85-
sink
86-
} = target
79+
const { renderContext, data, propsProxy, accessCache, type, sink } = target
8780

8881
// data / props / renderContext
8982
// This getter gets called for every property access on the render context
@@ -110,9 +103,9 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
110103
accessCache![key] = AccessTypes.CONTEXT
111104
return renderContext[key]
112105
} else if (type.props) {
113-
// only cache other properties when instance has declared (this stable)
106+
// only cache other properties when instance has declared (thus stable)
114107
// props
115-
if (hasOwn(props, key)) {
108+
if (hasOwn(normalizePropsOptions(type.props)[0], key)) {
116109
accessCache![key] = AccessTypes.PROPS
117110
// return the value from propsProxy for ref unwrapping and readonly
118111
return propsProxy![key]

0 commit comments

Comments
 (0)