diff options
-rw-r--r-- | js/text_encoding.ts | 24 | ||||
-rw-r--r-- | js/text_encoding_test.ts | 37 |
2 files changed, 53 insertions, 8 deletions
diff --git a/js/text_encoding.ts b/js/text_encoding.ts index 883451631..03cc966b1 100644 --- a/js/text_encoding.ts +++ b/js/text_encoding.ts @@ -176,20 +176,28 @@ class UTF8Encoder implements Encoder { /** Decodes a string of data which has been encoded using base-64. */ export function atob(s: string): string { - const rem = s.length % 4; - // base64-js requires length exactly times of 4 - if (rem > 0) { - s = s.padEnd(s.length + (4 - rem), "="); + s = String(s); + s = s.replace(/[\t\n\f\r ]/g, ""); + + if (s.length % 4 === 0) { + s = s.replace(/==?$/, ""); } - let byteArray; - try { - byteArray = base64.toByteArray(s); - } catch (_) { + + const rem = s.length % 4; + if (rem === 1 || /[^+/0-9A-Za-z]/.test(s)) { + // TODO: throw `DOMException` throw new DenoError( ErrorKind.InvalidInput, "The string to be decoded is not correctly encoded" ); } + + // base64-js requires length exactly times of 4 + if (rem > 0) { + s = s.padEnd(s.length + (4 - rem), "="); + } + + const byteArray: Uint8Array = base64.toByteArray(s); let result = ""; for (let i = 0; i < byteArray.length; i++) { result += String.fromCharCode(byteArray[i]); diff --git a/js/text_encoding_test.ts b/js/text_encoding_test.ts index 30a75f8d4..b5ce78a8f 100644 --- a/js/text_encoding_test.ts +++ b/js/text_encoding_test.ts @@ -13,6 +13,43 @@ test(function atobSuccess(): void { assertEquals(decoded, "hello world"); }); +test(function atobWithAsciiWhitespace(): void { + const encodedList = [ + " aGVsbG8gd29ybGQ=", + " aGVsbG8gd29ybGQ=", + "aGVsbG8gd29ybGQ= ", + "aGVsbG8gd29ybGQ=\n", + "aGVsbG\t8gd29ybGQ=", + `aGVsbG\t8g + d29ybGQ=` + ]; + + for (let encoded of encodedList) { + let decoded = atob(encoded); + assertEquals(decoded, "hello world"); + } +}); + +test(function atobThrows(): void { + let threw = false; + try { + atob("aGVsbG8gd29ybGQ=="); + } catch (e) { + threw = true; + } + assert(threw); +}); + +test(function atobThrows2(): void { + let threw = false; + try { + atob("aGVsbG8gd29ybGQ==="); + } catch (e) { + threw = true; + } + assert(threw); +}); + test(function btoaFailed(): void { const text = "你好"; let err; |