rquickjs_extension/
definition.rs

1use rquickjs::{
2    module::{Declarations, Exports},
3    Ctx, Object, Result,
4};
5
6/// A trait for defining an extension with options.
7///
8/// # Example
9///
10/// ```
11/// use rquickjs::{Ctx, JsLifetime, Object, Result};
12/// use rquickjs_extension::{Extension, ModuleImpl};
13///
14/// #[derive(JsLifetime, Debug)]
15/// struct MyExtensionOptions {
16///     user: String,
17/// }
18///
19/// struct MyExtension {
20///     options: MyExtensionOptions,
21/// }
22///
23/// impl MyExtension {
24///     pub fn new<T: Into<String>>(user: T) -> Self {
25///         Self {
26///             options: MyExtensionOptions {
27///                 user: user.into(),
28///             },
29///         }
30///     }
31/// }
32///
33/// impl Extension<MyExtensionOptions> for MyExtension {
34///     type Implementation = ModuleImpl<MyExtensionOptions>;
35///
36///     fn implementation() -> &'static Self::Implementation {
37///         &ModuleImpl {
38///             declare: |decl| {
39///                 decl.declare("user")?;
40///                 Ok(())
41///             },
42///             evaluate: |ctx, exports, options| {
43///                 exports.export("user", options.user.clone())?;
44///                 Ok(())
45///             },
46///             name: "my-module",
47///         }
48///     }
49///
50///     fn options(self) -> MyExtensionOptions {
51///         self.options
52///     }
53///
54///     fn globals(globals: &Object<'_>, options: &MyExtensionOptions) -> Result<()> {
55///         globals.set("user", options.user.clone())?;
56///         Ok(())
57///     }
58/// }
59/// ```
60pub trait Extension<O = ()> {
61    type Implementation: ExtensionType<O>;
62
63    fn globals(_globals: &Object<'_>, _options: &O) -> Result<()> {
64        Ok(())
65    }
66
67    fn implementation() -> &'static Self::Implementation;
68
69    fn options(self) -> O;
70}
71
72/// Marker trait for implementation types
73pub trait ExtensionType<T> {}
74
75/// Implementation type when you only need to define globals
76pub struct GlobalsOnly;
77impl<T> ExtensionType<T> for GlobalsOnly {}
78
79/// Implementation type when you need to define a module and
80/// optionally globals.
81pub struct ModuleImpl<O = ()> {
82    pub declare: fn(&Declarations) -> Result<()>,
83    pub evaluate: for<'js> fn(&Ctx<'js>, &Exports<'js>, &O) -> Result<()>,
84    pub name: &'static str,
85}
86impl<T> ExtensionType<T> for ModuleImpl<T> {}