Skip to content

Commit

Permalink
remove ts file replace with js and d.ts, add more testing to plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
afinch7 committed Mar 31, 2020
1 parent 9a1f1e2 commit 67bdd57
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 204 deletions.
86 changes: 86 additions & 0 deletions core/dispatch_json.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
/** Json based dispatch wrapper for core ops.
*
* Error kind mapping is controlled by errorFactory. Async handler is automatically
* set during construction.
*
* const opId = Deno.ops()["json_op"];
* const jsonOp = new DispatchJsonCoreOp(opId, (kind, msg) => return new CustomError(kind, msg));
* const response = jsonOp.dispatchSync({ data });
* console.log(response.items[3].name);
*/
export declare class DispatchJsonCoreOp extends DispatchJsonOp {
private readonly opId;
constructor(opId: number, errorFactory: ErrorFactory);
}

/** Json based dispatch wrapper for plugin ops.
*
* Error kind mapping is controlled by errorFactory. Async handler is automatically
* set during construction.
*
*/
export declare class DispatchJsonPluginOp extends DispatchJsonOp {
private readonly pluginOp;
constructor(pluginOp: PluginOp, errorFactory: ErrorFactory);
}

export declare type ErrorFactory = (kind: number, msg: string) => Error;

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

export declare interface AsyncHandler {
(msg: Uint8Array): void;
}

export declare interface PluginOp {
dispatch(
control: Uint8Array,
zeroCopy?: ArrayBufferView | null
): Uint8Array | null;
setAsyncHandler(handler: AsyncHandler): void;
}

interface Deferred<T> extends Promise<T> {
resolve: (value?: T | PromiseLike<T>) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
reject: (reason?: any) => void;
}

declare enum InternalErrorKinds {
JsonIoError = 1,
JsonSyntaxError = 2,
JsonDataError = 3,
JsonEofError = 4,
}

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

interface JsonResponse {
ok?: Ok;
err?: JsonError;
promiseId?: number;
}

declare abstract class DispatchJsonOp {
private readonly dispatch;
private readonly errorFactory;
protected readonly promiseTable: Map<number, Deferred<JsonResponse>>;
protected _nextPromiseId: number;
constructor(
dispatch: (
control: Uint8Array,
zeroCopy?: ArrayBufferView | null
) => Uint8Array | null,
errorFactory: ErrorFactory
);
protected nextPromiseId(): number;
protected unwrapResponse(res: JsonResponse): Ok;
protected handleAsync(resUi8: Uint8Array): void;
dispatchSync(args?: object, zeroCopy?: Uint8Array): Ok;
dispatchAsync(args?: object, zeroCopy?: Uint8Array): Promise<Ok>;
}
150 changes: 150 additions & 0 deletions core/dispatch_json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// These utilities are borrowed from std. We don't really
// have a better way to include them here yet.
class AssertionError extends Error {
constructor(message) {
super(message);
this.name = "AssertionError";
}
}
/** Make an assertion, if not `true`, then throw. */
function assert(expr, msg = "") {
if (!expr) {
throw new AssertionError(msg);
}
}
/** Creates a Promise with the `reject` and `resolve` functions
* placed as methods on the promise object itself. It allows you to do:
*
* const p = deferred<number>();
* // ...
* p.resolve(42);
*/
function deferred() {
let methods;
const promise = new Promise((resolve, reject) => {
methods = { resolve, reject };
});
return Object.assign(promise, methods);
}
// Actual dispatch_json code begins here.
// Warning! The values in this enum are duplicated in dispatch_json.rs
// Update carefully!
let InternalErrorKinds;
(function (InternalErrorKinds) {
InternalErrorKinds[(InternalErrorKinds["JsonIoError"] = 1)] = "JsonIoError";
InternalErrorKinds[(InternalErrorKinds["JsonSyntaxError"] = 2)] =
"JsonSyntaxError";
InternalErrorKinds[(InternalErrorKinds["JsonDataError"] = 3)] =
"JsonDataError";
InternalErrorKinds[(InternalErrorKinds["JsonEofError"] = 4)] = "JsonEofError";
})(InternalErrorKinds || (InternalErrorKinds = {}));
export class InternalDispatchJsonError extends Error {
constructor(kind, msg) {
super(msg);
this.name = InternalErrorKinds[kind];
}
}
const core = Deno["core"];
function decode(ui8) {
const s = core.decode(ui8);
return JSON.parse(s);
}
function encode(args) {
const s = JSON.stringify(args);
return core.encode(s);
}
class DispatchJsonOp {
constructor(dispatch, errorFactory) {
this.dispatch = dispatch;
this.errorFactory = errorFactory;
this.promiseTable = new Map();
this._nextPromiseId = 1;
}
nextPromiseId() {
return this._nextPromiseId++;
}
unwrapResponse(res) {
if (res.err != null) {
if (res.err.kind < 0) {
throw new InternalDispatchJsonError(
res.err.kind * -1, // Transform kind back to positive
res.err.message
);
} else if (res.err.kind > 0) {
throw this.errorFactory(res.err.kind, res.err.message);
} else {
throw new Error(res.err.message);
}
}
assert(res.ok != null);
return res.ok;
}
handleAsync(resUi8) {
const res = decode(resUi8);
assert(res.promiseId != null);
const promise = this.promiseTable.get(res.promiseId);
assert(promise != null);
this.promiseTable.delete(res.promiseId);
promise.resolve(res);
}
// Dispatch this op with a Sync call
dispatchSync(args = {}, zeroCopy) {
const argsUi8 = encode(args);
const resUi8 = this.dispatch(argsUi8, zeroCopy);
assert(resUi8 != null);
const res = decode(resUi8);
assert(res.promiseId == null);
return this.unwrapResponse(res);
}
// Dispatch this op with a Async call
async dispatchAsync(args = {}, zeroCopy) {
const promiseId = this.nextPromiseId();
args = Object.assign(args, { promiseId });
const promise = deferred();
const argsUi8 = encode(args);
const buf = this.dispatch(argsUi8, zeroCopy);
if (buf) {
// Sync result.
const res = decode(buf);
promise.resolve(res);
} else {
// Async result.
this.promiseTable.set(promiseId, promise);
}
const res = await promise;
return this.unwrapResponse(res);
}
}

