]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: save edison/fix/13029 13374/head
authordaiwei <daiwei521@126.com>
Fri, 23 May 2025 09:34:52 +0000 (17:34 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 23 May 2025 13:33:03 +0000 (21:33 +0800)
packages/runtime-dom/__tests__/customElement.spec.ts
packages/runtime-dom/src/apiCustomElement.ts

index 09d4b0bdee51e21bcc9bf5889ca134a4f15329ee..23d5ffed0fa2ecde41527ba543e7f4c31c7cc7f6 100644 (file)
@@ -977,6 +977,49 @@ describe('defineCustomElement', () => {
       assertStyles(el, [`div { color: green; }`, `div { color: blue; }`])
     })
 
+    test('inject nested child component styles', async () => {
+      const Baz = defineComponent({
+        styles: [`div { color: yellow; }`],
+        render() {
+          return h(Bar)
+        },
+      })
+      const Bar = defineComponent({
+        styles: [`div { color: green; }`],
+        render() {
+          return 'bar'
+        },
+      })
+      const WrapperBar = defineComponent({
+        styles: [`div { color: blue; }`],
+        render() {
+          return h(Baz)
+        },
+      })
+      const WBaz = defineComponent({
+        styles: [`div { color: black; }`],
+        render() {
+          return h(WrapperBar)
+        },
+      })
+      const Foo = defineCustomElement({
+        styles: [`div { color: red; }`],
+        render() {
+          return [h(Baz), h(WBaz)]
+        },
+      })
+      customElements.define('my-el-with-inject-nested-child-styles', Foo)
+      container.innerHTML = `<my-el-with-inject-nested-child-styles></my-el-with-inject-nested-child-styles>`
+      const el = container.childNodes[0] as VueElement
+      assertStyles(el, [
+        `div { color: green; }`,
+        `div { color: yellow; }`,
+        `div { color: blue; }`,
+        `div { color: black; }`,
+        `div { color: red; }`,
+      ])
+    })
+
     test('with nonce', () => {
       const Foo = defineCustomElement(
         {
index 15b3c33d8785d2bd602b128d65f792f4c04b2091..5de32735fd5e8a47f01d4cb73e6952c0ed812964 100644 (file)
@@ -232,7 +232,8 @@ export class VueElement
   private _styleChildren = new WeakSet()
   private _pendingResolve: Promise<void> | undefined
   private _parent: VueElement | undefined
-  private _styleAnchor?: HTMLStyleElement | Text
+  private _styleAnchors: WeakMap<ConcreteComponent, HTMLStyleElement | Text> =
+    new WeakMap()
   /**
    * dev only
    */
@@ -599,12 +600,13 @@ export class VueElement
     // to inject child styles before it.
     if (parentComp && !parentComp.styles) {
       const anchor = document.createTextNode('')
-      if (this._styleAnchor) {
-        this.shadowRoot!.insertBefore(anchor, this._styleAnchor)
+      const styleAnchor = this._styleAnchors.get(this._def)
+      if (styleAnchor) {
+        this.shadowRoot!.insertBefore(anchor, styleAnchor)
       } else {
         this.shadowRoot!.prepend(anchor)
       }
-      this._styleAnchor = anchor
+      this._styleAnchors.set(this._def, anchor)
     }
 
     const nonce = this._nonce
@@ -616,12 +618,19 @@ export class VueElement
 
       // inject styles before parent styles
       if (parentComp) {
-        this.shadowRoot!.insertBefore(s, last || this._styleAnchor!)
+        this.shadowRoot!.insertBefore(
+          s,
+          last ||
+            this._styleAnchors.get(parentComp) ||
+            this._styleAnchors.get(this._def) ||
+            null,
+        )
       } else {
         this.shadowRoot!.prepend(s)
-        this._styleAnchor = s
+        this._styleAnchors.set(this._def, s)
       }
       last = s
+      if (owner && i === 0) this._styleAnchors.set(owner, s)
 
       // record for HMR
       if (__DEV__) {