- From: Alex Russell <slightlyoff@google.com>
- Date: Thu, 30 Jun 2011 11:03:45 +0100
- To: Jonas Sicking <jonas@sicking.cc>
- Cc: Aryeh Gregor <Simetrical+w3c@gmail.com>, "Olli@pettay.fi" <Olli@pettay.fi>, Anne van Kesteren <annevk@opera.com>, Webapps WG <public-webapps@w3.org>
- Message-ID: <CANr5HFWxTcCwyazEOgMbU1xOyPrvnyMDLFS+BnLuyGZBuCo-8A@mail.gmail.com>
On Thu, Jun 30, 2011 at 2:11 AM, Jonas Sicking <jonas@sicking.cc> wrote: > On Wednesday, June 29, 2011, Aryeh Gregor <Simetrical+w3c@gmail.com> > wrote: > > On Tue, Jun 28, 2011 at 5:24 PM, Jonas Sicking <jonas@sicking.cc> wrote: > >> 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. > > > > So when exactly are these notifications going to be fired? In > > particular, I hope non-DOM Core specifications are going to have > > precise control over when they're fired. For instance, execCommand() > > will ideally want to do all its mutations at once and only then fire > > the notifications (which I'm told is how WebKit currently works). How > > will this work spec-wise? Will we have hooks to say things like > > "remove a node but don't fire the notifications yet", and then have to > > add an extra line someplace saying to fire all the notifications? > > This could be awkward in some cases. At least personally, I often say > > things like "call insertNode(foo) on the range" in the middle of a > > long algorithm, and I don't want magic happening at that point just > > because DOM Range fires notifications before returning from > > insertNode. > > Heh. It's like spec people has to deal with the same complexities as > implementors has had for years. Revenge at last!! > > Jokes aside. I think the way to do this is that the spec should > introduce the concept of a "compound mutating function". Functions > like insertBefore, removeChild and the innerHTML setter should claim > to be such functions. Any other function can also be defined to be > such a function, such as your execCommand function. > > Whenever a mutation happens, the notifications for it is put on a > list. Once the outermost compound mutation function exits, all > notifications are fired. > > > Also, even if specs have precise control, I take it the idea is > > authors won't, right? If a library wants to implement some fancy > > feature and be compatible with users of the library firing these > > notifications, they'd really want to be able to control when > > notifications are fired, just like specs want to. In practice, the > > only reason this isn't an issue with DOM mutation events is because > > they can say "don't use them", and in fact people rarely do use them, > > but that doesn't seem ideal -- it's just saying library authors > > shouldn't bother to be robust. > > The problem is that there is no good way to do this. The only API that > we could expose to JS is something like a beginBatch/endBatch pair of > functions. But what do we do if the author never calls endBatch? > > This is made especially bad by the fact that JavaScript uses > exceptions which makes it very easy to miss calling endBatch if an > exception is thrown unless the developer uses "finally", which most > don't. Since the execution turn is a DOM/host concept, we can add something like an event handler to the scope which fires before exit. Something like: window.addEventListener("turnEnd", ...); Listeners could be handed the mutation lists as members of the event object they're provided. I know Rafael has more concrete ideas here about the queues to be produced/consumed, but generally speaking, having the ability to continue to add turnEnd listeners while still in a turn gives you the power to operate on consistent state without forcing the start/end pair or specific exception handling logic. Think of it as a <script> element's "finally" block. > > Maybe this is a stupid question, since I'm not familiar at all with > > the use-cases involved, but why can't we delay firing the > > notifications until the event loop spins? If we're already delaying > > them such that there are no guarantees about what the DOM will look > > like by the time they fire, it seems like delaying them further > > shouldn't hurt the use-cases too much more. And then we don't have to > > put further effort into saying exactly when they fire for each method. > > But this is pretty obvious, so I assume there's some good reason not > > to do it. > > To enable things like widget libraries which want to keep state > up-to-date with a DOM. > > / Jonas > >
Received on Thursday, 30 June 2011 10:04:40 UTC