Skip to content

Commit

Permalink
feat: first pass at native plugins (#3372)
Browse files Browse the repository at this point in the history
  • Loading branch information
afinch7 authored and ry committed Dec 5, 2019
1 parent 214b3eb commit 7c3b9b4
Show file tree
Hide file tree
Showing 26 changed files with 574 additions and 7 deletions.
68 changes: 68 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ members = [
"core",
"tools/hyper_hello",
"deno_typescript",
"test_plugin"
]
1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ base64 = "0.11.0"
byteorder = "1.3.2"
clap = "2.33.0"
dirs = "2.0.2"
dlopen = "0.1.8"
futures = { version = "0.3", features = [ "compat", "io-compat" ] }
http = "0.1.19"
hyper = "0.12.35"
Expand Down
15 changes: 15 additions & 0 deletions cli/deno_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use crate::msg::ErrorKind;
use deno::AnyError;
use deno::ErrBox;
use deno::ModuleResolutionError;
use dlopen::Error as DlopenError;
use http::uri;
use hyper;
use reqwest;
Expand Down Expand Up @@ -292,6 +293,19 @@ mod unix {
}
}

impl GetErrorKind for DlopenError {
fn kind(&self) -> ErrorKind {
use dlopen::Error::*;
match self {
NullCharacter(_) => ErrorKind::Other,
OpeningLibraryError(e) => GetErrorKind::kind(e),
SymbolGettingError(e) => GetErrorKind::kind(e),
NullSymbol => ErrorKind::Other,
AddrNotMatchingDll(e) => GetErrorKind::kind(e),
}
}
}

impl GetErrorKind for dyn AnyError {
fn kind(&self) -> ErrorKind {
use self::GetErrorKind as Get;
Expand Down Expand Up @@ -325,6 +339,7 @@ impl GetErrorKind for dyn AnyError {
.downcast_ref::<serde_json::error::Error>()
.map(Get::kind)
})
.or_else(|| self.downcast_ref::<DlopenError>().map(Get::kind))
.or_else(|| unix_error_kind(self))
.unwrap_or_else(|| {
panic!("Can't get ErrorKind for {:?}", self);
Expand Down
17 changes: 17 additions & 0 deletions cli/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub struct DenoFlags {
pub net_whitelist: Vec<String>,
pub allow_env: bool,
pub allow_run: bool,
pub allow_plugin: bool,
pub allow_hrtime: bool,
pub no_prompts: bool,
pub no_remote: bool,
Expand Down Expand Up @@ -346,6 +347,7 @@ fn xeval_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_plugin = true;
flags.allow_hrtime = true;
flags.argv.push(XEVAL_URL.to_string());

Expand Down Expand Up @@ -373,6 +375,7 @@ fn repl_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_plugin = true;
flags.allow_hrtime = true;
}

Expand All @@ -383,6 +386,7 @@ fn eval_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_plugin = true;
flags.allow_hrtime = true;
let code: &str = matches.value_of("code").unwrap();
flags.argv.extend(vec![code.to_string()]);
Expand Down Expand Up @@ -465,6 +469,9 @@ fn run_test_args_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
if matches.is_present("allow-run") {
flags.allow_run = true;
}
if matches.is_present("allow-plugin") {
flags.allow_plugin = true;
}
if matches.is_present("allow-hrtime") {
flags.allow_hrtime = true;
}
Expand All @@ -475,6 +482,7 @@ fn run_test_args_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_plugin = true;
flags.allow_hrtime = true;
}
if matches.is_present("cached-only") {
Expand Down Expand Up @@ -942,6 +950,11 @@ fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
.long("allow-run")
.help("Allow running subprocesses"),
)
.arg(
Arg::with_name("allow-plugin")
.long("allow-plugin")
.help("Allow loading plugins"),
)
.arg(
Arg::with_name("allow-hrtime")
.long("allow-hrtime")
Expand Down Expand Up @@ -1408,6 +1421,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
Expand Down Expand Up @@ -1581,6 +1595,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
Expand All @@ -1600,6 +1615,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
Expand Down Expand Up @@ -1635,6 +1651,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
Expand Down
1 change: 1 addition & 0 deletions cli/js/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export {
} from "./permissions.ts";
export { truncateSync, truncate } from "./truncate.ts";
export { FileInfo } from "./file_info.ts";
export { openPlugin } from "./plugins.ts";
export { connect, dial, listen, Listener, Conn } from "./net.ts";
export { dialTLS, listenTLS } from "./tls.ts";
export { metrics, Metrics } from "./metrics.ts";
Expand Down
18 changes: 17 additions & 1 deletion cli/js/dispatch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import * as minimal from "./dispatch_minimal.ts";
import * as json from "./dispatch_json.ts";
import { AsyncHandler } from "./plugins.ts";

// These consts are shared with Rust. Update with care.
export let OP_READ: number;
Expand Down Expand Up @@ -67,6 +68,16 @@ export let OP_CWD: number;
export let OP_FETCH_ASSET: number;
export let OP_DIAL_TLS: number;
export let OP_HOSTNAME: number;
export let OP_OPEN_PLUGIN: number;

const PLUGIN_ASYNC_HANDLER_MAP: Map<number, AsyncHandler> = new Map();

export function setPluginAsyncHandler(
opId: number,
handler: AsyncHandler
): void {
PLUGIN_ASYNC_HANDLER_MAP.set(opId, handler);
}

export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
switch (opId) {
Expand Down Expand Up @@ -111,6 +122,11 @@ export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
json.asyncMsgFromRust(opId, ui8);
break;
default:
throw Error("bad async opId");
const handler = PLUGIN_ASYNC_HANDLER_MAP.get(opId);
if (handler) {
handler(ui8);
} else {
throw Error("bad async opId");
}
}
}
35 changes: 35 additions & 0 deletions cli/js/lib.deno_runtime.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,7 @@ declare namespace Deno {
| "write"
| "net"
| "env"
| "plugin"
| "hrtime";
/** https://w3c.github.io/permissions/#status-of-a-permission */
export type PermissionState = "granted" | "denied" | "prompt";
Expand All @@ -924,6 +925,9 @@ declare namespace Deno {
interface EnvPermissionDescriptor {
name: "env";
}
interface PluginPermissionDescriptor {
name: "plugin";
}
interface HrtimePermissionDescriptor {
name: "hrtime";
}
Expand All @@ -933,6 +937,7 @@ declare namespace Deno {
| ReadWritePermissionDescriptor
| NetPermissionDescriptor
| EnvPermissionDescriptor
| PluginPermissionDescriptor
| HrtimePermissionDescriptor;

export class Permissions {
Expand Down Expand Up @@ -982,6 +987,36 @@ declare namespace Deno {
*/
export function truncate(name: string, len?: number): Promise<void>;

// @url js/plugins.d.ts

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

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

export interface Plugin {
ops: {
[name: string]: PluginOp;
};
}

/** Open and initalize a plugin.
* Requires the `--allow-plugin` flag.
*
* const plugin = Deno.openPlugin("./path/to/some/plugin.so");
* const some_op = plugin.ops.some_op;
* const response = some_op.dispatch(new Uint8Array([1,2,3,4]));
* console.log(`Response from plugin ${response}`);
*/
export function openPlugin(filename: string): Plugin;

// @url js/net.d.ts

type Transport = "tcp";
Expand Down
Loading

0 comments on commit 7c3b9b4

Please sign in to comment.