@@ -348,6 +348,11 @@ let uuidData;
348348let uuidNotBuffered ;
349349let uuidBatch = 0 ;
350350
351+ let uuidDataV7 ;
352+ let uuidBatchV7 = 0 ;
353+ let v7LastTimestamp = - 1 ;
354+ let v7Counter = 0 ;
355+
351356let hexBytesCache ;
352357function getHexBytes ( ) {
353358 if ( hexBytesCache === undefined ) {
@@ -415,35 +420,55 @@ function randomUUID(options) {
415420 return disableEntropyCache ? getUnbufferedUUID ( ) : getBufferedUUID ( ) ;
416421}
417422
418- function writeTimestamp ( buf , offset ) {
423+ function advanceV7 ( seed ) {
419424 const now = DateNow ( ) ;
420- const msb = now / ( 2 ** 32 ) ;
425+ if ( now > v7LastTimestamp ) {
426+ v7LastTimestamp = now ;
427+ v7Counter = seed & 0xFFF ;
428+ } else {
429+ v7Counter ++ ;
430+ if ( v7Counter > 0xFFF ) {
431+ v7LastTimestamp ++ ;
432+ v7Counter = 0 ;
433+ }
434+ }
435+ }
436+
437+ function writeTimestampAndCounterV7 ( buf , offset ) {
438+ const ts = v7LastTimestamp ;
439+ const msb = ts / ( 2 ** 32 ) ;
421440 buf [ offset ] = msb >>> 8 ;
422441 buf [ offset + 1 ] = msb ;
423- buf [ offset + 2 ] = now >>> 24 ;
424- buf [ offset + 3 ] = now >>> 16 ;
425- buf [ offset + 4 ] = now >>> 8 ;
426- buf [ offset + 5 ] = now ;
442+ buf [ offset + 2 ] = ts >>> 24 ;
443+ buf [ offset + 3 ] = ts >>> 16 ;
444+ buf [ offset + 4 ] = ts >>> 8 ;
445+ buf [ offset + 5 ] = ts ;
446+ buf [ offset + 6 ] = ( v7Counter >>> 8 ) & 0x0f ;
447+ buf [ offset + 7 ] = v7Counter & 0xff ;
427448}
428449
429450function getBufferedUUIDv7 ( ) {
430- uuidData ??= secureBuffer ( 16 * kBatchSize ) ;
431- if ( uuidData === undefined )
451+ uuidDataV7 ??= secureBuffer ( 16 * kBatchSize ) ;
452+ if ( uuidDataV7 === undefined )
432453 throw new ERR_OPERATION_FAILED ( 'Out of memory' ) ;
433454
434- if ( uuidBatch === 0 ) randomFillSync ( uuidData ) ;
435- uuidBatch = ( uuidBatch + 1 ) % kBatchSize ;
436- const offset = uuidBatch * 16 ;
437- writeTimestamp ( uuidData , offset ) ;
438- return serializeUUID ( uuidData , 0x70 , 0x80 , offset ) ;
455+ if ( uuidBatchV7 === 0 ) randomFillSync ( uuidDataV7 ) ;
456+ uuidBatchV7 = ( uuidBatchV7 + 1 ) % kBatchSize ;
457+ const offset = uuidBatchV7 * 16 ;
458+ const seed = ( ( uuidDataV7 [ offset + 6 ] & 0x0f ) << 8 ) | uuidDataV7 [ offset + 7 ] ;
459+ advanceV7 ( seed ) ;
460+ writeTimestampAndCounterV7 ( uuidDataV7 , offset ) ;
461+ return serializeUUID ( uuidDataV7 , 0x70 , 0x80 , offset ) ;
439462}
440463
441464function getUnbufferedUUIDv7 ( ) {
442465 uuidNotBuffered ??= secureBuffer ( 16 ) ;
443466 if ( uuidNotBuffered === undefined )
444467 throw new ERR_OPERATION_FAILED ( 'Out of memory' ) ;
445468 randomFillSync ( uuidNotBuffered , 6 ) ;
446- writeTimestamp ( uuidNotBuffered , 0 ) ;
469+ const seed = ( ( uuidNotBuffered [ 6 ] & 0x0f ) << 8 ) | uuidNotBuffered [ 7 ] ;
470+ advanceV7 ( seed ) ;
471+ writeTimestampAndCounterV7 ( uuidNotBuffered , 0 ) ;
447472 return serializeUUID ( uuidNotBuffered , 0x70 , 0x80 ) ;
448473}
449474
0 commit comments