summaryrefslogtreecommitdiff
path: root/cli/ops/plugins.rs
blob: f8c1b5bd23ac93b1b1de8532f8953d1aaf0f6666 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use super::dispatch_json::{Deserialize, JsonOp, Value};
use crate::fs as deno_fs;
use crate::op_error::OpError;
use crate::ops::json_op;
use crate::state::State;
use deno_core::Isolate;
use deno_core::ZeroCopyBuf;
use dlopen::symbor::Library;
use std::ffi::OsStr;
use std::path::Path;

pub type PluginInitFn = fn(isolate: &mut deno_core::Isolate);

pub fn init(i: &mut Isolate, s: &State) {
  i.register_op(
    "op_open_plugin",
    s.core_op(json_op(s.stateful_op2(op_open_plugin))),
  );
}

fn open_plugin<P: AsRef<OsStr>>(lib_path: P) -> Result<Library, OpError> {
  debug!("Loading Plugin: {:#?}", lib_path.as_ref());
  Library::open(lib_path).map_err(OpError::from)
}

struct PluginResource {
  lib: Library,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct OpenPluginArgs {
  filename: String,
}

pub fn op_open_plugin(
  isolate: &mut deno_core::Isolate,
  state: &State,
  args: Value,
  _zero_copy: Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
  let args: OpenPluginArgs = serde_json::from_value(args).unwrap();
  let filename = deno_fs::resolve_from_cwd(Path::new(&args.filename))?;

  state.check_plugin(&filename)?;

  let lib = open_plugin(filename).unwrap();
  let plugin_resource = PluginResource { lib };

  let mut resource_table = isolate.resource_table.borrow_mut();
  let rid = resource_table.add("plugin", Box::new(plugin_resource));
  let plugin_resource = resource_table.get::<PluginResource>(rid).unwrap();

  let deno_plugin_init = *unsafe {
    plugin_resource
      .lib
      .symbol::<PluginInitFn>("deno_plugin_init")
  }
  .unwrap();
  drop(resource_table);

  deno_plugin_init(isolate);

  Ok(JsonOp::Sync(json!(rid)))
}