-
Notifications
You must be signed in to change notification settings - Fork 522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
the update intersection observations steps should happen after requestAnimationFrame callbacks and layout #263
Comments
@slightlyoff points out that the records delivered are out-of-date by a refresh cycle or more, which actually changes some of the arguments here, but I need to dig into that further. |
This might be interesting for @toddreifsteck to follow as well. |
I think the HTML spec is correct: IO should run after rAF, but before "update the rendering." Please correct me if I'm wrong, but "update the rendering" doesn't mean "update style and layout." As I understand it, the spec has no concept of "update style and layout". From the point of view of the spec, when DOM is modified the new style and layout is immediately available to javascript. My understanding is that "update the rendering" means "push pixels to the screen." If that's the case, then I think it's correct to run the IO algorithm before "update the rendering". |
On Tue, Nov 7, 2017 at 4:15 PM, Ryosuke Niwa ***@***.***> wrote:
Both of these feel wrong to me. I think it should run after both the
requestAnimationFrame callbacks and after the natural update of the layout,
since rAF is primarily a writing callback (so should be early, before the
natural style/layout), whereas IntersectionObserver is primarily a reading
callback (so should be late, after the natural style/layout). This ordering
makes the primary use of the callback less likely to cause extra
flush/update cycles.
But what happens if IntersectionObserver mutates DOM. Are we going to
cache the state of the document right before invoking IntersectionObserver,
and paint that version?? That is going to be extremely cumbersome to
implement.
Keep in mind that there are two separate timing considerations:
1) When does IntersectionObserver measure intersections?
2) When does IntersectionObserver deliver its notifications (i.e., run
callbacks)?
(1) Happens during frame generation. This is fine because it's a read-only
operation. If a new notification is generated, it is not delivered
immediately. Instead...
(2) When a notification is generated during (1), IntersectionObserver will
PostTask to deliver the observation. So, the callback will run during
regular js execution time, after the frame is finished.
IntersectionObserver is NOT intended to drive frame-precise layout in the
way that rAF is. It's intended to provide a notification after a frame has
already been displayed.
… —
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#263 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AF8gV-Tcf6wx2cybuLrpOoitRe9c9ZT0ks5s0PKKgaJpZM4QDpNX>
.
|
I agree the spec should be a lot clearer here, but I believe the intent is the opposite, and that "update the rendering or user interface ... to reflect the current state" does include updating style and layout. At least, that's how I've always read it. I think any serious attempt to specify the rendering loop couldn't possibly make the assumption that all DOM modifications lead to instantaneous updates to style and layout. I thought the specification defined the concept of flushing these somewhere, but I can't currently find it. |
Also, I think my statement that the IntersectionObserver steps involve reading and not writing is even stronger given that the script callbacks aren't actually run during those steps. If only the steps in the spec run, then I think it's clear that only reading happens during those steps, and therefore they should occur after style and layout updating happens. |
OK, I guess I see now that the spec's placement of the updates in the list would make sense given the interpretation of the HTML spec by @szager-chromium in #263 (comment) , whereas with my interpretation of the HTML spec in #263 (comment) I think my proposed movement of the IntersectionObserver updates after the update the rendering steps. So I think resolving this depends on whatwg/html#3246, which in turn probably depends on other things... |
This was modified a bit by #331 (which I propose changing a little further in #336). And a number of remaining issues are covered by whatwg/html#3246. But I think one pretty basic issue remains here, which is that I was suggesting that the update intersection observations steps should occur not only after |
Let's see if we can wrap this up so it's not looming over the design review. The current Event Loop spec has the following:
I don't really see how it makes sense to move IntersectionObserver any later in that list, @dbaron, WDYT? |
I think step 14 in "Update the rendering" is the really mysterious one. It updates both the "rendering or user interface" and the "browsing context". "Update the rendering or user interface" sounds like pushing pixels to me, which -- at least in chromium -- definitely happens after IntersectionObserver runs (and I think that ordering makes sense). I'm not sure what "Update the browsing context" means here, so I don't know if it should happen before or after IntersectionObserver. |
So the point I've been making (see, e.g., #263 (comment)) is that I think the "update intersection observations steps" should happen after the UA does layout. (The places where script is run might also do things that flush layout, but there's a default point where layout happens, and I think that should be before the update intersection observations steps.) |
FWIW, HTML5 spec's current model is that style & layout are always up-to-date so update the rendering means to update the rendering on the screen as suggested in #263 (comment) |
I don't think it's clear that that's the current spec model; I think it's at best unspecified. (And certainly none of the spec's editors said in whatwg/html#3246 that that's the current spec model.) |
I think it's pretty clear from the existing API that it needs to be that way. If someone modifies CSS rules then invokes offsetTop, left, etc... in the middle of resize event or scroll event handler, those events would see the updated dimensions, not some stale state from the past. In fact, this is pretty much how all browsers behave. |
I'm not disagreeing with the idea that APIs return up-to-date state. |
What I'm saying is that I've always seen that "update the rendering" statement in the spec as the start of a so-far-very-incomplete attempt to specify the flushing and batching that browsers do, and I've always interpreted it to say that that's where the default (i.e., before painting) style and layout flushes happen. |
I met this problem. IntersectionObserver always reports all observation targets. This behavior on the spec makes IntersectionObserver completely useless. |
I'm combining IntersectionObserver and requestAnimationFrame as follows: async function display() {
let start = Date.now();
let delta = 0;
let time = 0;
let resource = 100;
for (const el of update(document.getElementById('editor').value)) {
el.parentNode
? observer.observe(el)
: observer.unobserve(el);
delta = Date.now() - start;
time += delta;
resource = resource - delta > 0
? resource - delta
: void await new Promise(requestAnimationFrame) || 300;
start = Date.now();
}
return time += Date.now() - start;
} |
This CL complements the case in which the PEPC styling is changed, causing a move that but then move back instantaneously in requestAnimationFrame callback. Based on w3c/IntersectionObserver#263, it seems like if the re-layout happen in the requestAnimationFrame callback, IntersectionObserver won't send us a notification about a visibility change event, even if the layout totally hides the PEPC. We had another measure, calculating the intersection rect with the viewport using lifecycle update events, but that didn't work either because the intersection rect with the viewport stayed the same. So, we're making sure that even styling changes that affect the intersection rect will trigger the cooldown time, no matter if they happen in requestAnimationFrame or not. Fixed: 347509736, 348359040 Change-Id: I98dde8d42d696912d499b83be309630a1f4c9392 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5658195 Reviewed-by: Yi Gu <[email protected]> Commit-Queue: Thomas Nguyen <[email protected]> Reviewed-by: Mason Freed <[email protected]> Cr-Commit-Position: refs/heads/main@{#1322092}
This CL complements the case in which the PEPC styling is changed, causing a move that but then move back instantaneously in requestAnimationFrame callback. Based on w3c/IntersectionObserver#263, it seems like if the re-layout happen in the requestAnimationFrame callback, IntersectionObserver won't send us a notification about a visibility change event, even if the layout totally hides the PEPC. We had another measure, calculating the intersection rect with the viewport using lifecycle update events, but that didn't work either because the intersection rect with the viewport stayed the same. So, we're making sure that even styling changes that affect the intersection rect will trigger the cooldown time, no matter if they happen in requestAnimationFrame or not. (cherry picked from commit b45d131) Fixed: 347509736, 348359040 Change-Id: I98dde8d42d696912d499b83be309630a1f4c9392 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5658195 Reviewed-by: Yi Gu <[email protected]> Commit-Queue: Thomas Nguyen <[email protected]> Reviewed-by: Mason Freed <[email protected]> Cr-Original-Commit-Position: refs/heads/main@{#1322092} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5674519 Bot-Commit: Rubber Stamper <[email protected]> Reviewed-by: Kouhei Ueno <[email protected]> Cr-Commit-Position: refs/branch-heads/6533@{#1345} Cr-Branched-From: 7e0b87e-refs/heads/main@{#1313161}
The section on patching the event loop spec says that the insertion of the new step for processing IntersectionObserver should happen before the step for requestAnimationFrame callbacks.
This differs from the change which has already been edited into the HTML spec, which says it should happen after the requestAnimationFrame callbacks, but before the update of the style and layout.
Both of these feel wrong to me. I think it should run after both the requestAnimationFrame callbacks and after the natural update of the layout, since rAF is primarily a writing callback (so should be early, before the natural style/layout), whereas IntersectionObserver is primarily a reading callback (so should be late, after the natural style/layout). This ordering makes the primary use of the callback less likely to cause extra flush/update cycles.
Changing this probably requires a bit of investigation of both current behavior, and perhaps of whether what's described in the HTML spec actually reflects reality (which last time I was involved in a detailed discussion of it, it seemed not to be the case).
I got here from w3ctag/design-reviews#197.
The text was updated successfully, but these errors were encountered: