Skip to content

Commit

Permalink
More renaming
Browse files Browse the repository at this point in the history
  • Loading branch information
Sytten committed Nov 30, 2024
1 parent 8887501 commit ece6093
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 172 deletions.
20 changes: 10 additions & 10 deletions src/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@ use rquickjs::{
///
/// ```
/// use rquickjs::{Ctx, JsLifetime, Object, Result};
/// use rquickjs_module::{ModuleDefExt, ModuleImpl};
/// use rquickjs_extension::{Extension, ModuleImpl};
///
/// #[derive(JsLifetime, Debug)]
/// struct MyModuleOptions {
/// struct MyExtensionOptions {
/// user: String,
/// }
///
/// struct MyModule {
/// options: MyModuleOptions,
/// struct MyExtension {
/// options: MyExtensionOptions,
/// }
///
/// impl MyModule {
/// impl MyExtension {
/// pub fn new<T: Into<String>>(user: T) -> Self {
/// Self {
/// options: MyModuleOptions {
/// options: MyExtensionOptions {
/// user: user.into(),
/// },
/// }
/// }
/// }
///
/// impl ModuleDefExt<MyModuleOptions> for MyModule {
/// type Implementation = ModuleImpl<MyModuleOptions>;
/// impl Extension<MyExtensionOptions> for MyExtension {
/// type Implementation = ModuleImpl<MyExtensionOptions>;
///
/// fn implementation() -> &'static Self::Implementation {
/// &ModuleImpl {
Expand All @@ -48,11 +48,11 @@ use rquickjs::{
/// }
/// }
///
/// fn options(self) -> MyModuleOptions {
/// fn options(self) -> MyExtensionOptions {
/// self.options
/// }
///
/// fn globals(globals: &Object<'_>, options: &MyModuleOptions) -> Result<()> {
/// fn globals(globals: &Object<'_>, options: &MyExtensionOptions) -> Result<()> {
/// globals.set("user", options.user.clone())?;
/// Ok(())
/// }
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! that would allow it to have options as input and set global.
pub use self::definition::{Extension, GlobalsOnly, ModuleImpl};
pub use self::loader::{GlobalInitializer, ModuleLoader, ModuleLoaderBuilder, ModuleResolver};
pub use self::loader::{ExtensionBuilder, GlobalInitializer, ModuleLoader, ModuleResolver};

mod definition;
mod loader;
Expand Down
128 changes: 0 additions & 128 deletions src/loader/builder.rs

This file was deleted.

30 changes: 30 additions & 0 deletions src/loader/loader.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use std::collections::HashMap;

use rquickjs::{loader::Loader, Ctx, Error, Module, Result};

use super::ModuleLoadFn;

/// Rquickjs [`Loader`](rquickjs::loader::Loader) for Rust modules
/// defined using [`ModuleDefExt`](crate::ModuleDefExt).
///
/// See [`ModuleLoaderBuilder`] for usage.
pub struct ModuleLoader {
modules: HashMap<&'static str, ModuleLoadFn>,
}

impl ModuleLoader {
pub(crate) fn new(modules: HashMap<&'static str, ModuleLoadFn>) -> Self {
Self { modules }
}
}

impl Loader for ModuleLoader {
fn load<'js>(&mut self, ctx: &Ctx<'js>, path: &str) -> Result<Module<'js>> {
let load = self
.modules
.remove(path)
.ok_or_else(|| Error::new_loading(path))?;

(load)(ctx.clone(), Vec::from(path))
}
}
141 changes: 120 additions & 21 deletions src/loader/mod.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,142 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

use rquickjs::{loader::Loader, Ctx, Error, Module, Object, Result};
use rquickjs::{
module::{Module, ModuleDef},
Ctx, JsLifetime, Object, Result,
};

pub use self::builder::ModuleLoaderBuilder;
pub use self::global::GlobalInitializer;
pub use self::loader::ModuleLoader;
pub use self::resolver::ModuleResolver;
use crate::wrapper::{IntoModule, ModuleMeta};

mod builder;
mod global;
#[allow(clippy::module_inception)]
mod loader;
mod resolver;

type GlobalLoadFn = Box<dyn for<'js> FnOnce(&Ctx<'js>, &Object<'js>) -> Result<()> + Send + Sync>;
type ModuleLoadFn = for<'js> fn(Ctx<'js>, Vec<u8>) -> Result<Module<'js>>;

