fix(scoped): fixes for <slot />
and slotted nodes
#6082
Merged
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 is the current behavior?
A bunch of bugs related to
scoped: true
GitHub Issue Number:
::slotted(...)
selector not working appropriately inscoped: true
component #6081scoped: true
/ SSR components incorrectly resolve<slot />
during first render #6080scoped: true
SSR hydrated components get duplicated<style>
tags #6088What is the new behavior?
All attached bugs have been fixed combined with a bunch of refactoring (see below for in-depth reasoning).
Documentation
Does this introduce a breaking change?
Testing
::slotted(...)
selector specificity and making sure slotted nodes do not receive scoped classes.Other information
TL version
Refactored a bunch of internals in
vdom-render.ts
Removed
updateElementScopeIds()
&findScopeIds()
(in-favour of newaddRemoveSlotScopedClass()
)These methods combined would (too regularly) loop through an entire component tree adding scoped class variants (internal (
sc-...
), slot (internal +...-s
), and host (internal +...-h
)).This behaviour is incorrect for a number of reasons:
Children component internals receiving parent scoped class
Given an internal setup like:
cmp-b
s internal div would receive the internal scope classsc-cmp-a
- when it should not as it's not owned by cmp-a in any way.All component internals receiving the scoped slot class
The scoped slot class (e.g.
sc-cmp-a-s
) is a hook to use with::slotted(...)
type selectors. Currently it can be applied to the entire parent tree:This is incorrect - only the element surrounding the slot should have the class. The result is that
::slotted(...)
selectors are applied too liberally.Scope classes being applied to slotted elements
At present scoped classes apply to slotted elements (elements coming from outside of the component internals). This is incorrect as slotted elements are not 'owned' by the component and results in the behaviour in #6081.
New behaviour
All internal scoped classes are appropriately managed as elements are created. To manage the appropriate scoped slot class, as
<slot />
nodes move around the newaddRemoveSlotScopedClass()
adds / removes the class.Refactored
updateFallbackSlotVisibility()
updateFallbackSlotVisibility()
seemed unnecessarily opaque and unreliable. Much of the logic for slot & slotted nodes are managed quite succinctly withindom-extras.ts
so I reused it.As part of that process I moved all shared slot polyfill logic into a new
slot-polyfill-utils.ts
file.Tweaks to
isSameVnode()
isSameVnode
would intentionally not resolve<slot />
/<slot-fb />
nodes during SSR, forcing them to be reconstructed on the client. This had the side-effect of incorrectly resolving the overall VDOM in some instances (#6080).I've made it so a combination of changes to
client-hydrate.ts
&mock-doc/element.ts
now provide everything needed during SSR - these nodes no longer need to be reconstructed.