]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): prevent injecting child styles if shadowRoot is false (#12769)
authoredison <daiwei521@126.com>
Thu, 5 Jun 2025 02:02:26 +0000 (10:02 +0800)
committerGitHub <noreply@github.com>
Thu, 5 Jun 2025 02:02:26 +0000 (10:02 +0800)
close #12630

packages/runtime-core/src/renderer.ts
packages/runtime-dom/__tests__/customElement.spec.ts

index 7b39aa917a25f7bb26ea98c349d61c4c4265aaac..56f9759bc55123089cc28ca1e16a8cecdc9c5cef 100644 (file)
@@ -86,6 +86,7 @@ import { isAsyncWrapper } from './apiAsyncComponent'
 import { isCompatEnabled } from './compat/compatConfig'
 import { DeprecationTypes } from './compat/compatConfig'
 import type { TransitionHooks } from './components/BaseTransition'
+import type { VueElement } from '@vue/runtime-dom'
 
 export interface Renderer<HostElement = RendererElement> {
   render: RootRenderFunction<HostElement>
@@ -1348,7 +1349,11 @@ function baseCreateRenderer(
           }
         } else {
           // custom element style injection
-          if (root.ce) {
+          if (
+            root.ce &&
+            // @ts-expect-error _def is private
+            (root.ce as VueElement)._def.shadowRoot !== false
+          ) {
             root.ce._injectChildStyle(type)
           }
 
index eee2151716e59d87e052a357f01e3182da9d115c..a2b4c263699c38274ab6b7934187ed62f593f583 100644 (file)
@@ -916,6 +916,30 @@ describe('defineCustomElement', () => {
       assertStyles(el, [`div { color: blue; }`, `div { color: red; }`])
     })
 
+    test("child components should not inject styles to root element's shadow root w/ shadowRoot false", async () => {
+      const Bar = defineComponent({
+        styles: [`div { color: green; }`],
+        render() {
+          return 'bar'
+        },
+      })
+      const Baz = () => h(Bar)
+      const Foo = defineCustomElement(
+        {
+          render() {
+            return [h(Baz)]
+          },
+        },
+        { shadowRoot: false },
+      )
+
+      customElements.define('my-foo-with-shadowroot-false', Foo)
+      container.innerHTML = `<my-foo-with-shadowroot-false></my-foo-with-shadowroot-false>`
+      const el = container.childNodes[0] as VueElement
+      const style = el.shadowRoot?.querySelector('style')
+      expect(style).toBeUndefined()
+    })
+
     test('with nonce', () => {
       const Foo = defineCustomElement(
         {