blob: 0407b80688b73f50b48d903a5babd441a03f91f4 [file] [log] [blame] [edit]
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error(`FAIL: expected '${expected}' actual '${actual}'`);
}
function shouldBeObject(actual, expected) {
for (let key in expected) {
shouldBe(key in actual, true);
shouldBe(actual[key], expected[key]);
}
for (let key in actual)
shouldBe(key in expected, true);
}
function shouldBeArray(actual, expected) {
shouldBe(actual.length, expected.length);
for (let i = 0; i < expected.length; ++i)
shouldBe(actual[i], expected[i]);
}
function shouldThrow(callback, errorConstructor) {
try {
callback();
} catch (e) {
shouldBe(e instanceof errorConstructor, true);
return
}
throw new Error('FAIL: should have thrown');
}
function test(input, options, expectedResult, expectedValue) {
let uint8array = new Uint8Array([42, 42, 42, 42, 42]);
let result;
if (options)
result = uint8array.setFromBase64(input, options);
else
result = uint8array.setFromBase64(input);
while (expectedValue.length < 5)
expectedValue.push(42);
shouldBeObject(result, expectedResult);
shouldBeArray(uint8array, expectedValue);
}
test("", undefined, {read: 0, written: 0}, []);
test("AA", undefined, {read: 2, written: 1}, [0]);
test("AQ", undefined, {read: 2, written: 1}, [1]);
test("gA", undefined, {read: 2, written: 1}, [128]);
test("/g", undefined, {read: 2, written: 1}, [254]);
test("/w", undefined, {read: 2, written: 1}, [255]);
test("AAE", undefined, {read: 3, written: 2}, [0, 1]);
test("/v8", undefined, {read: 3, written: 2}, [254, 255]);
test("AAGA/v8", undefined, {read: 7, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", undefined, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA", undefined, {read: 4, written: 3}, [0, 1, 128]);
test("AA==", undefined, {read: 4, written: 1}, [0]);
test("AQ==", undefined, {read: 4, written: 1}, [1]);
test("gA==", undefined, {read: 4, written: 1}, [128]);
test("/g==", undefined, {read: 4, written: 1}, [254]);
test("/w==", undefined, {read: 4, written: 1}, [255]);
test("AAE=", undefined, {read: 4, written: 2}, [0, 1]);
test("/v8=", undefined, {read: 4, written: 2}, [254, 255]);
test("AAGA/v8=", undefined, {read: 8, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", undefined, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA==", undefined, {read: 4, written: 3}, [0, 1, 128]);
test(" ", undefined, {read: 2, written: 0}, []);
test(" A A ", undefined, {read: 8, written: 1}, [0]);
test(" A Q ", undefined, {read: 8, written: 1}, [1]);
test(" g A ", undefined, {read: 8, written: 1}, [128]);
test(" / g ", undefined, {read: 8, written: 1}, [254]);
test(" / w ", undefined, {read: 8, written: 1}, [255]);
test(" A A E ", undefined, {read: 11, written: 2}, [0, 1]);
test(" / v 8 ", undefined, {read: 11, written: 2}, [254, 255]);
test(" A A G A / v 8 ", undefined, {read: 23, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", undefined, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A ", undefined, {read: 12, written: 3}, [0, 1, 128]);
test(" A A = = ", undefined, {read: 14, written: 1}, [0]);
test(" A Q = = ", undefined, {read: 14, written: 1}, [1]);
test(" g A = = ", undefined, {read: 14, written: 1}, [128]);
test(" / g = = ", undefined, {read: 14, written: 1}, [254]);
test(" / w = = ", undefined, {read: 14, written: 1}, [255]);
test(" A A E = ", undefined, {read: 14, written: 2}, [0, 1]);
test(" / v 8 = ", undefined, {read: 14, written: 2}, [254, 255]);
test(" A A G A / v 8 = ", undefined, {read: 26, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", undefined, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A = = ", undefined, {read: 12, written: 3}, [0, 1, 128]);
test("", {}, {read: 0, written: 0}, []);
test("AA", {}, {read: 2, written: 1}, [0]);
test("AQ", {}, {read: 2, written: 1}, [1]);
test("gA", {}, {read: 2, written: 1}, [128]);
test("/g", {}, {read: 2, written: 1}, [254]);
test("/w", {}, {read: 2, written: 1}, [255]);
test("AAE", {}, {read: 3, written: 2}, [0, 1]);
test("/v8", {}, {read: 3, written: 2}, [254, 255]);
test("AAGA/v8", {}, {read: 7, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", {}, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA", {}, {read: 4, written: 3}, [0, 1, 128]);
test("AA==", {}, {read: 4, written: 1}, [0]);
test("AQ==", {}, {read: 4, written: 1}, [1]);
test("gA==", {}, {read: 4, written: 1}, [128]);
test("/g==", {}, {read: 4, written: 1}, [254]);
test("/w==", {}, {read: 4, written: 1}, [255]);
test("AAE=", {}, {read: 4, written: 2}, [0, 1]);
test("/v8=", {}, {read: 4, written: 2}, [254, 255]);
test("AAGA/v8=", {}, {read: 8, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", {}, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA==", {}, {read: 4, written: 3}, [0, 1, 128]);
test(" ", {}, {read: 2, written: 0}, []);
test(" A A ", {}, {read: 8, written: 1}, [0]);
test(" A Q ", {}, {read: 8, written: 1}, [1]);
test(" g A ", {}, {read: 8, written: 1}, [128]);
test(" / g ", {}, {read: 8, written: 1}, [254]);
test(" / w ", {}, {read: 8, written: 1}, [255]);
test(" A A E ", {}, {read: 11, written: 2}, [0, 1]);
test(" / v 8 ", {}, {read: 11, written: 2}, [254, 255]);
test(" A A G A / v 8 ", {}, {read: 23, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", {}, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A ", {}, {read: 12, written: 3}, [0, 1, 128]);
test(" A A = = ", {}, {read: 14, written: 1}, [0]);
test(" A Q = = ", {}, {read: 14, written: 1}, [1]);
test(" g A = = ", {}, {read: 14, written: 1}, [128]);
test(" / g = = ", {}, {read: 14, written: 1}, [254]);
test(" / w = = ", {}, {read: 14, written: 1}, [255]);
test(" A A E = ", {}, {read: 14, written: 2}, [0, 1]);
test(" / v 8 = ", {}, {read: 14, written: 2}, [254, 255]);
test(" A A G A / v 8 = ", {}, {read: 26, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", {}, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A = = ", {}, {read: 12, written: 3}, [0, 1, 128]);
for (let alphabet of [undefined, "base64"]) {
[
{alphabet},
{get alphabet() { return alphabet; }},
].forEach((options) => {
test("", options, {read: 0, written: 0}, []);
test("AA", options, {read: 2, written: 1}, [0]);
test("AQ", options, {read: 2, written: 1}, [1]);
test("gA", options, {read: 2, written: 1}, [128]);
test("/g", options, {read: 2, written: 1}, [254]);
test("/w", options, {read: 2, written: 1}, [255]);
test("AAE", options, {read: 3, written: 2}, [0, 1]);
test("/v8", options, {read: 3, written: 2}, [254, 255]);
test("AAGA/v8", options, {read: 7, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA", options, {read: 4, written: 3}, [0, 1, 128]);
test("AA==", options, {read: 4, written: 1}, [0]);
test("AQ==", options, {read: 4, written: 1}, [1]);
test("gA==", options, {read: 4, written: 1}, [128]);
test("/g==", options, {read: 4, written: 1}, [254]);
test("/w==", options, {read: 4, written: 1}, [255]);
test("AAE=", options, {read: 4, written: 2}, [0, 1]);
test("/v8=", options, {read: 4, written: 2}, [254, 255]);
test("AAGA/v8=", options, {read: 8, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA==", options, {read: 4, written: 3}, [0, 1, 128]);
test(" ", options, {read: 2, written: 0}, []);
test(" A A ", options, {read: 8, written: 1}, [0]);
test(" A Q ", options, {read: 8, written: 1}, [1]);
test(" g A ", options, {read: 8, written: 1}, [128]);
test(" / g ", options, {read: 8, written: 1}, [254]);
test(" / w ", options, {read: 8, written: 1}, [255]);
test(" A A E ", options, {read: 11, written: 2}, [0, 1]);
test(" / v 8 ", options, {read: 11, written: 2}, [254, 255]);
test(" A A G A / v 8 ", options, {read: 23, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A = = ", options, {read: 14, written: 1}, [0]);
test(" A Q = = ", options, {read: 14, written: 1}, [1]);
test(" g A = = ", options, {read: 14, written: 1}, [128]);
test(" / g = = ", options, {read: 14, written: 1}, [254]);
test(" / w = = ", options, {read: 14, written: 1}, [255]);
test(" A A E = ", options, {read: 14, written: 2}, [0, 1]);
test(" / v 8 = ", options, {read: 14, written: 2}, [254, 255]);
test(" A A G A / v 8 = ", options, {read: 26, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A = = ", options, {read: 12, written: 3}, [0, 1, 128]);
});
for (let lastChunkHandling of [undefined, "loose", "strict", "stop-before-partial"]) {
[
{alphabet, lastChunkHandling},
{get alphabet() { return alphabet; }, get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
test("", options, {read: 0, written: 0}, []);
test("AA==", options, {read: 4, written: 1}, [0]);
test("AQ==", options, {read: 4, written: 1}, [1]);
test("gA==", options, {read: 4, written: 1}, [128]);
test("/g==", options, {read: 4, written: 1}, [254]);
test("/w==", options, {read: 4, written: 1}, [255]);
test("AAE=", options, {read: 4, written: 2}, [0, 1]);
test("/v8=", options, {read: 4, written: 2}, [254, 255]);
test("AAGA/v8=", options, {read: 8, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA==", options, {read: 4, written: 3}, [0, 1, 128]);
test(" ", options, {read: 2, written: 0}, []);
test(" A A = = ", options, {read: 14, written: 1}, [0]);
test(" A Q = = ", options, {read: 14, written: 1}, [1]);
test(" g A = = ", options, {read: 14, written: 1}, [128]);
test(" / g = = ", options, {read: 14, written: 1}, [254]);
test(" / w = = ", options, {read: 14, written: 1}, [255]);
test(" A A E = ", options, {read: 14, written: 2}, [0, 1]);
test(" / v 8 = ", options, {read: 14, written: 2}, [254, 255]);
test(" A A G A / v 8 = ", options, {read: 26, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A = = ", options, {read: 12, written: 3}, [0, 1, 128]);
});
[
"AA===", " A A = = = ",
"AQ===", " A Q = = = ",
"gA===", " g A = = = ",
"/g===", " / g = = = ",
"/w===", " / w = = = ",
"AAE==", " A A E = = ",
"/v8==", " / v 8 = = ",
"AAGA/v8==", " A A G A / v 8 = = ",
].forEach((string) => {
[
{alphabet, lastChunkHandling},
{get alphabet() { return alphabet; }, get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
shouldThrow(() => {
test(string, options, {read: 0, written: 0}, []);
}, SyntaxError);
});
});
}
for (let lastChunkHandling of [undefined, "loose"]) {
[
{alphabet, lastChunkHandling},
{get alphabet() { return alphabet; }, get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
test("AA", options, {read: 2, written: 1}, [0]);
test("AQ", options, {read: 2, written: 1}, [1]);
test("gA", options, {read: 2, written: 1}, [128]);
test("/g", options, {read: 2, written: 1}, [254]);
test("/w", options, {read: 2, written: 1}, [255]);
test("AAE", options, {read: 3, written: 2}, [0, 1]);
test("/v8", options, {read: 3, written: 2}, [254, 255]);
test("AAGA/v8", options, {read: 7, written: 5}, [0, 1, 128, 254, 255]);
test(" A A ", options, {read: 8, written: 1}, [0]);
test(" A Q ", options, {read: 8, written: 1}, [1]);
test(" g A ", options, {read: 8, written: 1}, [128]);
test(" / g ", options, {read: 8, written: 1}, [254]);
test(" / w ", options, {read: 8, written: 1}, [255]);
test(" A A E ", options, {read: 11, written: 2}, [0, 1]);
test(" / v 8 ", options, {read: 11, written: 2}, [254, 255]);
test(" A A G A / v 8 ", options, {read: 23, written: 5}, [0, 1, 128, 254, 255]);
});
}
[
"AA", " A A ",
"AQ", " A Q ",
"gA", " g A ",
"/g", " / g ",
"/w", " / w ",
"AAE", " A A E ",
"/v8", " / v 8 ",
].forEach((string) => {
[
{alphabet, lastChunkHandling: "stop-before-partial"},
{get alphabet() { return alphabet; }, get lastChunkHandling() { return "stop-before-partial"; }},
].forEach((options) => {
test(string, options, {read: 0, written: 0}, []);
});
[
{alphabet, lastChunkHandling: "strict"},
{get alphabet() { return alphabet; }, get lastChunkHandling() { return "strict"; }},
].forEach((options) => {
shouldThrow(() => {
test(string, options, {read: 0, written: 0}, []);
}, SyntaxError);
});
});
[
{alphabet, lastChunkHandling: "stop-before-partial"},
{get alphabet() { return alphabet; }, get lastChunkHandling() { return "stop-before-partial"; }},
].forEach((options) => {
test("AAGA/v8", options, {read: 4, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 ", options, {read: 12, written: 3}, [0, 1, 128]);
});
[
{alphabet, lastChunkHandling: "strict"},
{get alphabet() { return alphabet; }, get lastChunkHandling() { return "strict"; }},
].forEach((options) => {
shouldThrow(() => {
test("AAGA/v8", options, {read: 0, written: 0}, []);
}, SyntaxError);
shouldThrow(() => {
test(" A A G A / v 8 ", options, {read: 0, written: 0}, []);
}, SyntaxError);
});
}
[
{alphabet: "base64url"},
{get alphabet() { return "base64url"; }},
].forEach((options) => {
test("", options, {read: 0, written: 0}, []);
test("AA", options, {read: 2, written: 1}, [0]);
test("AQ", options, {read: 2, written: 1}, [1]);
test("gA", options, {read: 2, written: 1}, [128]);
test("_g", options, {read: 2, written: 1}, [254]);
test("_w", options, {read: 2, written: 1}, [255]);
test("AAE", options, {read: 3, written: 2}, [0, 1]);
test("_v8", options, {read: 3, written: 2}, [254, 255]);
test("AAGA_v8", options, {read: 7, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA_v8z", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA_v8zzA", options, {read: 4, written: 3}, [0, 1, 128]);
test("AA==", options, {read: 4, written: 1}, [0]);
test("AQ==", options, {read: 4, written: 1}, [1]);
test("gA==", options, {read: 4, written: 1}, [128]);
test("_g==", options, {read: 4, written: 1}, [254]);
test("_w==", options, {read: 4, written: 1}, [255]);
test("AAE=", options, {read: 4, written: 2}, [0, 1]);
test("_v8=", options, {read: 4, written: 2}, [254, 255]);
test("AAGA_v8=", options, {read: 8, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA_v8z", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA_v8zzA==", options, {read: 4, written: 3}, [0, 1, 128]);
test(" ", options, {read: 2, written: 0}, []);
test(" A A ", options, {read: 8, written: 1}, [0]);
test(" A Q ", options, {read: 8, written: 1}, [1]);
test(" g A ", options, {read: 8, written: 1}, [128]);
test(" _ g ", options, {read: 8, written: 1}, [254]);
test(" _ w ", options, {read: 8, written: 1}, [255]);
test(" A A E ", options, {read: 11, written: 2}, [0, 1]);
test(" _ v 8 ", options, {read: 11, written: 2}, [254, 255]);
test(" A A G A _ v 8 ", options, {read: 23, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A _ v 8 z ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A _ v 8 z z A ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A = = ", options, {read: 14, written: 1}, [0]);
test(" A Q = = ", options, {read: 14, written: 1}, [1]);
test(" g A = = ", options, {read: 14, written: 1}, [128]);
test(" _ g = = ", options, {read: 14, written: 1}, [254]);
test(" _ w = = ", options, {read: 14, written: 1}, [255]);
test(" A A E = ", options, {read: 14, written: 2}, [0, 1]);
test(" _ v 8 = ", options, {read: 14, written: 2}, [254, 255]);
test(" A A G A _ v 8 = ", options, {read: 26, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A _ v 8 z ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A _ v 8 z z A = = ", options, {read: 12, written: 3}, [0, 1, 128]);
});
for (let lastChunkHandling of [undefined, "loose", "strict", "stop-before-partial"]) {
[
{alphabet: "base64url", lastChunkHandling},
{get alphabet() { return "base64url"; }, get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
test("", options, {read: 0, written: 0}, []);
test("AA==", options, {read: 4, written: 1}, [0]);
test("AQ==", options, {read: 4, written: 1}, [1]);
test("gA==", options, {read: 4, written: 1}, [128]);
test("_g==", options, {read: 4, written: 1}, [254]);
test("_w==", options, {read: 4, written: 1}, [255]);
test("AAE=", options, {read: 4, written: 2}, [0, 1]);
test("_v8=", options, {read: 4, written: 2}, [254, 255]);
test("AAGA_v8=", options, {read: 8, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA_v8z", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA_v8zzA", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA_v8zzA==", options, {read: 4, written: 3}, [0, 1, 128]);
test(" ", options, {read: 2, written: 0}, []);
test(" A A = = ", options, {read: 14, written: 1}, [0]);
test(" A Q = = ", options, {read: 14, written: 1}, [1]);
test(" g A = = ", options, {read: 14, written: 1}, [128]);
test(" _ g = = ", options, {read: 14, written: 1}, [254]);
test(" _ w = = ", options, {read: 14, written: 1}, [255]);
test(" A A E = ", options, {read: 14, written: 2}, [0, 1]);
test(" _ v 8 = ", options, {read: 14, written: 2}, [254, 255]);
test(" A A G A _ v 8 = ", options, {read: 26, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A _ v 8 z ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A _ v 8 z z A ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A _ v 8 z z A = = ", options, {read: 12, written: 3}, [0, 1, 128]);
});
[
"AA===", " A A = = = ",
"AQ===", " A Q = = = ",
"gA===", " g A = = = ",
"_g===", " _ g = = = ",
"_w===", " _ w = = = ",
"AAE==", " A A E = = ",
"_v8==", " _ v 8 = = ",
"AAGA_v8==", " A A G A _ v 8 = = ",
].forEach((string) => {
[
{alphabet: "base64url", lastChunkHandling},
{get alphabet() { return "base64url"; }, get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
shouldThrow(() => {
test(string, options, {read: 0, written: 0}, []);
}, SyntaxError);
});
});
}
for (let lastChunkHandling of [undefined, "loose"]) {
[
{alphabet: "base64url", lastChunkHandling},
{get alphabet() { return "base64url"; }, get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
test("AA", options, {read: 2, written: 1}, [0]);
test("AQ", options, {read: 2, written: 1}, [1]);
test("gA", options, {read: 2, written: 1}, [128]);
test("_g", options, {read: 2, written: 1}, [254]);
test("_w", options, {read: 2, written: 1}, [255]);
test("AAE", options, {read: 3, written: 2}, [0, 1]);
test("_v8", options, {read: 3, written: 2}, [254, 255]);
test("AAGA_v8", options, {read: 7, written: 5}, [0, 1, 128, 254, 255]);
test(" A A ", options, {read: 8, written: 1}, [0]);
test(" A Q ", options, {read: 8, written: 1}, [1]);
test(" g A ", options, {read: 8, written: 1}, [128]);
test(" _ g ", options, {read: 8, written: 1}, [254]);
test(" _ w ", options, {read: 8, written: 1}, [255]);
test(" A A E ", options, {read: 11, written: 2}, [0, 1]);
test(" _ v 8 ", options, {read: 11, written: 2}, [254, 255]);
test(" A A G A _ v 8 ", options, {read: 23, written: 5}, [0, 1, 128, 254, 255]);
});
}
[
"AA", " A A ",
"AQ", " A Q ",
"gA", " g A ",
"_g", " _ g ",
"_w", " _ w ",
"AAE", " A A E ",
"_v8", " _ v 8 ",
].forEach((string) => {
[
{alphabet: "base64url", lastChunkHandling: "stop-before-partial"},
{get alphabet() { return "base64url"; }, get lastChunkHandling() { return "stop-before-partial"; }},
].forEach((options) => {
test(string, options, {read: 0, written: 0}, []);
});
[
{alphabet: "base64url", lastChunkHandling: "strict"},
{get alphabet() { return "base64url"; }, get lastChunkHandling() { return "strict"; }},
].forEach((options) => {
shouldThrow(() => {
test(string, options, {read: 0, written: 0}, []);
}, SyntaxError);
});
});
[
{alphabet: "base64url", lastChunkHandling: "stop-before-partial"},
{get alphabet() { return "base64url"; }, get lastChunkHandling() { return "stop-before-partial"; }},
].forEach((options) => {
test("AAGA_v8", options, {read: 4, written: 3}, [0, 1, 128]);
test(" A A G A _ v 8 ", options, {read: 12, written: 3}, [0, 1, 128]);
});
[
{alphabet: "base64url", lastChunkHandling: "strict"},
{get alphabet() { return "base64url"; }, get lastChunkHandling() { return "strict"; }},
].forEach((options) => {
shouldThrow(() => {
test("AAGA_v8", options, {read: 0, written: 0}, []);
}, SyntaxError);
shouldThrow(() => {
test(" A A G A _ v 8 ", options, {read: 0, written: 0}, []);
}, SyntaxError);
});
for (let lastChunkHandling of [undefined, "loose", "strict", "stop-before-partial"]) {
[
{lastChunkHandling},
{get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
test("", options, {read: 0, written: 0}, []);
test("AA==", options, {read: 4, written: 1}, [0]);
test("AQ==", options, {read: 4, written: 1}, [1]);
test("gA==", options, {read: 4, written: 1}, [128]);
test("/g==", options, {read: 4, written: 1}, [254]);
test("/w==", options, {read: 4, written: 1}, [255]);
test("AAE=", options, {read: 4, written: 2}, [0, 1]);
test("/v8=", options, {read: 4, written: 2}, [254, 255]);
test("AAGA/v8=", options, {read: 8, written: 5}, [0, 1, 128, 254, 255]);
test("AAGA/v8z", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA", options, {read: 4, written: 3}, [0, 1, 128]);
test("AAGA/v8zzA==", options, {read: 4, written: 3}, [0, 1, 128]);
test(" ", options, {read: 2, written: 0}, []);
test(" A A = = ", options, {read: 14, written: 1}, [0]);
test(" A Q = = ", options, {read: 14, written: 1}, [1]);
test(" g A = = ", options, {read: 14, written: 1}, [128]);
test(" / g = = ", options, {read: 14, written: 1}, [254]);
test(" / w = = ", options, {read: 14, written: 1}, [255]);
test(" A A E = ", options, {read: 14, written: 2}, [0, 1]);
test(" / v 8 = ", options, {read: 14, written: 2}, [254, 255]);
test(" A A G A / v 8 = ", options, {read: 26, written: 5}, [0, 1, 128, 254, 255]);
test(" A A G A / v 8 z ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A ", options, {read: 12, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 z z A = = ", options, {read: 12, written: 3}, [0, 1, 128]);
});
[
"AA===", " A A = = = ",
"AQ===", " A Q = = = ",
"gA===", " g A = = = ",
"/g===", " / g = = = ",
"/w===", " / w = = = ",
"AAE==", " A A E = = ",
"/v8==", " / v 8 = = ",
"AAGA/v8==", " A A G A / v 8 = = ",
].forEach((string) => {
[
{lastChunkHandling},
{get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
shouldThrow(() => {
test(string, options, {read: 0, written: 0}, []);
}, SyntaxError);
});
});
}
for (let lastChunkHandling of [undefined, "loose"]) {
[
{lastChunkHandling},
{get lastChunkHandling() { return lastChunkHandling; }},
].forEach((options) => {
test("AA", options, {read: 2, written: 1}, [0]);
test("AQ", options, {read: 2, written: 1}, [1]);
test("gA", options, {read: 2, written: 1}, [128]);
test("/g", options, {read: 2, written: 1}, [254]);
test("/w", options, {read: 2, written: 1}, [255]);
test("AAE", options, {read: 3, written: 2}, [0, 1]);
test("/v8", options, {read: 3, written: 2}, [254, 255]);
test("AAGA/v8", options, {read: 7, written: 5}, [0, 1, 128, 254, 255]);
test(" A A ", options, {read: 8, written: 1}, [0]);
test(" A Q ", options, {read: 8, written: 1}, [1]);
test(" g A ", options, {read: 8, written: 1}, [128]);
test(" / g ", options, {read: 8, written: 1}, [254]);
test(" / w ", options, {read: 8, written: 1}, [255]);
test(" A A E ", options, {read: 11, written: 2}, [0, 1]);
test(" / v 8 ", options, {read: 11, written: 2}, [254, 255]);
test(" A A G A / v 8 ", options, {read: 23, written: 5}, [0, 1, 128, 254, 255]);
});
}
[
"AA", " A A ",
"AQ", " A Q ",
"gA", " g A ",
"/g", " / g ",
"/w", " / w ",
"AAE", " A A E ",
"/v8", " / v 8 ",
].forEach((string) => {
[
{lastChunkHandling: "stop-before-partial"},
{get lastChunkHandling() { return "stop-before-partial"; }},
].forEach((options) => {
test(string, options, {read: 0, written: 0}, []);
});
[
{lastChunkHandling: "strict"},
{get lastChunkHandling() { return "strict"; }},
].forEach((options) => {
shouldThrow(() => {
test(string, options, {read: 0, written: 0}, []);
}, SyntaxError);
});
});
[
{lastChunkHandling: "stop-before-partial"},
{get lastChunkHandling() { return "stop-before-partial"; }},
].forEach((options) => {
test("AAGA/v8", options, {read: 4, written: 3}, [0, 1, 128]);
test(" A A G A / v 8 ", options, {read: 12, written: 3}, [0, 1, 128]);
});
[
{lastChunkHandling: "strict"},
{get lastChunkHandling() { return "strict"; }},
].forEach((options) => {
shouldThrow(() => {
test("AAGA/v8", options, {read: 0, written: 0}, []);
}, SyntaxError);
shouldThrow(() => {
test(" A A G A / v 8 ", options, {read: 0, written: 0}, []);
}, SyntaxError);
});
shouldThrow(() => {
let uint8array = new Uint8Array;
$.detachArrayBuffer(uint8array.buffer);
uint8array.setFromBase64("");
}, TypeError);
for (let alphabet of [undefined, "base64", "base64url"]) {
shouldThrow(() => {
let uint8array = new Uint8Array;
uint8array.setFromBase64("", {
get alphabet() {
$.detachArrayBuffer(uint8array.buffer);
return alphabet;
},
});
}, TypeError);
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {
alphabet: {
toString() {
return alphabet;
},
},
});
}, TypeError);
}
for (let lastChunkHandling of [undefined, "loose", "strict", "stop-before-partial"]) {
shouldThrow(() => {
let uint8array = new Uint8Array;
uint8array.setFromBase64("", {
get lastChunkHandling() {
$.detachArrayBuffer(uint8array.buffer);
return lastChunkHandling;
},
});
}, TypeError);
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {
lastChunkHandling: {
toString() {
return lastChunkHandling;
},
},
});
}, TypeError);
}
for (let invalid of [undefined, null, false, true, 42, {}, []]) {
shouldThrow(() => {
(new Uint8Array).setFromBase64(invalid);
}, TypeError);
}
for (let options of [null, false, true, 42, "test"]) {
shouldThrow(() => {
(new Uint8Array).setFromBase64("", options);
}, TypeError);
}
for (let alphabet of [null, false, true, 42, "invalid", {}, []]) {
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {alphabet});
}, TypeError);
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {
get alphabet() { return alphabet; },
});
}, TypeError);
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {
alphabet: {
toString() {
return alphabet;
},
},
});
}, TypeError);
}
for (let lastChunkHandling of [null, false, true, 42, "invalid", {}, []]) {
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {lastChunkHandling});
}, TypeError);
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {
get lastChunkHandling() { return lastChunkHandling; },
});
}, TypeError);
shouldThrow(() => {
(new Uint8Array).setFromBase64("", {
lastChunkHandling: {
toString() {
return lastChunkHandling;
},
},
});
}, TypeError);
}