Conversation
Stop reparenting bare <img> carousel slides into a wrapper <div> in _prepareCarouselItems(). The <img> is a platform-owned node; on ODC (React runtime) moving it invalidates React's fiber parent record, so a ParameterOnChange aggregate refresh crashes the reconcile with 'NotFoundError: Failed to execute removeChild on Node' (OS-CLRT-60500). Regressed in v2.29.0 by c307023 (PR #1138). Restore the pre-regression class-add loop (no node creation/movement) and preserve PR #1138's a11y intent non-destructively: strip invalid ARIA roles from <img> slides at the attribute level in _applyListRoles/_setListRoles instead of moving them into a container.
gnbm
marked this pull request as draft
July 28, 2026 16:07
gnbm
marked this pull request as ready for review
July 28, 2026 17:31
- Skip list semantics when the carousel has bare <img> slides: images can't take role="listitem" without replacing their image semantics, and a role="list" without list items is invalid. Also drop a list role applied on a previous pass when content changes across platform refreshes. - Correct misleading comments: role="presentation" is valid on an image but removes it from the accessibility tree; roles are stripped so images stay announced via alt text. - Strip role="tabpanel" from slides that are native list elements (ul/ol/li) via tagName check instead of the descendant query — also fixes bare <li> slides that previously kept tabpanel.
OS-susmitabhowmik
previously approved these changes
Jul 28, 2026
There was a problem hiding this comment.
Pull request overview
Fixes a regression in the Carousel Splide provider where wrapping “bare” <img> slides caused React-driven platforms (O11/ODC) to throw NotFoundError: Failed to execute 'removeChild' on 'Node' during data refresh/reconcile, by ensuring no platform-owned nodes are reparented and by adjusting ARIA role handling for image-only slides.
Changes:
- Stop reparenting slide DOM nodes in
_prepareCarouselItems()(class-only mutation; no wrapper insertion). - Skip applying
role="list"/role="listitem"when the Splide list contains bare<img>slides, and remove a previously-appliedrole="list"if content changes to images. - Strip provider-assigned roles from bare
<img>slides to keep image semantics exposed to assistive tech; removerole="tabpanel"only for native list elements (ul/ol/li) where list semantics should remain implicit.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
joselrio
requested changes
Jul 29, 2026
joselrio
reviewed
Jul 29, 2026
…ousel Address review feedback: replace raw DOM calls with the framework helpers for consistency. - _applyListRoles: Attribute.Get/Set/Remove with A11YAttributes.Role constants (AttrName/List/Listitem); detect native-list and image slides by reading direct children and checking tagName (kept direct-child-only so wrapped images still receive list roles). - _prepareCarouselItems: Styles.ContainsClass / Styles.AddClass instead of classList.
…ector
Revert the Array.from(children).some() refactor: keep _hasImageSlides as a
concise direct-child querySelector (consistent with the adjacent
_hasNativeListChildren, which is now unchanged from 2.29.0) and restore the
querySelectorAll(':scope > *') loop. Keeps the Helper.Dom.Attribute/Styles +
Role-constant conversions from the review.
This reverts commit 53b2daa.
…ector Use Helper.Dom.TagSelector / TagSelectorAll (the framework querySelector wrapper, used across the codebase with compound selectors) instead of raw querySelector in _applyListRoles. The ':scope >' selectors keep the direct-child semantics (a wrapped image must still receive list roles), so _applyListRoles is now free of raw DOM queries.
|
joselrio
approved these changes
Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What was happening
On O11 and ODC, a Carousel with bare
<img>slides crashed withNotFoundError: Failed to execute 'removeChild' on 'Node'(OS-CLRT-60500) when aParameterOnChangeaction re-executed an aggregate feeding the carousel (and an IF around it).Regressed in v2.29.0 by commit
c30702391(PR #1138, ROU-12567):_prepareCarouselItems()started reparenting bare<img>slides into a newly created wrapper<div>:The
<img>is a platform-owned node. On O11 and ODC, the runtime is React; moving it invalidates React's fiber record of the node's parent, so the next reconcile (triggered by the aggregate refresh) callsparent.removeChild(img)against a parent that no longer contains it → throw. Every providerredraw()re-ran this and re-wrapped the fresh nodes, making it self-sustaining.What was done
Stop reparenting and keep the ARIA roles valid without moving any DOM — 3 changes in
Splide.ts:_prepareCarouselItems()— restored the pre-regression class-add loop: every item (incl.<img>) just gets thesplide__slideclass; no node is created or moved. Kept theArray.fromsnapshot._applyListRoles()— skip list semantics when the list has bare<img>slides: arole="list"whose children aren't list items is invalid ARIA, and an image can't takerole="listitem"without losing its image semantics. Also drops arole="list"left from a previous pass when content changes across platform refreshes. The images stay exposed to screen readers via their alt text._setListRoles()— strip the role Splide assigns to a bare<img>slide:role="presentation"is valid on an image but removes it from the accessibility tree, so stripping it keeps the image announced via its alt text. Also striprole="tabpanel"from slides that are native list elements (ul/ol/li), via atagNamecheck.PR #1138's other improvements (WCAG pagination target size, list/listitem roles for non-img slides, root
role="presentation") are preserved untouched.Test Steps
Test_Carousel_OnParameterChangedswitch a few times (re-runsOnParametersChanged).NotFoundError … removeChildin the console. After fix: no error; carousel keeps rendering.Screenshots
N.A.
Checklist