Path: blob/master/node_modules/abab/lib/atob.js
2591 views
"use strict";12/**3* Implementation of atob() according to the HTML and Infra specs, except that4* instead of throwing INVALID_CHARACTER_ERR we return null.5*/6function atob(data) {7// Web IDL requires DOMStrings to just be converted using ECMAScript8// ToString, which in our case amounts to using a template literal.9data = `${data}`;10// "Remove all ASCII whitespace from data."11data = data.replace(/[ \t\n\f\r]/g, "");12// "If data's length divides by 4 leaving no remainder, then: if data ends13// with one or two U+003D (=) code points, then remove them from data."14if (data.length % 4 === 0) {15data = data.replace(/==?$/, "");16}17// "If data's length divides by 4 leaving a remainder of 1, then return18// failure."19//20// "If data contains a code point that is not one of21//22// U+002B (+)23// U+002F (/)24// ASCII alphanumeric25//26// then return failure."27if (data.length % 4 === 1 || /[^+/0-9A-Za-z]/.test(data)) {28return null;29}30// "Let output be an empty byte sequence."31let output = "";32// "Let buffer be an empty buffer that can have bits appended to it."33//34// We append bits via left-shift and or. accumulatedBits is used to track35// when we've gotten to 24 bits.36let buffer = 0;37let accumulatedBits = 0;38// "Let position be a position variable for data, initially pointing at the39// start of data."40//41// "While position does not point past the end of data:"42for (let i = 0; i < data.length; i++) {43// "Find the code point pointed to by position in the second column of44// Table 1: The Base 64 Alphabet of RFC 4648. Let n be the number given in45// the first cell of the same row.46//47// "Append to buffer the six bits corresponding to n, most significant bit48// first."49//50// atobLookup() implements the table from RFC 4648.51buffer <<= 6;52buffer |= atobLookup(data[i]);53accumulatedBits += 6;54// "If buffer has accumulated 24 bits, interpret them as three 8-bit55// big-endian numbers. Append three bytes with values equal to those56// numbers to output, in the same order, and then empty buffer."57if (accumulatedBits === 24) {58output += String.fromCharCode((buffer & 0xff0000) >> 16);59output += String.fromCharCode((buffer & 0xff00) >> 8);60output += String.fromCharCode(buffer & 0xff);61buffer = accumulatedBits = 0;62}63// "Advance position by 1."64}65// "If buffer is not empty, it contains either 12 or 18 bits. If it contains66// 12 bits, then discard the last four and interpret the remaining eight as67// an 8-bit big-endian number. If it contains 18 bits, then discard the last68// two and interpret the remaining 16 as two 8-bit big-endian numbers. Append69// the one or two bytes with values equal to those one or two numbers to70// output, in the same order."71if (accumulatedBits === 12) {72buffer >>= 4;73output += String.fromCharCode(buffer);74} else if (accumulatedBits === 18) {75buffer >>= 2;76output += String.fromCharCode((buffer & 0xff00) >> 8);77output += String.fromCharCode(buffer & 0xff);78}79// "Return output."80return output;81}82/**83* A lookup table for atob(), which converts an ASCII character to the84* corresponding six-bit number.85*/8687const keystr =88"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";8990function atobLookup(chr) {91const index = keystr.indexOf(chr);92// Throw exception if character is not in the lookup string; should not be hit in tests93return index < 0 ? undefined : index;94}9596module.exports = atob;979899