- From: Jonas Sicking <jonas@sicking.cc>
- Date: Tue, 28 Jun 2011 14:24:49 -0700
- To: Olli@pettay.fi
- Cc: Anne van Kesteren <annevk@opera.com>, Webapps WG <public-webapps@w3.org>
On Tue, Jun 28, 2011 at 5:43 AM, Olli Pettay <Olli.Pettay@helsinki.fi> wrote: > On 06/28/2011 03:36 PM, Anne van Kesteren wrote: >> >> On Tue, 28 Jun 2011 13:30:09 +0200, Olli Pettay >> <Olli.Pettay@helsinki.fi> wrote: >>> >>> There is now a patch for Gecko to implement a variant of this >>> proposal https://bugzilla.mozilla.org/show_bug.cgi?id=641821 >>> >>> The patch adds the following methods (with moz prefix) to Node >>> (I assume Attr will not extend Node in the near future) >>> void addAttributeChangedListener(in MutationCallback aCallback); >>> void addChildlistChangedListener(in MutationCallback aCallback); >>> void addTextDataChangedListener(in MutationCallback aCallback); >>> void removeAttributeChangedListener(in MutationCallback aCallback); >>> void removeChildlistChangedListener(in MutationCallback aCallback); >>> void removeTextDataChangedListener(in MutationCallback aCallback); >>> >>> [Callback, NoInterfaceObject] >>> interface MutationCallback >>> { >>> // aNode is the node to which the listener was added. >>> // aChangeTarget is the node in which the mutation was made. >>> void handleMutation(in Node aNode, in Node aChangeTarget); >>> }; >>> >>> The changes to Jonas' proposal are merging non-Subtree methods to >>> xxxSubtreexxx methods and adding aChangeTarget to the callback. >>> >>> The basic idea behind the API is to have something simple, yet powerful. >>> Script libraries could add all sorts of filtering above the low level >>> API. >>> >>> Comments? >> >> I have a question. Given >> >> removeNode(...) >> teehee() >> >> will teehee() be executed after any relevant listeners have been invoked >> or before? > > teehee() would be executed after relevant callbacks have been invoked. > > >> That is, are listeners run while the removeNode() has not yet >> returned? And if so, is the problem with the original mutation events >> avoided because the node being removed is not exposed to the listeners? > > The problem with the original mutation events is avoided because the > callbacks are called at "safe" time. Right before the method returns, > but after all the mutations are done. So the DOM is at stable state when > callbacks runs. Two examples where the mutation events are run at bad times: 1. DOMNodeRemoved is fired *before* a mutation takes place. This one's tricky since you have to figure out all the removals you're going to do, then fire events for them, and then hope that the mutations actually still makes sense. A particularly good example of this is Node.normalize. After you've fired DOMNodeRemoved for all textnodes that should be removed, the DOM might look totally different and an entirely new set of nodes should be removed. 2. The spec is vague on when other mutation events should fire in cases when a operation does several modifications. For example, when inserting a DocumentFragment with multiple children, do you fire a DOMNodeInserted after each child has been inserted? Or after they're all inserted? The problem with firing them after each individual one is inserted is what do you do if the mutation event handler moves the newly inserted nodes back into the fragment? Or completely rearranges the DOM such that there is no clear point where to insert the next child? This new proposal solves both these by making all the modifications first, then firing all the events. Hence the implementation can separate implementing the mutating function from the code that sends out notifications. Conceptually, you simply queue all notifications in a queue as you're making modifications to the DOM, then right before returning from the function you insert a call like "flushAllPendingNotifications()". This way you don't have to care at all about what happens when those notifications fire. / Jonas
Received on Tuesday, 28 June 2011 21:25:47 UTC