Skip to content

Commit b3cde3f

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

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-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: 37 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,42 @@ describe('hot module replacement', () => {
10641065
)
10651066
})
10661067

1068+
test('reload setup only component', async () => {
1069+
const childId = 'test-child-reload-01'
1070+
const Child = defineVaporComponent({
1071+
__hmrId: childId,
1072+
render: compileToFunction(`<div>foo</div>`),
1073+
})
1074+
createRecord(childId, Child as any)
1075+
1076+
// Simulate router-view, it does not have a render function,
1077+
// so when it rerenders, the setup function will be called
1078+
const RouterView = defineVaporComponent({
1079+
setup() {
1080+
provide('foo', 'bar')
1081+
return createComponent(Child)
1082+
},
1083+
})
1084+
1085+
const { html } = define({
1086+
setup() {
1087+
return createComponent(RouterView)
1088+
},
1089+
}).render()
1090+
1091+
expect(html()).toBe('<div>foo</div>')
1092+
1093+
// will trigger parent rerender
1094+
reload(childId, {
1095+
__hmrId: childId,
1096+
render: compileToFunction(`<div>bar</div>`),
1097+
})
1098+
1099+
await nextTick()
1100+
expect(html()).toBe('<div>bar</div>')
1101+
expect('provide() can only be used inside setup()').not.toHaveBeenWarned()
1102+
})
1103+
10671104
describe('switch vapor/vdom modes', () => {
10681105
test('vapor -> vdom', async () => {
10691106
const id = 'vapor-to-vdom'

0 commit comments

Comments
 (0)