@@ -12,47 +12,33 @@ interface MsCryptoWindow extends Window {
12
12
msCrypto ?: Crypto ;
13
13
}
14
14
15
+ /** Many browser now support native uuid v4 generation */
16
+ interface CryptoWithRandomUUID extends Crypto {
17
+ randomUUID ?( ) : string ;
18
+ }
19
+
15
20
/**
16
21
* UUID4 generator
17
22
*
18
23
* @returns string Generated UUID4.
19
24
*/
20
25
export function uuid4 ( ) : string {
21
26
const global = getGlobalObject ( ) as MsCryptoWindow ;
22
- const crypto = global . crypto || global . msCrypto ;
27
+ const crypto = ( global . crypto || global . msCrypto ) as CryptoWithRandomUUID ;
23
28
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
+ }
35
32
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 ;
43
35
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
- }
48
36
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
49
- return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx' . replace ( / [ x y ] / 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 ( / [ 0 1 8 ] / g, c =>
52
39
// 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
+ ) ;
56
42
}
57
43
58
44
/**
0 commit comments