diff --git a/packages/lwc-engine/src/faux-shadow/events.ts b/packages/lwc-engine/src/faux-shadow/events.ts index ae5b8e181a..c2623f1c68 100644 --- a/packages/lwc-engine/src/faux-shadow/events.ts +++ b/packages/lwc-engine/src/faux-shadow/events.ts @@ -69,15 +69,17 @@ const EventPatchDescriptors: PropertyDescriptorMap = { return outerMostElement; } const eventContext = eventToContextMap.get(this); - // Executing event listener on component, target is always currentTarget + + // Retarget to currentTarget if the listener was added to a custom element. if (eventContext === EventListenerContext.CUSTOM_ELEMENT_LISTENER) { return patchShadowDomTraversalMethods(currentTarget as Element); } - const currentTargetRootNode = getRootNode.call(currentTarget, GET_ROOT_NODE_CONFIG_FALSE); // x-child - // Before we can process any events, we need to first determine three things: - // 1) What VM context was the event attached to? (e.g. in what VM context was addEventListener called in). - // 2) What VM owns the context where the event was attached? (e.g. who rendered the VM context from step 1). + const currentTargetRootNode = getRootNode.call(currentTarget, GET_ROOT_NODE_CONFIG_FALSE); + + // We need to determine three things in order to retarget correctly: + // 1) What VM context was the listener added? (e.g. in what VM context was addEventListener called in). + // 2) What VM owns the context where the listener was added? (e.g. who rendered the VM context from step 1). // 3) What is the event's original target's relationship to 1 and 2? // Determining Number 1: @@ -86,8 +88,8 @@ const EventPatchDescriptors: PropertyDescriptorMap = { // // x-parent.html // @@ -145,8 +147,15 @@ const EventPatchDescriptors: PropertyDescriptorMap = { // // let closestTarget = originalTarget; - while (getNodeOwnerKey(closestTarget as Node) !== myCurrentShadowKey && getNodeOwnerKey(closestTarget as Node) !== myOwnerKey) { + let nodeOwnerKey = getNodeOwnerKey(closestTarget as Node); + while (nodeOwnerKey !== myCurrentShadowKey && nodeOwnerKey !== myOwnerKey) { closestTarget = parentNodeGetter.call(closestTarget); + // In this case, the original target is in a detached root, making it + // impossible to retarget (unless we figure out something clever). + if (closestTarget === null) { + return originalTarget; + } + nodeOwnerKey = getNodeOwnerKey(closestTarget as Node); } /**