w3c/IntersectionObserver

Clarify IntersectionObserver behavior when an element is observed the first time

dvoytenko opened this issue · 8 comments

The main source of the confusion is whether the IntersectionObserver's callback must always be called when an element is observed for the first time. See for instance this Firefox issue. Per comments in this issue, it's treated as WAI.

Per https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API:

 The Intersection Observer API allows you to configure a callback that is called:
...
 (2) and whenever the observer is asked to watch a target for the very first time

So that seems clear enough that the callback should be called. However, https://www.w3.org/TR/intersection-observer/ is not so clear. For the observe method it states:

  1. (Set)..., a previousThresholdIndex property set to -1, and a previousIsIntersecting property set to false.
    ...
  2. Schedule an iteration of the event loop in the root's browsing context.

The spec doesn't specify queuing tasks for initial observation.

From the nature of observer pattern, it'd seem that the first measurement should always be returned.

For context: since the introduction of IntersectionObserver, it has been often used as a way to do a non-blocking initial measurement. The ResizeObserver can also now be used, but its cross-browser support is much less robust at this time. It'd be great if these APIs for consistent with each other and the initial measurement was always returned on the first observation.

This issue was previously discussed in:

#165

previousThresholdIndex gets an initial value of -1 for the express purpose of forcing a notification at the earliest opportunity, because the Run the Update Intersection Observations Steps procedure in the spec can never produce a thresholdIndex less than zero (see step 2.2.9).

Just a comment about the Firefox issue: the IntersectionObserver steps are only guaranteed to run during the "Update the rendering" part of the HTML event loop. If that never occurs, then it is correct behavior for IntersectionObserver never to send a notification. Calling observe() will, as the spec says, cause an iteration of the event loop to be scheduled; but if the event loop never gets to run the iteration (or if it runs the event loop but never gets a chance to run "update the rendering"), then a notification will never be generated or delivered.

but if the event loop never gets to run the iteration (or if it runs the event loop but never gets a chance to run "update the rendering"), then a notification will never be generated or delivered.

What situations are you referring to that would lead to this?

Chromium browsers also force an observation (including "update the rendering") even for backgrounded frames when observe() is called.

but if the event loop never gets to run the iteration (or if it runs the event loop but never gets a chance to run "update the rendering"), then a notification will never be generated or delivered.

What situations are you referring to that would lead to this?

Chromium browsers also force an observation (including "update the rendering") even for backgrounded frames when observe() is called.

The Firefox issue is about "late-executing scripts". I can imagine observe() being called just as a document is being unloaded or a window being closed, so that "update the rendering" never runs again.

The Firefox issue is about "late-executing scripts".

The repro steps, however, make it clear that it's not about a situation with windows being closed, it's about failing to trigger "update the rendering" after calling observe(). I agree that a window may be closed first.

Correct, repro steps are not about a window being closed. And that was the concerning part. We appear to observe some percent of such failures on our test infrastructure on Firefox, but never on other browsers.

Sounds like this is a Firefox issue.

There may be some language that could be added to the HTML spec to clarify this; for example, in the Processing Model spec, step 11.4 mentions skipping processing for documents that have no visual changes nor any requestAnimationFrame callbacks scheduled. It might make sense to tighten those conditions to also require that the document will not cause any new IntersectionObserver notifications to be created.

Adding that spec language would be fine, but I doubt that the Firefox issue is the result of them implementing the spec to the letter; I suspect it was just an oversight.