- From: Jatinder Mann <jmann@microsoft.com>
- Date: Wed, 14 Dec 2011 20:56:45 +0000
- To: James Robinson <jamesr@google.com>, Boris Zbarsky <bzbarsky@mit.edu>
- CC: "public-web-perf@w3.org" <public-web-perf@w3.org>
- Message-ID: <EE4C13A1D11CFA49A58343DE361B0B041369FB18@TK5EX14MBXC252.redmond.corp.microsoft.>
>>>In practice what WebKit does is prior to painting it iterates through >>>documents in DOM tree order and processes all the callbacks for that >>>document. >> >>OK, so this would correspond, in Gecko's case, to processing all the callbacks for one document before moving to the next one in the list (instead of concatenating all the lists then processing callbacks). >> >>I think it only makes a difference if a document changes its 'fully active' state, which should prevent any tasks for that document from happening and thus any callbacks for that document from firing. I haven't >>experimented with this scenario much - I guess you could navigate a document with pending callbacks synchronously to about:blank from a callback on an earlier document? >> >> >>What does IE do here? >> >That's a great question. Could someone from the IE team chime in here? If I understand correctly, IE is similar to Gecko in regards to the order. We maintain a list of windows (1:1 with documents), and in each window, a list of callbacks. When we decide to fire the callbacks, we notify each window to fire its callbacks, i.e. we'll finish one window's callbacks before moving to the next window. We don't maintain any particular order of the documents (windows), or the callbacks within a window. It's first come first serve. From: James Robinson [mailto:jamesr@google.com] Sent: Tuesday, December 06, 2011 10:57 PM To: Boris Zbarsky Cc: public-web-perf@w3.org Subject: Re: [RequestAnimationFrame] Processing model does not permit handling animation callbacks for multiple documents at once On Tue, Dec 6, 2011 at 10:04 PM, Boris Zbarsky <bzbarsky@mit.edu<mailto:bzbarsky@mit.edu>> wrote: On 12/7/11 12:56 AM, James Robinson wrote: On Tue, Dec 6, 2011 at 8:18 PM, Boris Zbarsky <bzbarsky@mit.edu<mailto:bzbarsky@mit.edu> <mailto:bzbarsky@mit.edu<mailto:bzbarsky@mit.edu>>> wrote: In at least Gecko's implementation, all documents in a given tab are treated in an atomic manner for purposes of animation callbacks, in the sense that all the callbacks from all those lists are placed into a single list, then all the document-level lists are cleared, and then the callbacks are processed. In what order are callbacks from different documents processed? In Gecko? When the first entry is added to a document's list of animation callbacks, that document is itself added to a list of documents that have animation callbacks. Then when it comes time to call the callbacks the lists of animation callbacks for those documents are just concatenated, with the ordering on lists matching the order of the "list of documents that have animation callbacks". How is the concatenation done? I would think the easiest thing to implement would be to do something like: for each document in "list of documents that have animation callbacks" append all callbacks within document to global list which would mean that all entries for a given document would be adjacent in the final, flattened list. This agrees with what the spec currently says and it nearly agrees with what WebKit does today, except that WebKit assembles this list by documents in document order, not by document in registration of initial callbacks order. This would be an observable different to some scripts so I think we should specify a behavior. So in other words, there is no particular attempt to impose any sort of ordering other than whatever was simple to implement. I didn't put a lot of effort into this in WebKit either, to be honest. Et voila. Since the UA controls exactly when tasks are entered into the "animation task source" task queue, and the UA can decide when to service that task queue relative to other task queues like timers, etc, UAs actually have a lot of freedom here. So what happens in practice when one of the callbacks does a sync XHR or puts up an alert? Both in terms of what implementations actually do and in terms of what the spec currently requires, if anything? So here it mattes what exactly the synchronous action is. For window.alert(), confirm(), prompt() and print() the spec says that the "pause" algorithm is invoked: http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#pause which invokes the same "If necessary, update the rendering..." language. So a conforming UA could either choose to go ahead and paint at that point or not. I believe the WebKit implementation today will not paint in that instance except for window.print() which is currently implemented in different ways in different WebKit embedders and probably has bugs in both. Synchronous XHR simply runs all of the steps of the loading sequence as part of the callback, so it just looks like a really long-running script. In particular there's no opportunity spec-wise to process tasks or to update the rendering before the sync XHR returns. I believe that WebKit matches the spec behavior here and just sits there not painting until the XHR send() algorithm returns, at least in Chromium. window.showModalDialog() is full of crazy because it spins the event loop inside of the task execution. It also marks all browsing contexts except for the showModalDialog's document's context as background, which has some implications for task scheduling as I understand it. I believe a confirming UA could decide to stop servicing the "animation task source" task queue completely while a showModalDialog() up, but it will typically have to paint while the dialog is up so some intermediate state is necessary. I haven't put too much thought into this particular case in the spec or in the WebKit implementation because it's just to full of stupid. I'd be happy saying that calling showModalDialog() during a rAF callback throws an exception and having that be the end of it. The HTML spec for showModalDialog lists "running animations" as an example of something that should continue to occur in backgrounded browsing contexts but I personally think that's a bad idea. Implementation wise, we generally have bugs with showModalDialog() across the board and don't really care all that much relative to other things. If we *were* to spend any time on showModalDialog() I think it should be designing and evangelizing its replacement. That's all of the synchronous actions I'm aware of that need consideration. Let me know if I've missed any. Based on these I don't think any spec text is needed, unless we want to add something about showModalDialog()'s behavior. In practice what WebKit does is prior to painting it iterates through documents in DOM tree order and processes all the callbacks for that document. OK, so this would correspond, in Gecko's case, to processing all the callbacks for one document before moving to the next one in the list (instead of concatenating all the lists then processing callbacks). I think it only makes a difference if a document changes its 'fully active' state, which should prevent any tasks for that document from happening and thus any callbacks for that document from firing. I haven't experimented with this scenario much - I guess you could navigate a document with pending callbacks synchronously to about:blank from a callback on an earlier document? What does IE do here? That's a great question. Could someone from the IE team chime in here? One consequence of this model is that all callbacks for a given document must be processed as an atomic block - they cannot be interspersed with callbacks from a different document. This is the case in Gecko too. This behavior somwhat falls out of the WebKit implementation details "for free" so I didn't put a ton of thought into making this clear in the spec text, although I believe it is there. Yeah, I believe the spec pretty clearly requires atomic processing for a single document (modulo the "blocking call" weirdness, of course). Do you think this is good or bad? I see a few possibilities here: 1.) Instead of queuing a task for each document, queue a task that runs over all documents and does the following: a) Create an empty list of <handle, callback> tuples called L b) For each document in DOM order i) Copy all entries in that document's animation frame request list into L ii) Clear that document's animation frame request list c) For each entry in L i) If that entry's callback's cancelled flag is not set, call the sample operation of that entry's callback and swallow any exception 2.) Same as (1) except that in step (b) iterate over documents in the order that the first animation callback was registered in that document instead of in DOM order 3.) Callbacks are run in the order they are registered, regardless of which document they are registered in. I believe that (1) is what I've attempted to implement in WebKit and (2) is what you are describing in Gecko. (3) has some advantage of consistency, but I dislike it as it intermingles callbacks from different documents and potentially different domains. I can't convince myself of any great reason to favor 1 or 2 over each other, and I suspect it won't be meaningful to too many authors, so let's just pick one. - James -Boris
Received on Wednesday, 14 December 2011 21:15:09 UTC