summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin (Kun) "Kassimo" Qian <kevinkassimo@gmail.com>2018-09-20 15:53:29 -0700
committerRyan Dahl <ry@tinyclouds.org>2018-09-20 18:53:29 -0400
commit4d16d54ff85d84723b8493e6a47caf70becc6660 (patch)
tree3eff7fdb9c77717e2930a548db374e40f7547279
parent52d415537b6b9f6be115dca4daee3f3a36be0ce9 (diff)
Add atob() and btoa() (#776)
-rw-r--r--js/globals.ts6
-rw-r--r--js/text_encoding.ts41
-rw-r--r--js/text_encoding_test.ts26
-rw-r--r--js/unit_tests.ts1
4 files changed, 74 insertions, 0 deletions
diff --git a/js/globals.ts b/js/globals.ts
index 912af7dc4..3e40db06c 100644
--- a/js/globals.ts
+++ b/js/globals.ts
@@ -25,6 +25,8 @@ declare global {
TextEncoder: typeof TextEncoder;
TextDecoder: typeof TextDecoder;
+ atob: typeof atob;
+ btoa: typeof btoa;
Headers: typeof Headers;
Blob: typeof Blob;
@@ -43,6 +45,8 @@ declare global {
// tslint:disable:variable-name
const TextEncoder: typeof textEncoding.TextEncoder;
const TextDecoder: typeof textEncoding.TextDecoder;
+ const atob: typeof textEncoding.atob;
+ const btoa: typeof textEncoding.btoa;
const Headers: typeof DenoHeaders;
const Blob: typeof DenoBlob;
// tslint:enable:variable-name
@@ -62,6 +66,8 @@ window.clearInterval = timers.clearTimer;
window.console = new Console(libdeno.print);
window.TextEncoder = textEncoding.TextEncoder;
window.TextDecoder = textEncoding.TextDecoder;
+window.atob = textEncoding.atob;
+window.btoa = textEncoding.btoa;
window.fetch = fetch_.fetch;
diff --git a/js/text_encoding.ts b/js/text_encoding.ts
index c8e262f5e..087bbc952 100644
--- a/js/text_encoding.ts
+++ b/js/text_encoding.ts
@@ -1,4 +1,45 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
+import * as base64 from "base64-js";
+import { DenoError, ErrorKind } from "./errors";
+
+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), "=");
+ }
+ let byteArray;
+ try {
+ byteArray = base64.toByteArray(s);
+ } catch (_) {
+ throw new DenoError(
+ ErrorKind.InvalidInput,
+ "The string to be decoded is not correctly encoded"
+ );
+ }
+ let result = "";
+ for (let i = 0; i < byteArray.length; i++) {
+ result += String.fromCharCode(byteArray[i]);
+ }
+ return result;
+}
+
+export function btoa(s: string): string {
+ const byteArray = [];
+ for (let i = 0; i < s.length; i++) {
+ const charCode = s[i].charCodeAt(0);
+ if (charCode > 0xff) {
+ throw new DenoError(
+ ErrorKind.InvalidInput,
+ "The string to be encoded contains characters " +
+ "outside of the Latin1 range."
+ );
+ }
+ byteArray.push(charCode);
+ }
+ const result = base64.fromByteArray(Uint8Array.from(byteArray));
+ return result;
+}
// @types/text-encoding relies on lib.dom.d.ts for some interfaces. We do not
// want to include lib.dom.d.ts (due to size) into deno's global type scope.
diff --git a/js/text_encoding_test.ts b/js/text_encoding_test.ts
new file mode 100644
index 000000000..7a9aec833
--- /dev/null
+++ b/js/text_encoding_test.ts
@@ -0,0 +1,26 @@
+// Copyright 2018 the Deno authors. All rights reserved. MIT license.
+import { test, assert, assertEqual } from "./test_util.ts";
+
+test(function atobSuccess() {
+ const text = "hello world";
+ const encoded = btoa(text);
+ assertEqual(encoded, "aGVsbG8gd29ybGQ=");
+});
+
+test(function btoaSuccess() {
+ const encoded = "aGVsbG8gd29ybGQ=";
+ const decoded = atob(encoded);
+ assertEqual(decoded, "hello world");
+});
+
+test(function btoaFailed() {
+ const text = "你好";
+ let err;
+ try {
+ btoa(text);
+ } catch (e) {
+ err = e;
+ }
+ assert(!!err);
+ assertEqual(err.name, "InvalidInput");
+});
diff --git a/js/unit_tests.ts b/js/unit_tests.ts
index a535aea55..9b85cf3ec 100644
--- a/js/unit_tests.ts
+++ b/js/unit_tests.ts
@@ -15,3 +15,4 @@ import "./blob_test.ts";
import "./timers_test.ts";
import "./symlink_test.ts";
import "./platform_test.ts";
+import "./text_encoding_test.ts";