Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: native plugins #3372

Merged
merged 27 commits into from
Dec 5, 2019
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4a11ec3
wip: native plugin ops
afinch7 Nov 18, 2019
6758ea9
implement native plugins in typescript
afinch7 Nov 18, 2019
7dc9fed
fix flags tests and adjust permissions for install
afinch7 Nov 18, 2019
631b257
wip: add test plugin
afinch7 Nov 18, 2019
fe8ed8d
rebase fixes
afinch7 Nov 18, 2019
112622d
added tests and fixed a issue with types
afinch7 Nov 19, 2019
cb94110
refactor `InitContext`
afinch7 Nov 20, 2019
2913dc9
patch by @bartlomieju
afinch7 Nov 22, 2019
496329a
fix issue with `setAsyncHandler` and added simple async test
afinch7 Nov 22, 2019
62c126c
make sure test native plugin gets built for tests
afinch7 Nov 22, 2019
102831e
fix debug test
afinch7 Nov 22, 2019
96d4afc
review fixes and other misc fixes
afinch7 Nov 23, 2019
33c6e4e
Merge branch 'master' into native_plugins_2
ry Nov 24, 2019
4b660e8
fix
ry Nov 24, 2019
2a38515
Move test_native_plugin to root - add failing test
ry Nov 24, 2019
a2e3783
Merge branch 'master' into native_plugins_2
ry Nov 27, 2019
8901da5
fix
ry Nov 27, 2019
e0004c3
test_plugin WIP
ry Nov 27, 2019
ae129f7
Fix test_plugin
ry Nov 28, 2019
e0dcb0b
clean up
ry Nov 28, 2019
26bd330
clean up
ry Nov 28, 2019
33b749f
fix scoping in plugin test
afinch7 Dec 3, 2019
a9df117
Merge remote-tracking branch 'upstream/master' into native_plugins_2
afinch7 Dec 3, 2019
10ad75c
fix another issue in plugin test
afinch7 Dec 3, 2019
230e926
fixes
afinch7 Dec 3, 2019
b96ec38
build test plugin during test
afinch7 Dec 3, 2019
ad9f9e2
fix windows issue
afinch7 Dec 3, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ jobs:
- name: Test debug
if: matrix.kind == 'test_debug'
run: |
cargo build --locked -p test_native_plugin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this step be somehow integrated into cli/tests/integration_tests.rs flow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to add a single test to test_native_plugin, but it still doesn't build automatically when running cargo test --all-targets. Not sure if there may be some other simple workaround here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should figure out a way to test this without making changes to ci.yml... I'm looking into it.

echo ::set-env name=DENO_BUILD_MODE::debug
cargo test --locked --all-targets

Expand Down
67 changes: 67 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",
"cli/tests/test_native_plugin"
afinch7 marked this conversation as resolved.
Show resolved Hide resolved
]
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 @@ -287,6 +288,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 @@ -320,6 +334,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 @@ -48,6 +48,7 @@ pub struct DenoFlags {
pub net_whitelist: Vec<String>,
pub allow_env: bool,
pub allow_run: bool,
pub allow_native: bool,
pub allow_hrtime: bool,
pub no_prompts: bool,
pub no_fetch: bool,
Expand Down Expand Up @@ -105,6 +106,11 @@ fn add_run_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
.long("allow-run")
.help("Allow running subprocesses"),
)
.arg(
Arg::with_name("allow-native")
afinch7 marked this conversation as resolved.
Show resolved Hide resolved
.long("allow-native")
.help("Allow opening native plugins"),
)
.arg(
Arg::with_name("allow-hrtime")
.long("allow-hrtime")
Expand Down Expand Up @@ -843,6 +849,9 @@ fn parse_run_args(mut flags: DenoFlags, matches: &ArgMatches) -> DenoFlags {
if matches.is_present("allow-run") {
flags.allow_run = true;
}
if matches.is_present("allow-native") {
flags.allow_native = true;
}
if matches.is_present("allow-hrtime") {
flags.allow_hrtime = true;
}
Expand All @@ -853,6 +862,7 @@ fn parse_run_args(mut flags: DenoFlags, matches: &ArgMatches) -> DenoFlags {
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
}
if matches.is_present("no-fetch") {
Expand Down Expand Up @@ -970,6 +980,7 @@ pub fn flags_from_vec(
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
let code: &str = eval_match.value_of("code").unwrap();
argv.extend(vec![code.to_string()]);
Expand Down Expand Up @@ -1138,6 +1149,7 @@ pub fn flags_from_vec(
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
argv.push(XEVAL_URL.to_string());

Expand Down Expand Up @@ -1181,6 +1193,7 @@ pub fn flags_from_vec(
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
flags.allow_native = true;
flags.allow_hrtime = true;
DenoSubcommand::Repl
}
Expand Down Expand Up @@ -1340,6 +1353,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_native: true,
allow_hrtime: true,
..DenoFlags::default()
}
Expand Down Expand Up @@ -1490,6 +1504,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_native: true,
allow_hrtime: true,
..DenoFlags::default()
}
Expand All @@ -1509,6 +1524,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_native: true,
allow_hrtime: true,
..DenoFlags::default()
}
Expand Down Expand Up @@ -1536,6 +1552,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
allow_native: 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 @@ -75,6 +75,7 @@ export {
} from "./permissions.ts";
export { truncateSync, truncate } from "./truncate.ts";
export { FileInfo } from "./file_info.ts";
export { openPlugin } from "./native_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 "./native_plugins.ts";

// These consts are shared with Rust. Update with care.
export let OP_READ: number;
Expand Down Expand Up @@ -66,6 +67,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_NATIVE_PLUGIN: number;

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

export function setPluginAsyncHandler(
afinch7 marked this conversation as resolved.
Show resolved Hide resolved
opId: number,
handler: AsyncHandler
): void {
NATIVE_PLUGIN_ASYNC_HANDLER_MAP.set(opId, handler);
}

export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
switch (opId) {
Expand Down Expand Up @@ -109,6 +120,11 @@ export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
json.asyncMsgFromRust(opId, ui8);
break;
default:
throw Error("bad async opId");
const handler = NATIVE_PLUGIN_ASYNC_HANDLER_MAP.get(opId);
if (handler) {
handler(ui8);
} else {
throw Error("bad async opId");
}
}
}
22 changes: 22 additions & 0 deletions cli/js/lib.deno_runtime.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,28 @@ declare namespace Deno {
*/
export function truncate(name: string, len?: number): Promise<void>;

// @url js/native_plugins.d.ts

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

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

export interface NativePlugin {
ops: {
[name: string]: NativePluginOp;
};
}

export function openPlugin(filename: string): NativePlugin;

// @url js/net.d.ts

type Transport = "tcp";
Expand Down
Loading