Skip to content

Commit

Permalink
kinda working
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Aug 21, 2019
1 parent ee47611 commit 83f53e2
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 23 deletions.
23 changes: 19 additions & 4 deletions cli/ops/dispatch_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ pub enum JsonOp {
Async(AsyncJsonOp),
}

fn json_err(err: ErrBox) -> Value {
use crate::deno_error::GetErrorKind;
json!({
"message": err.to_string(),
"kind": err.kind() as u32,
})
}

pub type Dispatcher = fn(
state: &ThreadSafeState,
args: Value,
Expand All @@ -28,7 +36,7 @@ fn serialize_result(
) -> Buf {
let value = match result {
Ok(v) => json!({ "ok": v, "promiseId": promise_id }),
Err(err) => json!({ "err": err.to_string(), "promiseId": promise_id }),
Err(err) => json!({ "err": json_err(err), "promiseId": promise_id }),
};
let vec = serde_json::to_vec(&value).unwrap();
vec.into_boxed_slice()
Expand All @@ -48,6 +56,7 @@ pub fn dispatch(
) -> 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();

let result = serde_json::from_slice(control)
.map_err(ErrBox::from)
Expand All @@ -64,7 +73,14 @@ pub fn dispatch(
}));
CoreOp::Async(fut2)
}
Err(sync_err) => CoreOp::Sync(serialize_result(promise_id, Err(sync_err))),
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 All @@ -88,8 +104,7 @@ where
F: 'static + Send + FnOnce() -> Result<Value, ErrBox>,
{
if is_sync {
let value = f()?;
Ok(JsonOp::Sync(value))
Ok(JsonOp::Sync(f()?))
} else {
Ok(JsonOp::Async(Box::new(futures::sync::oneshot::spawn(
tokio_util::poll_fn(move || convert_blocking_json(f)),
Expand Down
67 changes: 50 additions & 17 deletions js/dispatch_json.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// Do not add flatbuffer dependencies to this module.
// TODO(ry) Currently ErrorKind enum is defined in FlatBuffers. Therefore
// we must still reference the msg_generated.ts. This should be removed!
import { ErrorKind } from "gen/cli/msg_generated";
import * as util from "./util";
import { TextEncoder, TextDecoder } from "./text_encoding";
import { core } from "./core";
import { DenoError } from "./errors";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Ok = any;

interface JsonError {
kind: ErrorKind;
message: string;
}

interface JsonResponse {
ok?: Ok;
err?: JsonError;
promiseId?: number; // only present in async mesasges.
}

const promiseTable = new Map<number, util.Resolvable<number>>();
let _nextPromiseId = 1;
Expand All @@ -13,54 +31,69 @@ function nextPromiseId(): number {

export function handleAsyncMsgFromRust(opId: number, resUi8: Uint8Array): void {
const resStr = new TextDecoder().decode(resUi8);
const res = JSON.parse(resStr);

const promiseId = res["promiseId"];
const res = JSON.parse(resStr) as JsonResponse;
const promiseId = res.promiseId!;
const promise = promiseTable.get(promiseId)!;
if (!promise) {
throw Error(`Async op ${opId} had bad promiseId: ${resStr}`);
}
promiseTable.delete(promiseId);

if (!res["ok"]) {
promise.reject(new Error(`op ${opId} failed ${resStr}`));
if (res.err) {
let err = maybeError(res.err);
if (err) {
promise.reject(err);
} else {
promise.resolve();
}
} else {
promise.resolve(res["ok"]!);
promise.resolve(res.ok!);
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function sendSync(
opId: number,
args: object = {},
zeroCopy?: Uint8Array
): any {
): Ok {
const argsStr = JSON.stringify(args);
const argsUi8 = new TextEncoder().encode(argsStr);
const resUi8 = core.dispatch(opId, argsUi8);
const resUi8 = core.dispatch(opId, argsUi8, zeroCopy);
if (!resUi8) {
return;
}
const resStr = new TextDecoder().decode(resUi8);
const res = JSON.parse(resStr);
if (!res["ok"]) {
throw Error(`op ${opId} failed ${res["err"]}. Args: ${argsStr}`);
const res = JSON.parse(resStr) as JsonResponse;
util.assert(!res.promiseId);
if (res.err) {
const err = maybeError(res.err);
if (err != null) {
throw err;
}
}
return res["ok"];
return res.ok;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function sendAsync(
opId: number,
args: object = {},
zeroCopy?: Uint8Array
): Promise<any> {
): Promise<Ok> {
const promiseId = nextPromiseId();
args = Object.assign(args, { promiseId });
const argsStr = JSON.stringify(args);
const argsUi8 = new TextEncoder().encode(argsStr);
const promise = util.createResolvable<any>();
const promise = util.createResolvable<Ok>();
promiseTable.set(promiseId, promise);
core.dispatch(opId, argsUi8, zeroCopy);
const r = core.dispatch(opId, argsUi8, zeroCopy);
util.assert(!r);
return promise;
}

function maybeError(err: JsonError): null | DenoError<ErrorKind> {
if (err.kind === ErrorKind.NoError) {
return null;
} else {
return new DenoError(err.kind, err.message);
}
}
16 changes: 15 additions & 1 deletion js/os.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ export function exit(code = 0): never {
return util.unreachable();
}

function setEnv(key: string, value: string): void {
const builder = flatbuffers.createBuilder();
const key_ = builder.createString(key);
const value_ = builder.createString(value);
const inner = msg.SetEnv.createSetEnv(builder, key_, value_);
sendSync(builder, msg.Any.SetEnv, inner);
}

/** Returns a snapshot of the environment variables at invocation. Mutating a
* property in the object will set that variable in the environment for
* the process. The environment object will only accept `string`s
Expand All @@ -45,7 +53,13 @@ export function exit(code = 0): never {
* console.log(myEnv.TEST_VAR == newEnv.TEST_VAR);
*/
export function env(): { [index: string]: string } {
return dispatchJson.sendSync(dispatch.OP_ENV);
const env = dispatchJson.sendSync(dispatch.OP_ENV);
return new Proxy(env, {
set(obj, prop: string, value: string): boolean {
setEnv(prop, value);
return Reflect.set(obj, prop, value);
}
});
}

/** Send to the privileged side that we have setup and are ready. */
Expand Down
2 changes: 1 addition & 1 deletion js/utime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function utime(
atime: number | Date,
mtime: number | Date
): Promise<void> {
sendAsync(OP_UTIME, {
await sendAsync(OP_UTIME, {
filename,
atime: atime.valueOf(),
mtime: mtime.valueOf()
Expand Down

0 comments on commit 83f53e2

Please sign in to comment.