The Node.js® Website

fix: select arm64 by default (#6439)

* Fixed Issue #6364

* Fix arm64 select by default v2

* Fix arm64 select by default v2

* Update util/__tests__/getUserBitnessByArchitecture.test.mjs

Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com>
Signed-off-by: Rahil Shah <45811662+rhlshah@users.noreply.github.com>

* Update util/getUserBitnessByArchitecture.ts

Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com>
Signed-off-by: Rahil Shah <45811662+rhlshah@users.noreply.github.com>

* Update getUserBitnessByArchitecture.ts

Signed-off-by: Claudio W <cwunder@gnome.org>

* chore: fixed lint

---------

Signed-off-by: Rahil Shah <45811662+rhlshah@users.noreply.github.com>
Signed-off-by: Claudio W <cwunder@gnome.org>
Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com>
Co-authored-by: Claudio W <cwunder@gnome.org>

authored by Rahil Shah Brian Muenzenmeyer Claudio W and committed by GitHub 503d2653 a8efa11a

Changed files
+74 -15
components
Downloads
hooks
react-client
util
+9 -2
components/Downloads/Release/BitnessDropdown.tsx
··· 9 9 import { useDetectOS } from '@/hooks/react-client'; 10 10 import { ReleaseContext } from '@/providers/releaseProvider'; 11 11 import { bitnessItems, formatDropdownItems } from '@/util/downloadUtils'; 12 + import { getUserBitnessByArchitecture } from '@/util/getUserBitnessByArchitecture'; 12 13 13 14 const parseNumericBitness = (bitness: string) => 14 15 /^\d+$/.test(bitness) ? Number(bitness) : bitness; 15 16 16 17 const BitnessDropdown: FC = () => { 17 - const { bitness: userBitness } = useDetectOS(); 18 + const { bitness: userBitness, architecture: userArchitecture } = 19 + useDetectOS(); 18 20 const { bitness, os, release, setBitness } = useContext(ReleaseContext); 19 21 const t = useTranslations(); 20 22 21 23 // we also reset the bitness when the OS changes, because different OSs have 22 24 // different bitnesses available 23 - useEffect(() => setBitness(userBitness), [setBitness, userBitness]); 25 + 26 + useEffect(() => { 27 + setBitness(getUserBitnessByArchitecture(userArchitecture, userBitness)); 28 + // we shouldn't update the effect on setter state change 29 + // eslint-disable-next-line react-hooks/exhaustive-deps 30 + }, [userArchitecture, userBitness]); 24 31 25 32 // @TODO: We should have a proper utility that gives 26 33 // disabled OSs, Platforms, based on specific criteria
+3
hooks/react-client/__tests__/useDetectOS.test.mjs
··· 35 35 expect(result.current).toStrictEqual({ 36 36 os: 'WIN', 37 37 bitness: 64, 38 + architecture: '', 38 39 }); 39 40 }); 40 41 }); ··· 53 54 expect(result.current).toStrictEqual({ 54 55 os: 'WIN', 55 56 bitness: 64, 57 + architecture: '', 56 58 }); 57 59 }); 58 60 }); ··· 71 73 expect(result.current).toStrictEqual({ 72 74 os: 'MAC', 73 75 bitness: 86, 76 + architecture: '', 74 77 }); 75 78 }); 76 79 });
+20 -13
hooks/react-client/useDetectOS.ts
··· 4 4 5 5 import type { UserOS } from '@/types/userOS'; 6 6 import { detectOS } from '@/util/detectOS'; 7 + import { getArchitecture } from '@/util/getArchitecture'; 7 8 import { getBitness } from '@/util/getBitness'; 8 9 9 10 type UserOSState = { 10 11 os: UserOS; 11 12 bitness: number; 13 + architecture: string; 12 14 }; 13 15 14 16 const useDetectOS = () => { 15 17 const [userOSState, setUserOSState] = useState<UserOSState>({ 16 18 os: 'OTHER', 17 19 bitness: 86, 20 + architecture: 'ARM', 18 21 }); 19 22 20 23 useEffect(() => { 21 - getBitness().then(bitness => { 22 - const userAgent = navigator?.userAgent; 23 - 24 - setUserOSState({ 25 - os: detectOS(), 26 - bitness: 27 - bitness === '64' || 28 - userAgent?.includes('WOW64') || 29 - userAgent?.includes('Win64') 30 - ? 64 31 - : 86, 32 - }); 33 - }); 24 + Promise.all([getBitness(), getArchitecture()]).then( 25 + ([bitness, architecture]) => { 26 + const userAgent: string | undefined = 27 + (typeof navigator === 'object' && navigator.userAgent) || ''; 28 + const defaultBitness: number = 86; // Default bitness if unable to determine 29 + setUserOSState({ 30 + os: detectOS(), 31 + bitness: 32 + bitness === '64' || 33 + userAgent?.includes('WOW64') || 34 + userAgent?.includes('Win64') 35 + ? 64 36 + : defaultBitness, 37 + architecture: architecture ? architecture : '', 38 + }); 39 + } 40 + ); 34 41 }, []); 35 42 36 43 return userOSState;
+13
util/__tests__/getUserBitnessByArchitecture.test.mjs
··· 1 + import { getUserBitnessByArchitecture } from '@/util/getUserBitnessByArchitecture'; 2 + 3 + describe('getUserBitnessByArchitecture', () => { 4 + it('should return "arm64" for arm architecture and 64-bit', () => { 5 + const result = getUserBitnessByArchitecture('arm', 64); 6 + expect(result).toBe('arm64'); 7 + }); 8 + 9 + it('should return the user bitness for other architectures', () => { 10 + const result = getUserBitnessByArchitecture('x86', 32); 11 + expect(result).toBe(32); 12 + }); 13 + });
+19
util/getArchitecture.ts
··· 1 + /// <reference types="user-agent-data-types" /> 2 + 3 + export const getArchitecture = async () => { 4 + // This is necessary to detect Windows 11 on Edge. 5 + // [MDN](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData/getHighEntropyValues) 6 + // [MSFT](https://learn.microsoft.com/en-us/microsoft-edge/web-platform/how-to-detect-win11) 7 + if (typeof navigator?.userAgentData?.getHighEntropyValues === 'function') { 8 + const entropyValues = navigator.userAgentData.getHighEntropyValues([ 9 + 'architecture', 10 + ]); 11 + 12 + // Apparently in some cases this is not a Promise, we can Promisify it. 13 + return Promise.resolve(entropyValues) 14 + .then(({ architecture }) => architecture) 15 + .catch(() => undefined); 16 + } 17 + 18 + return undefined; 19 + };
+10
util/getUserBitnessByArchitecture.ts
··· 1 + export const getUserBitnessByArchitecture = ( 2 + userArchitecture: string, 3 + userBitness: number 4 + ) => { 5 + if (userArchitecture === 'arm' && userBitness === 64) { 6 + return 'arm64'; 7 + } 8 + 9 + return userBitness; 10 + };