question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Race condition in upward scrolling compensation system could fire scrollBy when user is scrolling

See original GitHub issue

Describe the bug Upward scrolling compensation might kick in while the user is still scrolling. This is noticeable on lower-end devices and when the components might take time to mount.

Reproduction Reproduction is tricky. I made a demo with variable-height elements to ensure there is a decent amount of compensation and added some synchronous calculations to the render function to slow the components down. Originally noticed in Firefox on Windows while testing lower-end devices, confirmed in a VM. https://healthy-thunder-sunflower.glitch.me (using glitch.me because I needed to compare it to a github fork). Depending on how fast your computer is, you might want to increase the value in the component to slow things more though can’t guarantee it would help. Almost impossible to repro on macOS Firefox. Definitely not as obvious as in the video, no matter the slowdown.

Looking at the code, deviation pipe filters out new values that have isScrolling === true. The question is why does isScrolling become false during scrolling.

Briefly looking at stateFlagsSystem, scroll end is detected by reporting false in a debounced handler. I suppose task queue could be full and let the debounced false value go through before a new scroll event is processed. In other words, before a new scrollTop value triggers the true branch (and resets the false, I guess, not sure how exactly merge works here).

Another finding: if the filter predicate passes, the invocation is throttled, which schedules a new task using setTimeout. Following the same logic of tasks scheduling in the event loop, the actual value of isScrolling could be different by the time the subscription callback is fired.

Attempted to make an illustration of how event loop might look. virtuoso_diagram_1

To Reproduce Steps to reproduce the behavior:

  1. Go to the provided demo
  2. Scroll up
  3. Observe viewport jumping down against the scroll sometimes

It should be more noticeable if you try to accumulate more deviation by scrolling non-stop. If you open devtools on the side, you could see that margin-top would reset to 0 sometimes during scrolling. The amount of difference with each element could change depending on the first item, so sometimes refreshing could give a more janky collection.

<video src=https://user-images.githubusercontent.com/4955642/157632286-b8de2cee-29e1-4322-b2dc-4f351375a327.mp4></video>

Recorded on FF 98, Windows 11 ARM VM. Used touchpad for scrolling.

Btw applying a fix that only checks for isScrolling before publish, without correcting for available scrollTop, exposes accumulated margin-top if you happen to reach the top.

Expected behavior Compensation should be firing only after user truly stopped scrolling

Desktop (please complete the following information): Firefox, tested on v97+ on Windows.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
petyosicommented, Mar 10, 2022

Agreed on the isScrolling - if that’s the root cause, that should be fixed. I will try to reproduce it. I will double-check on that, hopefully over the weekend.

0reactions
petyosicommented, Mar 12, 2022

Breaking the problem further and based on your diagram, I tried to cause debounce leak due to heavy queue. Here’s a simplified test. Maybe I am missing something here, but it looks like the extra ops don’t affect it. But I might be too gentle.

Ultimately, if the rendered components can cause sufficient timer delay, isScrolling is not the only flag that is going to get miscalculated. There are several other timers in the codebase. Here are a few ideas that can help:

  • Can you create a reliably failing e2e test? Ideally, without heavy components, as it gets quite subjective.
  • Can you try to ease the rendering through the scroll seek placeholders? They are meant to solve exactly that.
Read more comments on GitHub >

github_iconTop Results From Across the Web

ScrollEnd: race condition on compositor if new scroll starts ...
This bug relates to an unshipped feature, the scrollend DOM event. ... The code above fires the necessary DOM event based on scroll...
Read more >
Scroll event firing too many times. I only want it to fire a ...
This will fire the first scroll event immediately and then get you a scroll event approximately once every 100ms while the scrollbar is...
Read more >
Untitled
Trial and error theory, Fnog urban dictionary, 21 questions mp3 50 cent, ... Three line air brake system, Fcpx multicam sync, Loading on...
Read more >
Untitled
#Louwman Suomen vanhimmat kivet, Hkust math 3121, Kartinki na slovicka, Vype estick starter kit review, Metal oxide definition, How to use seak roof...
Read more >
cPU - River Thames Conditions - Environment Agency - GOV.UK
Use of internet in research methodology, Catacomba di palermo, Project64k crashes when loading rom, Poste italiane polignano a mare, Name 3 big rivers...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found