On Thursday 2011-06-23 15:49 +0000, Ian Hickson wrote:
> On Thu, 23 Jun 2011, Anne van Kesteren wrote:
> >
> > > Also, the spec currently says:
> > > # If the associated media query list changes in evaluation then,
> > > # for each listener in the list of media query list listeners — in
> > > # appending order, queue a task that invokes the listener, passing
> > > # as argument the MediaQueryList object.
> > > I'm not sure if "queue a task" is quite sufficient, since we may
> > > want to run these listeners earlier if something happens first that
> > > wants to flush style data. I don't know if the spec has a good way
> > > of describing that, though. (Also, I hope the definition of "queue
> > > a task" allows timer-based refreshing where on each refresh we flush
> > > different things based on the scope of what they can change
> > > (content, style, layout).)
> >
> > I am not sure how to resolve this. Ian, do you maybe have any ideas? The
> > relevant text can be found here (for now):
> >
> > http://dev.w3.org/csswg/cssom-view/#the-mediaquerylist-interface
>
> I don't fully follow the problem here. Can you elaborate?
The problem is that the spec describes "queue a task" for an action
that causes changes in style data. The way we do this doesn't
really match the HTML5 spec's description of queue a task. This is
because the intent of these listeners is to respond to media query
changes and, in many cases, change style data. This means we want
to run them before recomputing style data so that, for example, if
they're combined with media queries that change CSS, there won't be
an intermediate inconsistent state where the things changed by the
media queries have changed but the things changed in JavaScript by
the media query listeners have not changed.
So we do things differently from "queue a task" in two ways, by
doing things the same way as we handle changes to media queries
triggering restyling.
First, if script changes the width of an iframe and then does
something that flushes style data, such as:
getComputedStyle(element,"").color
we'll run the media query listeners resulting from the width change
inside the getComputedStyle call, since that requires getting style
data up to date, which requires flushing any buffered style changes
(including media query changes).
Second, if the change isn't triggered by a flush, it gets run by our
refresh driver, which does timer-based refreshing. I previously
thought that what it does isn't described by the HTML5 spec, but on
reconsideration it *mostly* matches the description given in:
http://dev.w3.org/html5/spec/webappapis.html#queue-a-taskhttp://dev.w3.org/html5/spec/webappapis.html#task-queue
if you assume that Gecko has a rather large number of task queues
(I'd guess maybe 20-ish and increasing with each Gecko version) with
quite specific purposes (e.g., media query changes). But I don't
think it quite matches, since for some of these purpose-specific
task queues we don't run things in the order the spec describes them
being queued since, for example, we don't track which media query
list was invalidated first (we just notify all the media query lists
whose result has changed in the order the media query lists were
created, whereas I think the spec's model of "queue a task" requires
tracking the order the changes happened, which we don't do).
I think what we do is a good thing because I think this close
grouping of changes with related potential effects makes getting to
an up-to-date state more efficient than running buffered changes in
the order triggered.
Forcing us to notify media query listeners in the order that changes
happened would, on the other hand, force us to track that
information rather than coalesce it through invalidation and
revalidation (making all changes that could change media query
results less efficient), and would also force us to notify multiple
times in many cases (or notify twice rather than zero changes in the
case of a temporary state that is never rendered).
-David
--
L. David Baron http://dbaron.org/
Mozilla Corporation http://www.mozilla.com/