Skip to content

Commit

Permalink
use Isolate::register_op in deno_cli (#3039)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartlomieju authored and ry committed Oct 1, 2019
1 parent ffbf0c2 commit 75eeac0
Show file tree
Hide file tree
Showing 8 changed files with 453 additions and 472 deletions.
69 changes: 32 additions & 37 deletions cli/ops/dispatch_json.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::state::ThreadSafeState;
use crate::tokio_util;
use deno::*;
use futures::Future;
Expand All @@ -23,12 +22,6 @@ fn json_err(err: ErrBox) -> Value {
})
}

pub type Dispatcher = fn(
state: &ThreadSafeState,
args: Value,
zero_copy: Option<PinnedBuf>,
) -> Result<JsonOp, ErrBox>;

fn serialize_result(
promise_id: Option<u64>,
result: Result<Value, ErrBox>,
Expand All @@ -50,37 +43,39 @@ struct AsyncArgs {
promise_id: Option<u64>,
}

pub fn dispatch(
d: Dispatcher,
state: &ThreadSafeState,
control: &[u8],
zero_copy: Option<PinnedBuf>,
) -> CoreOp {
let async_args: AsyncArgs = serde_json::from_slice(control).unwrap();
let promise_id = async_args.promise_id;
let is_sync = promise_id.is_none();
pub fn json_op<D>(d: D) -> impl Fn(&[u8], Option<PinnedBuf>) -> CoreOp
where
D: Fn(Value, Option<PinnedBuf>) -> Result<JsonOp, ErrBox>,
{
move |control: &[u8], zero_copy: Option<PinnedBuf>| {
let async_args: AsyncArgs = serde_json::from_slice(control).unwrap();
let promise_id = async_args.promise_id;
let is_sync = promise_id.is_none();

let result = serde_json::from_slice(control)
.map_err(ErrBox::from)
.and_then(move |args| d(state, args, zero_copy));
match result {
Ok(JsonOp::Sync(sync_value)) => {
assert!(promise_id.is_none());
CoreOp::Sync(serialize_result(promise_id, Ok(sync_value)))
}
Ok(JsonOp::Async(fut)) => {
assert!(promise_id.is_some());
let fut2 = Box::new(fut.then(move |result| -> Result<Buf, ()> {
Ok(serialize_result(promise_id, result))
}));
CoreOp::Async(fut2)
}
Err(sync_err) => {
let buf = serialize_result(promise_id, Err(sync_err));
if is_sync {
CoreOp::Sync(buf)
} else {
CoreOp::Async(Box::new(futures::future::ok(buf)))
let result = serde_json::from_slice(control)
.map_err(ErrBox::from)
.and_then(|args| d(args, zero_copy));

// Convert to CoreOp
match result {
Ok(JsonOp::Sync(sync_value)) => {
assert!(promise_id.is_none());
CoreOp::Sync(serialize_result(promise_id, Ok(sync_value)))
}
Ok(JsonOp::Async(fut)) => {
assert!(promise_id.is_some());
let fut2 = Box::new(fut.then(move |result| -> Result<Buf, ()> {
Ok(serialize_result(promise_id, result))
}));
CoreOp::Async(fut2)
}
Err(sync_err) => {
let buf = serialize_result(promise_id, Err(sync_err));
if is_sync {
CoreOp::Sync(buf)
} else {
CoreOp::Async(Box::new(futures::future::ok(buf)))
}
}
}
}
Expand Down
63 changes: 31 additions & 32 deletions cli/ops/dispatch_minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//! alternative to flatbuffers using a very simple list of int32s to lay out
//! messages. The first i32 is used to determine if a message a flatbuffer
//! message or a "minimal" message.
use crate::state::ThreadSafeState;
use deno::Buf;
use deno::CoreOp;
use deno::ErrBox;
Expand Down Expand Up @@ -72,40 +71,40 @@ fn test_parse_min_record() {
assert_eq!(parse_min_record(&buf), None);
}

pub fn dispatch(
pub fn minimal_op(
d: Dispatcher,
_state: &ThreadSafeState,
control: &[u8],
zero_copy: Option<PinnedBuf>,
) -> CoreOp {
let mut record = parse_min_record(control).unwrap();
let is_sync = record.promise_id == 0;
let rid = record.arg;
let min_op = d(rid, zero_copy);
) -> impl Fn(&[u8], Option<PinnedBuf>) -> CoreOp {
move |control: &[u8], zero_copy: Option<PinnedBuf>| {
let mut record = parse_min_record(control).unwrap();
let is_sync = record.promise_id == 0;
let rid = record.arg;
let min_op = d(rid, zero_copy);

let fut = Box::new(min_op.then(move |result| -> Result<Buf, ()> {
match result {
Ok(r) => {
record.result = r;
// Convert to CoreOp
let fut = Box::new(min_op.then(move |result| -> Result<Buf, ()> {
match result {
Ok(r) => {
record.result = r;
}
Err(err) => {
// TODO(ry) The dispatch_minimal doesn't properly pipe errors back to
// the caller.
debug!("swallowed err {}", err);
record.result = -1;
}
}
Err(err) => {
// TODO(ry) The dispatch_minimal doesn't properly pipe errors back to
// the caller.
debug!("swallowed err {}", err);
record.result = -1;
}
}
Ok(record.into())
}));
Ok(record.into())
}));

if is_sync {
// Warning! Possible deadlocks can occur if we try to wait for a future
// while in a future. The safe but expensive alternative is to use
// tokio_util::block_on.
// This block is only exercised for readSync and writeSync, which I think
// works since they're simple polling futures.
Op::Sync(fut.wait().unwrap())
} else {
Op::Async(fut)
if is_sync {
// Warning! Possible deadlocks can occur if we try to wait for a future
// while in a future. The safe but expensive alternative is to use
// tokio_util::block_on.
// This block is only exercised for readSync and writeSync, which I think
// works since they're simple polling futures.
Op::Sync(fut.wait().unwrap())
} else {
Op::Async(fut)
}
}
}
Loading

0 comments on commit 75eeac0

Please sign in to comment.