-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Which package(s) are affected?
Context (@lit-labs/context)
Description
Attaching a ContextRoot is designed to allow a ContextProvider to come into existence after a consumer requests the data.
We have a test for this by registering an element that has a ContextProvider after the consumer is registered.
However, another use case is for a ContextProvider controller to be added lazily to an element, after it is already registered/connected. The key difference here is when hostConnected runs: When calling addController on an already connected element, hostConnected will be run synchronous to that call; when calling addController during an element construction, hostConnected will be called later, when the element's connectedCallback lifecycle runs.
This difference manifests in a bug due to the fact that the ContextProvider controller's context-request listener is added after addController runs:
lit/packages/labs/context/src/lib/controllers/context-provider.ts
Lines 46 to 54 in 00b8c56
| constructor( | |
| protected host: ReactiveElement, | |
| private context: T, | |
| initialValue?: ContextType<T> | |
| ) { | |
| super(initialValue); | |
| this.host.addController(this); | |
| this.attachListeners(); | |
| } |
However during the hostConnected callback (which might be called synchronously to addController as mentioned above), we fire the context-provider that, when used in conjunction with ContextRoot, results in a context-request event being fired back to the provider:
lit/packages/labs/context/src/lib/controllers/context-provider.ts
Lines 76 to 79 in 00b8c56
| hostConnected(): void { | |
| // emit an event to signal a provider is available for this context | |
| this.host.dispatchEvent(new ContextProviderEvent(this.context)); | |
| } |
As such, the context-request event can be missed by the ContextProvider. The solution is hopefully as simple as flipping the addController() and attachListeners() lines.
Reproduction
https://lit.dev/playground/#gist=f709d0dc42035197bb2b4fc4ec65449a
Workaround
This workaround makes the above repro work as expectd:
const hostConnected = ContextProvider.prototype.hostConnected;
ContextProvider.prototype.hostConnected = async function() {
await 0;
hostConnected.call(this);
}
Is this a regression?
No or unsure. This never worked, or I haven't tried before.
Affected versions
@lit-labs/context 0.1.3
Browser/OS/Node environment
Browser: any
Metadata
Metadata
Assignees
Labels
Type
Projects
Status