]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
dx(runtime-core): warn if `this` is used in a `<script setup>` template (#7866)
authorskirtle <65301168+skirtles-code@users.noreply.github.com>
Fri, 10 Nov 2023 07:05:39 +0000 (07:05 +0000)
committerGitHub <noreply@github.com>
Fri, 10 Nov 2023 07:05:39 +0000 (15:05 +0800)
packages/runtime-core/__tests__/rendererComponent.spec.ts
packages/runtime-core/src/componentRenderUtils.ts

index 6f1d0288b217526a3cb1f0d74f5d13d8fea3b611..37daafa97254d1f93a56a83e20bedf8314d9913d 100644 (file)
@@ -354,4 +354,25 @@ describe('renderer: component', () => {
     expect(serializeInner(root)).toBe(`<h1>1</h1>`)
     expect(spy).toHaveBeenCalledTimes(2)
   })
+
+  it('should warn accessing `this` in a <script setup> template', () => {
+    const App = {
+      setup() {
+        return {
+          __isScriptSetup: true
+        }
+      },
+
+      render(this: any) {
+        return this.$attrs.id
+      }
+    }
+
+    const root = nodeOps.createElement('div')
+    render(h(App), root)
+
+    expect(
+      `Property '$attrs' was accessed via 'this'. Avoid using 'this' in templates.`
+    ).toHaveBeenWarned()
+  })
 })
index d9de968a074c24e5ca95af3c36f02c6fa5db9acb..2ed64f7b5773896c0693bcb3c13161d5793d910e 100644 (file)
@@ -73,9 +73,24 @@ export function renderComponentRoot(
       // withProxy is a proxy with a different `has` trap only for
       // runtime-compiled render functions using `with` block.
       const proxyToUse = withProxy || proxy
+      // 'this' isn't available in production builds with `<script setup>`,
+      // so warn if it's used in dev.
+      const thisProxy =
+        __DEV__ && setupState.__isScriptSetup
+          ? new Proxy(proxyToUse!, {
+              get(target, key, receiver) {
+                warn(
+                  `Property '${String(
+                    key
+                  )}' was accessed via 'this'. Avoid using 'this' in templates.`
+                )
+                return Reflect.get(target, key, receiver)
+              }
+            })
+          : proxyToUse
       result = normalizeVNode(
         render!.call(
-          proxyToUse,
+          thisProxy,
           proxyToUse!,
           renderCache,
           props,