Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: module.modules #8192

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export class ModuleDto {
get layer(): string | undefined
get blocks(): Array<DependenciesBlockDto>
size(ty?: string | undefined | null): number
get modules(): ModuleDTO | undefined
}
export type ModuleDTO = ModuleDto

Expand Down
60 changes: 39 additions & 21 deletions crates/rspack_binding_values/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{cell::RefCell, sync::Arc};

use napi_derive::napi;
use rspack_collections::Identifier;
use rspack_collections::IdentifierMap;
use rspack_core::{
AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, Compilation, CompilationId,
CompilerModuleContext, DependenciesBlock, Module, ModuleGraph, ModuleIdentifier,
Expand Down Expand Up @@ -99,7 +99,7 @@
.module_by_identifier(&self.module_id)
.unwrap_or_else(|| {
panic!(
"Cannot find module with id = {}. It might have been removed on the Rust side.",
"Cannot access module with id = {}. It might have been dropped on the Rust side.",
self.module_id
)
})
Expand Down Expand Up @@ -227,24 +227,46 @@
let ty = ty.map(|s| SourceType::from(s.as_str()));
module.size(ty.as_ref(), self.compilation)
}

#[napi(getter, ts_return_type = "ModuleDTO | undefined")]
pub fn modules(&self) -> Either<Vec<ModuleDTOWrapper>, ()> {
let module = self.module();
match module.try_as_concatenated_module() {
Ok(concatenated_module) => {
let inner_modules = concatenated_module
.get_modules()
.iter()
.map(|inner_module| ModuleDTOWrapper::new(inner_module.id, &self.compilation))

Check failure on line 239 in crates/rspack_binding_values/src/module.rs

View workflow job for this annotation

GitHub Actions / Rust check

this expression creates a reference which is immediately dereferenced by the compiler
.collect::<Vec<_>>();
Either::A(inner_modules)
}
Err(_) => Either::B(()),
}
}
}

type ModuleInstanceRefs = HashMap<Identifier, (Ref, napi_env)>;
struct ModuleInstanceRef {
env: napi_env,
inner: Ref,
}

#[derive(Default)]
struct ModuleInstanceRefsByCompilationId(RefCell<HashMap<CompilationId, ModuleInstanceRefs>>);
impl ModuleInstanceRef {
pub fn new(env: napi_env, inner: Ref) -> Self {
Self { env, inner }
}
}

impl Drop for ModuleInstanceRefsByCompilationId {
impl Drop for ModuleInstanceRef {
fn drop(&mut self) {
let mut refs_by_compilation_id = self.0.borrow_mut();
for (_, mut refs) in refs_by_compilation_id.drain() {
for (_, (mut r, env)) in refs.drain() {
let _ = r.unref(env);
}
}
let _ = self.inner.unref(self.env);
}
}

type ModuleInstanceRefs = IdentifierMap<ModuleInstanceRef>;

#[derive(Default)]
struct ModuleInstanceRefsByCompilationId(RefCell<HashMap<CompilationId, ModuleInstanceRefs>>);

thread_local! {
static MODULE_INSTANCE_REFS: ModuleInstanceRefsByCompilationId = Default::default();
}
Expand Down Expand Up @@ -278,11 +300,7 @@
pub fn cleanup(compilation_id: CompilationId) {
MODULE_INSTANCE_REFS.with(|refs| {
let mut refs_by_compilation_id = refs.0.borrow_mut();
if let Some(mut refs) = refs_by_compilation_id.remove(&compilation_id) {
for (_, (mut r, env)) in refs.drain() {
let _ = r.unref(env);
}
}
refs_by_compilation_id.remove(&compilation_id)
});
}
}
Expand All @@ -295,22 +313,22 @@
let refs = match entry {
std::collections::hash_map::Entry::Occupied(entry) => entry.into_mut(),
std::collections::hash_map::Entry::Vacant(entry) => {
let refs = HashMap::default();
let refs = IdentifierMap::default();
entry.insert(refs)
}
};
match refs.entry(val.module_id) {
std::collections::hash_map::Entry::Occupied(entry) => {
let r = entry.get();
ToNapiValue::to_napi_value(env, &r.0)
ToNapiValue::to_napi_value(env, &r.inner)
}
std::collections::hash_map::Entry::Vacant(entry) => {
let instance =
ModuleDTO::new(val.module_id, val.compilation).into_instance(Env::from_raw(env))?;
let napi_value = ToNapiValue::to_napi_value(env, instance)?;
let r = Ref::new(env, napi_value, 1)?;
let r = entry.insert((r, env));
ToNapiValue::to_napi_value(env, &r.0)
let r = entry.insert(ModuleInstanceRef::new(env, r));
ToNapiValue::to_napi_value(env, &r.inner)
}
}
})
Expand Down
Loading