fix(custom-element): ensure child component styles are injected in correct order before parent styles#13374
fix(custom-element): ensure child component styles are injected in correct order before parent styles#13374edison1105 merged 11 commits intomainfrom
Conversation
|
Important Review skippedThis PR was authored by the user configured for CodeRabbit reviews. CodeRabbit does not review PRs authored by this user. It's recommended to use a dedicated user account to post CodeRabbit review feedback. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughCustom element style injection was made parent-aware and now tracks per-component style anchors so child component styles are inserted before parent styles in shadow DOM; renderer and custom element APIs updated and tests added for nested/wrapper/HMR scenarios. Changes
Sequence Diagram(s)sequenceDiagram
participant Renderer as Renderer (setupRenderEffect)
participant Instance as Component Instance
participant VueElement as VueElement (custom element)
participant Shadow as ShadowRoot
Renderer->>Instance: mount -> determine type & parentType
Renderer->>VueElement: _injectChildStyle(type, parentType?)
VueElement->>VueElement: _applyStyles(styles, owner=type, parentComp=parentType?)
VueElement->>Shadow: _getStyleAnchor(parentComp) or _getRootStyleInsertionAnchor(root)
Shadow->>Shadow: insert style before parent's anchor or at root insertion point
VueElement->>VueElement: store/update _styleAnchors for owner
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Size ReportBundles
Usages
|
@vue/compiler-core
@vue/compiler-dom
@vue/compiler-sfc
@vue/compiler-ssr
@vue/reactivity
@vue/runtime-core
@vue/runtime-dom
@vue/server-renderer
@vue/shared
vue
@vue/compat
commit: |
468260b to
8b6b732
Compare
5b13a9e to
84a0439
Compare
84a0439 to
41379c4
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/runtime-dom/src/apiCustomElement.ts`:
- Around line 602-615: The root-style insertion unconditionally uses
root.prepend(s) which moves reloaded parent styles ahead of already-inserted
child styles; instead, when parentComp is falsy (owner/root styles) insert each
style node before the first non-STYLE child (or before the first existing style
anchor for this._def) so HMR re-inserts parent styles in-place rather than
moving them before children; locate the root branch where root.prepend(s) is
used, use this._styleAnchors.get(this._def) / scan root.childNodes for the first
node whose nodeName !== 'STYLE' (or first style anchor) as the insertion point,
and continue setting this._styleAnchors.set(this._def, s) as before.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6a34b117-31ae-422f-92b1-b8e003b35724
📒 Files selected for processing (2)
packages/runtime-dom/__tests__/customElement.spec.tspackages/runtime-dom/src/apiCustomElement.ts
|
/ecosystem-ci run |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/runtime-dom/src/apiCustomElement.ts (1)
610-640:⚠️ Potential issue | 🟡 MinorMinor type inconsistency between
_applyStylesand_injectChildStyle.The
parentCompparameter is typed asConcreteComponent & CustomElementOptionshere, but_injectChildStylepasses justConcreteComponent. SinceparentCompis only used as a WeakMap key lookup (line 626), the intersection withCustomElementOptionsis unnecessary.Suggested fix
private _applyStyles( styles: string[] | undefined, owner?: ConcreteComponent, - parentComp?: ConcreteComponent & CustomElementOptions, + parentComp?: ConcreteComponent, ) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/runtime-dom/src/apiCustomElement.ts` around lines 610 - 640, The type of the parentComp parameter on _applyStyles is unnecessarily specific; change its declaration from "parentComp?: ConcreteComponent & CustomElementOptions" to just "parentComp?: ConcreteComponent" (or ConcreteComponent | undefined) so it matches how _injectChildStyle calls it and is correct for use as a WeakMap key; update the function signature for _applyStyles accordingly and ensure any callers still pass the same values (no other logic changes required).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@packages/runtime-dom/src/apiCustomElement.ts`:
- Around line 610-640: The type of the parentComp parameter on _applyStyles is
unnecessarily specific; change its declaration from "parentComp?:
ConcreteComponent & CustomElementOptions" to just "parentComp?:
ConcreteComponent" (or ConcreteComponent | undefined) so it matches how
_injectChildStyle calls it and is correct for use as a WeakMap key; update the
function signature for _applyStyles accordingly and ensure any callers still
pass the same values (no other logic changes required).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5e86e7d0-4bb5-4b31-9871-87bcd57e5781
📒 Files selected for processing (4)
packages/runtime-core/src/component.tspackages/runtime-core/src/renderer.tspackages/runtime-dom/__tests__/customElement.spec.tspackages/runtime-dom/src/apiCustomElement.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/runtime-core/src/renderer.ts
|
📝 Ran ecosystem CI: Open
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/runtime-dom/src/apiCustomElement.ts (1)
625-639: Style insertion logic is correct.The anchor-based insertion properly ensures child styles are placed before parent styles in the DOM, matching the expected CSS cascade behavior for scoped style overrides.
One minor observation: the
this._styleAnchors.set(this._def, s)on line 636 executes on every loop iteration when!parentComp, but only the final iteration's value matters. This is functionally correct but slightly wasteful.,
Optional: Move anchor assignment outside the loop
for (let i = styles.length - 1; i >= 0; i--) { const s = document.createElement('style') if (nonce) s.setAttribute('nonce', nonce) s.textContent = styles[i] root.insertBefore(s, last || insertionAnchor) - if (!parentComp) { - this._styleAnchors.set(this._def, s) - } last = s - if (owner && i === 0) this._styleAnchors.set(owner, s) + if (i === 0) { + if (!parentComp) this._styleAnchors.set(this._def, s) + if (owner) this._styleAnchors.set(owner, s) + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/runtime-dom/src/apiCustomElement.ts` around lines 625 - 639, The loop sets this._styleAnchors.set(this._def, s) on every iteration when !parentComp, which is redundant; move the anchor assignment out of the for-loop so that after the loop completes (and last holds the final style element) you call this._styleAnchors.set(this._def, last) when !parentComp, keeping the existing behavior for owner (this._styleAnchors.set(owner, s) when i === 0) unchanged; update the code around the for-loop in apiCustomElement.ts (references: insertionAnchor, last, styles, nonce, this._styleAnchors, this._def, owner) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/runtime-dom/src/apiCustomElement.ts`:
- Around line 625-639: The loop sets this._styleAnchors.set(this._def, s) on
every iteration when !parentComp, which is redundant; move the anchor assignment
out of the for-loop so that after the loop completes (and last holds the final
style element) you call this._styleAnchors.set(this._def, last) when
!parentComp, keeping the existing behavior for owner
(this._styleAnchors.set(owner, s) when i === 0) unchanged; update the code
around the for-loop in apiCustomElement.ts (references: insertionAnchor, last,
styles, nonce, this._styleAnchors, this._def, owner) accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0aa9c11a-8cc1-44b6-9bff-ac4d4c79be49
📒 Files selected for processing (1)
packages/runtime-dom/src/apiCustomElement.ts
…tion order sync from #13374
close #13029
Summary by CodeRabbit
New Features
Bug Fixes
Tests