summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/Cargo.toml1
-rw-r--r--cli/deno_error.rs15
-rw-r--r--cli/flags.rs17
-rw-r--r--cli/js/deno.ts1
-rw-r--r--cli/js/dispatch.ts18
-rw-r--r--cli/js/lib.deno_runtime.d.ts35
-rw-r--r--cli/js/permissions.ts5
-rw-r--r--cli/js/permissions_test.ts14
-rw-r--r--cli/js/plugins.ts66
-rw-r--r--cli/js/test_util.ts14
-rw-r--r--cli/ops/mod.rs1
-rw-r--r--cli/ops/permissions.rs2
-rw-r--r--cli/ops/plugins.rs96
-rw-r--r--cli/ops/workers.rs7
-rw-r--r--cli/permissions.rs29
-rw-r--r--cli/state.rs5
-rw-r--r--cli/worker.rs2
17 files changed, 322 insertions, 6 deletions
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 4645f2445..417141ba3 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -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"
diff --git a/cli/deno_error.rs b/cli/deno_error.rs
index 8cff29d30..8d0eea201 100644
--- a/cli/deno_error.rs
+++ b/cli/deno_error.rs
@@ -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;
@@ -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;
@@ -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);
diff --git a/cli/flags.rs b/cli/flags.rs
index f23879e0f..770f422aa 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -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,
@@ -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());
@@ -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;
}
@@ -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()]);
@@ -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;
}
@@ -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") {
@@ -943,6 +951,11 @@ fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
.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")
.help("Allow high resolution time measurement"),
@@ -1408,6 +1421,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
+ allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
@@ -1581,6 +1595,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
+ allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
@@ -1600,6 +1615,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
+ allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
@@ -1635,6 +1651,7 @@ mod tests {
allow_run: true,
allow_read: true,
allow_write: true,
+ allow_plugin: true,
allow_hrtime: true,
..DenoFlags::default()
}
diff --git a/cli/js/deno.ts b/cli/js/deno.ts
index 6f07bef67..27a7bb3bd 100644
--- a/cli/js/deno.ts
+++ b/cli/js/deno.ts
@@ -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";
diff --git a/cli/js/dispatch.ts b/cli/js/dispatch.ts
index 35806c3ad..ed6f57052 100644
--- a/cli/js/dispatch.ts
+++ b/cli/js/dispatch.ts
@@ -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;
@@ -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) {
@@ -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");
+ }
}
}
diff --git a/cli/js/lib.deno_runtime.d.ts b/cli/js/lib.deno_runtime.d.ts
index fb7767aa6..0d3463869 100644
--- a/cli/js/lib.deno_runtime.d.ts
+++ b/cli/js/lib.deno_runtime.d.ts
@@ -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";
@@ -924,6 +925,9 @@ declare namespace Deno {
interface EnvPermissionDescriptor {
name: "env";
}
+ interface PluginPermissionDescriptor {
+ name: "plugin";
+ }
interface HrtimePermissionDescriptor {
name: "hrtime";
}
@@ -933,6 +937,7 @@ declare namespace Deno {
| ReadWritePermissionDescriptor
| NetPermissionDescriptor
| EnvPermissionDescriptor
+ | PluginPermissionDescriptor
| HrtimePermissionDescriptor;
export class Permissions {
@@ -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";
diff --git a/cli/js/permissions.ts b/cli/js/permissions.ts
index c3530e970..e0fb8a84c 100644
--- a/cli/js/permissions.ts
+++ b/cli/js/permissions.ts
@@ -11,6 +11,7 @@ export type PermissionName =
| "net"
| "env"
| "run"
+ | "plugin"
| "hrtime";
// NOTE: Keep in sync with cli/permissions.rs
@@ -31,6 +32,9 @@ interface NetPermissionDescriptor {
interface EnvPermissionDescriptor {
name: "env";
}
+interface PluginPermissionDescriptor {
+ name: "plugin";
+}
interface HrtimePermissionDescriptor {
name: "hrtime";
}
@@ -40,6 +44,7 @@ type PermissionDescriptor =
| ReadWritePermissionDescriptor
| NetPermissionDescriptor
| EnvPermissionDescriptor
+ | PluginPermissionDescriptor
| HrtimePermissionDescriptor;
/** https://w3c.github.io/permissions/#permissionstatus */
diff --git a/cli/js/permissions_test.ts b/cli/js/permissions_test.ts
index d9ba538f0..a50718652 100644
--- a/cli/js/permissions_test.ts
+++ b/cli/js/permissions_test.ts
@@ -7,11 +7,12 @@ const knownPermissions: Deno.PermissionName[] = [
"write",
"net",
"env",
+ "plugin",
"hrtime"
];
-for (const grant of knownPermissions) {
- testPerm({ [grant]: true }, async function envGranted(): Promise<void> {
+function genFunc(grant: Deno.PermissionName): () => Promise<void> {
+ const gen: () => Promise<void> = async function Granted(): Promise<void> {
const status0 = await Deno.permissions.query({ name: grant });
assert(status0 != null);
assertEquals(status0.state, "granted");
@@ -19,7 +20,14 @@ for (const grant of knownPermissions) {
const status1 = await Deno.permissions.revoke({ name: grant });
assert(status1 != null);
assertEquals(status1.state, "prompt");
- });
+ };
+ // Properly name these generated functions.
+ Object.defineProperty(gen, "name", { value: grant + "Granted" });
+ return gen;
+}
+
+for (const grant of knownPermissions) {
+ testPerm({ [grant]: true }, genFunc(grant));
}
test(async function permissionInvalidName(): Promise<void> {
diff --git a/cli/js/plugins.ts b/cli/js/plugins.ts
new file mode 100644
index 000000000..324ae3408
--- /dev/null
+++ b/cli/js/plugins.ts
@@ -0,0 +1,66 @@
+import { sendSync } from "./dispatch_json.ts";
+import { OP_OPEN_PLUGIN, setPluginAsyncHandler } from "./dispatch.ts";
+import { core } from "./core.ts";
+
+export interface AsyncHandler {
+ (msg: Uint8Array): void;
+}
+
+interface PluginOp {
+ dispatch(
+ control: Uint8Array,
+ zeroCopy?: ArrayBufferView | null
+ ): Uint8Array | null;
+ setAsyncHandler(handler: AsyncHandler): void;
+}
+
+class PluginOpImpl implements PluginOp {
+ constructor(private readonly opId: number) {}
+
+ dispatch(
+ control: Uint8Array,
+ zeroCopy?: ArrayBufferView | null
+ ): Uint8Array | null {
+ return core.dispatch(this.opId, control, zeroCopy);
+ }
+
+ setAsyncHandler(handler: AsyncHandler): void {
+ setPluginAsyncHandler(this.opId, handler);
+ }
+}
+
+// TODO(afinch7): add close method.
+
+interface Plugin {
+ ops: {
+ [name: string]: PluginOp;
+ };
+}
+
+class PluginImpl implements Plugin {
+ private _ops: { [name: string]: PluginOp } = {};
+
+ constructor(private readonly rid: number, ops: { [name: string]: number }) {
+ for (const op in ops) {
+ this._ops[op] = new PluginOpImpl(ops[op]);
+ }
+ }
+
+ get ops(): { [name: string]: PluginOp } {
+ return Object.assign({}, this._ops);
+ }
+}
+
+interface OpenPluginResponse {
+ rid: number;
+ ops: {
+ [name: string]: number;
+ };
+}
+
+export function openPlugin(filename: string): Plugin {
+ const response: OpenPluginResponse = sendSync(OP_OPEN_PLUGIN, {
+ filename
+ });
+ return new PluginImpl(response.rid, response.ops);
+}
diff --git a/cli/js/test_util.ts b/cli/js/test_util.ts
index 85fffabe6..aac70d2ed 100644
--- a/cli/js/test_util.ts
+++ b/cli/js/test_util.ts
@@ -26,6 +26,7 @@ interface TestPermissions {
net?: boolean;
env?: boolean;
run?: boolean;
+ plugin?: boolean;
hrtime?: boolean;
}
@@ -35,6 +36,7 @@ export interface Permissions {
net: boolean;
env: boolean;
run: boolean;
+ plugin: boolean;
hrtime: boolean;
}
@@ -48,6 +50,7 @@ async function getProcessPermissions(): Promise<Permissions> {
write: await isGranted("write"),
net: await isGranted("net"),
env: await isGranted("env"),
+ plugin: await isGranted("plugin"),
hrtime: await isGranted("hrtime")
};
}
@@ -75,8 +78,9 @@ function permToString(perms: Permissions): string {
const n = perms.net ? 1 : 0;
const e = perms.env ? 1 : 0;
const u = perms.run ? 1 : 0;
+ const p = perms.plugin ? 1 : 0;
const h = perms.hrtime ? 1 : 0;
- return `permR${r}W${w}N${n}E${e}U${u}H${h}`;
+ return `permR${r}W${w}N${n}E${e}U${u}P${p}H${h}`;
}
function registerPermCombination(perms: Permissions): void {
@@ -93,6 +97,7 @@ function normalizeTestPermissions(perms: TestPermissions): Permissions {
net: !!perms.net,
run: !!perms.run,
env: !!perms.env,
+ plugin: !!perms.plugin,
hrtime: !!perms.hrtime
};
}
@@ -120,6 +125,7 @@ export function test(fn: testing.TestFunction): void {
net: false,
env: false,
run: false,
+ plugin: false,
hrtime: false
},
fn
@@ -176,6 +182,7 @@ test(function permissionsMatches(): void {
net: false,
env: false,
run: false,
+ plugin: false,
hrtime: false
},
normalizeTestPermissions({ read: true })
@@ -190,6 +197,7 @@ test(function permissionsMatches(): void {
net: false,
env: false,
run: false,
+ plugin: false,
hrtime: false
},
normalizeTestPermissions({})
@@ -204,6 +212,7 @@ test(function permissionsMatches(): void {
net: true,
env: true,
run: true,
+ plugin: true,
hrtime: true
},
normalizeTestPermissions({ read: true })
@@ -219,6 +228,7 @@ test(function permissionsMatches(): void {
net: true,
env: false,
run: false,
+ plugin: false,
hrtime: false
},
normalizeTestPermissions({ read: true })
@@ -234,6 +244,7 @@ test(function permissionsMatches(): void {
net: true,
env: true,
run: true,
+ plugin: true,
hrtime: true
},
{
@@ -242,6 +253,7 @@ test(function permissionsMatches(): void {
net: true,
env: true,
run: true,
+ plugin: true,
hrtime: true
}
)
diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs
index 9b33d5918..28bf7e217 100644
--- a/cli/ops/mod.rs
+++ b/cli/ops/mod.rs
@@ -16,6 +16,7 @@ pub mod io;
pub mod net;
pub mod os;
pub mod permissions;
+pub mod plugins;
pub mod process;
pub mod random;
pub mod repl;
diff --git a/cli/ops/permissions.rs b/cli/ops/permissions.rs
index bd8340bf0..f513f2fab 100644
--- a/cli/ops/permissions.rs
+++ b/cli/ops/permissions.rs
@@ -55,6 +55,7 @@ pub fn op_revoke_permission(
"write" => permissions.allow_write.revoke(),
"net" => permissions.allow_net.revoke(),
"env" => permissions.allow_env.revoke(),
+ "plugin" => permissions.allow_plugin.revoke(),
"hrtime" => permissions.allow_hrtime.revoke(),
_ => {}
};
@@ -83,6 +84,7 @@ pub fn op_request_permission(
}
"net" => permissions.request_net(&args.url.as_ref().map(String::as_str)),
"env" => Ok(permissions.request_env()),
+ "plugin" => Ok(permissions.request_plugin()),
"hrtime" => Ok(permissions.request_hrtime()),
n => Err(type_error(format!("No such permission name: {}", n))),
}?;
diff --git a/cli/ops/plugins.rs b/cli/ops/plugins.rs
new file mode 100644
index 000000000..2673e3d6a
--- /dev/null
+++ b/cli/ops/plugins.rs
@@ -0,0 +1,96 @@
+use super::dispatch_json::{Deserialize, JsonOp, Value};
+use crate::fs as deno_fs;
+use crate::ops::json_op;
+use crate::state::ThreadSafeState;
+use deno::*;
+use dlopen::symbor::Library;
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::sync::Arc;
+
+pub fn init(i: &mut Isolate, s: &ThreadSafeState, r: Arc<deno::OpRegistry>) {
+ let r_ = r.clone();
+ i.register_op(
+ "open_plugin",
+ s.core_op(json_op(s.stateful_op(move |state, args, zero_copy| {
+ op_open_plugin(&r_, state, args, zero_copy)
+ }))),
+ );
+}
+
+fn open_plugin<P: AsRef<OsStr>>(lib_path: P) -> Result<Library, ErrBox> {
+ debug!("Loading Plugin: {:#?}", lib_path.as_ref());
+
+ Library::open(lib_path).map_err(ErrBox::from)
+}
+
+struct PluginResource {
+ lib: Library,
+ ops: HashMap<String, OpId>,
+}
+
+impl Resource for PluginResource {}
+
+struct InitContext {
+ ops: HashMap<String, Box<OpDispatcher>>,
+}
+
+impl PluginInitContext for InitContext {
+ fn register_op(&mut self, name: &str, op: Box<OpDispatcher>) {
+ let existing = self.ops.insert(name.to_string(), op);
+ assert!(
+ existing.is_none(),
+ format!("Op already registered: {}", name)
+ );
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct OpenPluginArgs {
+ filename: String,
+}
+
+pub fn op_open_plugin(
+ registry: &Arc<deno::OpRegistry>,
+ state: &ThreadSafeState,
+ args: Value,
+ _zero_copy: Option<PinnedBuf>,
+) -> Result<JsonOp, ErrBox> {
+ let args: OpenPluginArgs = serde_json::from_value(args)?;
+ let (filename, filename_) = deno_fs::resolve_from_cwd(&args.filename)?;
+
+ state.check_plugin(&filename_)?;
+
+ let lib = open_plugin(filename)?;
+ let plugin_resource = PluginResource {
+ lib,
+ ops: HashMap::new(),
+ };
+ let mut table = state.lock_resource_table();
+ let rid = table.add("plugin", Box::new(plugin_resource));
+ let plugin_resource = table.get_mut::<PluginResource>(rid).unwrap();
+
+ let init_fn = *unsafe {
+ plugin_resource
+ .lib
+ .symbol::<PluginInitFn>("deno_plugin_init")
+ }?;
+ let mut init_context = InitContext {
+ ops: HashMap::new(),
+ };
+ init_fn(&mut init_context);
+ for op in init_context.ops {
+ // Register each plugin op in the `OpRegistry` with the name
+ // formated like this `plugin_{plugin_rid}_{name}`.
+ // The inclusion of prefix and rid is designed to avoid any
+ // op name collision beyond the bound of a single loaded
+ // plugin instance.
+ let op_id = registry.register(&format!("plugin_{}_{}", rid, op.0), op.1);
+ plugin_resource.ops.insert(op.0, op_id);
+ }
+
+ Ok(JsonOp::Sync(
+ json!({ "rid": rid, "ops": plugin_resource.ops }),
+ ))
+}
diff --git a/cli/ops/workers.rs b/cli/ops/workers.rs
index 4bde38222..2b4d11e75 100644
--- a/cli/ops/workers.rs
+++ b/cli/ops/workers.rs
@@ -227,7 +227,12 @@ fn op_host_get_worker_closed(
};
let op = future.then(move |_result| {
let mut workers_table = state_.workers.lock().unwrap();
- workers_table.remove(&id);
+ let maybe_worker = workers_table.remove(&id);
+ if let Some(worker) = maybe_worker {
+ let mut channels = worker.state.worker_channels.lock().unwrap();
+ channels.sender.close_channel();
+ channels.receiver.close();
+ };
futures::future::ok(json!({}))
});
diff --git a/cli/permissions.rs b/cli/permissions.rs
index 8bad2f795..72a1a928a 100644
--- a/cli/permissions.rs
+++ b/cli/permissions.rs
@@ -108,6 +108,7 @@ pub struct DenoPermissions {
pub net_whitelist: HashSet<String>,
pub allow_env: PermissionState,
pub allow_run: PermissionState,
+ pub allow_plugin: PermissionState,
pub allow_hrtime: PermissionState,
}
@@ -122,6 +123,7 @@ impl DenoPermissions {
net_whitelist: flags.net_whitelist.iter().cloned().collect(),
allow_env: PermissionState::from(flags.allow_env),
allow_run: PermissionState::from(flags.allow_run),
+ allow_plugin: PermissionState::from(flags.allow_plugin),
allow_hrtime: PermissionState::from(flags.allow_hrtime),
}
}
@@ -207,6 +209,13 @@ impl DenoPermissions {
)
}
+ pub fn check_plugin(&self, filename: &str) -> Result<(), ErrBox> {
+ self.allow_plugin.check(
+ &format!("access to open a plugin: {}", filename),
+ "run again with the --allow-plugin flag",
+ )
+ }
+
pub fn request_run(&mut self) -> PermissionState {
self
.allow_run
@@ -258,6 +267,10 @@ impl DenoPermissions {
.request("Deno requests to access to high precision time.")
}
+ pub fn request_plugin(&mut self) -> PermissionState {
+ self.allow_plugin.request("Deno requests to open plugins.")
+ }
+
pub fn get_permission_state(
&self,
name: &str,
@@ -270,6 +283,7 @@ impl DenoPermissions {
"write" => Ok(self.get_state_write(path)),
"net" => self.get_state_net_url(url),
"env" => Ok(self.allow_env),
+ "plugin" => Ok(self.allow_plugin),
"hrtime" => Ok(self.allow_hrtime),
n => Err(type_error(format!("No such permission name: {}", n))),
}
@@ -653,6 +667,21 @@ mod tests {
}
#[test]
+ fn test_permissions_request_plugin() {
+ let mut perms0 = DenoPermissions::from_flags(&DenoFlags {
+ ..Default::default()
+ });
+ set_prompt_result(true);
+ assert_eq!(perms0.request_plugin(), PermissionState::Allow);
+
+ let mut perms1 = DenoPermissions::from_flags(&DenoFlags {
+ ..Default::default()
+ });
+ set_prompt_result(false);
+ assert_eq!(perms1.request_plugin(), PermissionState::Deny);
+ }
+
+ #[test]
fn test_permissions_request_hrtime() {
let mut perms0 = DenoPermissions::from_flags(&DenoFlags {
..Default::default()
diff --git a/cli/state.rs b/cli/state.rs
index e99bff08e..d31f667b5 100644
--- a/cli/state.rs
+++ b/cli/state.rs
@@ -295,6 +295,11 @@ impl ThreadSafeState {
self.permissions.lock().unwrap().check_run()
}
+ #[inline]
+ pub fn check_plugin(&self, filename: &str) -> Result<(), ErrBox> {
+ self.permissions.lock().unwrap().check_plugin(filename)
+ }
+
pub fn check_dyn_import(
self: &Self,
module_specifier: &ModuleSpecifier,
diff --git a/cli/worker.rs b/cli/worker.rs
index a8585b74e..814e7f440 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -50,6 +50,7 @@ impl Worker {
let isolate = Arc::new(Mutex::new(deno::Isolate::new(startup_data, false)));
{
let mut i = isolate.lock().unwrap();
+ let op_registry = i.op_registry.clone();
ops::compiler::init(&mut i, &state);
ops::errors::init(&mut i, &state);
@@ -57,6 +58,7 @@ impl Worker {
ops::files::init(&mut i, &state);
ops::fs::init(&mut i, &state);
ops::io::init(&mut i, &state);
+ ops::plugins::init(&mut i, &state, op_registry);
ops::net::init(&mut i, &state);
ops::tls::init(&mut i, &state);
ops::os::init(&mut i, &state);