rquickjs_core/loader/
native_loader.rs

1use crate::{loader::util::check_extensions, module::ModuleLoadFn, Ctx, Error, Module, Result};
2use alloc::{string::String, vec::Vec};
3
4use super::Loader;
5
6/// The native module loader
7///
8/// This loader can be used as the nested backing loader in user-defined loaders.
9#[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    /// Add library file extension
18    pub fn add_extension<X: Into<String>>(&mut self, extension: X) -> &mut Self {
19        self.extensions.push(extension.into());
20        self
21    }
22
23    /// Add library file extension
24    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>(&mut self, ctx: &Ctx<'js>, path: &str) -> Result<Module<'js>> {
52        use dlopen2::raw::Library;
53
54        if !check_extensions(path, &self.extensions) {
55            return Err(Error::new_loading(path));
56        }
57
58        let lib = Library::open(path)
59            .map_err(|_| Error::new_loading_message(path, "Unable to open library"))?;
60        let load: ModuleLoadFn = unsafe { lib.symbol("js_init_module") }.map_err(|_| {
61            Error::new_loading_message(path, "Unable to find symbol `js_init_module`")
62        })?;
63
64        let module = unsafe { Module::from_load_fn(ctx.clone(), path, load)? };
65
66        self.libs.push(lib);
67
68        Ok(module)
69    }
70}