Skip to content

Conversation

@markelog
Copy link
Member

@markelog markelog commented Mar 6, 2017

rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).

With it there was two substantial changes - one was explicitly mentioned
and the other was not.

First, if browser window was hidden aka document.hidden === true
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become 0 instead of 13 ms of a default value.

Which created possibility for circular executions in case if complete
method executed the same animation (see gh-3434 issue).

And the second one - since then there was two ways of scheduling animation:
with setInterval and requestAnimationFrame, but there was a
difference in their execution.

In case of setInterval it waited default jQuery.fx.interval value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka jQuery.fx.tick).

Whereas requestAnimationFrame first scheduled the call and executed
the step method right after that, counting the first call of
jQuery.fx.timer, tick was happening twice in one frame.

But since tests explicitly disabled rAF method i.e.
requestAnimationFrame = null and checking only setInterval logic,
since it's impossible to do it otherwise - we missed that change.

Faulty logic also was presented with cancelAnimationFrame, which couldn't
clear any timers since raf scheduler didn't define new timerId value.

Because that change was so subtle, apparently no user noticed it proving
that both cancelAnimationFrame and clearInterval code paths are redundant.

Since cancelAnimationFrame didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.

Therefore those code paths were removed.

These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses setTimeout making it more
consistent with rAF path.

Since ticks are happening globally we also don't require to listen
visibilitychange event.

It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.

No new tests were not introduced, since now setTimeout logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.

Fixes gh-3434

Summary

Checklist

Mark an [x] for completed items, if you're not sure leave them unchecked and we can assist.

Thanks! Bots and humans will be around shortly to check it out.

@jsf-clabot
Copy link

jsf-clabot commented Mar 6, 2017

CLA assistant check
All committers have signed the CLA.

@mention-bot
Copy link

@markelog, thanks for your PR! By analyzing the history of the files in this pull request, we identified @gnarf, @kswedberg and @gibson042 to be potential reviewers.


// Go to the end state if fx are off or if document is hidden
if ( jQuery.fx.off || document.hidden ) {
if ( jQuery.fx.off ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above seems out of date.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see jquerygh-1578 pull).

With it there was two substantial changes - one was explicitly mentioned
and the other was not.

First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.

Which created possibility for circular executions in case if `complete`
method executed the same animation (see jquerygh-3434 issue).

And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.

In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).

Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.

But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.

Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.

Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.

Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.

Therefore those code paths were removed.

These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.

Since ticks are happening globally we also don't require to listen
`visibilitychange` event.

It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.

No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.

Fixes jquerygh-3434
@markelog
Copy link
Member Author

markelog commented Mar 6, 2017

Updated

@markelog markelog closed this in 6d43dc4 Mar 6, 2017
@lock lock bot locked as resolved and limited conversation to collaborators Jan 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

"Too much recursion" with jQuery 3, Firefox, and animate's complete callback.

4 participants