[lexical-react] Fix: ensure selection listeners cleaned up from original owner document#7843
Conversation
…ct owner document
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Might be a good opportunity to set up a test suite that runs in vitest browser mode now that we are not using jest? My primary concern is that we don't know exactly when the The counter situation should be fixable by using a |
|
Will give that a go. |
cf52fb3 to
71278bb
Compare
|
Changed tack a little bit per your suggestion, and am now tracking which document the element was registered with, then decrementing the counter for that document. I stuck with
This is still a concern, however I couldn't see a good way to solve it in the general case. The closest I could find was Which is to say, it'll still be up to the caller to track how they're moving elements around in documents. For us, we'll be able to do something like: For posterity, I spent a bit of time trying to get browser mode going but couldn't get it over the line. Here's what I had:
|
|
An alternative to the WeakMap would be to store the owner document as a property on the editor. |
etrepum
left a comment
There was a problem hiding this comment.
This looks like a reasonable fix to me, I think we'll probably want to make this more robust later so the ownerDocument transition can just get fixed in place as soon as its detected. I think it's a high probability that some other event will also come along with the missed selectionchange (e.g. focus/blur) for any selectionchange that is relevant to the document
Description
When rendering into a different window using
createPortal, eg with react-new-window,ownerDocumentinitially refers to the document in which the element was created. Once React has mounted it into the portal however, it points to the portal's document.This causes an issue with ref counting in
addRootElementEvents/removeRootElementEventsas the counter is incremented for one document but decremented for the other, causinginvariant(newCount >= 0, 'Root element count less than 0')to fail. It also means that the listeners are not added to the document in which the root element is mounted.WhenuseCallbackrefs are used, the ref is called before the element is in DOM: in the debugger, we observed thatrootElement.isConnectedis false. By switching to an effect, the code is only called after the element has been attached to the new document, i.e.isConnectedis true andownerDocumenthas the correct reference.Rather than looking at
ownerDocumentagain when removing listeners, we now instead track what the owner document was at registration time, and decrement the counter/remove listeners for that document.Test plan
Wasn't able to repro in unit tests, but we monkey-patched this change into Lexical in our application and confirmed it fixes the crash.Added a unit test which fails pre-change.