|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 | 3 | const {
|
| 4 | + Array, |
4 | 5 | BigInt,
|
5 | 6 | FunctionPrototypeBind,
|
6 | 7 | FunctionPrototypeCall,
|
7 | 8 | MathMin,
|
8 | 9 | NumberIsNaN,
|
9 | 10 | NumberIsSafeInteger,
|
| 11 | + NumberPrototypeToString, |
| 12 | + StringPrototypePadStart, |
10 | 13 | } = primordials;
|
11 | 14 |
|
12 | 15 | const {
|
@@ -291,104 +294,79 @@ function getRandomValues(data) {
|
291 | 294 | // Implements an RFC 4122 version 4 random UUID.
|
292 | 295 | // To improve performance, random data is generated in batches
|
293 | 296 | // large enough to cover kBatchSize UUID's at a time. The uuidData
|
294 |
| -// and uuid buffers are reused. Each call to randomUUID() consumes |
295 |
| -// 16 bytes from the buffer. |
296 |
| - |
297 |
| -const kHexDigits = [ |
298 |
| - 48, 49, 50, 51, 52, 53, 54, 55, |
299 |
| - 56, 57, 97, 98, 99, 100, 101, 102, |
300 |
| -]; |
| 297 | +// buffer is reused. Each call to randomUUID() consumes 16 bytes |
| 298 | +// from the buffer. |
301 | 299 |
|
302 | 300 | const kBatchSize = 128;
|
303 | 301 | let uuidData;
|
304 | 302 | let uuidNotBuffered;
|
305 |
| -let uuid; |
306 | 303 | let uuidBatch = 0;
|
307 | 304 |
|
308 |
| -function getBufferedUUID() { |
309 |
| - if (uuidData === undefined) { |
310 |
| - uuidData = secureBuffer(16 * kBatchSize); |
311 |
| - if (uuidData === undefined) |
312 |
| - throw new ERR_OPERATION_FAILED('Out of memory'); |
| 305 | +let hexBytesCache; |
| 306 | +function getHexBytes() { |
| 307 | + if (hexBytesCache === undefined) { |
| 308 | + hexBytesCache = new Array(256); |
| 309 | + for (let i = 0; i < hexBytesCache.length; i++) { |
| 310 | + const hex = NumberPrototypeToString(i, 16); |
| 311 | + hexBytesCache[i] = StringPrototypePadStart(hex, 2, '0'); |
| 312 | + } |
313 | 313 | }
|
| 314 | + return hexBytesCache; |
| 315 | +} |
| 316 | + |
| 317 | +function serializeUUID(buf, offset = 0) { |
| 318 | + const kHexBytes = getHexBytes(); |
| 319 | + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| 320 | + return kHexBytes[buf[offset]] + |
| 321 | + kHexBytes[buf[offset + 1]] + |
| 322 | + kHexBytes[buf[offset + 2]] + |
| 323 | + kHexBytes[buf[offset + 3]] + |
| 324 | + '-' + |
| 325 | + kHexBytes[buf[offset + 4]] + |
| 326 | + kHexBytes[buf[offset + 5]] + |
| 327 | + '-' + |
| 328 | + kHexBytes[(buf[offset + 6] & 0x0f) | 0x40] + |
| 329 | + kHexBytes[buf[offset + 7]] + |
| 330 | + '-' + |
| 331 | + kHexBytes[(buf[offset + 8] & 0x3f) | 0x80] + |
| 332 | + kHexBytes[buf[offset + 9]] + |
| 333 | + '-' + |
| 334 | + kHexBytes[buf[offset + 10]] + |
| 335 | + kHexBytes[buf[offset + 11]] + |
| 336 | + kHexBytes[buf[offset + 12]] + |
| 337 | + kHexBytes[buf[offset + 13]] + |
| 338 | + kHexBytes[buf[offset + 14]] + |
| 339 | + kHexBytes[buf[offset + 15]]; |
| 340 | +} |
| 341 | + |
| 342 | +function getBufferedUUID() { |
| 343 | + uuidData ??= secureBuffer(16 * kBatchSize); |
| 344 | + if (uuidData === undefined) |
| 345 | + throw new ERR_OPERATION_FAILED('Out of memory'); |
314 | 346 |
|
315 | 347 | if (uuidBatch === 0) randomFillSync(uuidData);
|
316 | 348 | uuidBatch = (uuidBatch + 1) % kBatchSize;
|
317 |
| - return uuidData.slice(uuidBatch * 16, (uuidBatch * 16) + 16); |
| 349 | + return serializeUUID(uuidData, uuidBatch * 16); |
| 350 | +} |
| 351 | + |
| 352 | +function getUnbufferedUUID() { |
| 353 | + uuidNotBuffered ??= secureBuffer(16); |
| 354 | + if (uuidNotBuffered === undefined) |
| 355 | + throw new ERR_OPERATION_FAILED('Out of memory'); |
| 356 | + randomFillSync(uuidNotBuffered); |
| 357 | + return serializeUUID(uuidNotBuffered); |
318 | 358 | }
|
319 | 359 |
|
320 | 360 | function randomUUID(options) {
|
321 | 361 | if (options !== undefined)
|
322 | 362 | validateObject(options, 'options');
|
323 | 363 | const {
|
324 | 364 | disableEntropyCache = false,
|
325 |
| - } = { ...options }; |
| 365 | + } = options || {}; |
326 | 366 |
|
327 | 367 | validateBoolean(disableEntropyCache, 'options.disableEntropyCache');
|
328 | 368 |
|
329 |
| - if (uuid === undefined) { |
330 |
| - uuid = Buffer.alloc(36, '-'); |
331 |
| - uuid[14] = 52; // '4', identifies the UUID version |
332 |
| - } |
333 |
| - |
334 |
| - let uuidBuf; |
335 |
| - if (!disableEntropyCache) { |
336 |
| - uuidBuf = getBufferedUUID(); |
337 |
| - } else { |
338 |
| - uuidBuf = uuidNotBuffered; |
339 |
| - if (uuidBuf === undefined) |
340 |
| - uuidBuf = uuidNotBuffered = secureBuffer(16); |
341 |
| - if (uuidBuf === undefined) |
342 |
| - throw new ERR_OPERATION_FAILED('Out of memory'); |
343 |
| - randomFillSync(uuidBuf); |
344 |
| - } |
345 |
| - |
346 |
| - // Variant byte: 10xxxxxx (variant 1) |
347 |
| - uuidBuf[8] = (uuidBuf[8] & 0x3f) | 0x80; |
348 |
| - |
349 |
| - // This function is structured the way it is for performance. |
350 |
| - // The uuid buffer stores the serialization of the random |
351 |
| - // bytes from uuidData. |
352 |
| - // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
353 |
| - let n = 0; |
354 |
| - uuid[0] = kHexDigits[uuidBuf[n] >> 4]; |
355 |
| - uuid[1] = kHexDigits[uuidBuf[n++] & 0xf]; |
356 |
| - uuid[2] = kHexDigits[uuidBuf[n] >> 4]; |
357 |
| - uuid[3] = kHexDigits[uuidBuf[n++] & 0xf]; |
358 |
| - uuid[4] = kHexDigits[uuidBuf[n] >> 4]; |
359 |
| - uuid[5] = kHexDigits[uuidBuf[n++] & 0xf]; |
360 |
| - uuid[6] = kHexDigits[uuidBuf[n] >> 4]; |
361 |
| - uuid[7] = kHexDigits[uuidBuf[n++] & 0xf]; |
362 |
| - // - |
363 |
| - uuid[9] = kHexDigits[uuidBuf[n] >> 4]; |
364 |
| - uuid[10] = kHexDigits[uuidBuf[n++] & 0xf]; |
365 |
| - uuid[11] = kHexDigits[uuidBuf[n] >> 4]; |
366 |
| - uuid[12] = kHexDigits[uuidBuf[n++] & 0xf]; |
367 |
| - // - |
368 |
| - // 4, uuid[14] is set already... |
369 |
| - uuid[15] = kHexDigits[uuidBuf[n++] & 0xf]; |
370 |
| - uuid[16] = kHexDigits[uuidBuf[n] >> 4]; |
371 |
| - uuid[17] = kHexDigits[uuidBuf[n++] & 0xf]; |
372 |
| - // - |
373 |
| - uuid[19] = kHexDigits[uuidBuf[n] >> 4]; |
374 |
| - uuid[20] = kHexDigits[uuidBuf[n++] & 0xf]; |
375 |
| - uuid[21] = kHexDigits[uuidBuf[n] >> 4]; |
376 |
| - uuid[22] = kHexDigits[uuidBuf[n++] & 0xf]; |
377 |
| - // - |
378 |
| - uuid[24] = kHexDigits[uuidBuf[n] >> 4]; |
379 |
| - uuid[25] = kHexDigits[uuidBuf[n++] & 0xf]; |
380 |
| - uuid[26] = kHexDigits[uuidBuf[n] >> 4]; |
381 |
| - uuid[27] = kHexDigits[uuidBuf[n++] & 0xf]; |
382 |
| - uuid[28] = kHexDigits[uuidBuf[n] >> 4]; |
383 |
| - uuid[29] = kHexDigits[uuidBuf[n++] & 0xf]; |
384 |
| - uuid[30] = kHexDigits[uuidBuf[n] >> 4]; |
385 |
| - uuid[31] = kHexDigits[uuidBuf[n++] & 0xf]; |
386 |
| - uuid[32] = kHexDigits[uuidBuf[n] >> 4]; |
387 |
| - uuid[33] = kHexDigits[uuidBuf[n++] & 0xf]; |
388 |
| - uuid[34] = kHexDigits[uuidBuf[n] >> 4]; |
389 |
| - uuid[35] = kHexDigits[uuidBuf[n] & 0xf]; |
390 |
| - |
391 |
| - return uuid.latin1Slice(0, 36); |
| 369 | + return disableEntropyCache ? getUnbufferedUUID() : getBufferedUUID(); |
392 | 370 | }
|
393 | 371 |
|
394 | 372 | function createRandomPrimeJob(type, size, options) {
|
|
0 commit comments