From 54c5961ab13fbef46e030b711ac819f8ac32847a Mon Sep 17 00:00:00 2001 From: gwer Date: Tue, 28 Jan 2020 19:46:57 +0300 Subject: [PATCH 1/6] Reduce size by url generation and getRandomValues in loop --- async/index.browser.js | 29 +++++++++-------------------- index.browser.js | 28 ++++++++-------------------- package.json | 4 ++-- 3 files changed, 19 insertions(+), 42 deletions(-) diff --git a/async/index.browser.js b/async/index.browser.js index 68362643..abb1d016 100644 --- a/async/index.browser.js +++ b/async/index.browser.js @@ -7,36 +7,25 @@ var crypto = self.crypto || self.msCrypto // Despite the fact the source code is quite long, its entropy // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i -var url = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +var i = 36 +var url = '-_' - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, - - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +while (i--) { + url += i.toString(36) + i > 9 && (url += i.toString(36).toUpperCase()) +} module.exports = function (size) { - size = size || 21 var id = '' - var bytes = crypto.getRandomValues(new Uint8Array(size)) + size = size || 21 + // Compact alternative for `for (var i = 0; i < size; i++)` while (size--) { // We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. // This mask reduces random byte 0-255 to 0-63 values. // There is no need in `|| ''` and `* 1.6` hacks in here, // because bitmask trim bytes exact to alphabet size. - id += url[bytes[size] & 63] + id += url[crypto.getRandomValues(new Uint8Array(1)) & 63] } return Promise.resolve(id) } diff --git a/index.browser.js b/index.browser.js index ea4e395f..3a02e3cb 100644 --- a/index.browser.js +++ b/index.browser.js @@ -24,36 +24,24 @@ var crypto = self.crypto || self.msCrypto // Despite the fact the source code is quite long, its entropy // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i -var url = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +var i = 36 +var url = '-_' - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, - - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +while (i--) { + url += i.toString(36) + i > 9 && (url += i.toString(36).toUpperCase()) +} module.exports = function (size) { - size = size || 21 var id = '' - var bytes = crypto.getRandomValues(new Uint8Array(size)) + size = size || 21 // Compact alternative for `for (var i = 0; i < size; i++)` while (size--) { // We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. // This mask reduces random byte 0-255 to 0-63 values. // There is no need in `|| ''` and `* 1.6` hacks in here, // because bitmask trim bytes exact to alphabet size. - id += url[bytes[size] & 63] + id += url[crypto.getRandomValues(new Uint8Array(1)) & 63] } return id } diff --git a/package.json b/package.json index c90d26e9..7d1cb509 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "size-limit": [ { "path": "index.js", - "limit": "127 B" + "limit": "116 B" }, { "path": "generate.js", @@ -86,7 +86,7 @@ }, { "path": "async/index.js", - "limit": "139 B" + "limit": "126 B" }, { "path": "async/generate.js", From bd49e7ec2f6c319fbc98ce513d240d0207eab9ea Mon Sep 17 00:00:00 2001 From: gwer Date: Tue, 28 Jan 2020 20:46:23 +0300 Subject: [PATCH 2/6] Update non-secure index.js --- non-secure/index.js | 25 +++++++------------------ package.json | 2 +- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/non-secure/index.js b/non-secure/index.js index 08c4e319..1771a8e7 100644 --- a/non-secure/index.js +++ b/non-secure/index.js @@ -2,24 +2,13 @@ // Despite the fact the source code is quite long, its entropy // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i -var url = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +var i = 36 +var url = '-_' - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, - - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +while (i--) { + url += i.toString(36) + i > 9 && (url += i.toString(36).toUpperCase()) +} /** * Generate URL-friendly unique ID. This method use non-secure predictable @@ -37,8 +26,8 @@ var url = '_-' + String.fromCharCode( * @function */ module.exports = function (size) { - size = size || 21 var id = '' + size = size || 21 // Compact alternative for `for (var i = 0; i < size; i++)` while (size--) { // `| 0` is compact and faster alternative for `Math.floor()` diff --git a/package.json b/package.json index 7d1cb509..ea88b75b 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ }, { "path": "non-secure/index.js", - "limit": "89 B" + "limit": "84 B" }, { "path": "non-secure/generate.js", From dbe155509b79d9645c668e70a357a428918a89e5 Mon Sep 17 00:00:00 2001 From: gwer Date: Tue, 28 Jan 2020 20:54:47 +0300 Subject: [PATCH 3/6] Update url.js --- url.js | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/url.js b/url.js index 5be82d1c..6a2a0dcd 100644 --- a/url.js +++ b/url.js @@ -3,8 +3,6 @@ // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i - /** * URL safe symbols. * @@ -15,20 +13,10 @@ var i * const url = require('nanoid/url') * generate(url, 10) //=> "Uakgb_J5m9" */ -module.exports = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, - - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +module.exports = '-_' +var i = 36 +while (i--) { + module.exports += i.toString(36) + i > 9 && (module.exports += i.toString(36).toUpperCase()) +} From df8ccf1c8c739347ba09240d54ff7672730bc040 Mon Sep 17 00:00:00 2001 From: gwer Date: Wed, 29 Jan 2020 09:51:09 +0300 Subject: [PATCH 4/6] Single call crypto.getRandomValues --- async/index.browser.js | 15 ++++++++++----- index.browser.js | 16 +++++++++++----- non-secure/index.js | 12 ++++++++---- package.json | 6 +++--- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/async/index.browser.js b/async/index.browser.js index abb1d016..1ac42fae 100644 --- a/async/index.browser.js +++ b/async/index.browser.js @@ -7,25 +7,30 @@ var crypto = self.crypto || self.msCrypto // Despite the fact the source code is quite long, its entropy // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i = 36 var url = '-_' +var i = 36 while (i--) { url += i.toString(36) - i > 9 && (url += i.toString(36).toUpperCase()) +} + +i = 36 +while (i-- - 10) { + url += i.toString(36).toUpperCase() } module.exports = function (size) { var id = '' - size = size || 21 + var bytes = crypto.getRandomValues(new Uint8Array(size || 21)) + i = size || 21 // Compact alternative for `for (var i = 0; i < size; i++)` - while (size--) { + while (i--) { // We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. // This mask reduces random byte 0-255 to 0-63 values. // There is no need in `|| ''` and `* 1.6` hacks in here, // because bitmask trim bytes exact to alphabet size. - id += url[crypto.getRandomValues(new Uint8Array(1)) & 63] + id += url[bytes[i] & 63] } return Promise.resolve(id) } diff --git a/index.browser.js b/index.browser.js index 3a02e3cb..0310066f 100644 --- a/index.browser.js +++ b/index.browser.js @@ -24,24 +24,30 @@ var crypto = self.crypto || self.msCrypto // Despite the fact the source code is quite long, its entropy // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i = 36 var url = '-_' +var i = 36 while (i--) { url += i.toString(36) - i > 9 && (url += i.toString(36).toUpperCase()) +} + +i = 36 +while (i-- - 10) { + url += i.toString(36).toUpperCase() } module.exports = function (size) { var id = '' - size = size || 21 + var bytes = crypto.getRandomValues(new Uint8Array(size || 21)) + i = size || 21 + // Compact alternative for `for (var i = 0; i < size; i++)` - while (size--) { + while (i--) { // We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. // This mask reduces random byte 0-255 to 0-63 values. // There is no need in `|| ''` and `* 1.6` hacks in here, // because bitmask trim bytes exact to alphabet size. - id += url[crypto.getRandomValues(new Uint8Array(1)) & 63] + id += url[bytes[i] & 63] } return id } diff --git a/non-secure/index.js b/non-secure/index.js index 1771a8e7..53081482 100644 --- a/non-secure/index.js +++ b/non-secure/index.js @@ -2,12 +2,16 @@ // Despite the fact the source code is quite long, its entropy // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i = 36 var url = '-_' +var i = 36 while (i--) { url += i.toString(36) - i > 9 && (url += i.toString(36).toUpperCase()) +} + +i = 36 +while (i-- - 10) { + url += i.toString(36).toUpperCase() } /** @@ -27,9 +31,9 @@ while (i--) { */ module.exports = function (size) { var id = '' - size = size || 21 + i = size || 21 // Compact alternative for `for (var i = 0; i < size; i++)` - while (size--) { + while (i--) { // `| 0` is compact and faster alternative for `Math.floor()` id += url[Math.random() * 64 | 0] } diff --git a/package.json b/package.json index ea88b75b..2e3f8619 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "size-limit": [ { "path": "index.js", - "limit": "116 B" + "limit": "119 B" }, { "path": "generate.js", @@ -78,7 +78,7 @@ }, { "path": "non-secure/index.js", - "limit": "84 B" + "limit": "82 B" }, { "path": "non-secure/generate.js", @@ -86,7 +86,7 @@ }, { "path": "async/index.js", - "limit": "126 B" + "limit": "130 B" }, { "path": "async/generate.js", From 1d7ef8baa1c90685b40612da7b1259543303a489 Mon Sep 17 00:00:00 2001 From: gwer Date: Wed, 29 Jan 2020 10:43:55 +0300 Subject: [PATCH 5/6] Update comments --- async/index.browser.js | 11 ++++++++--- index.browser.js | 11 ++++++++--- non-secure/index.js | 11 ++++++++--- url.js | 4 ++++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/async/index.browser.js b/async/index.browser.js index 1ac42fae..a58bc209 100644 --- a/async/index.browser.js +++ b/async/index.browser.js @@ -4,17 +4,22 @@ var crypto = self.crypto || self.msCrypto // This alphabet uses a-z A-Z 0-9 _- symbols. -// Despite the fact the source code is quite long, its entropy -// is low and there are lots of duplicates - just what compressors -// like GZIP and Brotli likes the best. +// Symbols are generated for better gzip compression. +// Final url is +// '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA' var url = '-_' var i = 36 while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z url += i.toString(36) } i = 36 +// Loop from 36 to 10 (from Z to A in Base36) while (i-- - 10) { url += i.toString(36).toUpperCase() } diff --git a/index.browser.js b/index.browser.js index 0310066f..8a3fac1b 100644 --- a/index.browser.js +++ b/index.browser.js @@ -21,17 +21,22 @@ if (process.env.NODE_ENV !== 'production') { var crypto = self.crypto || self.msCrypto // This alphabet uses a-z A-Z 0-9 _- symbols. -// Despite the fact the source code is quite long, its entropy -// is low and there are lots of duplicates - just what compressors -// like GZIP and Brotli likes the best. +// Symbols are generated for better gzip compression. +// Final url is +// '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA' var url = '-_' var i = 36 while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z url += i.toString(36) } i = 36 +// Loop from 36 to 10 (from Z to A in Base36) while (i-- - 10) { url += i.toString(36).toUpperCase() } diff --git a/non-secure/index.js b/non-secure/index.js index 53081482..b57dd893 100644 --- a/non-secure/index.js +++ b/non-secure/index.js @@ -1,15 +1,20 @@ // This alphabet uses a-z A-Z 0-9 _- symbols. -// Despite the fact the source code is quite long, its entropy -// is low and there are lots of duplicates - just what compressors -// like GZIP and Brotli likes the best. +// Symbols are generated for better gzip compression. +// Final url is +// '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA' var url = '-_' var i = 36 while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z url += i.toString(36) } i = 36 +// Loop from 36 to 10 (from Z to A in Base36) while (i-- - 10) { url += i.toString(36).toUpperCase() } diff --git a/url.js b/url.js index 6a2a0dcd..d567de25 100644 --- a/url.js +++ b/url.js @@ -17,6 +17,10 @@ module.exports = '-_' var i = 36 while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z module.exports += i.toString(36) i > 9 && (module.exports += i.toString(36).toUpperCase()) } From 6c6c0c6db3564139029034cf396c4636c21121c7 Mon Sep 17 00:00:00 2001 From: gwer Date: Wed, 29 Jan 2020 10:57:04 +0300 Subject: [PATCH 6/6] A-Z => a-z --- async/index.browser.js | 4 ++-- index.browser.js | 4 ++-- non-secure/index.js | 4 ++-- url.js | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/async/index.browser.js b/async/index.browser.js index a58bc209..2ead6973 100644 --- a/async/index.browser.js +++ b/async/index.browser.js @@ -12,9 +12,9 @@ var url = '-_' var i = 36 while (i--) { // 36 is radix. - // Number.prototype.toString(36) returns number in Base36 representation + // Number.prototype.toString(36) returns number in Base36 representation. // Base36 is like hex, - // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z url += i.toString(36) } diff --git a/index.browser.js b/index.browser.js index 8a3fac1b..2f5e2f65 100644 --- a/index.browser.js +++ b/index.browser.js @@ -29,9 +29,9 @@ var url = '-_' var i = 36 while (i--) { // 36 is radix. - // Number.prototype.toString(36) returns number in Base36 representation + // Number.prototype.toString(36) returns number in Base36 representation. // Base36 is like hex, - // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z url += i.toString(36) } diff --git a/non-secure/index.js b/non-secure/index.js index b57dd893..94f0cbd9 100644 --- a/non-secure/index.js +++ b/non-secure/index.js @@ -7,9 +7,9 @@ var url = '-_' var i = 36 while (i--) { // 36 is radix. - // Number.prototype.toString(36) returns number in Base36 representation + // Number.prototype.toString(36) returns number in Base36 representation. // Base36 is like hex, - // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z url += i.toString(36) } diff --git a/url.js b/url.js index d567de25..cf95ea4d 100644 --- a/url.js +++ b/url.js @@ -18,9 +18,9 @@ module.exports = '-_' var i = 36 while (i--) { // 36 is radix. - // Number.prototype.toString(36) returns number in Base36 representation + // Number.prototype.toString(36) returns number in Base36 representation. // Base36 is like hex, - // but Base36 is represented using the numerals 0–9 and the Latin letters A–Z + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z module.exports += i.toString(36) i > 9 && (module.exports += i.toString(36).toUpperCase()) }