Skip to content

Commit

Permalink
Fixes ContextRoot for requesters in nested shadowRoots (#3834)
Browse files Browse the repository at this point in the history
Ensure ContextRoot stores event root target avoiding event re-targeting issues when context
requesting elements are in nested shadowRoots, fixes #3833.
  • Loading branch information
Steve Orvell committed Apr 24, 2023
1 parent 4a1c589 commit 9a4a178
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/mean-elephants-cough.md
@@ -0,0 +1,5 @@
---
'@lit-labs/context': patch
---

Fixes ContextRoot for requesters in nested shadowRoots, #3833
5 changes: 4 additions & 1 deletion packages/labs/context/src/lib/context-root.ts
Expand Up @@ -94,7 +94,10 @@ export class ContextRoot {
return;
}

const element = event.target as HTMLElement;
// Note, it's important to use the initial target via composedPath()
// since that's the requesting element and the event may be re-targeted
// to an outer host element.
const element = event.composedPath()[0] as HTMLElement;
const callback = event.callback;

let pendingContextRequests = this.pendingContextRequests.get(event.context);
Expand Down
51 changes: 51 additions & 0 deletions packages/labs/context/src/test/late-provider_test.ts
Expand Up @@ -113,6 +113,57 @@ suiteSkipIE('late context provider', () => {
assert.strictEqual(consumer.onceValue, 0);
});

test(`handles late upgrade properly in nested shadowRoot`, async () => {
const host = document.createElement('div');

host.attachShadow({mode: 'open'});
const root = host.shadowRoot!;
root.innerHTML = `
<late-context-provider-nested value="1000">
<context-consumer></context-consumer>
</late-context-provider-nested>
`;

container.append(host);

const provider = root.querySelector(
'late-context-provider-nested'
) as LateContextProviderElement;

const consumer = root.querySelector(
'context-consumer'
) as ContextConsumerElement;

await consumer.updateComplete;

// Initially consumer has initial value
assert.strictEqual(consumer.value, 0);
assert.strictEqual(consumer.onceValue, 0);

// Define provider element
customElements.define(
'late-context-provider-nested',
class extends LateContextProviderElement {}
);

await provider.updateComplete;
await consumer.updateComplete;

// `value` should now be provided
assert.strictEqual(consumer.value, 1000);

// but only to the subscribed value
assert.strictEqual(consumer.onceValue, 0);

// Confirm subscription is established
provider.value = 500;
await consumer.updateComplete;
assert.strictEqual(consumer.value, 500);

// and once was not updated
assert.strictEqual(consumer.onceValue, 0);
});

test('lazy added provider', async () => {
@customElement('lazy-context-provider')
class LazyContextProviderElement extends LitElement {
Expand Down

0 comments on commit 9a4a178

Please sign in to comment.