Skip to content

Commit 9bef3be

Browse files
authored
fix(runtime-vapor): add dev-only warning for non-existent property access during render (#14162)
1 parent a3a20af commit 9bef3be

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

packages/runtime-vapor/__tests__/component.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,22 @@ describe('component', () => {
416416
'Vapor component setup() returned non-block value, and has no render function',
417417
).toHaveBeenWarned()
418418
})
419+
420+
it('warn non-existent property access', () => {
421+
define({
422+
setup() {
423+
return {}
424+
},
425+
render(ctx: any) {
426+
ctx.foo
427+
return []
428+
},
429+
}).render()
430+
431+
expect(
432+
'Property "foo" was accessed during render but is not defined on instance.',
433+
).toHaveBeenWarned()
434+
})
419435
})
420436

421437
function getEffectsCount(scope: EffectScope): number {

packages/runtime-vapor/__tests__/hmr.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ describe('hot module replacement', () => {
631631
},
632632
render: compileToFunction(`
633633
<teleport :to="target">
634-
<div :style="style">
634+
<div>
635635
<slot/>
636636
</div>
637637
</teleport>

packages/runtime-vapor/src/component.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@ import {
4545
onScopeDispose,
4646
proxyRefs,
4747
setActiveSub,
48+
toRaw,
4849
unref,
4950
} from '@vue/reactivity'
5051
import {
5152
EMPTY_OBJ,
5253
ShapeFlags,
54+
hasOwn,
5355
invokeArrayFns,
5456
isArray,
5557
isFunction,
@@ -381,9 +383,10 @@ export function setupComponent(
381383
)
382384
instance.block = []
383385
} else {
384-
instance.devtoolsRawSetupState = setupResult
385-
// TODO make the proxy warn non-existent property access during dev
386386
instance.setupState = proxyRefs(setupResult)
387+
if (__DEV__) {
388+
instance.setupState = createDevSetupStateProxy(instance)
389+
}
387390
devRender(instance)
388391
}
389392
} else {
@@ -449,6 +452,31 @@ export function applyFallthroughProps(
449452
isApplyingFallthroughProps = false
450453
}
451454

455+
/**
456+
* dev only
457+
*/
458+
function createDevSetupStateProxy(
459+
instance: VaporComponentInstance,
460+
): Record<string, any> {
461+
const { setupState } = instance
462+
return new Proxy(setupState!, {
463+
get(target, key: string | symbol, receiver) {
464+
if (
465+
isString(key) &&
466+
!key.startsWith('__v') &&
467+
!hasOwn(toRaw(setupState)!, key)
468+
) {
469+
warn(
470+
`Property ${JSON.stringify(key)} was accessed during render ` +
471+
`but is not defined on instance.`,
472+
)
473+
}
474+
475+
return Reflect.get(target, key, receiver)
476+
},
477+
})
478+
}
479+
452480
/**
453481
* dev only
454482
*/

0 commit comments

Comments
 (0)