Background (my understanding of transient registered mutation observers--TRMOs):
I believe that TRMOs are designed the way they are to make it so that the order of removal mutations becomes largely unimportant to ensuring an observer receives a complete view of all the changes between individual checkpoints. Given the following tree:
If you attach an observer to the <div>, remove the <span>, and then remove the <p>, you’ll see two mutation records generated. If you reverse the order of the removals, however, you would only see the removal record for the <p>, if not for TRMOs. With TRMOs, when the <p> is removed, a TRMO is attached to it, and then the removal of the <span> can be observed, which would otherwise be lost due to the <div> not being in the <p>’s parent chain anymore.
The spec states that TRMOs are to be removed at checkpoint time. They’re not supposed to be permanent, they’re just supposed to be there long enough for script to see that some the <p> left the tree. If it’s interested, it can register an observer on it and not miss anything as things move forward.
Question to consider:
Do we think checkpoint time is the right time to remove TRMOs? The spec and Firefox/Chrome do it that way. However, after thinking about this for a while, I think the right time is actually any time the list of records is retrieved (checkpoint time, as well as calls to takeRecords). If TRMOs are not removed during takeRecords, then script will continue to receive transient observer notifications anytime between that call to takeRecords and the future checkpoint, and this to me seems confusing and possibly unwanted. When takeRecords is called, the array contains the removal record for the <p>, but script will continue to receive transient records until the next checkpoint. Perhaps weirder, if script does attach an observer to the <p> right after calling takeRecords, then it’ll potentially get double removal records until the next checkpoint (and there isn’t an easy way to avoid this, short of it manually deduplicating the records).
Thoughts? Should the spec be changed so that TRMOs are additionally cleared at takeRecords() time?
Agreed. Clearing TRMOs is probably best at any deliver point (including takeRecords). I talked with Adam about this and we're fine changing both the spec and the webkit implementation (it's highly unlikely that any one will be broken by this change).
I don't say yes to the change immediately. Need to think about this a day or two.
(I'm traveling right now so need to find some time to go through various
So, when takeRecords() was added I was thinking, and still do, that it shouldn't
affect to MutationRecord creation. It is just a way to get the current
records which can be then handled before the end of microtask.
There shouldn't be problem with double MutationRecords. There is just
one per mutation per MutationObserver.
Also, if you do want to clear transient observers, just disconnect()/observer()
So, it is not clear to me why we'd want to change the spec (also given that there has been two compatible implementations shipping quite some time).
Olli is right that there isn't much risk of duplicate records (you'd need to create a *different* observer -- but in that case, you'd expect duplicate records).
I think Olli's mental model is also compelling.
Honestly, I'm actually not sure it matters much and I think both behaviors are fine. I can't think of a use-case reason to prefer one behavior to the other.
Can anyone else?
Well, thanks for the discussion folks. If there's no other objection, it seems like keeping the status quo may be the best option, especially since there is already interop among the implementing browsers in this case. Thanks for hearing me out.