Skip to content

Commit

Permalink
Deploying to gh-pages from @ 66fa8c8 🚀
Browse files Browse the repository at this point in the history
  • Loading branch information
bakkot committed Jun 11, 2024
1 parent 7e919b7 commit f57b8eb
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 41 deletions.
90 changes: 57 additions & 33 deletions polyfill-core.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function skipAsciiWhitespace(string, index) {

function fromBase64(string, alphabet, lastChunkHandling, maxLength) {
if (maxLength === 0) {
return { read: 0, bytes: [] };
return { read: 0, bytes: [], error: null };
}

let read = 0;
Expand All @@ -138,62 +138,69 @@ function fromBase64(string, alphabet, lastChunkHandling, maxLength) {
if (index === string.length) {
if (chunk.length > 0) {
if (lastChunkHandling === 'stop-before-partial') {
return { bytes, read };
return { bytes, read, error: null };
} else if (lastChunkHandling === 'loose') {
if (chunk.length === 1) {
throw new SyntaxError('malformed padding: exactly one additional character');
let error = new SyntaxError('malformed padding: exactly one additional character');
return { bytes, read, error };
}
bytes.push(...decodeBase64Chunk(chunk, false));
} else {
assert(lastChunkHandling === 'strict');
throw new SyntaxError('missing padding');
let error = new SyntaxError('missing padding');
return { bytes, read, error };
}
}
return { bytes, read: string.length };
return { bytes, read: string.length, error: null };
}
let char = string[index];
++index;
if (char === '=') {
if (chunk.length < 2) {
throw new SyntaxError('padding is too early');
let error = new SyntaxError('padding is too early');
return { bytes, read, error };
}
index = skipAsciiWhitespace(string, index);
if (chunk.length === 2) {
if (index === string.length) {
if (lastChunkHandling === 'stop-before-partial') {
// two characters then `=` then EOS: this is, technically, a partial chunk
return { bytes, read };
return { bytes, read, error: null };
}
throw new SyntaxError('malformed padding - only one =');
let error = new SyntaxError('malformed padding - only one =');
return { bytes, read, error };
}
if (string[index] === '=') {
++index;
index = skipAsciiWhitespace(string, index);
}
}
if (index < string.length) {
throw new SyntaxError('unexpected character after padding');
let error = new SyntaxError('unexpected character after padding');
return { bytes, read, error };
}
bytes.push(...decodeBase64Chunk(chunk, lastChunkHandling === 'strict'));
assert(bytes.length <= maxLength);
return { bytes, read: string.length };
return { bytes, read: string.length, error: null };
}
if (alphabet === 'base64url') {
if (char === '+' || char === '/') {
throw new SyntaxError(`unexpected character ${JSON.stringify(char)}`);
let error = new SyntaxError(`unexpected character ${JSON.stringify(char)}`);
return { bytes, read, error };
} else if (char === '-') {
char = '+';
} else if (char === '_') {
char = '/';
}
}
if (!base64Characters.includes(char)) {
throw new SyntaxError(`unexpected character ${JSON.stringify(char)}`);
let error = new SyntaxError(`unexpected character ${JSON.stringify(char)}`);
return { bytes, read, error };
}
let remainingBytes = maxLength - bytes.length;
if (remainingBytes === 1 && chunk.length === 2 || remainingBytes === 2 && chunk.length === 3) {
// special case: we can fit exactly the number of bytes currently represented by chunk, so we were just checking for `=`
return { bytes, read };
return { bytes, read, error: null };
}

chunk += char;
Expand All @@ -203,7 +210,7 @@ function fromBase64(string, alphabet, lastChunkHandling, maxLength) {
read = index;
assert(bytes.length <= maxLength);
if (bytes.length === maxLength) {
return { bytes, read };
return { bytes, read, error: null };
}
}
}
Expand Down Expand Up @@ -231,14 +238,21 @@ export function base64ToUint8Array(string, options, into) {

let maxLength = into ? into.length : 2 ** 53 - 1;

let { bytes, read } = fromBase64(string, alphabet, lastChunkHandling, maxLength);
let { bytes, read, error } = fromBase64(string, alphabet, lastChunkHandling, maxLength);
if (error && !into) {
throw error;
}

bytes = new Uint8Array(bytes);
if (into && bytes.length > 0) {
assert(bytes.length <= into.length);
into.set(bytes);
}

if (error) {
throw error;
}

return { read, bytes };
}

Expand All @@ -254,6 +268,26 @@ export function uint8ArrayToHex(arr) {
return out;
}

function fromHex(string, maxLength) {
let bytes = [];
let read = 0;
if (maxLength > 0) {
while (read < string.length) {
let hexits = string.slice(read, read + 2);
if (/[^0-9a-fA-F]/.test(hexits)) {
let error = new SyntaxError('string should only contain hex characters');
return { read, bytes, error }
}
bytes.push(parseInt(hexits, 16));
read += 2;
if (bytes.length === maxLength) {
break;
}
}
}
return { read, bytes, error: null }
}

export function hexToUint8Array(string, into) {
if (typeof string !== 'string') {
throw new TypeError('expected string to be a string');
Expand All @@ -266,23 +300,9 @@ export function hexToUint8Array(string, into) {
}

let maxLength = into ? into.length : 2 ** 53 - 1;

// TODO should hex allow whitespace?
// TODO should hex support lastChunkHandling? (only 'strict' or 'stop-before-partial')
let bytes = [];
let index = 0;
if (maxLength > 0) {
while (index < string.length) {
let hexits = string.slice(index, index + 2);
if (/[^0-9a-fA-F]/.test(hexits)) {
throw new SyntaxError('string should only contain hex characters');
}
bytes.push(parseInt(hexits, 16));
index += 2;
if (bytes.length === maxLength) {
break;
}
}
let { read, bytes, error } = fromHex(string, maxLength);
if (error && !into) {
throw error;
}

bytes = new Uint8Array(bytes);
Expand All @@ -291,5 +311,9 @@ export function hexToUint8Array(string, into) {
into.set(bytes);
}

return { read: index, bytes };
if (error) {
throw error;
}

return { read, bytes };
}
Loading

0 comments on commit f57b8eb

Please sign in to comment.