FlexGrid: infinite async invalidation loop (related to _getDefaultRowHeight?)

Posted by: aharper on 9 January 2019, 5:27 am EST

    • Post Options:
    • Link

    Posted 9 January 2019, 5:27 am EST - Updated 3 October 2022, 11:13 am EST

    I’m in the process of upgrading from 5.20151.48 to 5.20183.550 and I’ve come across a problem related to FlexGrid in my app.

    In the past, I occasionally have reason to call grid.invalidate. When I upgraded wijmo, I noticed that doing that would cause a grid to start “shuddering”, for lack of a better term. By that I mean it would continuously resize itself.

    For example:

    I have traced through your code and have narrowed it to the fact that

    _getDefaultRowHeight
    does not return the same value each time it is called.

    And here’s what the call stack ends up looking like:

    So that’s what I’m dealing with. I can’t think of any reason my code would be explicitly causing this (like manually changing element sizes or something).

    This is a vanilla js app, Chrome dev 73.0.3664.3, Windows 10. I haven’t been able to trigger this in other browsers.

  • Posted 9 January 2019, 10:36 am EST - Updated 3 October 2022, 11:13 am EST

    Really my assessment is that there should not be an infinite loop here. The changing default size stuff is weird but not the core problem… re-entracy is the core problem.

    Since

    refresh
    calls various
    _setDefaultSize
    functions, which themselves may call
    invalidate
    , which can schedule another async
    refresh
    , this is how you get an infinite loop and I believe that should not happen.

    In that light, I have written a proof of concept workaround; The grid’s

    refresh
    method can protect against triggering invalidations by incrementing
    this._updating
    :

  • Posted 9 January 2019, 4:31 pm EST

    Hi,

    Thanks for taking the time to investigate the issue. However, we are sorry but we are unable to replicate the issue at our end.

    Could you please have a look at the following sample and let us know if we are missing something to replicate the issue:

    https://stackblitz.com/edit/js-9xjn5r?file=index.js

    If you would like, you may also share a sample of your own replicating the issue. That would be really helpful in the investigation of the issue.

    ~Sharad

  • Posted 10 January 2019, 2:19 am EST

    Here, I’ve updated your example to simulate the observed behavior. The point here isn’t “if you hack some internal function, it breaks” but rather “flexgrid has a condition that can trigger an infinite loop”.

    https://stackblitz.com/edit/js-ue6lkx?file=index.js

  • Posted 10 January 2019, 9:37 pm EST

    We are further investigating the issue and will update you soon regarding the issue.

  • Posted 13 January 2019, 4:22 pm EST

    Hi Andrew,

    We had a discussion with the devs and they have fixed the issue in the latest nightly build 5.20183.566-rc. You may confirm the same from the following sample which uses the nightly build: https://stackblitz.com/edit/js-kvey6j?file=index.js

    Thanks for reporting the issue.

    Further, we are still unable to replicate the issue with _getDefaultRowHeight method returning a different value each time. Could you please share a sample that replicates the issue?

    P.S. Nightly builds are not tested for production and should not be used in the production build.

  • Posted 14 January 2019, 3:06 am EST

    We had a discussion with the devs and they have fixed the issue in the latest nightly build 5.20183.566-rc

    Excellent, this is great news, thank you. I agree that it appears to be fixed in the demo. Manually clicking “invalidate” or “refresh” still recomputes the size, but this is an acceptable limitation, and kind of makes sense that it would since you are explicitly asking the grid to re-render.

    Further, we are still unable to replicate the issue with _getDefaultRowHeight method returning a different value each time. Could you please share a sample that replicates the issue?

    I would like to be able to. I am still trying to figure out how to produce an isolated example. If I am able to do so I will share it.

    P.S. Nightly builds are not tested for production and should not be used in the production build.

    I understand. Is it possible to provide the RC as a plain js distribution, so I can test it in my real app (non-production testing only)?

  • Posted 14 January 2019, 4:11 pm EST

    Thanks, we will be looking forward to your sample.

    You may find the latest RC build here: http://prerelease.componentone.com/wijmo5/latest/

  • Posted 15 January 2019, 8:06 am EST - Updated 3 October 2022, 11:13 am EST

    Great, I have begun testing the RC and things seem better.

    I do not have a 100% perfect reproduction of the changing getDefaultRowHeight situation, but I do have a better example case:

    https://stackblitz.com/edit/js-yockkn

    To demonstrate, open the console tab in-app (bottom of preview screen) where the reported height will be printed via console.warn. Then use your browser’s zoom functionality to toggle between 90% - 100% - 110% and so forth. For me, this changes the row height between 28 and 29 only in Chrome. Firefox & Edge report consistently.

    (Note: this is just to trigger the repro on stackblitz. In real life, I noticed this happens reliably at 90% zoom, when the height is fractional… 28.4 according to this._eFocus.getBoundingClientRect(), and yet the offsetHeight is reported as 29. At 100% zoom this._eFocus.getBoundingClientRect() also reports 29, same as offsetHeight)

    I realize that may mean it is a quirk of chrome and not a responsibility of flexgrid. However, this behavior isn’t happening in 5.20151.48 and is happening in 5.20183.550 & 5.20183.567 (RC), so to me it still feels like a regression.

  • Posted 16 January 2019, 12:28 am EST

    We could observe that default height is returning a different value on zoom in/out but also for a fixed level of zoom, returned height is always the same(either 28 or 29) so this doesn’t seem like much of an issue.

    Also, we tested that with 5.20183.550 version, and that doesn’t throw the grid into an infinite async loop as in the original issue.

    As for getBoundingClientRect() and offsetHeight, they are the method/properties of Element class and browser is responsible for handling this and there isn’t anything Grid could do about that.

    We have updated the sample to demonstrate that using button tag:

    https://stackblitz.com/edit/js-y7nnhm?file=index.js

    Just open the console and notice the difference in offsetHeight and height returned by the getBoundingClientRect().

  • Posted 16 January 2019, 2:27 am EST

    As for getBoundingClientRect() and offsetHeight, they are the method/properties of Element class and browser is responsible for handling this and there isn’t anything Grid could do about that.

    Yes, I am definitely leaning towards saying this is an unfortunate quirk of Chrome under certain conditions, especially since it doesn’t happen in any other browser.

    Since you guys fixed the infinite loop problem, I marked that post as the answer to the question, and I’m okay to leave it at that.

    However I do wonder if FlexGrid could read the offsetHeight of the dummy cell element in _getDefaultRowHeight, and cache that internally for the life of the grid rather than re-reading it from the browser each time? That would be a nice change to isolate FlexGrid from browser nonsense like that.

    Thank you for your assistance & I am looking forward to the final release of 5.20183.566.

  • Posted 16 January 2019, 3:38 pm EST

    Hello,

    Thanks for notification and suggestion.

    ~Manish

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels