diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2021-07-11 18:12:26 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-11 18:12:26 -0700 |
commit | 511c48a03adee54aaadbefdeb2d2d521f6a45843 (patch) | |
tree | 817acc25f4c598fdc985f306f29fb3c318f87c55 /runtime/ops/plugin.rs | |
parent | eea6000ef6e30e6684995619e630d3beb7d7484b (diff) |
Revert "Remove unstable native plugins (#10908)"
This reverts commit 7dd4090c2a3dc0222fd6ff611eeb2bd69cd28224.
Diffstat (limited to 'runtime/ops/plugin.rs')
-rw-r--r-- | runtime/ops/plugin.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/runtime/ops/plugin.rs b/runtime/ops/plugin.rs new file mode 100644 index 000000000..cc3bf93d5 --- /dev/null +++ b/runtime/ops/plugin.rs @@ -0,0 +1,86 @@ +// 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()) + } +} |