fix(web): use ES2022-safe array copies in client code - #1707
Conversation
Array.prototype.toSorted and toReversed are ES2023 (Chrome/Edge 110, Safari 16.4, Firefox 115). tsconfig targets ES2017, which downlevels syntax but never adds built-ins, and lib includes esnext so TypeScript does not warn. Five client-side call sites therefore throw on older browsers -- one of them inside a useMemo, so it takes the notifications dropdown down during render. Two of the five sorted an array held in a Map, so they copy before sorting rather than switching to an in-place sort. Also apply biome's formatting to app/(home)/free/[model_slug]/page.tsx. That error is already on dev, and biome-check-web runs always_run with pass_filenames: false, so it fails Frontend Quality for every open PR.
|
@Yigtwxx is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Checks came back: Frontend Quality and Quality Gate are green here, which is worth noting because they are currently red on every other open PR — including backend-only ones that touch no TypeScript. That is the Vercel is the usual fork Journey is red here too, and for the same reason it is red everywhere: the stack never comes up. |
The dashboard throws
.filter(...).toSorted is not a functionon Chrome 109 and any other browser below the ES2023 line.Array.prototype.toSortedandtoReversedshipped in Chrome/Edge 110, Safari 16.4 and Firefox 115, and nothing in the build adds them. This replaces the five client-side uses with ES2022-safe equivalents.Description
Five call sites in
surfsense_web:components/layout/ui/sidebar/NotificationsDropdown.tsx:127.filter(...).toSorted(cmp).filter(...).sort(cmp)hooks/use-comments-sync.ts:122(group.replies.get(raw.id) ?? []).toSorted(cmp)[...(group.replies.get(raw.id) ?? [])].sort(cmp)components/free-chat/free-model-selector.tsx:51models.toSorted(cmp)[...models].sort(cmp)lib/chat/activity-journal.ts:92[...activities].toSorted(cmp)[...activities].sort(cmp)lib/chat/message-utils.ts:209olderIdxs.toReversed()[...olderIdxs].reverse()Where the receiver is already a fresh array — the
filterresult inNotificationsDropdown, the spread inactivity-journal— sorting in place is safe and no extra copy is added. Everywhere else the receiver is state or a value held in aMap, so the copy is not optional; see below.Symptom
Two auto-filed bug reports carry the same diagnostics block:
#1645and#1644are the same defect, four minutes apart, from the same reporter. The stack points atNotificationsDropdown, where the call is inside auseMemo— so it throws during render and takes the notifications dropdown down with it, rather than failing quietly.Root cause
surfsense_web/tsconfig.jsonsets"target": "ES2017". That downlevels syntax only; it never adds built-in methods, and there is no polyfill in the app. TypeScript does not warn either, because"lib"includesesnext, which declarestoSorted/toReversedas available. There is nobrowserslistkey inpackage.jsonand no.browserslistrc, so the support floor is implicit and nothing enforces it.Two of these were also mutation bugs
hooks/use-comments-sync.ts:122sortsgroup.replies.get(raw.id), an array stored in aMapthat the same pass reads again. A naive.toSorted→.sortswap there would reorder the stored array in place.lib/chat/message-utils.ts:209reversesmergeInto.get(i), also a stored array.Both now copy before sorting, so the shared arrays are left alone. That is a small behavioural improvement, not just a compatibility fix.
What is deliberately not changed
app/(home)/changelog/page.tsx:36also callstoSorted, and it is left alone: that page renders on the server, where Node 20+ has the method. Including it would have widened the diff without fixing a user-visible failure. The same reasoning applies tofeatures/chat-messages/timeline/grouping.ts:168, which usesfindLastIndex— also ES2023, but supported since Chrome 97, so it is not part of this failure.One unrelated formatting fix, and why it is here
app/(home)/free/[model_slug]/page.tsxcarries aformaterror that is already ondev:The
biome-check-webhook in.pre-commit-config.yamlsetsalways_run: truewithpass_filenames: false, so it checks the wholesurfsense_webtree regardless of what a PR touched — the workflow's--from-ref/--to-refnarrowing does not reach it. That one error therefore failsFrontend Qualityfor every open PR, including backend-only ones. The fix is the unmodified output ofbiome check --writeon that single file: a two-line reflow, no logic.Motivation and Context
FIX #1645
#1644is the same defect from the same reporter and is also resolved by this change. Since contributions merge intodevrather than the default branch, GitHub will not close either automatically.Screenshots
Not applicable — no visual change. Sort order and rendering are identical.
API Changes
Change Type
Testing Performed
Tested locally
Manual/QA verification
biome check --diagnostic-level=error .insurfsense_web, pinned 2.4.6:Checked 1097 files. No fixes applied.— zero errors, wheredevreports one. Measured on an LF checkout, since a Windows working tree reports a format error on every file otherwise.tsc --noEmit: 19 errors, the same 19 as on a cleandevcheckout, none of them in the six files this PR touches. I did not try to fix them; they are unrelated.Confirmed no
toSorted/toReversedremains outside the server-rendered changelog page.What does not change
Array.prototype.sortis stable in every engine this targets, so orderings are identical.[...arr].sort(cmp)andarr.toSorted(cmp)both yieldT[].tsconfig.json. See below.Remaining risk
Small, but worth naming: this fixes the five sites that exist today and adds no guard against the sixth. The obvious guard would be narrowing
"lib"fromesnexttoes2022intsconfig.json, which turns any ES2023 built-in into a compile error. I did not include it, because it would also flagfindLastIndex, which is fine on the browsers this bug is about, and the resulting rewrite would have nothing to do with the report. Abrowserslistentry documents intent but does not enforce it for built-ins. Happy to follow up with whichever you prefer.Checklist
High-level PR Summary
This PR fixes browser compatibility issues by replacing ES2023 methods (
toSortedandtoReversed) with ES2022-safe equivalents in client-side code. The changes prevent "is not a function" errors on Chrome 109 and other browsers that don't support ES2023 array methods. The fix converts five call sites to use array spread withsort()andreverse()instead, which also resolves two mutation bugs where shared arrays were being modified in place. An unrelated formatting fix inpage.tsxis included to unblock CI checks.⏱️ Estimated Review Time: 5-15 minutes
💡 Review Order Suggestion
surfsense_web/app/(home)/free/[model_slug]/page.tsxsurfsense_web/components/layout/ui/sidebar/NotificationsDropdown.tsxsurfsense_web/components/free-chat/free-model-selector.tsxsurfsense_web/lib/chat/activity-journal.tssurfsense_web/hooks/use-comments-sync.tssurfsense_web/lib/chat/message-utils.tssurfsense_web/app/(home)/free/[model_slug]/page.tsx