diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/Cargo.toml | 4 | ||||
-rw-r--r-- | core/README.md | 4 | ||||
-rw-r--r-- | core/benches/op_baseline.rs | 31 | ||||
-rw-r--r-- | core/core.js | 22 | ||||
-rw-r--r-- | core/examples/hello_world.rs | 12 | ||||
-rw-r--r-- | core/examples/http_bench_bin_ops.js | 71 | ||||
-rw-r--r-- | core/examples/http_bench_bin_ops.rs | 228 | ||||
-rw-r--r-- | core/examples/http_bench_json_ops.js | 12 | ||||
-rw-r--r-- | core/examples/http_bench_json_ops.rs | 10 | ||||
-rw-r--r-- | core/lib.deno_core.d.ts | 8 | ||||
-rw-r--r-- | core/lib.rs | 8 | ||||
-rw-r--r-- | core/ops.rs | 4 | ||||
-rw-r--r-- | core/ops_bin.rs | 142 | ||||
-rw-r--r-- | core/ops_json.rs | 18 | ||||
-rw-r--r-- | core/runtime.rs | 4 |
15 files changed, 50 insertions, 528 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index bf4c7dc14..572d48713 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -27,10 +27,6 @@ serde_v8 = { version = "0.1.0", path = "../serde_v8" } url = { version = "2.2.1", features = ["serde"] } [[example]] -name = "http_bench_bin_ops" -path = "examples/http_bench_bin_ops.rs" - -[[example]] name = "http_bench_json_ops" path = "examples/http_bench_json_ops.rs" diff --git a/core/README.md b/core/README.md index 55ec05a2d..fc1fc3d31 100644 --- a/core/README.md +++ b/core/README.md @@ -21,9 +21,7 @@ function to trigger the "dispatch" callback in Rust. The user is responsible for encoding both the request and response into a Uint8Array. Documentation for this crate is thin at the moment. Please see -[http_bench_bin_ops.rs](https://github.com/denoland/deno/blob/main/core/examples/http_bench_bin_ops.rs) -and -[http_bench_json_ops.rs](https://github.com/denoland/deno/blob/main/core/examples/http_bench_json_ops.rs) +[http_bench_ops.rs](https://github.com/denoland/deno/blob/main/core/examples/http_bench_ops.rs) as a simple example of usage. TypeScript support and a lot of other functionality is not available at this diff --git a/core/benches/op_baseline.rs b/core/benches/op_baseline.rs index 81c5d89b8..5287a7a8b 100644 --- a/core/benches/op_baseline.rs +++ b/core/benches/op_baseline.rs @@ -1,9 +1,8 @@ use bencher::{benchmark_group, benchmark_main, Bencher}; -use deno_core::bin_op_sync; use deno_core::error::AnyError; -use deno_core::json_op_async; -use deno_core::json_op_sync; +use deno_core::op_async; +use deno_core::op_sync; use deno_core::v8; use deno_core::JsRuntime; use deno_core::Op; @@ -16,9 +15,8 @@ use std::rc::Rc; fn create_js_runtime() -> JsRuntime { let mut runtime = JsRuntime::new(Default::default()); - runtime.register_op("pi_bin", bin_op_sync(|_, _, _| Ok(314159))); - runtime.register_op("pi_json", json_op_sync(|_, _: (), _| Ok(314159))); - runtime.register_op("pi_async", json_op_async(op_pi_async)); + runtime.register_op("pi_json", op_sync(|_, _: (), _| Ok(314159))); + runtime.register_op("pi_async", op_async(op_pi_async)); runtime .register_op("nop", |_, _, _| Op::Sync(OpResponse::Value(Box::new(9)))); @@ -70,20 +68,11 @@ pub fn bench_runtime_js_async(b: &mut Bencher, src: &str) { }); } -fn bench_op_pi_bin(b: &mut Bencher) { - bench_runtime_js( - b, - r#"for(let i=0; i < 1e3; i++) { - Deno.core.binOpSync("pi_bin", 0, null); - }"#, - ); -} - fn bench_op_pi_json(b: &mut Bencher) { bench_runtime_js( b, r#"for(let i=0; i < 1e3; i++) { - Deno.core.jsonOpSync("pi_json", null); + Deno.core.opSync("pi_json", null); }"#, ); } @@ -101,16 +90,10 @@ fn bench_op_async(b: &mut Bencher) { bench_runtime_js_async( b, r#"for(let i=0; i < 1e3; i++) { - Deno.core.jsonOpAsync("pi_async", null); + Deno.core.opAsync("pi_async", null); }"#, ); } -benchmark_group!( - benches, - bench_op_pi_bin, - bench_op_pi_json, - bench_op_nop, - bench_op_async -); +benchmark_group!(benches, bench_op_pi_json, bench_op_nop, bench_op_async); benchmark_main!(benches); diff --git a/core/core.js b/core/core.js index 3142aa93a..0697458de 100644 --- a/core/core.js +++ b/core/core.js @@ -102,7 +102,7 @@ return res; } - function jsonOpAsync(opName, args = null, zeroCopy = null) { + function opAsync(opName, args = null, zeroCopy = null) { const promiseId = nextPromiseId++; const maybeError = dispatch(opName, promiseId, args, zeroCopy); // Handle sync error (e.g: error parsing args) @@ -110,31 +110,21 @@ return setPromise(promiseId).then(unwrapOpResult); } - function jsonOpSync(opName, args = null, zeroCopy = null) { + function opSync(opName, args = null, zeroCopy = null) { return unwrapOpResult(dispatch(opName, null, args, zeroCopy)); } - function binOpSync(opName, args = null, zeroCopy = null) { - return jsonOpSync(opName, args, zeroCopy); - } - - function binOpAsync(opName, args = null, zeroCopy = null) { - return jsonOpAsync(opName, args, zeroCopy); - } - function resources() { - return Object.fromEntries(jsonOpSync("op_resources")); + return Object.fromEntries(opSync("op_resources")); } function close(rid) { - jsonOpSync("op_close", rid); + opSync("op_close", rid); } Object.assign(window.Deno.core, { - binOpAsync, - binOpSync, - jsonOpAsync, - jsonOpSync, + opAsync, + opSync, dispatch: send, dispatchByName: dispatch, ops, diff --git a/core/examples/hello_world.rs b/core/examples/hello_world.rs index 11fc5ff0e..154c05d97 100644 --- a/core/examples/hello_world.rs +++ b/core/examples/hello_world.rs @@ -2,7 +2,7 @@ //! This example shows you how to define ops in Rust and then call them from //! JavaScript. -use deno_core::json_op_sync; +use deno_core::op_sync; use deno_core::JsRuntime; use std::io::Write; @@ -26,7 +26,7 @@ fn main() { // The op_fn callback takes a state object OpState, // a structured arg of type `T` and an optional ZeroCopyBuf, // a mutable reference to a JavaScript ArrayBuffer - json_op_sync(|_state, msg: Option<String>, zero_copy| { + op_sync(|_state, msg: Option<String>, zero_copy| { let mut out = std::io::stdout(); // Write msg to stdout @@ -46,10 +46,10 @@ fn main() { // Register the JSON op for summing a number array. runtime.register_op( "op_sum", - // The json_op_sync function automatically deserializes + // The op_sync function automatically deserializes // the first ZeroCopyBuf and serializes the return value // to reduce boilerplate - json_op_sync(|_state, nums: Vec<f64>, _| { + op_sync(|_state, nums: Vec<f64>, _| { // Sum inputs let sum = nums.iter().fold(0.0, |a, v| a + v); // return as a Result<f64, AnyError> @@ -91,11 +91,11 @@ const arr = [1, 2, 3]; print("The sum of"); print(arr); print("is"); -print(Deno.core.jsonOpSync('op_sum', arr)); +print(Deno.core.opSync('op_sum', arr)); // And incorrect usage try { - print(Deno.core.jsonOpSync('op_sum', 0)); + print(Deno.core.opSync('op_sum', 0)); } catch(e) { print('Exception:'); print(e); diff --git a/core/examples/http_bench_bin_ops.js b/core/examples/http_bench_bin_ops.js deleted file mode 100644 index c3128dbb2..000000000 --- a/core/examples/http_bench_bin_ops.js +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -// This is not a real HTTP server. We read blindly one time into 'requestBuf', -// then write this fixed 'responseBuf'. The point of this benchmark is to -// exercise the event loop in a simple yet semi-realistic way. -const requestBuf = new Uint8Array(64 * 1024); -const responseBuf = new Uint8Array( - "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n" - .split("") - .map((c) => c.charCodeAt(0)), -); - -/** Listens on 0.0.0.0:4500, returns rid. */ -function listen() { - return Deno.core.binOpSync("listen", 0); -} - -/** Accepts a connection, returns rid. */ -function accept(rid) { - return Deno.core.binOpAsync("accept", rid); -} - -/** - * Reads a packet from the rid, presumably an http request. data is ignored. - * Returns bytes read. - */ -function read(rid, data) { - return Deno.core.binOpAsync("read", rid, data); -} - -/** Writes a fixed HTTP response to the socket rid. Returns bytes written. */ -function write(rid, data) { - return Deno.core.binOpAsync("write", rid, data); -} - -function close(rid) { - Deno.core.binOpSync("close", rid); -} - -async function serve(rid) { - try { - while (true) { - await read(rid, requestBuf); - await write(rid, responseBuf); - } - } catch (e) { - if ( - !e.message.includes("Broken pipe") && - !e.message.includes("Connection reset by peer") - ) { - throw e; - } - } - close(rid); -} - -async function main() { - Deno.core.ops(); - Deno.core.registerErrorClass("Error", Error); - - const listenerRid = listen(); - Deno.core.print( - `http_bench_bin_ops listening on http://127.0.0.1:4544/\n`, - ); - - while (true) { - const rid = await accept(listenerRid); - serve(rid); - } -} - -main(); diff --git a/core/examples/http_bench_bin_ops.rs b/core/examples/http_bench_bin_ops.rs deleted file mode 100644 index 0ba7b6706..000000000 --- a/core/examples/http_bench_bin_ops.rs +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::error::bad_resource_id; -use deno_core::error::null_opbuf; -use deno_core::error::AnyError; -use deno_core::AsyncRefCell; -use deno_core::CancelHandle; -use deno_core::CancelTryFuture; -use deno_core::JsRuntime; -use deno_core::OpState; -use deno_core::RcRef; -use deno_core::Resource; -use deno_core::ResourceId; -use deno_core::ZeroCopyBuf; -use std::cell::RefCell; -use std::convert::TryFrom; -use std::env; -use std::io::Error; -use std::net::SocketAddr; -use std::rc::Rc; -use tokio::io::AsyncReadExt; -use tokio::io::AsyncWriteExt; - -struct Logger; - -impl log::Log for Logger { - fn enabled(&self, metadata: &log::Metadata) -> bool { - metadata.level() <= log::max_level() - } - - fn log(&self, record: &log::Record) { - if self.enabled(record.metadata()) { - println!("{} - {}", record.level(), record.args()); - } - } - - fn flush(&self) {} -} - -// Note: a `tokio::net::TcpListener` doesn't need to be wrapped in a cell, -// because it only supports one op (`accept`) which does not require a mutable -// reference to the listener. -struct TcpListener { - inner: tokio::net::TcpListener, - cancel: CancelHandle, -} - -impl TcpListener { - async fn accept(self: Rc<Self>) -> Result<TcpStream, Error> { - let cancel = RcRef::map(&self, |r| &r.cancel); - let stream = self.inner.accept().try_or_cancel(cancel).await?.0.into(); - Ok(stream) - } -} - -impl Resource for TcpListener { - fn close(self: Rc<Self>) { - self.cancel.cancel(); - } -} - -impl TryFrom<std::net::TcpListener> for TcpListener { - type Error = Error; - fn try_from( - std_listener: std::net::TcpListener, - ) -> Result<Self, Self::Error> { - tokio::net::TcpListener::try_from(std_listener).map(|tokio_listener| Self { - inner: tokio_listener, - cancel: Default::default(), - }) - } -} - -struct TcpStream { - rd: AsyncRefCell<tokio::net::tcp::OwnedReadHalf>, - wr: AsyncRefCell<tokio::net::tcp::OwnedWriteHalf>, - // When a `TcpStream` resource is closed, all pending 'read' ops are - // canceled, while 'write' ops are allowed to complete. Therefore only - // 'read' futures are attached to this cancel handle. - cancel: CancelHandle, -} - -impl TcpStream { - async fn read(self: Rc<Self>, buf: &mut [u8]) -> Result<usize, Error> { - let mut rd = RcRef::map(&self, |r| &r.rd).borrow_mut().await; - let cancel = RcRef::map(self, |r| &r.cancel); - rd.read(buf).try_or_cancel(cancel).await - } - - async fn write(self: Rc<Self>, buf: &[u8]) -> Result<usize, Error> { - let mut wr = RcRef::map(self, |r| &r.wr).borrow_mut().await; - wr.write(buf).await - } -} - -impl Resource for TcpStream { - fn close(self: Rc<Self>) { - self.cancel.cancel() - } -} - -impl From<tokio::net::TcpStream> for TcpStream { - fn from(s: tokio::net::TcpStream) -> Self { - let (rd, wr) = s.into_split(); - Self { - rd: rd.into(), - wr: wr.into(), - cancel: Default::default(), - } - } -} - -fn create_js_runtime() -> JsRuntime { - let mut runtime = JsRuntime::new(Default::default()); - runtime.register_op("listen", deno_core::bin_op_sync(op_listen)); - runtime.register_op("close", deno_core::bin_op_sync(op_close)); - runtime.register_op("accept", deno_core::bin_op_async(op_accept)); - runtime.register_op("read", deno_core::bin_op_async(op_read)); - runtime.register_op("write", deno_core::bin_op_async(op_write)); - runtime -} - -fn op_listen( - state: &mut OpState, - _rid: ResourceId, - _bufs: Option<ZeroCopyBuf>, -) -> Result<u32, AnyError> { - log::debug!("listen"); - let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap(); - let std_listener = std::net::TcpListener::bind(&addr)?; - std_listener.set_nonblocking(true)?; - let listener = TcpListener::try_from(std_listener)?; - let rid = state.resource_table.add(listener); - Ok(rid) -} - -fn op_close( - state: &mut OpState, - rid: ResourceId, - _bufs: Option<ZeroCopyBuf>, -) -> Result<u32, AnyError> { - log::debug!("close rid={}", rid); - state - .resource_table - .close(rid) - .map(|_| 0) - .ok_or_else(bad_resource_id) -} - -async fn op_accept( - state: Rc<RefCell<OpState>>, - rid: ResourceId, - _bufs: Option<ZeroCopyBuf>, -) -> Result<u32, AnyError> { - log::debug!("accept rid={}", rid); - - let listener = state - .borrow() - .resource_table - .get::<TcpListener>(rid) - .ok_or_else(bad_resource_id)?; - let stream = listener.accept().await?; - let rid = state.borrow_mut().resource_table.add(stream); - Ok(rid) -} - -async fn op_read( - state: Rc<RefCell<OpState>>, - rid: ResourceId, - buf: Option<ZeroCopyBuf>, -) -> Result<u32, AnyError> { - let mut buf = buf.ok_or_else(null_opbuf)?; - log::debug!("read rid={}", rid); - - let stream = state - .borrow() - .resource_table - .get::<TcpStream>(rid) - .ok_or_else(bad_resource_id)?; - let nread = stream.read(&mut buf).await?; - Ok(nread as u32) -} - -async fn op_write( - state: Rc<RefCell<OpState>>, - rid: ResourceId, - buf: Option<ZeroCopyBuf>, -) -> Result<u32, AnyError> { - let buf = buf.ok_or_else(null_opbuf)?; - log::debug!("write rid={}", rid); - - let stream = state - .borrow() - .resource_table - .get::<TcpStream>(rid) - .ok_or_else(bad_resource_id)?; - let nwritten = stream.write(&buf).await?; - Ok(nwritten as u32) -} - -fn main() { - log::set_logger(&Logger).unwrap(); - log::set_max_level( - env::args() - .find(|a| a == "-D") - .map(|_| log::LevelFilter::Debug) - .unwrap_or(log::LevelFilter::Warn), - ); - - // NOTE: `--help` arg will display V8 help and exit - deno_core::v8_set_flags(env::args().collect()); - - let mut js_runtime = create_js_runtime(); - let runtime = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .unwrap(); - - let future = async move { - js_runtime - .execute( - "http_bench_bin_ops.js", - include_str!("http_bench_bin_ops.js"), - ) - .unwrap(); - js_runtime.run_event_loop().await - }; - runtime.block_on(future).unwrap(); -} diff --git a/core/examples/http_bench_json_ops.js b/core/examples/http_bench_json_ops.js index f8ac05353..687be7ec1 100644 --- a/core/examples/http_bench_json_ops.js +++ b/core/examples/http_bench_json_ops.js @@ -11,12 +11,12 @@ const responseBuf = new Uint8Array( /** Listens on 0.0.0.0:4500, returns rid. */ function listen() { - return Deno.core.jsonOpSync("listen"); + return Deno.core.opSync("listen"); } /** Accepts a connection, returns rid. */ function accept(serverRid) { - return Deno.core.jsonOpAsync("accept", serverRid); + return Deno.core.opAsync("accept", serverRid); } /** @@ -24,16 +24,16 @@ function accept(serverRid) { * Returns bytes read. */ function read(rid, data) { - return Deno.core.jsonOpAsync("read", rid, data); + return Deno.core.opAsync("read", rid, data); } /** Writes a fixed HTTP response to the socket rid. Returns bytes written. */ function write(rid, data) { - return Deno.core.jsonOpAsync("write", rid, data); + return Deno.core.opAsync("write", rid, data); } function close(rid) { - Deno.core.jsonOpSync("close", rid); + Deno.core.opSync("close", rid); } async function serve(rid) { @@ -58,7 +58,7 @@ async function main() { Deno.core.registerErrorClass("Error", Error); const listenerRid = listen(); - Deno.core.print(`http_bench_json_ops listening on http://127.0.0.1:4544/\n`); + Deno.core.print(`http_bench_ops listening on http://127.0.0.1:4544/\n`); while (true) { const rid = await accept(listenerRid); diff --git a/core/examples/http_bench_json_ops.rs b/core/examples/http_bench_json_ops.rs index cb3c64945..e1b435e4c 100644 --- a/core/examples/http_bench_json_ops.rs +++ b/core/examples/http_bench_json_ops.rs @@ -111,11 +111,11 @@ impl From<tokio::net::TcpStream> for TcpStream { fn create_js_runtime() -> JsRuntime { let mut runtime = JsRuntime::new(Default::default()); - runtime.register_op("listen", deno_core::json_op_sync(op_listen)); - runtime.register_op("close", deno_core::json_op_sync(op_close)); - runtime.register_op("accept", deno_core::json_op_async(op_accept)); - runtime.register_op("read", deno_core::json_op_async(op_read)); - runtime.register_op("write", deno_core::json_op_async(op_write)); + runtime.register_op("listen", deno_core::op_sync(op_listen)); + runtime.register_op("close", deno_core::op_sync(op_close)); + runtime.register_op("accept", deno_core::op_async(op_accept)); + runtime.register_op("read", deno_core::op_async(op_read)); + runtime.register_op("write", deno_core::op_async(op_write)); runtime } diff --git a/core/lib.deno_core.d.ts b/core/lib.deno_core.d.ts index b12879a9b..2da28b413 100644 --- a/core/lib.deno_core.d.ts +++ b/core/lib.deno_core.d.ts @@ -7,15 +7,15 @@ declare namespace Deno { declare namespace core { - /** Send a JSON op to Rust, and synchronously receive the result. */ - function jsonOpSync( + /** Call an op in Rust, and synchronously receive the result. */ + function opSync( opName: string, args?: any, zeroCopy?: Uint8Array, ): any; - /** Send a JSON op to Rust, and asynchronously receive the result. */ - function jsonOpAsync( + /** Call an op in Rust, and asynchronously receive the result. */ + function opAsync( opName: string, args?: any, zeroCopy?: Uint8Array, diff --git a/core/lib.rs b/core/lib.rs index f51411083..b49de3b7b 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -9,7 +9,6 @@ mod module_specifier; mod modules; mod normalize_path; mod ops; -mod ops_bin; mod ops_json; pub mod plugin_api; mod resources; @@ -65,11 +64,8 @@ pub use crate::ops::OpResponse; pub use crate::ops::OpState; pub use crate::ops::OpTable; pub use crate::ops::PromiseId; -pub use crate::ops_bin::bin_op_async; -pub use crate::ops_bin::bin_op_sync; -pub use crate::ops_bin::ValueOrVector; -pub use crate::ops_json::json_op_async; -pub use crate::ops_json::json_op_sync; +pub use crate::ops_json::op_async; +pub use crate::ops_json::op_sync; pub use crate::resources::Resource; pub use crate::resources::ResourceId; pub use crate::resources::ResourceTable; diff --git a/core/ops.rs b/core/ops.rs index 53aec4ae4..3cc24c8cc 100644 --- a/core/ops.rs +++ b/core/ops.rs @@ -188,7 +188,7 @@ impl Default for OpTable { /// Return map of resources with id as key /// and string representation as value. /// -/// This op must be wrapped in `json_op_sync`. +/// This op must be wrapped in `op_sync`. pub fn op_resources( state: &mut OpState, _args: (), @@ -204,7 +204,7 @@ pub fn op_resources( /// Remove a resource from the resource table. /// -/// This op must be wrapped in `json_op_sync`. +/// This op must be wrapped in `op_sync`. pub fn op_close( state: &mut OpState, rid: Option<ResourceId>, diff --git a/core/ops_bin.rs b/core/ops_bin.rs deleted file mode 100644 index c4c57f4b9..000000000 --- a/core/ops_bin.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -use crate::error::AnyError; -use crate::futures::future::FutureExt; -use crate::serialize_op_result; -use crate::Op; -use crate::OpFn; -use crate::OpPayload; -use crate::OpResponse; -use crate::OpState; -use crate::ZeroCopyBuf; -use std::boxed::Box; -use std::cell::RefCell; -use std::future::Future; -use std::rc::Rc; - -// TODO: rewrite this, to have consistent buffer returns -// possibly via direct serde_v8 support -pub trait ValueOrVector { - fn value(&self) -> u32; - fn vector(self) -> Option<Vec<u8>>; -} - -impl ValueOrVector for Vec<u8> { - fn value(&self) -> u32 { - self.len() as u32 - } - fn vector(self) -> Option<Vec<u8>> { - Some(self) - } -} - -impl ValueOrVector for u32 { - fn value(&self) -> u32 { - *self - } - fn vector(self) -> Option<Vec<u8>> { - None - } -} - -/// Creates an op that passes data synchronously using raw ui8 buffer. -/// -/// The provided function `op_fn` has the following parameters: -/// * `&mut OpState`: the op state, can be used to read/write resources in the runtime from an op. -/// * `argument`: the i32 value that is passed to the Rust function. -/// * `&mut [ZeroCopyBuf]`: raw bytes passed along. -/// -/// `op_fn` returns an array buffer value, which is directly returned to JavaScript. -/// -/// When registering an op like this... -/// ```ignore -/// let mut runtime = JsRuntime::new(...); -/// runtime.register_op("hello", deno_core::bin_op_sync(Self::hello_op)); -/// ``` -/// -/// ...it can be invoked from JS using the provided name, for example: -/// ```js -/// Deno.core.ops(); -/// let result = Deno.core.binOpSync("function_name", args); -/// ``` -/// -/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization. -/// A more complete example is available in the examples directory. -pub fn bin_op_sync<F, R>(op_fn: F) -> Box<OpFn> -where - F: - Fn(&mut OpState, u32, Option<ZeroCopyBuf>) -> Result<R, AnyError> + 'static, - R: ValueOrVector, -{ - Box::new(move |state, payload, buf| -> Op { - let min_arg: u32 = payload.deserialize().unwrap(); - let result = op_fn(&mut state.borrow_mut(), min_arg, buf); - Op::Sync(serialize_bin_result(result, state)) - }) -} - -// wraps serialize_op_result but handles ValueOrVector -fn serialize_bin_result<R>( - result: Result<R, AnyError>, - state: Rc<RefCell<OpState>>, -) -> OpResponse -where - R: ValueOrVector, -{ - match result { - Ok(v) => { - let min_val = v.value(); - match v.vector() { - // Warning! this is incorrect, but buffers aren't use ATM, will fix in future PR - Some(vec) => OpResponse::Buffer(vec.into()), - // u32 - None => serialize_op_result(Ok(min_val), state), - } - } - Err(e) => serialize_op_result::<()>(Err(e), state), - } -} - -/// Creates an op that passes data asynchronously using raw ui8 buffer. -/// -/// The provided function `op_fn` has the following parameters: -/// * `Rc<RefCell<OpState>>`: the op state, can be used to read/write resources in the runtime from an op. -/// * `argument`: the i32 value that is passed to the Rust function. -/// * `BufVec`: raw bytes passed along, usually not needed if the JSON value is used. -/// -/// `op_fn` returns a future, whose output is a JSON value. This value will be asynchronously -/// returned to JavaScript. -/// -/// When registering an op like this... -/// ```ignore -/// let mut runtime = JsRuntime::new(...); -/// runtime.register_op("hello", deno_core::json_op_async(Self::hello_op)); -/// ``` -/// -/// ...it can be invoked from JS using the provided name, for example: -/// ```js -/// Deno.core.ops(); -/// let future = Deno.core.jsonOpAsync("function_name", args); -/// ``` -/// -/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization. -/// A more complete example is available in the examples directory. -pub fn bin_op_async<F, R, RV>(op_fn: F) -> Box<OpFn> -where - F: Fn(Rc<RefCell<OpState>>, u32, Option<ZeroCopyBuf>) -> R + 'static, - R: Future<Output = Result<RV, AnyError>> + 'static, - RV: ValueOrVector, -{ - Box::new( - move |state: Rc<RefCell<OpState>>, - p: OpPayload, - b: Option<ZeroCopyBuf>| - -> Op { - let pid = p.promise_id; - let min_arg: u32 = p.deserialize().unwrap(); - let fut = op_fn(state.clone(), min_arg, b) - .map(move |result| (pid, serialize_bin_result(result, state))); - Op::Async(Box::pin(fut)) - }, - ) -} diff --git a/core/ops_json.rs b/core/ops_json.rs index 3e2b532d0..cf2e6230b 100644 --- a/core/ops_json.rs +++ b/core/ops_json.rs @@ -25,18 +25,18 @@ use std::rc::Rc; /// When registering an op like this... /// ```ignore /// let mut runtime = JsRuntime::new(...); -/// runtime.register_op("hello", deno_core::json_op_sync(Self::hello_op)); +/// runtime.register_op("hello", deno_core::op_sync(Self::hello_op)); /// ``` /// /// ...it can be invoked from JS using the provided name, for example: /// ```js /// Deno.core.ops(); -/// let result = Deno.core.jsonOpSync("function_name", args); +/// let result = Deno.core.opSync("function_name", args); /// ``` /// /// The `Deno.core.ops()` statement is needed once before any op calls, for initialization. /// A more complete example is available in the examples directory. -pub fn json_op_sync<F, V, R>(op_fn: F) -> Box<OpFn> +pub fn op_sync<F, V, R>(op_fn: F) -> Box<OpFn> where F: Fn(&mut OpState, V, Option<ZeroCopyBuf>) -> Result<R, AnyError> + 'static, V: DeserializeOwned, @@ -63,18 +63,18 @@ where /// When registering an op like this... /// ```ignore /// let mut runtime = JsRuntime::new(...); -/// runtime.register_op("hello", deno_core::json_op_async(Self::hello_op)); +/// runtime.register_op("hello", deno_core::op_async(Self::hello_op)); /// ``` /// /// ...it can be invoked from JS using the provided name, for example: /// ```js /// Deno.core.ops(); -/// let future = Deno.core.jsonOpAsync("function_name", args); +/// let future = Deno.core.opAsync("function_name", args); /// ``` /// /// The `Deno.core.ops()` statement is needed once before any op calls, for initialization. /// A more complete example is available in the examples directory. -pub fn json_op_async<F, V, R, RV>(op_fn: F) -> Box<OpFn> +pub fn op_async<F, V, R, RV>(op_fn: F) -> Box<OpFn> where F: Fn(Rc<RefCell<OpState>>, V, Option<ZeroCopyBuf>) -> R + 'static, V: DeserializeOwned, @@ -115,7 +115,7 @@ mod tests { use super::*; #[tokio::test] - async fn json_op_async_stack_trace() { + async fn op_async_stack_trace() { let mut runtime = crate::JsRuntime::new(Default::default()); async fn op_throw( @@ -128,7 +128,7 @@ mod tests { Err(crate::error::generic_error("foo")) } - runtime.register_op("op_throw", json_op_async(op_throw)); + runtime.register_op("op_throw", op_async(op_throw)); runtime .execute( "<init>", @@ -139,7 +139,7 @@ mod tests { Deno.core.registerErrorClass('Error', Error); async function f1() { - await Deno.core.jsonOpAsync('op_throw', 'hello'); + await Deno.core.opAsync('op_throw', 'hello'); } async function f2() { diff --git a/core/runtime.rs b/core/runtime.rs index 28f015fda..3583ad89e 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -438,8 +438,8 @@ impl JsRuntime { /// /// This function provides byte-level bindings. To pass data via JSON, the /// following functions can be passed as an argument for `op_fn`: - /// * [json_op_sync()](fn.json_op_sync.html) - /// * [json_op_async()](fn.json_op_async.html) + /// * [op_sync()](fn.op_sync.html) + /// * [op_async()](fn.op_async.html) pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId where F: Fn(Rc<RefCell<OpState>>, OpPayload, Option<ZeroCopyBuf>) -> Op + 'static, |