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
cancelAnimationFrame should also cancel pending callbacks #4359
Comments
To summarise: function one() {
console.log('one');
cancelAnimationFrame(twoHandle);
}
function two() {
console.log('two');
}
const oneHandle = requestAnimationFrame(one);
const twoHandle = requestAnimationFrame(two); Should "two" be logged? Demo. Chrome, Edge, Safari say no. Firefox and the spec say yes. In the spec This feels unintuitive for me. For instance: let animOneHandle;
let animTwoHandle;
function animOne() {
// …
animOneHandle = requestAnimationFrame(animOne);
}
function animTwo() {
// …
animTwoHandle = requestAnimationFrame(animTwo);
}
function startAnims() {
animOneHandle = requestAnimationFrame(animOne);
animTwoHandle = requestAnimationFrame(animTwo);
}
function stopAnims() {
cancelAnimationFrame(animOneHandle);
cancelAnimationFrame(animTwoHandle);
} With this pattern, I also find Flackr's comparison to event listeners compelling. In terms of updating the spec, instead of cloning the map, it should clone the keys. Then, it can get each callback from the original map, skipping it if it's missing. Items are removed from the original map after each callback. |
I asked Twitter, and I'm really surprised at how close the vote is https://twitter.com/jaffathecake/status/1095662236230733824. However, it seems like there's a lot of confusion around how animation callbacks are queued. A lot of folks think the order is random, or they happen in parallel somehow. Oh, and a few folks seem to think it's a scoping issue. |
I think the first comment here is a compelling argument for changing the spec. Originally I didn't have |
It sounds like we should change this (great find!) but I'd love to hear from Firefox folks before changing the spec out from under them. Let's hope @birtles can chime in soon. |
Another case for the proposed behavior is consistency with setTimeout, which has the same semantics in this demo. I believe both a and b's time has come up when a is called, but b is still canceled by a. |
Each |
FWIW |
I agree that the first comment is particularly compelling. I'm ok with this change. |
@wanderview how does that allow for it? What you're suggesting would mean a |
You always get a microtask checkpoint when the stack empties, so if a browser were running multiple timeout callbacks in a single task it wouldn't change promise behaviour. But yeah the spec doesn't seem to allow this grouping. |
In that case (executing two in a single task vs each in their own task not being observable) @wanderview is correct as they do share a task source and the user agent is allowed to prioritize that task source over others. |
FWIW, I tried to removing this batching to improve interactivity and ran into web compat issues. See this post for more details. (Sorry for the thread hijack regarding this.) |
Sounds like we have agreement. Is anyone willing to work on a spec change and tests PR? I wasn't able to gather the exact model for the spec change proposed; I thought maybe it was just not doing the clone, but Chrome at least seems to have two callback collections ( |
Yes, we don't want to drop the cloning, otherwise calls to
It looks like getting the keys of an ordered map already creates a new ordered set so if we want to avoid having two callback collections like in Chrome, I guess we could do something like:
Does that seem right? |
Looks good to me. |
@birtles suggestion looks good to me. On a side note, the existing blink implementation uses a cancelled flag (similar to Event.cancelled) and tests that flag before calling each callback. This avoids duplicating the collection. |
Thanks for the feedback. I'll work on a PR and WPT for this. |
Calling cancelAnimationFrame from within a requestAnimationFrame callback should cancel any requestAnimationFrame callbacks that are pending for the current frame. The currently specified behavior does not permit that, however, since it clones the set of callbacks before iterating over them. This patch updates the algorithm to run animation frame callbacks such that it is possible to cancel a pending animation frame callback. This also brings the specified behavior into line with its implementation in Blink, EdgeHTML, and WebKit. This closes whatwg#4359.
Calling cancelAnimationFrame() from within a requestAnimationFrame() callback should cancel any animation frame callbacks that are pending for the current frame. The currently specified behavior does not permit that, however, since it clones the set of callbacks before iterating over them. This patch updates the algorithm to run animation frame callbacks such that it is possible to cancel a pending animation frame callback. This also brings the specified behavior into line with its implementation in Blink, EdgeHTML, and WebKit. Tests: web-platform-tests/wpt#15455. Closes #4359.
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 --HG-- extra : rebase_source : ff3c69a82f0ef61f562edd1610017a17c8f26276
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 --HG-- extra : moz-landing-system : lando
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 --HG-- extra : rebase_source : 696dde4f205f2d12a67a4e9649d629a0f4e7de27
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: 65c438efa01fc8478aa3d1d69bab22f758038b62
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: da0f977287bdc5fc72623f644953d9da00fbd38c
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: 65c438efa01fc8478aa3d1d69bab22f758038b62
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: da0f977287bdc5fc72623f644953d9da00fbd38c
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: 65c438efa01fc8478aa3d1d69bab22f758038b62
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: da0f977287bdc5fc72623f644953d9da00fbd38c
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: 70dd07f15ae1548c63c80d85470246f98d8d58a3
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: 70dd07f15ae1548c63c80d85470246f98d8d58a3
…e callback scheduled in the same frame; r=farre As per the following change to the HTML spec: whatwg/html@86b05f8 when running a requestAnimationFrame callback it should be possible to cancel another requestAnimationFrame callback scheduled to run in the same frame by using cancelAnimationFrame. See issue: whatwg/html#4359 Differential Revision: https://phabricator.services.mozilla.com/D20974 UltraBlame original commit: 70dd07f15ae1548c63c80d85470246f98d8d58a3
requestAnimationFrame callbacks cannot reliably cancel other requestAnimationFrame callbacks.
Calls to requestAnimationFrame will not add callbacks to the current callback loop, but instead adds them to the next callback loop. This allows callbacks to re-register themselves if they need to continue operating, which is a very common pattern for developers.
cancelAnimationFrame follows the same pattern, and as a result requestAnimationFrame callbacks have somewhat unpredictable results if they make calls to cancelAnimationFrame.
For example, assume a page has called requestAnimationFrame with rAF-callback1 and rAF-callback2, each of which loops by calling rAF on themselves at the end of the callback.
Recommend that we amend the spec so that calls to cancelAnimationFrame also cancel pending callbacks within the current callback loop.
Many browsers (including Chromium, Edge, Safari) already follow this implementation. Previous discussion on this issue can be found in mozilla and chromium
The text was updated successfully, but these errors were encountered: