Skip to content

Commit 8124f5a

Browse files
committed
feat: implement base64 utility functions atob/btoa, taken implementations from core-js
1 parent 59642c3 commit 8124f5a

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

python/pythonmonkey/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
import importlib.metadata
77
__version__= importlib.metadata.version(__name__)
88

9-
# Load the module by default to make `console` globally available
9+
# Load the module by default to make `console`/`atob`/`btoa` globally available
1010
require("console")
11+
require("base64")
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* @file base64.js
3+
* @author Tom Tang <[email protected]>
4+
* @date May 2023
5+
*/
6+
7+
/*!
8+
* Modified from https://github.com/zloirock/core-js/blob/44cf9e8/packages/core-js/modules/web.atob.js and
9+
* https://github.com/zloirock/core-js/blob/44cf9e8/packages/core-js/modules/web.btoa.js
10+
* core-js
11+
* MIT License, Copyright (c) 2014-2023 Denis Pushkarev
12+
*/
13+
14+
var uncurryThis = function (fn) {
15+
// Modified from https://github.com/zloirock/core-js/blob/44cf9e8/packages/core-js/internals/
16+
return function () {
17+
return Function.prototype.call.apply(fn, arguments);
18+
};
19+
};
20+
var toString = (arg) => String(arg);
21+
var hasOwn = Object.hasOwn;
22+
23+
// Taken from https://github.com/zloirock/core-js/blob/44cf9e8/packages/core-js/internals/validate-arguments-length.js
24+
function validateArgumentsLength(passed, required) {
25+
if (passed < required) throw TypeError('Not enough arguments');
26+
return passed;
27+
};
28+
29+
// Taken from https://github.com/zloirock/core-js/blob/44cf9e8/packages/core-js/internals/base64-map.js
30+
var itoc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
31+
var ctoi = {};
32+
for (var index = 0; index < 66; index++) ctoi[itoc.charAt(index)] = index;
33+
34+
var disallowed = /[^\d+/a-z]/i;
35+
var whitespaces = /[\t\n\f\r ]+/g;
36+
var finalEq = /[=]{1,2}$/;
37+
38+
var fromCharCode = String.fromCharCode;
39+
var charAt = uncurryThis(''.charAt);
40+
var charCodeAt = uncurryThis(''.charCodeAt);
41+
var replace = uncurryThis(''.replace);
42+
var exec = uncurryThis(disallowed.exec);
43+
44+
function atob(data) {
45+
validateArgumentsLength(arguments.length, 1);
46+
var string = replace(toString(data), whitespaces, '');
47+
var output = '';
48+
var position = 0;
49+
var bc = 0;
50+
var chr, bs = 0;
51+
if (string.length % 4 == 0) {
52+
string = replace(string, finalEq, '');
53+
}
54+
if (string.length % 4 == 1 || exec(disallowed, string)) {
55+
// throw new (getBuiltIn('DOMException'))('The string is not correctly encoded', 'InvalidCharacterError');
56+
throw new Error('InvalidCharacterError: The string is not correctly encoded');
57+
}
58+
while (chr = charAt(string, position++)) {
59+
if (hasOwn(ctoi, chr)) {
60+
bs = bc % 4 ? bs * 64 + ctoi[chr] : ctoi[chr];
61+
if (bc++ % 4) output += fromCharCode(255 & bs >> (-2 * bc & 6));
62+
}
63+
} return output;
64+
}
65+
66+
function btoa(data) {
67+
validateArgumentsLength(arguments.length, 1);
68+
var string = toString(data);
69+
var output = '';
70+
var position = 0;
71+
var map = itoc;
72+
var block = 0, charCode;
73+
while (charAt(string, position) || (map = '=', position % 1)) {
74+
charCode = charCodeAt(string, position += 3 / 4);
75+
if (charCode > 0xFF) {
76+
// throw new (getBuiltIn('DOMException'))('The string contains characters outside of the Latin1 range', 'InvalidCharacterError');
77+
throw new Error('InvalidCharacterError: The string contains characters outside of the Latin1 range');
78+
}
79+
block = block << 8 | charCode;
80+
output += charAt(map, 63 & block >> 8 - position % 1 * 8);
81+
} return output;
82+
}
83+
84+
// Make `atob`/`btoa` globally available
85+
if (!globalThis["atob"]) {
86+
globalThis["atob"] = atob;
87+
}
88+
if (!globalThis["btoa"]) {
89+
globalThis["btoa"] = btoa;
90+
}
91+
92+
exports.atob = atob;
93+
exports.btoa = btoa;

0 commit comments

Comments
 (0)