Skip to content

Commit

Permalink
fix(renderer): add hostname to host slot node finder method
Browse files Browse the repository at this point in the history
expected hostname is added to the getHostSlotNode method to retrieve the correct host's slot node since it was getting the first found slot node. However, same slot name or even another custom component's default slot can be placed before the searching host element's slot node

fixes one of the issues raised in ionic-team#5335
  • Loading branch information
yigityuce committed Feb 24, 2024
1 parent 8ebacae commit c69160e
Showing 1 changed file with 9 additions and 8 deletions.
17 changes: 9 additions & 8 deletions src/runtime/dom-extras.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const patchSlotAppendChild = (HostElementPrototype: any) => {
HostElementPrototype.__appendChild = HostElementPrototype.appendChild;
HostElementPrototype.appendChild = function (this: d.RenderNode, newChild: d.RenderNode) {
const slotName = (newChild['s-sn'] = getSlotName(newChild));
const slotNode = getHostSlotNode(this.childNodes, slotName);
const slotNode = getHostSlotNode(this.childNodes, slotName, this.tagName);
if (slotNode) {
const slotChildNodes = getHostSlotChildNodes(slotNode, slotName);
const appendAfter = slotChildNodes[slotChildNodes.length - 1];
Expand Down Expand Up @@ -108,7 +108,7 @@ const patchSlotRemoveChild = (ElementPrototype: any) => {
ElementPrototype.__removeChild = ElementPrototype.removeChild;
ElementPrototype.removeChild = function (this: d.RenderNode, toRemove: d.RenderNode) {
if (toRemove && typeof toRemove['s-sn'] !== 'undefined') {
const slotNode = getHostSlotNode(this.childNodes, toRemove['s-sn']);
const slotNode = getHostSlotNode(this.childNodes, toRemove['s-sn'], this.tagName);
if (slotNode) {
// Get all slot content
const slotChildNodes = getHostSlotChildNodes(slotNode, toRemove['s-sn']);
Expand Down Expand Up @@ -142,7 +142,7 @@ export const patchSlotPrepend = (HostElementPrototype: HTMLElement) => {
newChild = this.ownerDocument.createTextNode(newChild) as unknown as d.RenderNode;
}
const slotName = (newChild['s-sn'] = getSlotName(newChild));
const slotNode = getHostSlotNode(this.childNodes, slotName);
const slotNode = getHostSlotNode(this.childNodes, slotName, this.tagName);
if (slotNode) {
const slotPlaceholder: d.RenderNode = document.createTextNode('') as any;
slotPlaceholder['s-nr'] = newChild;
Expand Down Expand Up @@ -323,7 +323,7 @@ export const patchTextContent = (hostElementPrototype: HTMLElement): void => {
get(): string | null {
// get the 'default slot', which would be the first slot in a shadow tree (if we were using one), whose name is
// the empty string
const slotNode = getHostSlotNode(this.childNodes, '');
const slotNode = getHostSlotNode(this.childNodes, '', this.tagName);
// when a slot node is found, the textContent _may_ be found in the next sibling (text) node, depending on how
// nodes were reordered during the vdom render. first try to get the text content from the sibling.
if (slotNode?.nextSibling?.nodeType === NODE_TYPES.TEXT_NODE) {
Expand All @@ -339,7 +339,7 @@ export const patchTextContent = (hostElementPrototype: HTMLElement): void => {
set(value: string | null) {
// get the 'default slot', which would be the first slot in a shadow tree (if we were using one), whose name is
// the empty string
const slotNode = getHostSlotNode(this.childNodes, '');
const slotNode = getHostSlotNode(this.childNodes, '', this.tagName);
// when a slot node is found, the textContent _may_ need to be placed in the next sibling (text) node,
// depending on how nodes were reordered during the vdom render. first try to set the text content on the
// sibling.
Expand Down Expand Up @@ -432,18 +432,19 @@ const getSlotName = (node: d.RenderNode) =>
* Recursively searches a series of child nodes for a slot with the provided name.
* @param childNodes the nodes to search for a slot with a specific name.
* @param slotName the name of the slot to match on.
* @param hostName the host name of the slot to match on.
* @returns a reference to the slot node that matches the provided name, `null` otherwise
*/
const getHostSlotNode = (childNodes: NodeListOf<ChildNode>, slotName: string) => {
const getHostSlotNode = (childNodes: NodeListOf<ChildNode>, slotName: string, hostName: string) => {
let i = 0;
let childNode: d.RenderNode;

for (; i < childNodes.length; i++) {
childNode = childNodes[i] as any;
if (childNode['s-sr'] && childNode['s-sn'] === slotName) {
if (childNode['s-sr'] && childNode['s-sn'] === slotName && childNode['s-hn'] === hostName) {
return childNode;
}
childNode = getHostSlotNode(childNode.childNodes, slotName);
childNode = getHostSlotNode(childNode.childNodes, slotName, hostName);
if (childNode) {
return childNode;
}
Expand Down

0 comments on commit c69160e

Please sign in to comment.