浏览代码

fix(runtime-core): improve consistency of `PublicInstanceProxyHandlers.has` (#13507)

skirtle 8 月之前
父节点
当前提交
d7283f3b7f

+ 30 - 1
packages/runtime-core/__tests__/componentPublicInstance.spec.ts

@@ -167,13 +167,26 @@ describe('component: proxy', () => {
       data() {
         return {
           foo: 0,
+          $foo: 0,
         }
       },
+      computed: {
+        cmp: () => {
+          throw new Error('value of cmp should not be accessed')
+        },
+        $cmp: () => {
+          throw new Error('value of $cmp should not be read')
+        },
+      },
       setup() {
         return {
           bar: 1,
         }
       },
+      __cssModules: {
+        $style: {},
+        cssStyles: {},
+      },
       mounted() {
         instanceProxy = this
       },
@@ -181,6 +194,7 @@ describe('component: proxy', () => {
 
     const app = createApp(Comp, { msg: 'hello' })
     app.config.globalProperties.global = 1
+    app.config.globalProperties.$global = 1
 
     app.mount(nodeOps.createElement('div'))
 
@@ -188,12 +202,20 @@ describe('component: proxy', () => {
     expect('msg' in instanceProxy).toBe(true)
     // data
     expect('foo' in instanceProxy).toBe(true)
-    // ctx
+    expect('$foo' in instanceProxy).toBe(false)
+    // setupState
     expect('bar' in instanceProxy).toBe(true)
+    // ctx
+    expect('cmp' in instanceProxy).toBe(true)
+    expect('$cmp' in instanceProxy).toBe(true)
     // public properties
     expect('$el' in instanceProxy).toBe(true)
+    // CSS modules
+    expect('$style' in instanceProxy).toBe(true)
+    expect('cssStyles' in instanceProxy).toBe(true)
     // global properties
     expect('global' in instanceProxy).toBe(true)
+    expect('$global' in instanceProxy).toBe(true)
 
     // non-existent
     expect('$foobar' in instanceProxy).toBe(false)
@@ -202,11 +224,15 @@ describe('component: proxy', () => {
     // #4962 triggering getter should not cause non-existent property to
     // pass the has check
     instanceProxy.baz
+    instanceProxy.$baz
     expect('baz' in instanceProxy).toBe(false)
+    expect('$baz' in instanceProxy).toBe(false)
 
     // set non-existent (goes into proxyTarget sink)
     instanceProxy.baz = 1
     expect('baz' in instanceProxy).toBe(true)
+    instanceProxy.$baz = 1
+    expect('$baz' in instanceProxy).toBe(true)
 
     // dev mode ownKeys check for console inspection
     // should only expose own keys
@@ -214,7 +240,10 @@ describe('component: proxy', () => {
       'msg',
       'bar',
       'foo',
+      'cmp',
+      '$cmp',
       'baz',
+      '$baz',
     ])
   })
 

+ 7 - 6
packages/runtime-core/src/componentPublicInstance.ts

@@ -575,19 +575,20 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
 
   has(
     {
-      _: { data, setupState, accessCache, ctx, appContext, propsOptions },
+      _: { data, setupState, accessCache, ctx, appContext, propsOptions, type },
     }: ComponentRenderContext,
     key: string,
   ) {
-    let normalizedProps
-    return (
-      !!accessCache![key] ||
-      (data !== EMPTY_OBJ && hasOwn(data, key)) ||
+    let normalizedProps, cssModules
+    return !!(
+      accessCache![key] ||
+      (data !== EMPTY_OBJ && key[0] !== '$' && hasOwn(data, key)) ||
       hasSetupBinding(setupState, key) ||
       ((normalizedProps = propsOptions[0]) && hasOwn(normalizedProps, key)) ||
       hasOwn(ctx, key) ||
       hasOwn(publicPropertiesMap, key) ||
-      hasOwn(appContext.config.globalProperties, key)
+      hasOwn(appContext.config.globalProperties, key) ||
+      ((cssModules = type.__cssModules) && cssModules[key])
     )
   },