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> {}