Improve performance and avoid DOM update issues with CollectionView sorting.
Review Request #11666 — Created June 21, 2021 and submitted
RB.CollectionViewmade an attempt to rebuild the list of views
whenever there was a
sortevent. There were some performance and DOM
update issues that came from this, and during the investigation, it
turned out that sort handling was often run unnecessarily.
collection.fetch(), by default, would prepare a list of models, add
them to the collection, sort them silently (avoiding any event
triggers), and then eventually trigger some events (including
By the time
sortevent, the models were
actually in the correct order, yet it would go through and rebuild the
views and re-add to the DOM.
This would have been harmless, but it actually broke
children. On initial render, an
<option selected>would normally
appear selected in the browser, but the sort would then happen
immediately after that render, and browsers wouldn't preserve the sort
order (tested with Chrome and Firefox).
This manifested as a bug in the New Review Request page's Branches
drop-down, where the last item would be selected despite the default
branch being marked as
selected. It wasn't an issue in Review Board 3,
due to Backbone 1.0 only triggering this
sortevent if we were
actually intentionally sorting (the version we use in Review Board 4,
1.3.3, along with the latest version, 4.0, trigger it under more
conditions, including when populating an empty collection for the first
time without specifying
reset: trueas an option).
To avoid this, we're now comparing the order of stored views with the
new order. If it differs, we re-build the order of views and re-add to
the DOM. Otherwise, we skip the entire operation.
That not only fixes the
<option selected>issue, but it also improves
There's one more performance improvement in this change, which is the
manner by which views are sorted and removed. We were looping through
the list of views, trying to find one with the proper model, and while
there was logic to reduce the search space, a more efficient approach is
just to keep a map of model IDs to views and use that for all lookup.
Combined, this change improves any views using
avoids browser quirks.
All unit tests passed.
Tested the New Review Request page with a Mercurial repository. Saw that
the correct default branch was selected in the Branches list, instead of
the last branch in the list. Verified this on Chrome and Firefox.
Should we also do delete this._viewsByModelID[item.cid]?
Removal of a model now clears the corresponding view from the lookup map.
Revision 2 (+218 -70)
Checks run (2 succeeded)