diff --git a/packages/runtime-vapor/__tests__/componentProps.spec.ts b/packages/runtime-vapor/__tests__/componentProps.spec.ts index c068e8044cb..55b492408c0 100644 --- a/packages/runtime-vapor/__tests__/componentProps.spec.ts +++ b/packages/runtime-vapor/__tests__/componentProps.spec.ts @@ -497,6 +497,36 @@ describe('component: props', () => { expect(changeSpy).toHaveBeenCalledTimes(1) }) + test('should not warn invalid watch source when directly watching props', async () => { + const changeSpy = vi.fn() + const { render, html } = define({ + props: { + foo: { + type: String, + }, + }, + setup(props: any) { + watch(props, changeSpy) + const t0 = template('

') + const n0 = t0() + renderEffect(() => { + setElementText(n0, String(props.foo)) + }) + return n0 + }, + }) + + const foo = ref('foo') + render({ foo: () => foo.value }) + expect(html()).toBe(`

foo

`) + expect('Invalid watch source').not.toHaveBeenWarned() + + foo.value = 'bar' + await nextTick() + expect(html()).toBe(`

bar

`) + expect(changeSpy).toHaveBeenCalledTimes(1) + }) + test('support null in required + multiple-type declarations', () => { const { render } = define({ props: { diff --git a/packages/runtime-vapor/src/componentProps.ts b/packages/runtime-vapor/src/componentProps.ts index a5e9daad229..6de001ffb92 100644 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@ -21,6 +21,7 @@ import { validateProps, warn, } from '@vue/runtime-dom' +import { ReactiveFlags } from '@vue/reactivity' import { normalizeEmitsOptions } from './componentEmits' import { renderEffect } from './renderEffect' @@ -63,6 +64,9 @@ export function getPropsProxyHandlers( : YES const getProp = (instance: VaporComponentInstance, key: string | symbol) => { + // this enables direct watching of props and prevents `Invalid watch source` DEV warnings. + if (key === ReactiveFlags.IS_REACTIVE) return true + if (!isProp(key)) return const rawProps = instance.rawProps const dynamicSources = rawProps.$