Repository navigation
Polyfill Array.prototype.at so web-vitals' CLS tracker stops crashing in Chrome 85–91 - #305
Merged
Merged
Conversation
web-vitals' INP and CLS trackers call Array.prototype.at in their PerformanceObserver callbacks. In engines without it (Chrome < 92, Safari < 15.4) every layout shift threw "this.o.at is not a function", an uncaught error our own monitoring then reported as a crash (Trello XzwkYl7L, a Chrome 79 visitor on /). LCP is unaffected and is still collected there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Review feedback: skipping INP and CLS where .at is missing drops vitals from the older, slower devices most likely to push a page's p75 into "poor". A spec-matching, non-enumerable polyfill, installed before web-vitals starts, fixes the crash and keeps that data. (The reported "Chrome 79" can't run the bundle, which uses optional chaining: the affected engines are Chrome 80-91, Safari < 15.4, Firefox < 90, or the user agent was spoofed.) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Review round 2: install the polyfill when arrayAt.ts is evaluated and import it first in monitoringSetup.ts, so it's in place before any later import's module body runs, not only before web-vitals' callbacks. Use unary + (ToNumber), which throws on a BigInt as the native at() does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Review round 3: INP needs interactionId (Chrome 96+), which every engine with it pairs with a native .at, so the polyfill restores CLS only; and the bundle's logical assignment needs Chrome 85+. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Review round 5: production relies on the install-on-import call, which every test bypassed by calling installArrayAt() itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Review round 6: a language polyfill belongs at the app entry, not inside monitoring setup; and check the installed descriptor matches native rather than only that for…in skips it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5
Deploying funder-finder with
|
| Latest commit: |
f0060d6
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://ddf77125.funder-finder.pages.dev |
| Branch Preview URL: | https://claude-compassionate-newton.funder-finder.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the crash reported on Trello card XzwkYl7L:
TypeError: this.o.at is not a functionon/.Cause
The minified stack (
index-BshaS873.js:2:3839; our local build has the same hash) points toweb-vitals'LayoutShiftManager, which callsthis._sessionEntries.at(-1)in its PerformanceObserver callback.Array.prototype.atonly exists in Chrome 92+, Safari 15.4+ and Firefox 90+. So in older engines every layout shift threw, and our crash monitoring reported that uncaught error.The reported "Chrome 79" can't actually run the bundle, which uses
??=(Chrome 85+). The affected engines are Chrome 85–91, or a browser that spoofs its user agent.Fix
src/lib/arrayAt.ts: a small polyfill that matches the spec. It isn't enumerable, has the native property flags, and uses ToNumber on the index (so it throws on BigInt, as native does). It installs itself on import.src/main.tsx: imports it first.A polyfill keeps CLS from these older, slower devices, which skipping the metric would have lost, so they still count towards each page's p75.
web-vitals' INP tracker also calls
.at, butonINPneedsinteractionId(Chrome 96+), so in practice only CLS was affected. Nothing else in the bundle uses newer built-ins (Object.hasOwn,findLast,structuredClone, …).Testing
npm testpasses (74 tests). The newtests/array-at.test.mjschecks:at()across indexes, including holes, NaN, ±Infinity, fractions, strings and BigInt;npm run lint,tsc -bandvite buildpass.Array.prototype.atdeleted, the local build served asfundermatch.orgso monitoring is on, and three layout shifts set off:main:this.o.at is not a functionthree times, and no CLS sent.I ran several local code-review rounds and applied their findings. Points considered and declined as having no real caller:
Symbol.unscopables;.at;@vitejs/plugin-legacy/ core-js), which would change the build setup and the supported-browser policy beyond this fix.🤖 Generated with Claude Code
https://claude.ai/code/session_015VQKSm8kLY3Q2qRtXGY1X5