@@ -11,6 +11,7 @@ const {
1111 BigIntPrototypeToString,
1212 DataView,
1313 DataViewPrototypeGetUint8,
14+ DateNow,
1415 FunctionPrototypeBind,
1516 FunctionPrototypeCall,
1617 MathMin,
@@ -359,7 +360,7 @@ function getHexBytes() {
359360 return hexBytesCache ;
360361}
361362
362- function serializeUUID ( buf , offset = 0 ) {
363+ function serializeUUID ( buf , version , variant , offset = 0 ) {
363364 const kHexBytes = getHexBytes ( ) ;
364365 // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
365366 return kHexBytes [ buf [ offset ] ] +
@@ -370,10 +371,10 @@ function serializeUUID(buf, offset = 0) {
370371 kHexBytes [ buf [ offset + 4 ] ] +
371372 kHexBytes [ buf [ offset + 5 ] ] +
372373 '-' +
373- kHexBytes [ ( buf [ offset + 6 ] & 0x0f ) | 0x40 ] +
374+ kHexBytes [ ( buf [ offset + 6 ] & 0x0f ) | version ] +
374375 kHexBytes [ buf [ offset + 7 ] ] +
375376 '-' +
376- kHexBytes [ ( buf [ offset + 8 ] & 0x3f ) | 0x80 ] +
377+ kHexBytes [ ( buf [ offset + 8 ] & 0x3f ) | variant ] +
377378 kHexBytes [ buf [ offset + 9 ] ] +
378379 '-' +
379380 kHexBytes [ buf [ offset + 10 ] ] +
@@ -391,15 +392,15 @@ function getBufferedUUID() {
391392
392393 if ( uuidBatch === 0 ) randomFillSync ( uuidData ) ;
393394 uuidBatch = ( uuidBatch + 1 ) % kBatchSize ;
394- return serializeUUID ( uuidData , uuidBatch * 16 ) ;
395+ return serializeUUID ( uuidData , 0x40 , 0x80 , uuidBatch * 16 ) ;
395396}
396397
397398function getUnbufferedUUID ( ) {
398399 uuidNotBuffered ??= secureBuffer ( 16 ) ;
399400 if ( uuidNotBuffered === undefined )
400401 throw new ERR_OPERATION_FAILED ( 'Out of memory' ) ;
401402 randomFillSync ( uuidNotBuffered ) ;
402- return serializeUUID ( uuidNotBuffered ) ;
403+ return serializeUUID ( uuidNotBuffered , 0x40 , 0x80 ) ;
403404}
404405
405406function randomUUID ( options ) {
@@ -414,6 +415,50 @@ function randomUUID(options) {
414415 return disableEntropyCache ? getUnbufferedUUID ( ) : getBufferedUUID ( ) ;
415416}
416417
418+ function writeTimestamp ( buf , offset ) {
419+ const now = DateNow ( ) ;
420+ const msb = now / ( 2 ** 32 ) ;
421+ buf [ offset ] = msb >>> 8 ;
422+ 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 ;
427+ }
428+
429+ function getBufferedUUIDv7 ( ) {
430+ uuidData ??= secureBuffer ( 16 * kBatchSize ) ;
431+ if ( uuidData === undefined )
432+ throw new ERR_OPERATION_FAILED ( 'Out of memory' ) ;
433+
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 ) ;
439+ }
440+
441+ function getUnbufferedUUIDv7 ( ) {
442+ uuidNotBuffered ??= secureBuffer ( 16 ) ;
443+ if ( uuidNotBuffered === undefined )
444+ throw new ERR_OPERATION_FAILED ( 'Out of memory' ) ;
445+ randomFillSync ( uuidNotBuffered , 6 ) ;
446+ writeTimestamp ( uuidNotBuffered , 0 ) ;
447+ return serializeUUID ( uuidNotBuffered , 0x70 , 0x80 ) ;
448+ }
449+
450+ function randomUUIDv7 ( options ) {
451+ if ( options !== undefined )
452+ validateObject ( options , 'options' ) ;
453+ const {
454+ disableEntropyCache = false ,
455+ } = options || kEmptyObject ;
456+
457+ validateBoolean ( disableEntropyCache , 'options.disableEntropyCache' ) ;
458+
459+ return disableEntropyCache ? getUnbufferedUUIDv7 ( ) : getBufferedUUIDv7 ( ) ;
460+ }
461+
417462function createRandomPrimeJob ( type , size , options ) {
418463 validateObject ( options , 'options' ) ;
419464
@@ -611,6 +656,7 @@ module.exports = {
611656 randomInt,
612657 getRandomValues,
613658 randomUUID,
659+ randomUUIDv7,
614660 generatePrime,
615661 generatePrimeSync,
616662} ;
0 commit comments