Skip to content

Commit eadd8b2

Browse files
committed
fix(hmr): suppress provide() warning during HMR updates for mounted instances
1 parent cd98691 commit eadd8b2

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

packages/runtime-core/src/apiInject.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { isFunction } from '@vue/shared'
22
import { currentInstance, getCurrentGenericInstance } from './component'
33
import { currentApp } from './apiCreateApp'
44
import { warn } from './warning'
5+
import { isHmrUpdating } from './hmr'
56

67
interface InjectionConstraint<T> {}
78

@@ -12,7 +13,7 @@ export function provide<T, K = InjectionKey<T> | string | number>(
1213
value: K extends InjectionKey<infer V> ? V : T,
1314
): void {
1415
if (__DEV__) {
15-
if (!currentInstance || currentInstance.isMounted) {
16+
if (!currentInstance || (currentInstance.isMounted && !isHmrUpdating)) {
1617
warn(`provide() can only be used inside setup().`)
1718
}
1819
}

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
onDeactivated,
99
onMounted,
1010
onUnmounted,
11+
provide,
1112
ref,
1213
toDisplayString,
1314
} from '@vue/runtime-dom'
@@ -1064,6 +1065,44 @@ describe('hot module replacement', () => {
10641065
)
10651066
})
10661067

1068+
// Vapor router-view has no render function (setup-only).
1069+
// When HMR rerender is triggered, the setup function is re-executed.
1070+
// Ensure provide() warning is suppressed.
1071+
test('rerender setup-only component', async () => {
1072+
const childId = 'test-child-reload-01'
1073+
const Child = defineVaporComponent({
1074+
__hmrId: childId,
1075+
render: compileToFunction(`<div>foo</div>`),
1076+
})
1077+
createRecord(childId, Child as any)
1078+
1079+
// without a render function
1080+
const Parent = defineVaporComponent({
1081+
setup() {
1082+
provide('foo', 'bar')
1083+
return createComponent(Child)
1084+
},
1085+
})
1086+
1087+
const { html } = define({
1088+
setup() {
1089+
return createComponent(Parent)
1090+
},
1091+
}).render()
1092+
1093+
expect(html()).toBe('<div>foo</div>')
1094+
1095+
// will trigger parent rerender
1096+
reload(childId, {
1097+
__hmrId: childId,
1098+
render: compileToFunction(`<div>bar</div>`),
1099+
})
1100+
1101+
await nextTick()
1102+
expect(html()).toBe('<div>bar</div>')
1103+
expect('provide() can only be used inside setup()').not.toHaveBeenWarned()
1104+
})
1105+
10671106
describe('switch vapor/vdom modes', () => {
10681107
test('vapor -> vdom', async () => {
10691108
const id = 'vapor-to-vdom'

0 commit comments

Comments
 (0)