From 864370654b28fcce3b663796a8077651ccaf5551 Mon Sep 17 00:00:00 2001 From: Abdulsattar Mohammed Date: Wed, 27 Mar 2024 17:58:42 -0400 Subject: [PATCH] fix: children and childNodes not returning top-level slotted children (#4098) * fix: children and childNodes not returning top-level slotted children * fix: revert getAllMatches and do no filtering * Update packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts Co-authored-by: Eugene Kashida * fix: comment --------- Co-authored-by: Eugene Kashida --- .../integration-karma/test/light-dom/root/index.spec.js | 2 ++ packages/@lwc/synthetic-shadow/src/faux-shadow/element.ts | 6 +++++- packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts | 6 +++++- packages/@lwc/synthetic-shadow/src/shared/node-ownership.ts | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/@lwc/integration-karma/test/light-dom/root/index.spec.js b/packages/@lwc/integration-karma/test/light-dom/root/index.spec.js index 7055e5f3a9..ad5e11ce10 100644 --- a/packages/@lwc/integration-karma/test/light-dom/root/index.spec.js +++ b/packages/@lwc/integration-karma/test/light-dom/root/index.spec.js @@ -78,5 +78,7 @@ describe('root light element', () => { expect(nodes['x-list'].querySelector('button')).toEqual(nodes.button); expect(nodes['x-list'].getElementsByTagName('button')[0]).toEqual(nodes.button); expect(nodes['x-list'].getElementsByClassName('button')[0]).toEqual(nodes.button); + expect(nodes['x-list'].childNodes[0]).toEqual(nodes.button); + expect(nodes['x-list'].children[0]).toEqual(nodes.button); }); }); diff --git a/packages/@lwc/synthetic-shadow/src/faux-shadow/element.ts b/packages/@lwc/synthetic-shadow/src/faux-shadow/element.ts index 528d32f838..97c9b9d8a2 100644 --- a/packages/@lwc/synthetic-shadow/src/faux-shadow/element.ts +++ b/packages/@lwc/synthetic-shadow/src/faux-shadow/element.ts @@ -92,7 +92,11 @@ function shadowRootGetterPatched(this: Element): ShadowRoot | null { function childrenGetterPatched(this: Element): HTMLCollectionOf { const owner = getNodeOwner(this); - const childNodes = isNull(owner) ? [] : getAllMatches(owner, getFilteredChildNodes(this)); + const filteredChildNodes = getFilteredChildNodes(this); + // No need to filter by owner for non-shadowed nodes + const childNodes = isNull(owner) + ? filteredChildNodes + : getAllMatches(owner, filteredChildNodes); return createStaticHTMLCollection( ArrayFilter.call(childNodes, (node: Node | Element) => node instanceof Element) ); diff --git a/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts b/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts index 493ee5b644..e1a7a89595 100644 --- a/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts +++ b/packages/@lwc/synthetic-shadow/src/faux-shadow/node.ts @@ -173,7 +173,11 @@ function cloneNodePatched(this: Node, deep?: boolean): Node { function childNodesGetterPatched(this: Node): NodeListOf { if (isSyntheticShadowHost(this)) { const owner = getNodeOwner(this); - const childNodes = isNull(owner) ? [] : getAllMatches(owner, getFilteredChildNodes(this)); + const filteredChildNodes = getFilteredChildNodes(this); + // No need to filter by owner for non-shadowed nodes + const childNodes = isNull(owner) + ? filteredChildNodes + : getAllMatches(owner, filteredChildNodes); return createStaticNodeList(childNodes); } // nothing to do here since this does not have a synthetic shadow attached to it diff --git a/packages/@lwc/synthetic-shadow/src/shared/node-ownership.ts b/packages/@lwc/synthetic-shadow/src/shared/node-ownership.ts index 63ddd73b56..eac9d58502 100644 --- a/packages/@lwc/synthetic-shadow/src/shared/node-ownership.ts +++ b/packages/@lwc/synthetic-shadow/src/shared/node-ownership.ts @@ -58,6 +58,8 @@ export function getNodeNearestOwnerKey(node: Node): number | undefined { } host = parentNodeGetter.call(host) as ShadowedNode | null; + // Elements slotted from top level light DOM into synthetic shadow + // reach the slot tag from the shadow element first if (!isNull(host) && isSyntheticSlotElement(host)) { return undefined; }