diff --git a/packages/runtime-core/src/compat/__tests__/componentVModel.spec.ts b/packages/runtime-core/src/compat/__tests__/componentVModel.spec.ts
new file mode 100644
index 00000000..ed8dc418
--- /dev/null
+++ b/packages/runtime-core/src/compat/__tests__/componentVModel.spec.ts
@@ -0,0 +1,85 @@
+import Vue from '@vue/compat'
+import { ComponentOptions } from '../../component'
+import { nextTick } from '../../scheduler'
+import {
+ DeprecationTypes,
+ deprecationData,
+ toggleDeprecationWarning
+} from '../compatConfig'
+import { triggerEvent } from './utils'
+
+beforeEach(() => {
+ toggleDeprecationWarning(true)
+ Vue.configureCompat({
+ MODE: 2,
+ GLOBAL_MOUNT: 'suppress-warning'
+ })
+})
+
+afterEach(() => {
+ toggleDeprecationWarning(false)
+ Vue.configureCompat({ MODE: 3 })
+})
+
+describe('COMPONENT_V_MODEL', () => {
+ async function runTest(CustomInput: ComponentOptions) {
+ const vm = new Vue({
+ data() {
+ return {
+ text: 'foo'
+ }
+ },
+ components: { CustomInput },
+ template: `
+
+ {{ text }}
+
+
+ `
+ }).$mount() as any
+
+ const input = vm.$el.querySelector('input')
+ const span = vm.$el.querySelector('span')
+
+ expect(input.value).toBe('foo')
+ expect(span.textContent).toBe('foo')
+
+ expect(
+ (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(
+ CustomInput
+ )
+ ).toHaveBeenWarned()
+
+ input.value = 'bar'
+ triggerEvent(input, 'input')
+ await nextTick()
+
+ expect(input.value).toBe('bar')
+ expect(span.textContent).toBe('bar')
+
+ vm.text = 'baz'
+ await nextTick()
+ expect(input.value).toBe('baz')
+ expect(span.textContent).toBe('baz')
+ }
+
+ test('basic usage', async () => {
+ await runTest({
+ name: 'CustomInput',
+ props: ['value'],
+ template: ``
+ })
+ })
+
+ test('with model option', async () => {
+ await runTest({
+ name: 'CustomInput',
+ props: ['input'],
+ model: {
+ prop: 'input',
+ event: 'update'
+ },
+ template: ``
+ })
+ })
+})
diff --git a/packages/runtime-core/src/compat/__tests__/globalConfig.spec.ts b/packages/runtime-core/src/compat/__tests__/globalConfig.spec.ts
index d7a7bc26..c5084d50 100644
--- a/packages/runtime-core/src/compat/__tests__/globalConfig.spec.ts
+++ b/packages/runtime-core/src/compat/__tests__/globalConfig.spec.ts
@@ -1,5 +1,6 @@
import Vue from '@vue/compat'
import { toggleDeprecationWarning } from '../compatConfig'
+import { triggerEvent } from './utils'
beforeEach(() => {
toggleDeprecationWarning(false)
@@ -11,18 +12,6 @@ afterEach(() => {
toggleDeprecationWarning(false)
})
-function triggerEvent(
- target: Element,
- event: string,
- process?: (e: any) => any
-) {
- const e = document.createEvent('HTMLEvents')
- e.initEvent(event, true, true)
- if (process) process(e)
- target.dispatchEvent(e)
- return e
-}
-
// only testing config options that affect runtime behavior.
test('GLOBAL_KEY_CODES', () => {
diff --git a/packages/runtime-core/src/compat/__tests__/misc.spec.ts b/packages/runtime-core/src/compat/__tests__/misc.spec.ts
index 21574ca3..8b10c121 100644
--- a/packages/runtime-core/src/compat/__tests__/misc.spec.ts
+++ b/packages/runtime-core/src/compat/__tests__/misc.spec.ts
@@ -5,6 +5,7 @@ import {
deprecationData,
toggleDeprecationWarning
} from '../compatConfig'
+import { triggerEvent } from './utils'
beforeEach(() => {
toggleDeprecationWarning(true)
@@ -19,18 +20,6 @@ afterEach(() => {
Vue.configureCompat({ MODE: 3 })
})
-function triggerEvent(
- target: Element,
- event: string,
- process?: (e: any) => any
-) {
- const e = document.createEvent('HTMLEvents')
- e.initEvent(event, true, true)
- if (process) process(e)
- target.dispatchEvent(e)
- return e
-}
-
test('WATCH_ARRAY', async () => {
const spy = jest.fn()
const vm = new Vue({
diff --git a/packages/runtime-core/src/compat/__tests__/utils.ts b/packages/runtime-core/src/compat/__tests__/utils.ts
new file mode 100644
index 00000000..bcf72b29
--- /dev/null
+++ b/packages/runtime-core/src/compat/__tests__/utils.ts
@@ -0,0 +1,11 @@
+export function triggerEvent(
+ target: Element,
+ event: string,
+ process?: (e: any) => any
+) {
+ const e = document.createEvent('HTMLEvents')
+ e.initEvent(event, true, true)
+ if (process) process(e)
+ target.dispatchEvent(e)
+ return e
+}
diff --git a/packages/runtime-core/src/compat/__tests__/vModel.spec.ts b/packages/runtime-core/src/compat/__tests__/vModel.spec.ts
deleted file mode 100644
index e69de29b..00000000
diff --git a/packages/runtime-core/src/compat/vModel.ts b/packages/runtime-core/src/compat/componentVModel.ts
similarity index 100%
rename from packages/runtime-core/src/compat/vModel.ts
rename to packages/runtime-core/src/compat/componentVModel.ts
diff --git a/packages/runtime-core/src/compat/renderFn.ts b/packages/runtime-core/src/compat/renderFn.ts
index c4dbcf29..ffbd34e7 100644
--- a/packages/runtime-core/src/compat/renderFn.ts
+++ b/packages/runtime-core/src/compat/renderFn.ts
@@ -37,7 +37,7 @@ import {
DeprecationTypes,
isCompatEnabled
} from './compatConfig'
-import { compatModelEventPrefix } from './vModel'
+import { compatModelEventPrefix } from './componentVModel'
const v3CompiledRenderFnRE = /^(?:function \w+)?\(_ctx, _cache/
diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts
index d5e2cb9f..44f9765d 100644
--- a/packages/runtime-core/src/componentEmits.ts
+++ b/packages/runtime-core/src/componentEmits.ts
@@ -22,7 +22,10 @@ import { UnionToIntersection } from './helpers/typeUtils'
import { devtoolsComponentEmit } from './devtools'
import { AppContext } from './apiCreateApp'
import { emit as compatInstanceEmit } from './compat/instanceEventEmitter'
-import { compatModelEventPrefix, compatModelEmit } from './compat/vModel'
+import {
+ compatModelEventPrefix,
+ compatModelEmit
+} from './compat/componentVModel'
export type ObjectEmitsOptions = Record<
string,
diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts
index dc002225..930db771 100644
--- a/packages/runtime-core/src/vnode.ts
+++ b/packages/runtime-core/src/vnode.ts
@@ -42,7 +42,7 @@ import { NULL_DYNAMIC_COMPONENT } from './helpers/resolveAssets'
import { hmrDirtyComponents } from './hmr'
import { setCompiledSlotRendering } from './helpers/renderSlot'
import { convertLegacyComponent } from './compat/component'
-import { convertLegacyVModelProps } from './compat/vModel'
+import { convertLegacyVModelProps } from './compat/componentVModel'
import { defineLegacyVNodeProperties } from './compat/renderFn'
import { convertLegacyRefInFor } from './compat/ref'