diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/js/40_plugins.js | 16 | ||||
-rw-r--r-- | runtime/js/90_deno_ns.js | 1 | ||||
-rw-r--r-- | runtime/ops/mod.rs | 1 | ||||
-rw-r--r-- | runtime/ops/plugin.rs | 86 | ||||
-rw-r--r-- | runtime/web_worker.rs | 1 | ||||
-rw-r--r-- | runtime/worker.rs | 1 |
6 files changed, 106 insertions, 0 deletions
diff --git a/runtime/js/40_plugins.js b/runtime/js/40_plugins.js new file mode 100644 index 000000000..0796fd5ce --- /dev/null +++ b/runtime/js/40_plugins.js @@ -0,0 +1,16 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +"use strict"; + +((window) => { + const core = window.Deno.core; + + function openPlugin(filename) { + const rid = core.opSync("op_open_plugin", filename); + core.syncOpsCache(); + return rid; + } + + window.__bootstrap.plugins = { + openPlugin, + }; +})(this); diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 89c9ef060..e4d0b00f2 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -109,6 +109,7 @@ Signal: __bootstrap.signals.Signal, SignalStream: __bootstrap.signals.SignalStream, emit: __bootstrap.compilerApi.emit, + openPlugin: __bootstrap.plugins.openPlugin, kill: __bootstrap.process.kill, setRaw: __bootstrap.tty.setRaw, consoleSize: __bootstrap.tty.consoleSize, diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs index 7b0832618..c94020780 100644 --- a/runtime/ops/mod.rs +++ b/runtime/ops/mod.rs @@ -5,6 +5,7 @@ pub mod fs_events; 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/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()) + } +} diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 1fcd57dc2..57a8142be 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -335,6 +335,7 @@ impl WebWorker { deno_net::init::<Permissions>(options.unstable), ops::os::init(), ops::permissions::init(), + ops::plugin::init(), ops::process::init(), ops::signal::init(), ops::tty::init(), diff --git a/runtime/worker.rs b/runtime/worker.rs index 543eae6f6..91810449d 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -126,6 +126,7 @@ impl MainWorker { deno_net::init::<Permissions>(options.unstable), ops::os::init(), ops::permissions::init(), + ops::plugin::init(), ops::process::init(), ops::signal::init(), ops::tty::init(), |