Просмотр исходного кода

fix(runtime-core): fix component proxy props presence check

fix #864
Evan You 6 лет назад
Родитель
Сommit
b3890a93e3

+ 14 - 0
packages/runtime-core/__tests__/componentProxy.spec.ts

@@ -175,4 +175,18 @@ describe('component: proxy', () => {
     instanceProxy.baz = 1
     instanceProxy.baz = 1
     expect('baz' in instanceProxy).toBe(true)
     expect('baz' in instanceProxy).toBe(true)
   })
   })
+
+  // #864
+  test('should not warn declared but absent props', () => {
+    const Comp = {
+      props: ['test'],
+      render(this: any) {
+        return this.test
+      }
+    }
+    render(h(Comp), nodeOps.createElement('div'))
+    expect(
+      `was accessed during render but is not defined`
+    ).not.toHaveBeenWarned()
+  })
 })
 })

+ 4 - 3
packages/runtime-core/src/componentProps.ts

@@ -12,7 +12,8 @@ import {
   toRawType,
   toRawType,
   PatchFlags,
   PatchFlags,
   makeMap,
   makeMap,
-  isReservedProp
+  isReservedProp,
+  EMPTY_ARR
 } from '@vue/shared'
 } from '@vue/shared'
 import { warn } from './warning'
 import { warn } from './warning'
 import { Data, ComponentInternalInstance } from './component'
 import { Data, ComponentInternalInstance } from './component'
@@ -216,11 +217,11 @@ function validatePropName(key: string) {
   return false
   return false
 }
 }
 
 
-function normalizePropsOptions(
+export function normalizePropsOptions(
   raw: ComponentPropsOptions | void
   raw: ComponentPropsOptions | void
 ): NormalizedPropsOptions {
 ): NormalizedPropsOptions {
   if (!raw) {
   if (!raw) {
-    return [] as any
+    return EMPTY_ARR as any
   }
   }
   if (normalizationMap.has(raw)) {
   if (normalizationMap.has(raw)) {
     return normalizationMap.get(raw)!
     return normalizationMap.get(raw)!

+ 4 - 11
packages/runtime-core/src/componentProxy.ts

@@ -15,6 +15,7 @@ import {
   currentRenderingInstance,
   currentRenderingInstance,
   markAttrsAccessed
   markAttrsAccessed
 } from './componentRenderUtils'
 } from './componentRenderUtils'
+import { normalizePropsOptions } from './componentProps'
 
 
 // public properties exposed on the proxy, which is used as the render context
 // public properties exposed on the proxy, which is used as the render context
 // in templates (as `this` in the render option)
 // in templates (as `this` in the render option)
@@ -75,15 +76,7 @@ const enum AccessTypes {
 
 
 export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
 export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
   get(target: ComponentInternalInstance, key: string) {
   get(target: ComponentInternalInstance, key: string) {
-    const {
-      renderContext,
-      data,
-      props,
-      propsProxy,
-      accessCache,
-      type,
-      sink
-    } = target
+    const { renderContext, data, propsProxy, accessCache, type, sink } = target
 
 
     // data / props / renderContext
     // data / props / renderContext
     // This getter gets called for every property access on the render context
     // This getter gets called for every property access on the render context
@@ -110,9 +103,9 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
         accessCache![key] = AccessTypes.CONTEXT
         accessCache![key] = AccessTypes.CONTEXT
         return renderContext[key]
         return renderContext[key]
       } else if (type.props) {
       } else if (type.props) {
-        // only cache other properties when instance has declared (this stable)
+        // only cache other properties when instance has declared (thus stable)
         // props
         // props
-        if (hasOwn(props, key)) {
+        if (hasOwn(normalizePropsOptions(type.props)[0], key)) {
           accessCache![key] = AccessTypes.PROPS
           accessCache![key] = AccessTypes.PROPS
           // return the value from propsProxy for ref unwrapping and readonly
           // return the value from propsProxy for ref unwrapping and readonly
           return propsProxy![key]
           return propsProxy![key]