Skip to content

Commit 7b9025f

Browse files
committed
Better uuid generation?
1 parent d2800c1 commit 7b9025f

File tree

1 file changed

+15
-29
lines changed

1 file changed

+15
-29
lines changed

packages/utils/src/misc.ts

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,33 @@ interface MsCryptoWindow extends Window {
1212
msCrypto?: Crypto;
1313
}
1414

15+
/** Many browser now support native uuid v4 generation */
16+
interface CryptoWithRandomUUID extends Crypto {
17+
randomUUID?(): string;
18+
}
19+
1520
/**
1621
* UUID4 generator
1722
*
1823
* @returns string Generated UUID4.
1924
*/
2025
export function uuid4(): string {
2126
const global = getGlobalObject() as MsCryptoWindow;
22-
const crypto = global.crypto || global.msCrypto;
27+
const crypto = (global.crypto || global.msCrypto) as CryptoWithRandomUUID;
2328

24-
if (!(crypto === void 0) && crypto.getRandomValues) {
25-
// Use window.crypto API if available
26-
const arr = new Uint16Array(8);
27-
crypto.getRandomValues(arr);
28-
29-
// set 4 in byte 7
30-
// eslint-disable-next-line no-bitwise
31-
arr[3] = (arr[3] & 0xfff) | 0x4000;
32-
// set 2 most significant bits of byte 9 to '10'
33-
// eslint-disable-next-line no-bitwise
34-
arr[4] = (arr[4] & 0x3fff) | 0x8000;
29+
if (crypto && crypto.randomUUID) {
30+
return crypto.randomUUID().replace(/-/g, '');
31+
}
3532

36-
const pad = (num: number): string => {
37-
let v = num.toString(16);
38-
while (v.length < 4) {
39-
v = `0${v}`;
40-
}
41-
return v;
42-
};
33+
const getRandomByte =
34+
crypto && crypto.getRandomValues ? () => crypto.getRandomValues(new Uint8Array(1))[0] : () => Math.random() * 16;
4335

44-
return (
45-
pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) + pad(arr[5]) + pad(arr[6]) + pad(arr[7])
46-
);
47-
}
4836
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
49-
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, c => {
50-
// eslint-disable-next-line no-bitwise
51-
const r = (Math.random() * 16) | 0;
37+
// Concatenating the following numbers as strings results in '10000000100040008000100000000000'
38+
return (([1e7] as unknown as string) + 1e3 + 4e3 + 8e3 + 1e11).replace(/[018]/g, c =>
5239
// eslint-disable-next-line no-bitwise
53-
const v = c === 'x' ? r : (r & 0x3) | 0x8;
54-
return v.toString(16);
55-
});
40+
((c as unknown as number) ^ ((getRandomByte() & 15) >> ((c as unknown as number) / 4))).toString(16),
41+
);
5642
}
5743

5844
/**

0 commit comments

Comments
 (0)