import type * as d from '../declarations' ; import { BUILD } from '@app-data' ; import { NODE_TYPES } from '@stencil/core/mock-doc' ; import { CMP_FLAGS , HOST_FLAGS } from '@utils' ; import { PLATFORM_FLAGS } from './runtime-constants' ; import { plt , supportsShadow , getHostRef } from '@platform' ; export const patchCloneNode = ( HostElementPrototype ) => { const orgCloneNode = HostElementPrototype . cloneNode ; HostElementPrototype . cloneNode = function ( deep ? ) { const srcNode = this ; const isShadowDom = BUILD . shadowDom ? srcNode . shadowRoot && supportsShadow : false ; const clonedNode = orgCloneNode . call ( srcNode , isShadowDom ? deep : false ) as Node ; if ( BUILD . slot && ! isShadowDom && deep ) { let i = 0 ; let slotted , nonStencilNode ; let stencilPrivates = [ 's-id' , 's-cr' , 's-lr' , 's-rc' , 's-sc' , 's-p' , 's-cn' , 's-sr' , 's-sn' , 's-hn' , 's-ol' , 's-nr' , 's-si' , ] ; for ( ; i < srcNode . childNodes . length ; i ++ ) { slotted = ( srcNode . childNodes [ i ] as any ) [ 's-nr' ] ; nonStencilNode = stencilPrivates . every ( ( privateField ) => ! ( srcNode . childNodes [ i ] as any ) [ privateField ] ) ; if ( slotted ) { if ( BUILD . appendChildSlotFix && ( clonedNode as any ) . __appendChild ) { ( clonedNode as any ) . __appendChild ( slotted . cloneNode ( true ) ) ; } else { clonedNode . appendChild ( slotted . cloneNode ( true ) ) ; } } if ( nonStencilNode ) { clonedNode . appendChild ( ( srcNode . childNodes [ i ] as any ) . cloneNode ( true ) ) ; } } } return clonedNode ; } ; } ; export const patchSlotAppendChild = ( HostElementPrototype ) => { HostElementPrototype . __appendChild = HostElementPrototype . appendChild ; HostElementPrototype . appendChild = function ( this , newChild ) { const slotName = ( newChild [ 's-sn' ] = getSlotName ( newChild ) ) ; const slotNode = getHostSlotNode ( this . childNodes , slotName ) ; if ( slotNode ) { const slotChildNodes = getHostSlotChildNodes ( slotNode , slotName ) ; const appendAfter = slotChildNodes [ slotChildNodes . length - 1 ] ; return appendAfter . parentNode . insertBefore ( newChild , appendAfter . nextSibling ) ; } return ( this as any ) . __appendChild ( newChild ) ; } ; } ; param hostElementPrototype param cmpMeta export const patchTextContent = ( hostElementPrototype , cmpMeta ) : void => { if ( BUILD . scoped && cmpMeta . $flags$ & CMP_FLAGS . scopedCssEncapsulation ) { const descriptor = Object . getOwnPropertyDescriptor ( Node . prototype , 'textContent' ) ; Object . defineProperty ( hostElementPrototype , '__textContent' , descriptor ) ; Object . defineProperty ( hostElementPrototype , 'textContent' , { get ( ) { const slotNode = getHostSlotNode ( this . childNodes , '' ) ; if ( slotNode ?. nextSibling ?. nodeType === NODE_TYPES . TEXT_NODE ) { return slotNode . nextSibling . textContent ; } else if ( slotNode ) { return slotNode . textContent ; } else { return this . __textContent ; } } , set ( value ) { const slotNode = getHostSlotNode ( this . childNodes , '' ) ; if ( slotNode ?. nextSibling ?. nodeType === NODE_TYPES . TEXT_NODE ) { slotNode . nextSibling . textContent = value ; } else if ( slotNode ) { slotNode . textContent = value ; } else { this . __textContent = value ; const contentRefElm = this [ 's-cr' ] ; if ( contentRefElm ) { this . insertBefore ( contentRefElm , this . firstChild ) ; } } } , } ) ; } } ; export const patchChildSlotNodes = ( elm , cmpMeta ) => { class FakeNodeList extends Array { item ( n ) { return this [ n ] ; } } if ( cmpMeta . $flags$ & CMP_FLAGS . needsShadowDomShim ) { const childNodesFn = elm . __lookupGetter__ ( 'childNodes' ) ; Object . defineProperty ( elm , 'children' , { get ( ) { return this . childNodes . map ( ( n ) => n . nodeType === 1 ) ; } , } ) ; Object . defineProperty ( elm , 'childElementCount' , { get ( ) { return elm . children . length ; } , } ) ; Object . defineProperty ( elm , 'childNodes' , { get ( ) { const childNodes = childNodesFn . call ( this ) ; if ( ( plt . $flags$ & PLATFORM_FLAGS . isTmpDisconnected ) === 0 && getHostRef ( this ) . $flags$ & HOST_FLAGS . hasRendered ) { const result = new FakeNodeList ( ) ; for ( let i = 0 ; i < childNodes . length ; i ++ ) { const slot = childNodes [ i ] [ 's-nr' ] ; if ( slot ) { result . push ( slot ) ; } } return result ; } return FakeNodeList . from ( childNodes ) ; } , } ) ; } } ; const getSlotName = ( node ) => node [ 's-sn' ] || ( node . nodeType === 1 && ( node as Element ) . getAttribute ( 'slot' ) ) || '' ; param childNodes param slotName returns const getHostSlotNode = ( childNodes , slotName ) => { let i = 0 ; let childNode ; for ( ; i < childNodes . length ; i ++ ) { childNode = childNodes [ i ] as any ; if ( childNode [ 's-sr' ] && childNode [ 's-sn' ] === slotName ) { return childNode ; } childNode = getHostSlotNode ( childNode . childNodes , slotName ) ; if ( childNode ) { return childNode ; } } return null ; } ; const getHostSlotChildNodes = ( n , slotName ) => { const childNodes = [ n ] ; while ( ( n = n . nextSibling as any ) && ( n as d . RenderNode ) [ 's-sn' ] === slotName ) { childNodes . push ( n as any ) ; } return childNodes ; } ;