/// Rquickjs [`Loader`](rquickjs::loader::Loader) for Rust modules
/// defined using [`ModuleDefExt`](crate::ModuleDefExt).
fn load_module_func<D: ModuleDef>(ctx: Ctx<'_>, name: Vec<u8>) -> Result<Module<'_>> {
Module::declare_def::<D, _>(ctx, name)
}

/// Builder to create a [`ModuleLoader`], [`ModuleResolver`] and [`GlobalInitializer`]
///
/// # Example
/// ```rust
/// use rquickjs_module::{ModuleLoader, ModuleDefExt, ModuleImpl};
///
/// struct MyExtension;
///
/// impl Extension for MyExtension {
/// type Implementation = ModuleImpl<()>;
///
/// See [`ModuleLoaderBuilder`] for usage.
pub struct ModuleLoader {
/// fn implementation() -> &'static Self::Implementation {
/// &ModuleImpl {
/// declare: |decl| {
/// decl.declare("hello")?;
/// Ok(())
/// },
/// evaluate: |ctx, exports, options| {
/// exports.export("hello", "world".to_string())?;
/// Ok(())
/// },
/// name: "my-module",
/// }
/// }
///
/// fn options(self) -> () {}
/// }
///
/// ```
#[derive(Default)]
pub struct ExtensionBuilder {
modules: HashMap<&'static str, ModuleLoadFn>,
globals: Vec<GlobalLoadFn>,
names: HashSet<&'static str>,
}

impl ModuleLoader {
pub(crate) fn new(modules: HashMap<&'static str, ModuleLoadFn>) -> Self {
Self { modules }
impl ExtensionBuilder {
pub fn new() -> Self {
Self::default()
}

pub fn builder() -> ModuleLoaderBuilder {
ModuleLoaderBuilder::default()
#[must_use]
pub fn with_extension<O, M, R>(mut self, extension: M) -> Self
where
for<'js> O: JsLifetime<'js> + Send + Sync + 'static,
R: ModuleDef + ModuleMeta,
M: IntoModule<O, R>,
{
self.process_extension(extension, None);
self
}

#[must_use]
pub fn with_extension_named<O, M, R>(mut self, extension: M, name: &'static str) -> Self
where
for<'js> O: JsLifetime<'js> + Send + Sync + 'static,
R: ModuleDef + ModuleMeta,
M: IntoModule<O, R>,
{
self.process_extension(extension, Some(name));
self
}
}

impl Loader for ModuleLoader {
fn load<'js>(&mut self, ctx: &Ctx<'js>, path: &str) -> Result<Module<'js>> {
let load = self
.modules
.remove(path)
.ok_or_else(|| Error::new_loading(path))?;
pub fn add_extension<O, M, R>(&mut self, extension: M) -> &mut Self
where
for<'js> O: JsLifetime<'js> + Send + Sync + 'static,
R: ModuleDef + ModuleMeta,
M: IntoModule<O, R>,
{
self.process_extension(extension, None)
}

pub fn add_extension_named<O, M, R>(&mut self, extension: M, name: &'static str) -> &mut Self
where
for<'js> O: JsLifetime<'js> + Send + Sync + 'static,
R: ModuleDef + ModuleMeta,
M: IntoModule<O, R>,
{
self.process_extension(extension, Some(name))
}

fn process_extension<O, M, R>(&mut self, extension: M, name: Option<&'static str>) -> &mut Self
where
for<'js> O: JsLifetime<'js> + Send + Sync + 'static,
R: ModuleDef + ModuleMeta,
M: IntoModule<O, R>,
{
let o = extension.options();

// Create a new closure that explicitly captures 'js lifetime
let globals_fn = move |ctx: &Ctx<'_>, globals: &Object<'_>| {
let globals_fn = M::globals;
globals_fn(globals, &o)?;
let _ = ctx.store_userdata(o);
Ok(())
};

// Box the closure with explicit lifetime bounds
let boxed_globals: GlobalLoadFn = Box::new(globals_fn);

if R::is_module() {
let name = name.unwrap_or(R::name());
self.names.insert(name);
self.modules.insert(name, load_module_func::<R>);
}

self.globals.push(boxed_globals);
self
}

(load)(ctx.clone(), Vec::from(path))
pub fn build(self) -> (ModuleLoader, ModuleResolver, GlobalInitializer) {
(
ModuleLoader::new(self.modules),
ModuleResolver::new(self.names),
GlobalInitializer::new(self.globals),
)
}
}
Loading

0 comments on commit ece6093

Please sign in to comment.