]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): avoid script setup bindings overwriting reserved ctx properties...
authorygj6 <7699524+ygj6@users.noreply.github.com>
Thu, 16 Sep 2021 15:16:07 +0000 (23:16 +0800)
committerGitHub <noreply@github.com>
Thu, 16 Sep 2021 15:16:07 +0000 (11:16 -0400)
packages/runtime-core/__tests__/apiCreateApp.spec.ts
packages/runtime-core/src/componentPublicInstance.ts

index 3dfc040b70773c1edc700cab1df2be00d6a642f2..e5e9a5906b1ce5fa167e827267bdb34f48c4cb4e 100644 (file)
@@ -482,6 +482,54 @@ describe('api: createApp', () => {
     expect(serializeInner(root)).toBe('hello')
   })
 
+  test('return property "_" should not overwrite "ctx._", __isScriptSetup: false', () => {
+    const Comp = defineComponent({
+      setup() {
+        return {
+          _: ref(0) // return property "_" should not overwrite "ctx._"
+        }
+      },
+      render() {
+        return h('input', {
+          ref: 'input'
+        })
+      }
+    })
+
+    const root1 = nodeOps.createElement('div')
+    createApp(Comp).mount(root1)
+
+    expect(
+      `setup() return property "_" should not start with "$" or "_" which are reserved prefixes for Vue internals.`
+    ).toHaveBeenWarned()
+  })
+
+  test('return property "_" should not overwrite "ctx._", __isScriptSetup: true', () => {
+    const Comp = defineComponent({
+      setup() {
+        return {
+          _: ref(0), // return property "_" should not overwrite "ctx._"
+          __isScriptSetup: true // mock __isScriptSetup = true
+        }
+      },
+      render() {
+        return h('input', {
+          ref: 'input'
+        })
+      }
+    })
+
+    const root1 = nodeOps.createElement('div')
+    const app = createApp(Comp).mount(root1)
+
+    // trigger
+    app.$refs.input
+
+    expect(
+      `TypeError: Cannot read property '__isScriptSetup' of undefined`
+    ).not.toHaveBeenWarned()
+  })
+
   // config.compilerOptions is tested in packages/vue since it is only
   // supported in the full build.
 })
index aad6207ec466970e2f471a61b23e2503f3fb1661..dd385a815c97ab9058991b44f6610f780c24145f 100644 (file)
@@ -538,20 +538,22 @@ export function exposeSetupStateOnRenderContext(
 ) {
   const { ctx, setupState } = instance
   Object.keys(toRaw(setupState)).forEach(key => {
-    if (!setupState.__isScriptSetup && (key[0] === '$' || key[0] === '_')) {
-      warn(
-        `setup() return property ${JSON.stringify(
-          key
-        )} should not start with "$" or "_" ` +
-          `which are reserved prefixes for Vue internals.`
-      )
-      return
+    if (!setupState.__isScriptSetup) {
+      if (key[0] === '$' || key[0] === '_') {
+        warn(
+          `setup() return property ${JSON.stringify(
+            key
+          )} should not start with "$" or "_" ` +
+            `which are reserved prefixes for Vue internals.`
+        )
+        return
+      }
+      Object.defineProperty(ctx, key, {
+        enumerable: true,
+        configurable: true,
+        get: () => setupState[key],
+        set: NOOP
+      })
     }
-    Object.defineProperty(ctx, key, {
-      enumerable: true,
-      configurable: true,
-      get: () => setupState[key],
-      set: NOOP
-    })
   })
 }