rquickjs_core/loader/
native_loader.rs1use crate::{loader::util::check_extensions, module::ModuleLoadFn, Ctx, Error, Module, Result};
2use alloc::{string::String, vec::Vec};
3
4use super::Loader;
5
6#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "dyn-load")))]
10#[derive(Debug)]
11pub struct NativeLoader {
12 extensions: Vec<String>,
13 libs: Vec<dlopen2::raw::Library>,
14}
15
16impl NativeLoader {
17 pub fn add_extension<X: Into<String>>(&mut self, extension: X) -> &mut Self {
19 self.extensions.push(extension.into());
20 self
21 }
22
23 pub fn with_extension<X: Into<String>>(&mut self, extension: X) -> &mut Self {
25 self.add_extension(extension);
26 self
27 }
28}
29
30impl Default for NativeLoader {
31 fn default() -> Self {
32 let mut loader = Self {
33 extensions: Vec::new(),
34 libs: Vec::new(),
35 };
36
37 #[cfg(target_family = "windows")]
38 loader.add_extension("dll");
39
40 #[cfg(target_family = "unix")]
41 loader.add_extension("so");
42
43 #[cfg(target_vendor = "apple")]
44 loader.add_extension("dylib");
45
46 loader
47 }
48}
49
50impl Loader for NativeLoader {
51 fn load<'js>(
52 &mut self,
53 ctx: &Ctx<'js>,
54 path: &str,
55 _attributes: Option<crate::loader::ImportAttributes<'js>>,
56 ) -> Result<Module<'js>> {
57 use dlopen2::raw::Library;
58
59 if !check_extensions(path, &self.extensions) {
60 return Err(Error::new_loading(path));
61 }
62
63 let lib = Library::open(path)
64 .map_err(|_| Error::new_loading_message(path, "Unable to open library"))?;
65 let load: ModuleLoadFn = unsafe { lib.symbol("js_init_module") }.map_err(|_| {
66 Error::new_loading_message(path, "Unable to find symbol `js_init_module`")
67 })?;
68
69 let module = unsafe { Module::from_load_fn(ctx.clone(), path, load)? };
70
71 self.libs.push(lib);
72
73 Ok(module)
74 }
75}