Skip to content
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

Insert- and AddMutations applied in wrong order at Receiver-side #519

Open
mfal opened this issue Dec 19, 2024 · 0 comments · May be fixed by #521
Open

Insert- and AddMutations applied in wrong order at Receiver-side #519

mfal opened this issue Dec 19, 2024 · 0 comments · May be fixed by #521

Comments

@mfal
Copy link

mfal commented Dec 19, 2024

Browser

(Chrome 131.0.6778.140)

Error description

In some situation where an observed remote-mutation includes interleaved insertions and additions of nodes, the (index-based) application of these mutations at receivers-side leads to accessing the children-collection at wrong indexes with the following downstream errors:

  • insertion at wrong index

    TypeError: Cannot read properties of undefined (reading 'eventListeners')
        at Object.updateProperty (RemoteReceiver.mjs:125:1)
        at mutate (connection.mjs:25:1)
    
  • removal at wrong index

    TypeError: Cannot read properties of undefined (reading 'id')
        at detach (RemoteReceiver.mjs:226:1)
        at Object.removeChild (RemoteReceiver.mjs:111:1)
        at mutate (connection.mjs:25:1)
    

I investigated on this issue and it comes up that this only happens if the amount of children is the same after the mutation. When this happens, the mutation observer seems to "batch" insertions and additions – first removals, then additions. This totally messes up the application of mutations at the receiver side, because it assumes an "ordered" mutations array.

Example

// From
<remote-parent>
  <remote-child key="2" />
  <remote-child key="3" />
</remote-parent>
// To
<remote-parent>
  <remote-child key="1" />
  <remote-child key="2" />
</remote-parent>

The mutations collected by the RemoteMutationObserver are:

[
  // remove child (key 3) at index 2
  [MUTATION_TYPE_REMOVE_CHILD, 'parent-id', 2],
  // add child  (key 1) at index 0 
  [MUTATION_TYPE_INSERT_CHILD, 'parent-id', { */ serialized child */ }, 0],
]

When the RemoteReceiver tries to apply the first mutation, it wants to remove the child at index 2, which does not exist 💥. Instead it should have done the insertion before and then the removal. In case of more than two mutations (which can be interleaved as well) all the removals are recorded before all insertions.

I don't know why the Mutation Observer API behaves this way (maybe some internal optimization), but this leads to unexpected behaviour (or even errors) on the host side.

Possible solution

The RemoteMutationObserver could sort the mutations by their index before sending them to the receiver. This should only be necessary if there are insertions and removals in one mutation and and amount of removals and insertions is equal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant