summaryrefslogtreecommitdiff
path: root/runtime/ops
diff options
context:
space:
mode:
authorElias Sjögreen <eliassjogreen1@gmail.com>2021-08-06 23:28:10 +0200
committerGitHub <noreply@github.com>2021-08-06 23:28:10 +0200
commit33c8d790c3d358a475c9ba828043e2c19e8d4b37 (patch)
tree4ab33b3e5b352d49667d55631c76ee76af2ec5e2 /runtime/ops
parent0d1a522a03c22749e96dab06ca7b3e8b428df701 (diff)
feat: ffi to replace plugins (#11152)
This commit removes implementation of "native plugins" and replaces it with FFI API. Effectively "Deno.openPlugin" API was replaced with "Deno.dlopen" API.
Diffstat (limited to 'runtime/ops')
-rw-r--r--runtime/ops/mod.rs1
-rw-r--r--runtime/ops/permissions.rs7
-rw-r--r--runtime/ops/plugin.rs86
-rw-r--r--runtime/ops/worker_host.rs43
4 files changed, 44 insertions, 93 deletions
diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs
index 82ccf0506..e08ddd1c0 100644
--- a/runtime/ops/mod.rs
+++ b/runtime/ops/mod.rs
@@ -6,7 +6,6 @@ pub mod http;
pub mod io;
pub mod os;
pub mod permissions;
-pub mod plugin;
pub mod process;
pub mod runtime;
pub mod signal;
diff --git a/runtime/ops/permissions.rs b/runtime/ops/permissions.rs
index 3395430e4..d9f341633 100644
--- a/runtime/ops/permissions.rs
+++ b/runtime/ops/permissions.rs
@@ -28,6 +28,7 @@ pub struct PermissionArgs {
host: Option<String>,
variable: Option<String>,
command: Option<String>,
+ library: Option<String>,
}
pub fn op_query_permission(
@@ -49,7 +50,7 @@ pub fn op_query_permission(
),
"env" => permissions.env.query(args.variable.as_deref()),
"run" => permissions.run.query(args.command.as_deref()),
- "plugin" => permissions.plugin.query(),
+ "ffi" => permissions.ffi.query(args.library.as_deref()),
"hrtime" => permissions.hrtime.query(),
n => {
return Err(custom_error(
@@ -80,7 +81,7 @@ pub fn op_revoke_permission(
),
"env" => permissions.env.revoke(args.variable.as_deref()),
"run" => permissions.run.revoke(args.command.as_deref()),
- "plugin" => permissions.plugin.revoke(),
+ "ffi" => permissions.ffi.revoke(args.library.as_deref()),
"hrtime" => permissions.hrtime.revoke(),
n => {
return Err(custom_error(
@@ -111,7 +112,7 @@ pub fn op_request_permission(
),
"env" => permissions.env.request(args.variable.as_deref()),
"run" => permissions.run.request(args.command.as_deref()),
- "plugin" => permissions.plugin.request(),
+ "ffi" => permissions.ffi.request(args.library.as_deref()),
"hrtime" => permissions.hrtime.request(),
n => {
return Err(custom_error(
diff --git a/runtime/ops/plugin.rs b/runtime/ops/plugin.rs
deleted file mode 100644
index cc3bf93d5..000000000
--- a/runtime/ops/plugin.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-use crate::permissions::Permissions;
-use deno_core::error::AnyError;
-use deno_core::op_sync;
-use deno_core::Extension;
-use deno_core::OpState;
-use deno_core::Resource;
-use deno_core::ResourceId;
-use dlopen::symbor::Library;
-use log::debug;
-use std::borrow::Cow;
-use std::mem;
-use std::path::PathBuf;
-use std::rc::Rc;
-
-/// A default `init` function for plugins which mimics the way the internal
-/// extensions are initalized. Plugins currently do not support all extension
-/// features and are most likely not going to in the future. Currently only
-/// `init_state` and `init_ops` are supported while `init_middleware` and `init_js`
-/// are not. Currently the `PluginResource` does not support being closed due to
-/// certain risks in unloading the dynamic library without unloading dependent
-/// functions and resources.
-pub type InitFn = fn() -> Extension;
-
-pub fn init() -> Extension {
- Extension::builder()
- .ops(vec![("op_open_plugin", op_sync(op_open_plugin))])
- .build()
-}
-
-pub fn op_open_plugin(
- state: &mut OpState,
- filename: String,
- _: (),
-) -> Result<ResourceId, AnyError> {
- let filename = PathBuf::from(&filename);
-
- super::check_unstable(state, "Deno.openPlugin");
- let permissions = state.borrow_mut::<Permissions>();
- permissions.plugin.check()?;
-
- debug!("Loading Plugin: {:#?}", filename);
- let plugin_lib = Library::open(filename).map(Rc::new)?;
- let plugin_resource = PluginResource::new(&plugin_lib);
-
- // Forgets the plugin_lib value to prevent segfaults when the process exits
- mem::forget(plugin_lib);
-
- let init = *unsafe { plugin_resource.0.symbol::<InitFn>("init") }?;
- let rid = state.resource_table.add(plugin_resource);
- let mut extension = init();
-
- if !extension.init_js().is_empty() {
- panic!("Plugins do not support loading js");
- }
-
- if extension.init_middleware().is_some() {
- panic!("Plugins do not support middleware");
- }
-
- extension.init_state(state)?;
- let ops = extension.init_ops().unwrap_or_default();
- for (name, opfn) in ops {
- state.op_table.register_op(name, opfn);
- }
-
- Ok(rid)
-}
-
-struct PluginResource(Rc<Library>);
-
-impl Resource for PluginResource {
- fn name(&self) -> Cow<str> {
- "plugin".into()
- }
-
- fn close(self: Rc<Self>) {
- unimplemented!();
- }
-}
-
-impl PluginResource {
- fn new(lib: &Rc<Library>) -> Self {
- Self(lib.clone())
- }
-}
diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs
index 2cd9a14ad..5315ff5c7 100644
--- a/runtime/ops/worker_host.rs
+++ b/runtime/ops/worker_host.rs
@@ -3,6 +3,7 @@
use crate::permissions::resolve_read_allowlist;
use crate::permissions::resolve_write_allowlist;
use crate::permissions::EnvDescriptor;
+use crate::permissions::FfiDescriptor;
use crate::permissions::NetDescriptor;
use crate::permissions::PermissionState;
use crate::permissions::Permissions;
@@ -218,6 +219,26 @@ fn merge_run_permission(
Ok(main)
}
+fn merge_ffi_permission(
+ mut main: UnaryPermission<FfiDescriptor>,
+ worker: Option<UnaryPermission<FfiDescriptor>>,
+) -> Result<UnaryPermission<FfiDescriptor>, AnyError> {
+ if let Some(worker) = worker {
+ if (worker.global_state < main.global_state)
+ || !worker.granted_list.iter().all(|x| main.check(&x.0).is_ok())
+ {
+ return Err(custom_error(
+ "PermissionDenied",
+ "Can't escalate parent thread permissions",
+ ));
+ } else {
+ main.global_state = worker.global_state;
+ main.granted_list = worker.granted_list;
+ }
+ }
+ Ok(main)
+}
+
pub fn create_worker_permissions(
main_perms: Permissions,
worker_perms: PermissionsArg,
@@ -226,7 +247,7 @@ pub fn create_worker_permissions(
env: merge_env_permission(main_perms.env, worker_perms.env)?,
hrtime: merge_boolean_permission(main_perms.hrtime, worker_perms.hrtime)?,
net: merge_net_permission(main_perms.net, worker_perms.net)?,
- plugin: merge_boolean_permission(main_perms.plugin, worker_perms.plugin)?,
+ ffi: merge_ffi_permission(main_perms.ffi, worker_perms.ffi)?,
read: merge_read_permission(main_perms.read, worker_perms.read)?,
run: merge_run_permission(main_perms.run, worker_perms.run)?,
write: merge_write_permission(main_perms.write, worker_perms.write)?,
@@ -241,8 +262,8 @@ pub struct PermissionsArg {
hrtime: Option<PermissionState>,
#[serde(default, deserialize_with = "as_unary_net_permission")]
net: Option<UnaryPermission<NetDescriptor>>,
- #[serde(default, deserialize_with = "as_permission_state")]
- plugin: Option<PermissionState>,
+ #[serde(default, deserialize_with = "as_unary_ffi_permission")]
+ ffi: Option<UnaryPermission<FfiDescriptor>>,
#[serde(default, deserialize_with = "as_unary_read_permission")]
read: Option<UnaryPermission<ReadDescriptor>>,
#[serde(default, deserialize_with = "as_unary_run_permission")]
@@ -414,6 +435,22 @@ where
}))
}
+fn as_unary_ffi_permission<'de, D>(
+ deserializer: D,
+) -> Result<Option<UnaryPermission<FfiDescriptor>>, D::Error>
+where
+ D: Deserializer<'de>,
+{
+ let value: UnaryPermissionBase =
+ deserializer.deserialize_any(ParseBooleanOrStringVec)?;
+
+ Ok(Some(UnaryPermission::<FfiDescriptor> {
+ global_state: value.global_state,
+ granted_list: value.paths.into_iter().map(FfiDescriptor).collect(),
+ ..Default::default()
+ }))
+}
+
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateWorkerArgs {