diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 57a53a39b76..93169008fe7 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -224,6 +224,10 @@ export interface ComponentInternalInstance { parent: ComponentInternalInstance | null root: ComponentInternalInstance appContext: AppContext + /** + * ShadowRoot of custom element if it is + */ + container: ShadowRoot | null /** * Vnode representing this component in its parent's vdom tree */ @@ -497,6 +501,7 @@ export function createComponentInstance( type, parent, appContext, + container: null, // will be set synchronously before setup root: null!, // to be immediately set next: null, subTree: null!, // will be set synchronously right after creation diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 383e17fb0f5..ef1e24cc9b1 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1201,6 +1201,7 @@ function baseCreateRenderer( parentComponent, parentSuspense )) + instance.isCE && (instance.container = container as ShadowRoot) if (__DEV__ && instance.type.__hmrId) { registerHMR(instance) @@ -2237,6 +2238,8 @@ function baseCreateRenderer( invokeArrayFns(bum) } + instance.container = null + if ( __COMPAT__ && isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 6ccf02c4fa6..5b76952d3f6 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -2,6 +2,7 @@ import { defineAsyncComponent, defineComponent, defineCustomElement, + getCurrentInstance, h, inject, nextTick, @@ -693,4 +694,24 @@ describe('defineCustomElement', () => { ) }) }) + + describe('shadowRoot', () => { + // #6113 + test('shadowRoot accessible for css-in-js', () => { + const Foo = defineCustomElement({ + setup() { + const ins = getCurrentInstance()! + const style = document.createElement('style') + style.innerHTML = `div { color: red; }` + ins.container!.appendChild(style) + return () => h('div', 'hello') + } + }) + customElements.define('my-el', Foo) + container.innerHTML = `` + const el = container.childNodes[0] as VueElement + const style = el.shadowRoot?.querySelector('style')! + expect(style.textContent).toBe(`div { color: red; }`) + }) + }) })