Changeset 0c6b92a for imaps-frontend/node_modules/nanoid/async/index.cjs
Legend:
- Unmodified
- Added
- Removed
-
imaps-frontend/node_modules/nanoid/async/index.cjs
rd565449 r0c6b92a 1 1 let crypto = require('crypto') 2 2 3 let { urlAlphabet } = require('../url-alphabet/index.cjs') 4 5 // `crypto.randomFill()` is a little faster than `crypto.randomBytes()`, 6 // because it is possible to use in combination with `Buffer.allocUnsafe()`. 3 7 let random = bytes => 4 8 new Promise((resolve, reject) => { 9 // `Buffer.allocUnsafe()` is faster because it doesn’t flush the memory. 10 // Memory flushing is unnecessary since the buffer allocation itself resets 11 // the memory with the new bytes. 5 12 crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => { 6 13 if (err) { … … 11 18 }) 12 19 }) 20 13 21 let customAlphabet = (alphabet, defaultSize = 21) => { 22 // First, a bitmask is necessary to generate the ID. The bitmask makes bytes 23 // values closer to the alphabet size. The bitmask calculates the closest 24 // `2^31 - 1` number, which exceeds the alphabet size. 25 // For example, the bitmask for the alphabet size 30 is 31 (00011111). 14 26 let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1 27 // Though, the bitmask solution is not perfect since the bytes exceeding 28 // the alphabet size are refused. Therefore, to reliably generate the ID, 29 // the random bytes redundancy has to be satisfied. 30 31 // Note: every hardware random generator call is performance expensive, 32 // because the system call for entropy collection takes a lot of time. 33 // So, to avoid additional system calls, extra bytes are requested in advance. 34 35 // Next, a step determines how many random bytes to generate. 36 // The number of random bytes gets decided upon the ID size, mask, 37 // alphabet size, and magic number 1.6 (using 1.6 peaks at performance 38 // according to benchmarks). 15 39 let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length) 40 16 41 let tick = (id, size = defaultSize) => 17 42 random(step).then(bytes => { 43 // A compact alternative for `for (var i = 0; i < step; i++)`. 18 44 let i = step 19 45 while (i--) { 46 // Adding `|| ''` refuses a random byte that exceeds the alphabet size. 20 47 id += alphabet[bytes[i] & mask] || '' 21 if (id.length === size) return id48 if (id.length >= size) return id 22 49 } 23 50 return tick(id, size) 24 51 }) 52 25 53 return size => tick('', size) 26 54 } 55 27 56 let nanoid = (size = 21) => 28 random( size).then(bytes => {57 random((size |= 0)).then(bytes => { 29 58 let id = '' 59 // A compact alternative for `for (var i = 0; i < step; i++)`. 30 60 while (size--) { 61 // It is incorrect to use bytes exceeding the alphabet size. 62 // The following mask reduces the random byte in the 0-255 value 63 // range to the 0-63 value range. Therefore, adding hacks, such 64 // as empty string fallback or magic numbers, is unneccessary because 65 // the bitmask trims bytes down to the alphabet size. 31 66 id += urlAlphabet[bytes[size] & 63] 32 67 } 33 68 return id 34 69 }) 70 35 71 module.exports = { nanoid, customAlphabet, random }
Note:
See TracChangeset
for help on using the changeset viewer.