Re: Mutation events replacement

On 7/20/11 12:11 PM, Ryosuke Niwa wrote:
> On Wed, Jul 20, 2011 at 11:56 AM, Aryeh Gregor 
> <Simetrical+w3c@gmail.com <mailto:Simetrical%2Bw3c@gmail.com>> wrote:
>
>     On Wed, Jul 20, 2011 at 1:43 AM, David Flanagan
>     <dflanagan@mozilla.com <mailto:dflanagan@mozilla.com>> wrote:
>     > Finally, I still think it is worth thinking about trying to
>     model the
>     > distinction between removing nodes from the document tree and
>     moving them
>     > (atomically) within the tree.
>
>     I'll chip in that I think this is useful.  It makes things somewhat
>     more complicated, but remove/insert and move are conceptually very
>     different.
>
>
> But internally, a node movement is a removal then an insertion. 
>  There's always possibility that a node gets removed then inserted 
> again after mutation observers are invoked.  Also, what happens if a 
> function removed a bunch of nodes and then inserted back one of them?
>
My definition of moving a node atomically is taking a node that is 
already in the tree and passing it to appendChild() or insertBefore().  
Everything else is regular node removal followed by node insertion.

If you get a mutation event that says that node A was removed from node 
B and inserted into node C, you know nothing about the state of node A, 
since it could have been mutated while it was outside of the tree and no 
mutation events would have been recorded.  Its attributes, text and 
children all could have changed, so the mutation listener has to 
basically discard everything it knows about node A and treat it as a 
brand-new node.

If, on the other hand, there was some way for the listener to know that 
the node was moved atomically, then it would know that it hadn't missed 
any mutation events and it could retain whatever cached state it had for 
node A, changing only the parent.

Here's one possible way that the distinction between move and remove 
could be made: keep the added and removed lists of nodes exactly as they 
are now.  But when a node is moved atomically, also add it to an array 
of moved nodes.  Listeners that don't care about the move/remove 
distinction can just use the added and removed properties as in the 
current proposal.  But listeners that do care can check any added or 
removed node against the moved array to see if it was an atomic move.

Another approach that might work: define a "reparent" or "move" mutation 
event type.  So when node A is moved from parent B to parent C, the 
mutations would be:

[{target:A, type:"reparent"},
  {target:B, type:"childList", removed:[A]},
  {target:C, type:"childList", added:[B]}]

To make this work, if an atomic move was followed by a removal, the 
reparent mutation would have to be removed from the list of mutations.

     David

>     e.g. say we have <div>hello<br>world<br>w3c<br></div>
>
>     And we have a hypothetical function that does:
>
>      1. Remove all children of div
>      2. Inserts "w3c" back after div.
>
>     Then what should the list of mutations contain?  Should it contain
>     2 items one that says it removed "hello", "world", and 3 br's, and
>     then another one saying "w3c" moved?  But then child nodes are not
>     all consecutive and scripts won't be able to infer where these
>     nodes were even if we provided offsets or before/after node.
>
>     Should it contain 3 items, one that says "hello", "world" and the
>     first 2 br's are removed, then one for moving "w3c", and then
>     another one for removing the last br?  But then UAs have to keep
>     reorganizing the list as the function modifies more DOM because
>     there is no way to differentiate "w3c" until it's inserted back
>     into DOM.
>
>
> - Ryosuke

Received on Wednesday, 20 July 2011 20:18:47 UTC