diff options
-rw-r--r-- | cli/tests/unit/text_encoding_test.ts | 58 | ||||
-rw-r--r-- | ext/web/10_filereader.js | 12 | ||||
-rw-r--r-- | ext/web/lib.rs | 6 |
3 files changed, 66 insertions, 10 deletions
diff --git a/cli/tests/unit/text_encoding_test.ts b/cli/tests/unit/text_encoding_test.ts index 70942d98d..06ec09048 100644 --- a/cli/tests/unit/text_encoding_test.ts +++ b/cli/tests/unit/text_encoding_test.ts @@ -247,6 +247,7 @@ Deno.test(function toStringShouldBeWebCompatibility() { const decoder = new TextDecoder(); assertEquals(decoder.toString(), "[object TextDecoder]"); }); + Deno.test(function textEncoderShouldCoerceToString() { const encoder = new TextEncoder(); const fixutreText = "text"; @@ -261,3 +262,60 @@ Deno.test(function textEncoderShouldCoerceToString() { const decoded = decoder.decode(bytes); assertEquals(decoded, fixutreText); }); + +Deno.test(function binaryEncode() { + // @ts-ignore: Deno.core allowed + const ops = Deno.core.ops; + function asBinaryString(bytes: Uint8Array): string { + return Array.from(bytes).map( + (v: number) => String.fromCodePoint(v), + ).join(""); + } + + function decodeBinary(binaryString: string) { + const chars: string[] = Array.from(binaryString); + return chars.map((v: string): number | undefined => v.codePointAt(0)); + } + + // invalid utf-8 code points + const invalid = new Uint8Array([0xC0]); + assertEquals( + ops.op_encode_binary_string(invalid), + asBinaryString(invalid), + ); + + const invalid2 = new Uint8Array([0xC1]); + assertEquals( + ops.op_encode_binary_string(invalid2), + asBinaryString(invalid2), + ); + + for (let i = 0, j = 255; i <= 255; i++, j--) { + const bytes = new Uint8Array([i, j]); + const binaryString = ops.op_encode_binary_string(bytes); + assertEquals( + binaryString, + asBinaryString(bytes), + ); + assertEquals(Array.from(bytes), decodeBinary(binaryString)); + } + + const inputs = [ + "σ😀", + "Кириллица is Cyrillic", + "𝓽𝓮𝔁𝓽", + "lone𝄞\ud888surrogate", + "\udc00\ud800", + "\ud800", + ]; + for (const input of inputs) { + const bytes = new TextEncoder().encode(input); + const binaryString = ops.op_encode_binary_string(bytes); + assertEquals( + binaryString, + asBinaryString(bytes), + ); + + assertEquals(Array.from(bytes), decodeBinary(binaryString)); + } +}); diff --git a/ext/web/10_filereader.js b/ext/web/10_filereader.js index 8a76b2e0f..49f4babe1 100644 --- a/ext/web/10_filereader.js +++ b/ext/web/10_filereader.js @@ -13,6 +13,7 @@ "use strict"; ((window) => { + const core = window.Deno.core; const webidl = window.__bootstrap.webidl; const { forgivingBase64Encode } = window.__bootstrap.infra; const { ProgressEvent } = window.__bootstrap.event; @@ -21,8 +22,6 @@ const { parseMimeType } = window.__bootstrap.mimesniff; const { DOMException } = window.__bootstrap.domException; const { - ArrayPrototypeJoin, - ArrayPrototypeMap, ArrayPrototypePush, ArrayPrototypeReduce, FunctionPrototypeCall, @@ -33,7 +32,6 @@ ObjectPrototypeIsPrototypeOf, queueMicrotask, SafeArrayIterator, - StringFromCodePoint, Symbol, TypedArrayPrototypeSet, TypeError, @@ -170,13 +168,7 @@ break; } case "BinaryString": - this[result] = ArrayPrototypeJoin( - ArrayPrototypeMap( - [...new Uint8Array(bytes.buffer)], - (v) => StringFromCodePoint(v), - ), - "", - ); + this[result] = core.ops.op_encode_binary_string(bytes); break; case "Text": { let decoder = undefined; diff --git a/ext/web/lib.rs b/ext/web/lib.rs index 85e32b70a..8a9d3e18c 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -94,6 +94,7 @@ pub fn init<P: TimersPermission + 'static>( op_encoding_new_decoder::decl(), op_encoding_decode::decl(), op_encoding_encode_into::decl(), + op_encode_binary_string::decl(), op_blob_create_part::decl(), op_blob_slice_part::decl(), op_blob_read_part::decl(), @@ -337,6 +338,11 @@ fn op_encoding_encode_into( Ok(()) } +#[op] +fn op_encode_binary_string(s: &[u8]) -> ByteString { + ByteString::from(s) +} + /// Creates a [`CancelHandle`] resource that can be used to cancel invocations of certain ops. #[op(fast)] pub fn op_cancel_handle(state: &mut OpState) -> u32 { |