From 319c69a78839b3306dddd8738c048c508306f876 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Fri, 24 Nov 2023 08:13:21 +0700 Subject: [PATCH] add `.toBase64` method --- packages/core-js-compat/src/data.mjs | 4 ++ .../src/modules-by-versions.mjs | 2 + packages/core-js/internals/base64-map.js | 18 +++++-- .../modules/esnext.uint8-array.from-base64.js | 16 ++++++ .../modules/esnext.uint8-array.from-hex.js | 2 +- .../modules/esnext.uint8-array.to-base64.js | 51 +++++++++++++++++++ .../modules/esnext.uint8-array.to-hex.js | 2 +- packages/core-js/modules/web.atob.js | 4 +- packages/core-js/modules/web.btoa.js | 4 +- .../core-js/proposals/array-buffer-base64.js | 2 + packages/core-js/stage/2.js | 1 + packages/core-js/stage/3.js | 1 - tests/compat/tests.js | 6 +++ 13 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 packages/core-js/modules/esnext.uint8-array.from-base64.js create mode 100644 packages/core-js/modules/esnext.uint8-array.to-base64.js diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index 91fac8d6419e..1f1d95a1e3f8 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -2343,8 +2343,12 @@ export const data = { }, // TODO: Remove from `core-js@4` 'esnext.typed-array.with': null, + 'esnext.uint8-array.from-base64': { + }, 'esnext.uint8-array.from-hex': { }, + 'esnext.uint8-array.to-base64': { + }, 'esnext.uint8-array.to-hex': { }, 'esnext.weak-map.delete-all': { diff --git a/packages/core-js-compat/src/modules-by-versions.mjs b/packages/core-js-compat/src/modules-by-versions.mjs index edcc58943488..fafe14b1b1b3 100644 --- a/packages/core-js-compat/src/modules-by-versions.mjs +++ b/packages/core-js-compat/src/modules-by-versions.mjs @@ -227,7 +227,9 @@ export default { 'es.map.group-by', 'es.object.group-by', 'es.promise.with-resolvers', + 'esnext.uint8-array.from-base64', 'esnext.uint8-array.from-hex', + 'esnext.uint8-array.to-base64', 'esnext.uint8-array.to-hex', ], }; diff --git a/packages/core-js/internals/base64-map.js b/packages/core-js/internals/base64-map.js index ebe1e9b304c7..b2e521524066 100644 --- a/packages/core-js/internals/base64-map.js +++ b/packages/core-js/internals/base64-map.js @@ -1,10 +1,18 @@ 'use strict'; -var itoc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; -var ctoi = {}; +var commonAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; +var base64Alphabet = commonAlphabet + '+/'; +var base64UrlAlphabet = commonAlphabet + '-_'; -for (var index = 0; index < 64; index++) ctoi[itoc.charAt(index)] = index; +var inverse = function (characters) { + var result = {}; + var index = 0; + for (; index < 64; index++) result[characters.charAt(index)] = index; + return result; +}; module.exports = { - itoc: itoc, - ctoi: ctoi + i2c: base64Alphabet, + c2i: inverse(base64Alphabet), + i2cUrl: base64UrlAlphabet, + c2iUrl: inverse(base64UrlAlphabet) }; diff --git a/packages/core-js/modules/esnext.uint8-array.from-base64.js b/packages/core-js/modules/esnext.uint8-array.from-base64.js new file mode 100644 index 000000000000..295b379eaf93 --- /dev/null +++ b/packages/core-js/modules/esnext.uint8-array.from-base64.js @@ -0,0 +1,16 @@ +'use strict'; +var $ = require('../internals/export'); +var global = require('../internals/global'); +var aString = require('../internals/a-string'); + +var Uint8Array = global.Uint8Array; + +// `Uint8Array.fromBase64` method +// https://github.com/tc39/proposal-arraybuffer-base64 +if (Uint8Array) $({ target: 'Uint8Array', stat: true, forced: true }, { + fromBase64: function fromBase64(string) { + aString(string); + // TODO + return new Uint8Array(8); + } +}); diff --git a/packages/core-js/modules/esnext.uint8-array.from-hex.js b/packages/core-js/modules/esnext.uint8-array.from-hex.js index ca10cb84885c..304a8e5f7b84 100644 --- a/packages/core-js/modules/esnext.uint8-array.from-hex.js +++ b/packages/core-js/modules/esnext.uint8-array.from-hex.js @@ -13,7 +13,7 @@ var stringSlice = uncurryThis(''.slice); // `Uint8Array.fromHex` method // https://github.com/tc39/proposal-arraybuffer-base64 -if (Uint8Array) $({ target: 'Uint8Array', stat: true }, { +if (Uint8Array) $({ target: 'Uint8Array', stat: true, forced: true }, { fromHex: function fromHex(string) { aString(string); var stringLength = string.length; diff --git a/packages/core-js/modules/esnext.uint8-array.to-base64.js b/packages/core-js/modules/esnext.uint8-array.to-base64.js new file mode 100644 index 000000000000..e101d7e56562 --- /dev/null +++ b/packages/core-js/modules/esnext.uint8-array.to-base64.js @@ -0,0 +1,51 @@ +'use strict'; +var $ = require('../internals/export'); +var global = require('../internals/global'); +var uncurryThis = require('../internals/function-uncurry-this'); +var isObject = require('../internals/is-object'); +var anUint8Array = require('../internals/an-uint8-array'); +var base64Map = require('../internals/base64-map'); + +var base64Alphabet = base64Map.i2c; +var base64UrlAlphabet = base64Map.i2cUrl; + +var Uint8Array = global.Uint8Array; +var TypeError = global.TypeError; +var charAt = uncurryThis(''.charAt); +var BASE64 = 'base64'; + +// `Uint8Array..prototype.toBase64` method +// https://github.com/tc39/proposal-arraybuffer-base64 +if (Uint8Array) $({ target: 'Uint8Array', proto: true, forced: true }, { + toBase64: function toBase64(options) { + var array = anUint8Array(this); + if (options !== undefined && !isObject(options)) throw new TypeError('Incorrect options'); + var $alphabet = options && options.alphabet; + if ($alphabet === undefined) $alphabet = BASE64; + if ($alphabet !== BASE64 && $alphabet !== 'base64url') throw new TypeError('Incorrect `alphabet` option'); + var alphabet = $alphabet === BASE64 ? base64Alphabet : base64UrlAlphabet; + + var result = ''; + var i = 0; + var length = array.length; + var triplet; + + var at = function (bit) { + return charAt(alphabet, (triplet >> bit) & 63); + }; + + for (; i + 2 < length; i += 3) { + triplet = (array[i] << 16) + (array[i + 1] << 8) + array[i + 2]; + result += at(18) + at(12) + at(6) + at(0); + } + if (i + 2 === length) { + triplet = (array[i] << 16) + (array[i + 1] << 8); + result += at(18) + at(12) + at(6) + '='; + } else if (i + 1 === length) { + triplet = array[i] << 16; + result += at(18) + at(12) + '=='; + } + + return result; + } +}); diff --git a/packages/core-js/modules/esnext.uint8-array.to-hex.js b/packages/core-js/modules/esnext.uint8-array.to-hex.js index 2988387c8145..fd379b632817 100644 --- a/packages/core-js/modules/esnext.uint8-array.to-hex.js +++ b/packages/core-js/modules/esnext.uint8-array.to-hex.js @@ -9,7 +9,7 @@ var numberToString = uncurryThis(1.0.toString); // `Uint8Array..prototype.toHex` method // https://github.com/tc39/proposal-arraybuffer-base64 -if (Uint8Array) $({ target: 'Uint8Array', proto: true }, { +if (Uint8Array) $({ target: 'Uint8Array', proto: true, forced: true }, { toHex: function toHex() { anUint8Array(this); var result = ''; diff --git a/packages/core-js/modules/web.atob.js b/packages/core-js/modules/web.atob.js index b735c90827f1..b6624011fbd1 100644 --- a/packages/core-js/modules/web.atob.js +++ b/packages/core-js/modules/web.atob.js @@ -7,7 +7,7 @@ var call = require('../internals/function-call'); var fails = require('../internals/fails'); var toString = require('../internals/to-string'); var validateArgumentsLength = require('../internals/validate-arguments-length'); -var ctoi = require('../internals/base64-map').ctoi; +var c2i = require('../internals/base64-map').c2i; var disallowed = /[^\d+/a-z]/i; var whitespaces = /[\t\n\f\r ]+/g; @@ -60,7 +60,7 @@ $({ global: true, bind: true, enumerable: true, forced: FORCED }, { } while (position < length) { chr = charAt(string, position++); - bs = bc % 4 ? bs * 64 + ctoi[chr] : ctoi[chr]; + bs = bc % 4 ? bs * 64 + c2i[chr] : c2i[chr]; if (bc++ % 4) output += fromCharCode(255 & bs >> (-2 * bc & 6)); } return output; } diff --git a/packages/core-js/modules/web.btoa.js b/packages/core-js/modules/web.btoa.js index d218420792b4..0696e8c2d6b2 100644 --- a/packages/core-js/modules/web.btoa.js +++ b/packages/core-js/modules/web.btoa.js @@ -7,7 +7,7 @@ var call = require('../internals/function-call'); var fails = require('../internals/fails'); var toString = require('../internals/to-string'); var validateArgumentsLength = require('../internals/validate-arguments-length'); -var itoc = require('../internals/base64-map').itoc; +var i2c = require('../internals/base64-map').i2c; var $btoa = getBuiltIn('btoa'); var charAt = uncurryThis(''.charAt); @@ -37,7 +37,7 @@ $({ global: true, bind: true, enumerable: true, forced: !BASIC || NO_ARG_RECEIVI var string = toString(data); var output = ''; var position = 0; - var map = itoc; + var map = i2c; var block, charCode; while (charAt(string, position) || (map = '=', position % 1)) { charCode = charCodeAt(string, position += 3 / 4); diff --git a/packages/core-js/proposals/array-buffer-base64.js b/packages/core-js/proposals/array-buffer-base64.js index 3cb25459dc9e..6aceb4a1c93a 100644 --- a/packages/core-js/proposals/array-buffer-base64.js +++ b/packages/core-js/proposals/array-buffer-base64.js @@ -1,4 +1,6 @@ 'use strict'; // https://github.com/tc39/proposal-arraybuffer-base64 +require('../modules/esnext.uint8-array.from-base64'); require('../modules/esnext.uint8-array.from-hex'); +require('../modules/esnext.uint8-array.to-base64'); require('../modules/esnext.uint8-array.to-hex'); diff --git a/packages/core-js/stage/2.js b/packages/core-js/stage/2.js index 68141057a3b7..18a0f73af914 100644 --- a/packages/core-js/stage/2.js +++ b/packages/core-js/stage/2.js @@ -1,6 +1,7 @@ 'use strict'; var parent = require('./3'); +require('../proposals/array-buffer-base64'); require('../proposals/array-is-template-object'); require('../proposals/async-iterator-helpers'); require('../proposals/iterator-range'); diff --git a/packages/core-js/stage/3.js b/packages/core-js/stage/3.js index 8df952c244cd..e82ca7059331 100644 --- a/packages/core-js/stage/3.js +++ b/packages/core-js/stage/3.js @@ -1,7 +1,6 @@ 'use strict'; var parent = require('./4'); -require('../proposals/array-buffer-base64'); require('../proposals/array-buffer-transfer'); require('../proposals/array-from-async-stage-2'); require('../proposals/decorator-metadata-v2'); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index a7dd4094ad0a..073896d458a7 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1830,9 +1830,15 @@ GLOBAL.tests = { 'esnext.typed-array.unique-by': function () { return Int8Array.prototype.uniqueBy; }, + 'esnext.uint8-array.from-base64': function () { + return Uint8Array.fromBase64; + }, 'esnext.uint8-array.from-hex': function () { return Uint8Array.fromHex; }, + 'esnext.uint8-array.to-base64': function () { + return Uint8Array.prototype.toBase64; + }, 'esnext.uint8-array.to-hex': function () { return Uint8Array.prototype.toHex; },