-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevents missing child from causing removal of last node #522
Prevents missing child from causing removal of last node #522
Conversation
a5b1f4a
to
9e18b93
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the right thing to do 👍 I believe Thomas has a shop to reproduce the error in a Shopify checkout and was able to see it fixed with this patch but I'll let him confirm.
Yes! I can prove it's working. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give me a bit more detail on how this can actually happen in practice? This change being on the host implies that the remote environment is sending the request — what causes it to send a request to remove an element that does not exist?
This solution does work, but it feels like it hides a deeper bug.
The real bug is that calling The way this comes up from calling |
If the issue is on the caller of |
If I'm understanding, then we should be fixing the missing child issue - but it will only be fixed for new extensions. I think it'd just be something like this in root function removeChild(
const {strict} = rootInternals;
return perform(container, rootInternals, {
- remote: (channel) =>
- channel(
- ACTION_REMOVE_CHILD,
- (container as any).id,
- container.children.indexOf(child as any),
- ),
+ remote: (channel) => {
+ const childIndex = container.children.indexOf(child as any);
+ if (childIndex === -1) {
+ return;
+ }
+ return channel(ACTION_REMOVE_CHILD, (container as any).id, childIndex);
+ },
local: () => {
removeNodeFromContainer(child, rootInternals); If child isn't found, do nothing (or something if we want to call attention to it). I don't understand everything in remote-ui, so I'm not sure if the local function needs a fix as well. The error happens frequently, so we need to handle it somehow. Would wrapping the call to |
@thomas-marcucci yes, that is roughly what I was imagining. I think you can move the check outside of the I still think your change on the host might be appropriate, but I'd want to pair it with this change to the remote, and a new API that can inform the consumer when such an invalid message has been received. This gives the consumer the full complement of support — we make it hard to make the mistake in the first place, by updating the remote environment, and we give them the ability to degrade gracefully in the case where invalid messages are received on the host (e.g., because an obnoxious extension was manually sending invalid postmessages, rather than using |
9e18b93
to
e9a7bc9
Compare
e9a7bc9
to
2fe4b53
Compare
Description
There is an error being thrown when
removeChild
is being called and the root is empty.-1
gets passed in as the index, no child is found, thendetach
runs and a type error is thrownchild.id
becausechild
isundefined
.What this does
On the remote, it validates that a child is found when
removeChild
is called. When the child node is not found, instead of passing the-1
index through, it returns early doing nothing. This will prevent the exception as well as the removal of the last child from the parent.On the host, it prevents the error from occurring by checking for a
undefined
result when the child node is supposed to be removed and returning early.