/** Json based dispatch wrapper for core ops.
*
* Error kind mapping is controlled by errorFactory. Async handler is automatically
* set during construction.
*
* const opId = Deno.ops()["json_op"];
* const jsonOp = new DispatchJsonCoreOp(opId, (kind, msg) => return new CustomError(kind, msg));
* const response = jsonOp.dispatchSync({ data });
* console.log(response.items[3].name);
*/
export class DispatchJsonCoreOp extends DispatchJsonOp {
constructor(opId, errorFactory) {
super((c, zc) => core.dispatch(this.opId, c, zc), errorFactory);
this.opId = opId;
core.setAsyncHandler(this.opId, (resUi8) => this.handleAsync(resUi8));
}
}

/** Json based dispatch wrapper for plugin ops.
*
* Error kind mapping is controlled by errorFactory. Async handler is automatically
* set during construction.
*
*/
export class DispatchJsonPluginOp extends DispatchJsonOp {
constructor(pluginOp, errorFactory) {
super((c, zc) => this.pluginOp.dispatch(c, zc), errorFactory);
this.pluginOp = pluginOp;
this.pluginOp.setAsyncHandler((resUi8) => this.handleAsync(resUi8));
}
}
18 changes: 9 additions & 9 deletions core/dispatch_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ fn serialize_result(
// Update carefully
#[derive(Clone, Copy, PartialEq, Debug)]
enum InternalErrorKinds {
JsonIoError = 1,
JsonSyntaxError = 2,
JsonDataError = 3,
JsonEofError = 4,
Io = 1,
Syntax = 2,
Data = 3,
Eof = 4,
}

/// Internal error expression and conversion implementation.
Expand All @@ -204,7 +204,7 @@ trait InternalError {
let kind = match self.kind() {
JsonErrorKind::Kind(k) => {
assert!(k != 0, "kind = 0 is reserved for UnKind");
k as i64 * -1
-(k as i64)
}
JsonErrorKind::UnKind => 0,
};
Expand All @@ -219,10 +219,10 @@ impl InternalError for serde_json::error::Error {
fn kind(&self) -> JsonErrorKind {
use serde_json::error::Category::*;
JsonErrorKind::Kind(match self.classify() {
Io => InternalErrorKinds::JsonIoError,
Syntax => InternalErrorKinds::JsonSyntaxError,
Data => InternalErrorKinds::JsonDataError,
Eof => InternalErrorKinds::JsonEofError,
Io => InternalErrorKinds::Io,
Syntax => InternalErrorKinds::Syntax,
Data => InternalErrorKinds::Data,
Eof => InternalErrorKinds::Eof,
} as u32)
}

Expand Down
Loading

0 comments on commit 67bdd57

Please sign in to comment.