- From: John J. Barton <johnjbarton@johnjbarton.com>
- Date: Sun, 03 Jul 2011 10:04:25 -0700
- To: Ryosuke Niwa <rniwa@webkit.org>
- CC: public-webapps@w3.org
On 7/2/2011 12:36 PM, Ryosuke Niwa wrote: > On Sat, Jul 2, 2011 at 10:46 AM, John J. Barton > <johnjbarton@johnjbarton.com> wrote: >> 1) break on mutation. In Firebug we add DOM mutation listeners to >> implement graphical breakpoints. The replacement would work fine for >> local, element observation breakpoints like add/remove attribute. >> If my goal is to break on addition of elements with class="foo", then >> I guess I have to listen for addChildlistChanged on all elements, and >> add an additional addChildlistChanged listener for each new element? >> So in general one would implement document observation by walking >> the DOM and covering it with listeners? > I don't think we can support this use case in general. We're trying > to avoid invoking scripts synchronously and your use case requires > exactly that. Are you talking about the algorithm described by Olli and Jonas: http://www.mail-archive.com/public-webapps@w3.org/msg14008.html ? If I set a breakpoint in a listener in their algorithm I would expect to halt the browser before the algorithm completed and especially before another DOM change can occur. (An entirely separate issue is how the debugger mutates the document). The only part that is async in the Mutation Event replacement is further DOM events. >> 2) element transformation. The replacement fires "after" a mutation. >> Library or tools that want to transform the application dynamically want >> to get notification "before" the mutation. > Why do you need to get notified before the mutation? Because developers want to take actions before the mutation. Removing mutations after they are committed is a kludge we should try to avoid. > Again, this is > exactly the sort of usage that causes us headaches and what we want to > avoid because scripts can then modify DOM before we make mutations. >> A common solution then is to bracket changes: >> "beforeChange" or "onModelChanging" >> "afterChange" or "onModelChanged" >> Of course element transformation may want to prevent the current >> change and replace it. Some changes are reversible so the observed >> change can be countered with a remove (at unknown cost to performance >> and user experience). > I don't think we can address your use case here. Scripts' > intercepting and preventing mutations browser is about to make or > mutating DOM in the way browser doesn't expect is exactly what we want > to avoid. The stated properties (goals) of the replacement are (rephased): 1. No script operation in the middle of mutation, 2. Callback in order of mutation, 3. No propagation chain, Importantly the current proposal has an undesirable feature: 4. DOM modification in listeners is asynchronous. Preventing mutation in a 'before' listener still allows all of the properties as far as I know. A "two-phase-commit" like solution can have all of these properties. Copy Jonas' AttributeChanged algorithm from the page cited above. Replace "...ed" with "...ing". Add a flag 'cancelChange' initially false. Add step 8b. If cancelChange is true, abort these steps and the DOM mutation. Fire event DOMMutationCanceled The 'before' version would be more powerful. The Mutation events replacement gains its advantages from property 3 and especially 4. Whether you enter the callback algorithm before or after the mutation does not change this. In fact I think from the API point of view the 'before' version is clearer. If the developer knows that the callback is 'before' the mutation, they are naturally set up to think about the meaning of additional DOM mutations. The arguments in the callback are known to be in flight. In fact we could go one step further and eliminate the undesirable feature #4: if notifyingCallbacks is true, all DOM write operations fail. That way developers are never surprised by DOM functions that fail as in the current version. Instead developers will explicitly have to cascade modifications via separate events. This would be a much less mysterious solution. In some places Firefox already works in the mystery way and speaking from experience it is not fun to figure out why your function calls have no effect. If you have both a before and and after event and both events prevent DOM write, then the programming paradigm could be clear: before handlers cancel mutations and signal 'after' handlers to stage alternatives after handlers stage responses to mutation or alternatives to canceled mutations. jjb
Received on Sunday, 3 July 2011 17:04:47 UTC