UNPKG

2.81 kBJavaScriptView Raw
1'use strict';
2var $ = require('../internals/export');
3var global = require('../internals/global');
4var uncurryThis = require('../internals/function-uncurry-this');
5var anObjectOrUndefined = require('../internals/an-object-or-undefined');
6var aString = require('../internals/a-string');
7var hasOwn = require('../internals/has-own-property');
8var arrayFromConstructorAndList = require('../internals/array-from-constructor-and-list');
9var base64Map = require('../internals/base64-map');
10var getAlphabetOption = require('../internals/get-alphabet-option');
11
12var base64Alphabet = base64Map.c2i;
13var base64UrlAlphabet = base64Map.c2iUrl;
14
15var Uint8Array = global.Uint8Array;
16var SyntaxError = global.SyntaxError;
17var charAt = uncurryThis(''.charAt);
18var replace = uncurryThis(''.replace);
19var stringSlice = uncurryThis(''.slice);
20var push = uncurryThis([].push);
21var SPACES = /[\t\n\f\r ]/g;
22var EXTRA_BITS = 'Extra bits';
23
24// `Uint8Array.fromBase64` method
25// https://github.com/tc39/proposal-arraybuffer-base64
26if (Uint8Array) $({ target: 'Uint8Array', stat: true, forced: true }, {
27 fromBase64: function fromBase64(string /* , options */) {
28 aString(string);
29 var options = arguments.length > 1 ? anObjectOrUndefined(arguments[1]) : undefined;
30 var alphabet = getAlphabetOption(options) === 'base64' ? base64Alphabet : base64UrlAlphabet;
31 var strict = options ? !!options.strict : false;
32
33 var input = strict ? string : replace(string, SPACES, '');
34
35 if (input.length % 4 === 0) {
36 if (stringSlice(input, -2) === '==') input = stringSlice(input, 0, -2);
37 else if (stringSlice(input, -1) === '=') input = stringSlice(input, 0, -1);
38 } else if (strict) throw new SyntaxError('Input is not correctly padded');
39
40 var lastChunkSize = input.length % 4;
41
42 switch (lastChunkSize) {
43 case 1: throw new SyntaxError('Bad input length');
44 case 2: input += 'AA'; break;
45 case 3: input += 'A';
46 }
47
48 var bytes = [];
49 var i = 0;
50 var inputLength = input.length;
51
52 var at = function (shift) {
53 var chr = charAt(input, i + shift);
54 if (!hasOwn(alphabet, chr)) throw new SyntaxError('Bad char in input: "' + chr + '"');
55 return alphabet[chr] << (18 - 6 * shift);
56 };
57
58 for (; i < inputLength; i += 4) {
59 var triplet = at(0) + at(1) + at(2) + at(3);
60 push(bytes, (triplet >> 16) & 255, (triplet >> 8) & 255, triplet & 255);
61 }
62
63 var byteLength = bytes.length;
64
65 if (lastChunkSize === 2) {
66 if (strict && bytes[byteLength - 2] !== 0) throw new SyntaxError(EXTRA_BITS);
67 byteLength -= 2;
68 } else if (lastChunkSize === 3) {
69 if (strict && bytes[byteLength - 1] !== 0) throw new SyntaxError(EXTRA_BITS);
70 byteLength--;
71 }
72
73 return arrayFromConstructorAndList(Uint8Array, bytes, byteLength);
74 }
75});