-
-
Notifications
You must be signed in to change notification settings - Fork 8.9k
fix(custom-element): use PatchFlags.BAIL for slot when props are present #13907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughUpdates renderSlot to detect when slot props are passed and use Changes
Sequence Diagram(s)sequenceDiagram
participant C as Component
participant R as Renderer
participant RS as renderSlot
participant P as Patcher
participant D as DOM
C->>R: render()
R->>RS: renderSlot(name, props, children)
RS->>RS: hasProps = Object.keys(props).length > 0
alt hasProps
RS-->>P: create Fragment with PatchFlags.BAIL
Note over RS,P: Bailout path for dynamic props (forces full patch)
else no props
RS-->>P: create Fragment with PatchFlags.STABLE_FRAGMENT
Note over RS,P: Stable fragment optimization
end
P->>D: apply updates to native <slot/> in shadowRoot
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests
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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/runtime-dom/__tests__/customElement.spec.ts (3)
658-666
: Prefer DOM-based assertions over full innerHTML string.Asserting the slot element’s class directly is less brittle and lets us extend checks (e.g., attribute removal) without relying on serialization details.
Apply this diff in this test:
- expect(e.shadowRoot!.innerHTML).toBe( - `<div><slot class="foo"></slot></div>`, - ) + const slotEl = e.shadowRoot!.querySelector('slot')! + expect(slotEl.getAttribute('class')).toBe('foo') foo.value = 'bar' await nextTick() - expect(e.shadowRoot!.innerHTML).toBe( - `<div><slot class="bar"></slot></div>`, - ) + expect(slotEl.getAttribute('class')).toBe('bar') + // optional: ensure DOM node was patched, not replaced + expect(e.shadowRoot!.querySelector('slot')).toBe(slotEl)
642-667
: Add coverage for attribute removal (original bug scenario).Issue #13904 mentions the class should be removed when toggled off. Let’s assert removal when the prop becomes undefined.
Add a new test (or extend this one) like:
test('remove slot attribute when prop becomes undefined', async () => { const foo = ref<string | undefined>('foo') const E = defineCustomElement({ render() { return h('div', null, renderSlot(this.$slots, 'default', { class: foo.value })) } }) customElements.define('my-el-slot-props-removal', E) container.innerHTML = `<my-el-slot-props-removal><span>hi</span></my-el-slot-props-removal>` const e = container.childNodes[0] as VueElement const slotEl = e.shadowRoot!.querySelector('slot')! expect(slotEl.getAttribute('class')).toBe('foo') foo.value = undefined await nextTick() expect(slotEl.hasAttribute('class')).toBe(false) })
642-667
: Consider a named-slot case to ensure props + name co-exist.Validates BAIL path when props are present on non-default slots and that the name attribute is preserved.
You can add:
test('render named slot with props', async () => { const foo = ref('a') const E = defineCustomElement({ render() { return h('div', null, renderSlot(this.$slots, 'named', { class: foo.value })) } }) customElements.define('my-el-named-slot-props', E) container.innerHTML = `<my-el-named-slot-props><span slot="named">hi</span></my-el-named-slot-props>` const e = container.childNodes[0] as VueElement const slotEl = e.shadowRoot!.querySelector('slot[name="named"]')! expect(slotEl.getAttribute('class')).toBe('a') foo.value = 'b' await nextTick() expect(slotEl.getAttribute('class')).toBe('b') })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/runtime-dom/__tests__/customElement.spec.ts
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/runtime-dom/__tests__/customElement.spec.ts (2)
packages/runtime-dom/src/apiCustomElement.ts (2)
defineCustomElement
(167-185)VueElement
(202-689)packages/runtime-core/src/helpers/renderSlot.ts (1)
renderSlot
(25-101)
🪛 ast-grep (0.38.6)
packages/runtime-dom/__tests__/customElement.spec.ts
[warning] 655-655: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: container.innerHTML = <my-el-slot-props><span>hi</span></my-el-slot-props>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html
(unsafe-html-content-assignment)
[warning] 655-655: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: container.innerHTML = <my-el-slot-props><span>hi</span></my-el-slot-props>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html
(dom-content-modification)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Redirect rules
- GitHub Check: Header rules
- GitHub Check: Pages changed
- GitHub Check: test / e2e-test
🔇 Additional comments (1)
packages/runtime-dom/__tests__/customElement.spec.ts (1)
642-667
: Good targeted test for the CE slot-props regression.This reliably exercises reactive updates on native attributes for custom elements and guards the PatchFlags.BAIL change.
close #13904
Summary by CodeRabbit