11import { BUILD } from '@app-data' ;
22import { doc , plt } from '@platform' ;
3+ import { CMP_FLAGS } from '@utils' ;
34
45import type * as d from '../declarations' ;
5- import { addSlotRelocateNode , patchNextPrev } from './dom-extras' ;
6+ import { patchNextPrev } from './dom-extras' ;
67import { createTime } from './profile' ;
78import {
89 COMMENT_NODE_ID ,
@@ -13,7 +14,9 @@ import {
1314 ORG_LOCATION_ID ,
1415 SLOT_NODE_ID ,
1516 TEXT_NODE_ID ,
17+ VNODE_FLAGS ,
1618} from './runtime-constants' ;
19+ import { addSlotRelocateNode } from './slot-polyfill-utils' ;
1720import { newVNode } from './vdom/h' ;
1821
1922/**
@@ -50,6 +53,17 @@ export const initializeClientHydrate = (
5053 const vnode : d . VNode = newVNode ( tagName , null ) ;
5154 vnode . $elm$ = hostElm ;
5255
56+ let scopeId : string ;
57+ if ( BUILD . scoped ) {
58+ const cmpMeta = hostRef . $cmpMeta$ ;
59+ if ( cmpMeta && cmpMeta . $flags$ & CMP_FLAGS . needsScopedEncapsulation && hostElm [ 's-sc' ] ) {
60+ scopeId = hostElm [ 's-sc' ] ;
61+ hostElm . classList . add ( scopeId + '-h' ) ;
62+ } else if ( hostElm [ 's-sc' ] ) {
63+ delete hostElm [ 's-sc' ] ;
64+ }
65+ }
66+
5367 if ( ! plt . $orgLocNodes$ ) {
5468 // This is the first pass over of this whole document;
5569 // does a scrape to construct a 'bare-bones' tree of what elements we have and where content has been moved from
@@ -94,20 +108,36 @@ export const initializeClientHydrate = (
94108 }
95109 }
96110
111+ if ( childRenderNode . $tag$ === 'slot' ) {
112+ if ( childRenderNode . $children$ ) {
113+ childRenderNode . $flags$ |= VNODE_FLAGS . isSlotFallback ;
114+
115+ if ( ! childRenderNode . $elm$ . childNodes . length ) {
116+ // idiosyncrasy with slot fallback nodes during SSR + `serializeShadowRoot: false`:
117+ // the slot node is created here (in `addSlot()`) via a comment node,
118+ // but the children aren't moved into it. Let's do that now
119+ childRenderNode . $children$ . forEach ( ( c ) => {
120+ childRenderNode . $elm$ . appendChild ( c . $elm$ ) ;
121+ } ) ;
122+ }
123+ } else {
124+ childRenderNode . $flags$ |= VNODE_FLAGS . isSlotReference ;
125+ }
126+ }
127+
97128 if ( orgLocationNode && orgLocationNode . isConnected ) {
98129 if ( shadowRoot && orgLocationNode [ 's-en' ] === '' ) {
99130 // if this node is within a shadowDOM, with an original location home
100131 // we're safe to move it now
101132 orgLocationNode . parentNode . insertBefore ( node , orgLocationNode . nextSibling ) ;
102133 }
103- // Remove original location / slot reference comment now regardless:
104- // 1) Stops SSR frameworks complaining about mismatches
105- // 2) is un-required for non-shadow, slotted nodes as we'll add all the meta nodes we need when we deal with *all* slotted nodes ↓↓↓
134+ // Remove original location / slot reference comment now.
135+ // we'll handle it via `addSlotRelocateNode` later
106136 orgLocationNode . parentNode . removeChild ( orgLocationNode ) ;
107137
108138 if ( ! shadowRoot ) {
109139 // Add the Original Order of this node.
110- // We'll use it later to make sure slotted nodes get added in the correct order
140+ // We'll use it to make sure slotted nodes get added in the correct order
111141 node [ 's-oo' ] = parseInt ( childRenderNode . $nodeId$ ) ;
112142 }
113143 }
@@ -116,14 +146,15 @@ export const initializeClientHydrate = (
116146 }
117147
118148 const hosts : d . HostElement [ ] = [ ] ;
119- let snIndex = 0 ;
120149 const snLen = slottedNodes . length ;
150+ let snIndex = 0 ;
121151 let slotGroup : SlottedNodes ;
122152 let snGroupIdx : number ;
123153 let snGroupLen : number ;
124154 let slottedItem : SlottedNodes [ 0 ] ;
125155
126- // Loops through all the slotted nodes we found while stepping through this component
156+ // Loops through all the slotted nodes we found while stepping through this component.
157+ // creates slot relocation nodes (non-shadow) or moves nodes to their new home (shadow)
127158 for ( snIndex ; snIndex < snLen ; snIndex ++ ) {
128159 slotGroup = slottedNodes [ snIndex ] ;
129160
@@ -157,8 +188,7 @@ export const initializeClientHydrate = (
157188 } else {
158189 // If all else fails - just set the CR as the first child
159190 // (9/10 if node['s-cr'] hasn't been set, the node will be at the element root)
160- const hostChildren = ( hostEle as any ) . __childNodes || hostEle . childNodes ;
161- slottedItem . slot [ 's-cr' ] = hostChildren [ 0 ] as d . RenderNode ;
191+ slottedItem . slot [ 's-cr' ] = ( ( hostEle as any ) . __childNodes || hostEle . childNodes ) [ 0 ] ;
162192 }
163193 // Create our 'Original Location' node
164194 addSlotRelocateNode ( slottedItem . node , slottedItem . slot , false , slottedItem . node [ 's-oo' ] ) ;
@@ -176,6 +206,13 @@ export const initializeClientHydrate = (
176206 }
177207 }
178208
209+ if ( BUILD . scoped && scopeId && slotNodes . length ) {
210+ slotNodes . forEach ( ( slot ) => {
211+ // Host is `scoped: true` - add the slotted scoped class to the slot parent
212+ slot . $elm$ . parentElement . classList . add ( scopeId + '-s' ) ;
213+ } ) ;
214+ }
215+
179216 if ( BUILD . shadowDom && shadowRoot ) {
180217 // Add all the root nodes in the shadowDOM (a root node can have a whole nested DOM tree)
181218 let rnIdex = 0 ;
@@ -247,9 +284,9 @@ const clientHydrate = (
247284 $index$ : childIdSplt [ 3 ] ,
248285 $tag$ : node . tagName . toLowerCase ( ) ,
249286 $elm$ : node ,
250- // If we don't add the initial classes to the VNode, the first `vdom-render.ts` reconciliation will fail:
251- // client side changes before componentDidLoad will be ignored, ` set-accessor.ts` will just take the element's initial classes
252- $attrs$ : { class : node . className } ,
287+ // If we don't add the initial classes to the VNode, the first `vdom-render.ts` patch
288+ // won't try to reconcile them. Classes set on the node will be blown away.
289+ $attrs$ : { class : node . className || '' } ,
253290 } ) ;
254291
255292 childRenderNodes . push ( childVNode ) ;
@@ -260,6 +297,13 @@ const clientHydrate = (
260297 parentVNode . $children$ = [ ] ;
261298 }
262299
300+ if ( BUILD . scoped && scopeId ) {
301+ // Host is `scoped: true` - add that flag to the child.
302+ // It's used in 'set-accessor.ts' to make sure our scoped class is present
303+ node [ 's-si' ] = scopeId ;
304+ childVNode . $attrs$ . class += ' ' + scopeId ;
305+ }
306+
263307 // Test if this element was 'slotted' or is a 'slot' (with fallback). Recreate node attributes
264308 const slotName = childVNode . $elm$ . getAttribute ( 's-sn' ) ;
265309 if ( typeof slotName === 'string' ) {
@@ -276,6 +320,12 @@ const clientHydrate = (
276320 shadowRootNodes ,
277321 slottedNodes ,
278322 ) ;
323+
324+ if ( BUILD . scoped && scopeId ) {
325+ // Host is `scoped: true` - a slot-fb node
326+ // never goes through 'set-accessor.ts' so add the class now
327+ node . classList . add ( scopeId ) ;
328+ }
279329 }
280330 childVNode . $elm$ [ 's-sn' ] = slotName ;
281331 childVNode . $elm$ . removeAttribute ( 's-sn' ) ;
@@ -285,10 +335,6 @@ const clientHydrate = (
285335 parentVNode . $children$ [ childVNode . $index$ as any ] = childVNode ;
286336 }
287337
288- // Host is `scoped: true` - add that flag to the child.
289- // It's used in 'set-accessor.ts' to make sure our scoped class is present
290- if ( scopeId ) node [ 's-si' ] = scopeId ;
291-
292338 // This is now the new parent VNode for all the next child checks
293339 parentVNode = childVNode ;
294340
@@ -390,10 +436,10 @@ const clientHydrate = (
390436 if ( childNodeType === SLOT_NODE_ID ) {
391437 // Comment refers to a slot node:
392438 // `${SLOT_NODE_ID}.${hostId}.${nodeId}.${depth}.${index}.${slotName}`;
393- childVNode . $tag$ = 'slot' ;
394439
395440 // Add the slot name
396- const slotName = ( node [ 's-sn' ] = childVNode . $name$ = childIdSplt [ 5 ] || '' ) ;
441+ const slotName = ( node [ 's-sn' ] = childIdSplt [ 5 ] || '' ) ;
442+
397443 // add the `<slot>` node to the VNode tree and prepare any slotted any child nodes
398444 addSlot (
399445 slotName ,
@@ -502,6 +548,8 @@ function addSlot(
502548 slottedNodes : SlottedNodes [ ] ,
503549) {
504550 node [ 's-sr' ] = true ;
551+ childVNode . $name$ = slotName || null ;
552+ childVNode . $tag$ = 'slot' ;
505553
506554 // Find this slots' current host parent (as dictated by the VDOM tree).
507555 // Important because where it is now in the constructed SSR markup might be different to where to *should* be
@@ -604,4 +652,5 @@ interface RenderNodeData extends d.VNode {
604652 $nodeId$ : string ;
605653 $depth$ : string ;
606654 $index$ : string ;
655+ $elm$ : d . RenderNode ;
607656}
0 commit comments