Răsfoiți Sursa

fix(compat): handle v-model deprecation warning with missing appContext (#14203)

close #14202
edison 4 luni în urmă
părinte
comite
945a543152

+ 9 - 1
packages/runtime-core/src/compat/componentVModel.ts

@@ -1,5 +1,6 @@
 import { ShapeFlags, extend } from '@vue/shared'
 import type { ComponentInternalInstance, ComponentOptions } from '../component'
+import { createAppContext } from '../apiCreateApp'
 import { ErrorCodes, callWithErrorHandling } from '../errorHandling'
 import type { VNode } from '../vnode'
 import { popWarningContext, pushWarningContext } from '../warning'
@@ -31,7 +32,14 @@ export function convertLegacyVModelProps(vnode: VNode): void {
 
     if (__DEV__ && !warnedTypes.has(comp)) {
       pushWarningContext(vnode)
-      warnDeprecation(DeprecationTypes.COMPONENT_V_MODEL, { type } as any, comp)
+      warnDeprecation(
+        DeprecationTypes.COMPONENT_V_MODEL,
+        {
+          type,
+          appContext: (vnode.ctx && vnode.ctx.appContext) || createAppContext(),
+        } as any,
+        comp,
+      )
       popWarningContext()
       warnedTypes.add(comp)
     }

+ 37 - 0
packages/vue-compat/__tests__/componentVModel.spec.ts

@@ -140,4 +140,41 @@ describe('COMPONENT_V_MODEL', () => {
       template: `<input :value="foo" @input="$emit('bar', $event.target.value)">`,
     })
   })
+
+  // #14202
+  test('should handle v-model deprecation warning with missing appContext', async () => {
+    const ChildComponent = {
+      template: `<div @click="$emit('input', 'new val')">{{ value }}</div>`,
+      props: ['value'],
+    }
+
+    const vm = new Vue({
+      components: { ChildComponent },
+      data() {
+        return {
+          myVal: 'initial',
+        }
+      },
+      template: `
+        <div>
+          <child-component v-model="myVal"></child-component>
+        </div>
+      `,
+    }).$mount() as any
+
+    expect(vm.$el.textContent).toContain('initial')
+
+    expect(
+      (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(
+        ChildComponent,
+      ),
+    ).toHaveBeenWarned()
+
+    // Should work correctly
+    const child = vm.$el.querySelector('div')
+    child.click()
+    await nextTick()
+    expect(vm.myVal).toBe('new val')
+    expect(vm.$el.textContent).toContain('new val')
+  })
 })