diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts
index dd087ad279d..c45aaa0081d 100644
--- a/packages/runtime-dom/__tests__/customElement.spec.ts
+++ b/packages/runtime-dom/__tests__/customElement.spec.ts
@@ -337,6 +337,52 @@ describe('defineCustomElement', () => {
await nextTick()
expect(consumer.shadowRoot!.innerHTML).toBe(`
changed!
`)
})
+
+ test('inherited from ancestors', async () => {
+ const fooA = ref('FooA!')
+ const fooB = ref('FooB!')
+ const ProviderA = defineCustomElement({
+ provide: {
+ fooA
+ },
+ render() {
+ return h('provider-b')
+ }
+ })
+ const ProviderB = defineCustomElement({
+ provide: {
+ fooB
+ },
+ render() {
+ return h('my-multi-consumer')
+ }
+ })
+
+ const Consumer = defineCustomElement({
+ setup() {
+ const fooA = inject[('fooA')!
+ const fooB = inject][('fooB')!
+ return () => h('div', `${fooA.value} ${fooB.value}`)
+ }
+ })
+
+ customElements.define('provider-a', ProviderA)
+ customElements.define('provider-b', ProviderB)
+ customElements.define('my-multi-consumer', Consumer)
+ container.innerHTML = ``
+ const providerA = container.childNodes[0] as VueElement
+ const providerB = providerA.shadowRoot!.childNodes[0] as VueElement
+ const consumer = providerB.shadowRoot!.childNodes[0] as VueElement
+
+ expect(consumer.shadowRoot!.innerHTML).toBe(`]FooA! FooB!
`)
+
+ fooA.value = 'changedA!'
+ fooB.value = 'changedB!'
+ await nextTick()
+ expect(consumer.shadowRoot!.innerHTML).toBe(
+ `changedA! changedB!
`
+ )
+ })
})
describe('styles', () => {
diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts
index 5108e3bdfbe..5bd81345a45 100644
--- a/packages/runtime-dom/src/apiCustomElement.ts
+++ b/packages/runtime-dom/src/apiCustomElement.ts
@@ -368,6 +368,7 @@ export class VueElement extends BaseClass {
) {
if (parent instanceof VueElement) {
instance.parent = parent._instance
+ instance.provides = parent._instance!.provides
break
}
}