Skip to content

Commit f01afda

Browse files
dx(runtime-core): warn if this is used in a <script setup> template (#7866)
1 parent 5a41231 commit f01afda

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,4 +354,25 @@ describe('renderer: component', () => {
354354
expect(serializeInner(root)).toBe(`<h1>1</h1>`)
355355
expect(spy).toHaveBeenCalledTimes(2)
356356
})
357+
358+
it('should warn accessing `this` in a <script setup> template', () => {
359+
const App = {
360+
setup() {
361+
return {
362+
__isScriptSetup: true
363+
}
364+
},
365+
366+
render(this: any) {
367+
return this.$attrs.id
368+
}
369+
}
370+
371+
const root = nodeOps.createElement('div')
372+
render(h(App), root)
373+
374+
expect(
375+
`Property '$attrs' was accessed via 'this'. Avoid using 'this' in templates.`
376+
).toHaveBeenWarned()
377+
})
357378
})

packages/runtime-core/src/componentRenderUtils.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,24 @@ export function renderComponentRoot(
7373
// withProxy is a proxy with a different `has` trap only for
7474
// runtime-compiled render functions using `with` block.
7575
const proxyToUse = withProxy || proxy
76+
// 'this' isn't available in production builds with `<script setup>`,
77+
// so warn if it's used in dev.
78+
const thisProxy =
79+
__DEV__ && setupState.__isScriptSetup
80+
? new Proxy(proxyToUse!, {
81+
get(target, key, receiver) {
82+
warn(
83+
`Property '${String(
84+
key
85+
)}' was accessed via 'this'. Avoid using 'this' in templates.`
86+
)
87+
return Reflect.get(target, key, receiver)
88+
}
89+
})
90+
: proxyToUse
7691
result = normalizeVNode(
7792
render!.call(
78-
proxyToUse,
93+
thisProxy,
7994
proxyToUse!,
8095
renderCache,
8196
props,

0 commit comments

Comments
 (0)