diff options
Diffstat (limited to 'cli/ops')
-rw-r--r-- | cli/ops/mod.rs | 1 | ||||
-rw-r--r-- | cli/ops/permissions.rs | 2 | ||||
-rw-r--r-- | cli/ops/plugins.rs | 96 | ||||
-rw-r--r-- | cli/ops/workers.rs | 7 |
4 files changed, 105 insertions, 1 deletions
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!({})) }); |