btoa.js
1 "use strict"; 2 3 /** 4 * btoa() as defined by the HTML and Infra specs, which mostly just references 5 * RFC 4648. 6 */ 7 function btoa(s) { 8 let i; 9 // String conversion as required by Web IDL. 10 s = `${s}`; 11 // "The btoa() method must throw an "InvalidCharacterError" DOMException if 12 // data contains any character whose code point is greater than U+00FF." 13 for (i = 0; i < s.length; i++) { 14 if (s.charCodeAt(i) > 255) { 15 return null; 16 } 17 } 18 let out = ""; 19 for (i = 0; i < s.length; i += 3) { 20 const groupsOfSix = [undefined, undefined, undefined, undefined]; 21 groupsOfSix[0] = s.charCodeAt(i) >> 2; 22 groupsOfSix[1] = (s.charCodeAt(i) & 0x03) << 4; 23 if (s.length > i + 1) { 24 groupsOfSix[1] |= s.charCodeAt(i + 1) >> 4; 25 groupsOfSix[2] = (s.charCodeAt(i + 1) & 0x0f) << 2; 26 } 27 if (s.length > i + 2) { 28 groupsOfSix[2] |= s.charCodeAt(i + 2) >> 6; 29 groupsOfSix[3] = s.charCodeAt(i + 2) & 0x3f; 30 } 31 for (let j = 0; j < groupsOfSix.length; j++) { 32 if (typeof groupsOfSix[j] === "undefined") { 33 out += "="; 34 } else { 35 out += btoaLookup(groupsOfSix[j]); 36 } 37 } 38 } 39 return out; 40 } 41 42 /** 43 * Lookup table for btoa(), which converts a six-bit number into the 44 * corresponding ASCII character. 45 */ 46 const keystr = 47 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 48 49 function btoaLookup(index) { 50 if (index >= 0 && index < 64) { 51 return keystr[index]; 52 } 53 54 // Throw INVALID_CHARACTER_ERR exception here -- won't be hit in the tests. 55 return undefined; 56 } 57 58 module.exports = btoa;