Skip to content

Commit

Permalink
fix(engine): fixes issue #658 - parentNode on slotted elements (#661)
Browse files Browse the repository at this point in the history
* fix(engine): fixes issue #658 - parentNode on slotted elements
  • Loading branch information
caridy authored Sep 25, 2018
1 parent 69ece4b commit d22bdd8
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
39 changes: 39 additions & 0 deletions packages/lwc-engine/src/faux-shadow/__tests__/slot.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,4 +502,43 @@ describe('slotted elements', () => {
const button = getHostShadowRoot(child as HTMLUnknownElement).querySelector('button');
button.click();
});

it('should allow traversing up to its parentNode', () => {
const childHTML = compileTemplate(`<template>
<slot>
</slot>
</template>`);

let childTemplate;
class ChildComponent extends LightningElement {
render() {
childTemplate = this.template;
return childHTML;
}
}
const parentHTML = compileTemplate(`<template>
<c-child>
<div>Slotted</div>
</c-child>
</template>`, {
modules: {
'c-child': ChildComponent
}
});
let parentTemplate;
class ParentComponent extends LightningElement {
render() {
parentTemplate = this.template;
return parentHTML;
}
}
const elm = createElement('x-parent', { is: ParentComponent, fallback: true });
document.body.appendChild(elm);
const divFromParent = parentTemplate.querySelector('div');
const child = parentTemplate.querySelector('c-child');
const slottedDiv = childTemplate.querySelector('slot').assignedElements()[0];
expect(slottedDiv).toBe(divFromParent);
expect(slottedDiv.parentNode).toBe(child);
});

});
4 changes: 2 additions & 2 deletions packages/lwc-engine/src/faux-shadow/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ function getWrappedShadowRootListener(sr: ShadowRoot, listener: EventListener):
if (
// it is composed and was not dispatched onto the custom element directly
(composed === true && target !== currentTarget) ||
// it is coming from an slotted element
// it is coming from a slotted element
isChildNode(getRootNode.call(target, event), currentTarget as Node) ||
// it is not composed and its is coming from from shadow
(composed === false && getRootNode.call(target) === currentTarget)) {
Expand Down Expand Up @@ -347,7 +347,7 @@ function isValidEventForCustomElement(event: Event): boolean {
composed === true ||
// it is dispatched onto the custom element directly, or
target === currentTarget ||
// it is coming from an slotted element
// it is coming from a slotted element
isChildNode(getRootNode.call(target, NON_COMPOSED), currentTarget as Node)
);
}
Expand Down
17 changes: 14 additions & 3 deletions packages/lwc-engine/src/faux-shadow/traverse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,20 @@ function getShadowParent(node: HTMLElement, value: undefined | HTMLElement): Sha
if (value === owner) {
// walking up via parent chain might end up in the shadow root element
return getShadowRoot(owner);
} else if (value instanceof Element && getNodeOwnerKey(node) === getNodeOwnerKey(value)) {
// cutting out access to something outside of the shadow of the current target (usually slots)
return patchShadowDomTraversalMethods(value);
} else if (value instanceof Element) {
if (getNodeOwnerKey(node) === getNodeOwnerKey(value)) {
// the element and its parent node belong to the same shadow root
return patchShadowDomTraversalMethods(value);
} else if (!isNull(owner) && tagNameGetter.call(value) === 'SLOT') {
// slotted elements must be top level childNodes of the slot element
// where they slotted into, but its shadowed parent is always the
// owner of the slot.
const slotOwner = getNodeOwner(value);
if (!isNull(slotOwner) && isNodeOwnedBy(owner, slotOwner)) {
// it is a slotted element, and therefore its parent is always going to be the host of the slot
return patchShadowDomTraversalMethods(slotOwner);
}
}
}
return null;
}
Expand Down

0 comments on commit d22bdd8

Please sign in to comment.