diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/bindings.rs | 68 | ||||
-rw-r--r-- | core/encode_decode_test.js | 40 | ||||
-rw-r--r-- | core/isolate.rs | 14 |
3 files changed, 122 insertions, 0 deletions
diff --git a/core/bindings.rs b/core/bindings.rs index cb9c15ee1..9df9a78a0 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -35,6 +35,12 @@ lazy_static! { v8::ExternalReference { function: queue_microtask.map_fn_to() }, + v8::ExternalReference { + function: encode.map_fn_to() + }, + v8::ExternalReference { + function: decode.map_fn_to() + }, ]); } @@ -156,6 +162,22 @@ pub fn initialize_context<'s>( format_error_val.into(), ); + let mut encode_tmpl = v8::FunctionTemplate::new(scope, encode); + let encode_val = encode_tmpl.get_function(scope, context).unwrap(); + core_val.set( + context, + v8::String::new(scope, "encode").unwrap().into(), + encode_val.into(), + ); + + let mut decode_tmpl = v8::FunctionTemplate::new(scope, decode); + let decode_val = decode_tmpl.get_function(scope, context).unwrap(); + core_val.set( + context, + v8::String::new(scope, "decode").unwrap().into(), + decode_val.into(), + ); + core_val.set_accessor( context, v8::String::new(scope, "shared").unwrap().into(), @@ -551,6 +573,52 @@ fn format_error( rv.set(e.into()) } +fn encode( + scope: v8::FunctionCallbackScope, + args: v8::FunctionCallbackArguments, + mut rv: v8::ReturnValue, +) { + let text = match v8::Local::<v8::String>::try_from(args.get(0)) { + Ok(s) => s, + Err(_) => { + let msg = v8::String::new(scope, "Invalid argument").unwrap(); + let exception = v8::Exception::type_error(scope, msg); + scope.isolate().throw_exception(exception); + return; + } + }; + let text_str = text.to_rust_string_lossy(scope); + let text_bytes = text_str.as_bytes().to_vec().into_boxed_slice(); + let buf = boxed_slice_to_uint8array(scope, text_bytes); + rv.set(buf.into()) +} + +fn decode( + scope: v8::FunctionCallbackScope, + args: v8::FunctionCallbackArguments, + mut rv: v8::ReturnValue, +) { + let buf = match v8::Local::<v8::ArrayBufferView>::try_from(args.get(0)) { + Ok(view) => { + let byte_offset = view.byte_offset(); + let byte_length = view.byte_length(); + let backing_store = view.buffer().unwrap().get_backing_store(); + let buf = unsafe { &**backing_store.get() }; + &buf[byte_offset..byte_offset + byte_length] + } + Err(..) => { + let msg = v8::String::new(scope, "Invalid argument").unwrap(); + let exception = v8::Exception::type_error(scope, msg); + scope.isolate().throw_exception(exception); + return; + } + }; + + let text_str = + v8::String::new_from_utf8(scope, &buf, v8::NewStringType::Normal).unwrap(); + rv.set(text_str.into()) +} + fn queue_microtask( scope: v8::FunctionCallbackScope, args: v8::FunctionCallbackArguments, diff --git a/core/encode_decode_test.js b/core/encode_decode_test.js new file mode 100644 index 000000000..8a366dd66 --- /dev/null +++ b/core/encode_decode_test.js @@ -0,0 +1,40 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +function assertArrayEquals(a1, a2) { + if (a1.length !== a2.length) throw Error("assert"); + + for (const index in a1) { + if (a1[index] !== a2[index]) { + throw Error("assert"); + } + } +} + +function main() { + // prettier-ignore + const fixture1 = [ + 0xf0, 0x9d, 0x93, 0xbd, + 0xf0, 0x9d, 0x93, 0xae, + 0xf0, 0x9d, 0x94, 0x81, + 0xf0, 0x9d, 0x93, 0xbd + ]; + // prettier-ignore + const fixture2 = [ + 72, 101, 108, 108, + 111, 32, 239, 191, + 189, 239, 191, 189, + 32, 87, 111, 114, + 108, 100 + ]; + + assertArrayEquals(Array.from(Deno.core.encode("𝓽𝓮𝔁𝓽")), fixture1); + assertArrayEquals( + Array.from(Deno.core.encode("Hello \udc12\ud834 World")), + fixture2 + ); + + assert(Deno.core.decode(new Uint8Array(fixture1)) === "𝓽𝓮𝔁𝓽"); + assert(Deno.core.decode(new Uint8Array(fixture2)) === "Hello �� World"); +} + +main(); diff --git a/core/isolate.rs b/core/isolate.rs index cb4bdaaf4..9efe86c0e 100644 --- a/core/isolate.rs +++ b/core/isolate.rs @@ -1113,6 +1113,20 @@ pub mod tests { } #[test] + fn test_encode_decode() { + run_in_task(|mut cx| { + let (mut isolate, _dispatch_count) = setup(Mode::Async); + js_check(isolate.execute( + "encode_decode_test.js", + include_str!("encode_decode_test.js"), + )); + if let Poll::Ready(Err(_)) = isolate.poll_unpin(&mut cx) { + unreachable!(); + } + }); + } + + #[test] fn will_snapshot() { let snapshot = { let mut isolate = Isolate::new(StartupData::None, true); |