diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index c41042bbc8b..00ab1dd5555 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -19,12 +19,6 @@ export class ExternalObject { [K: symbol]: T } } -export class DependenciesBlockDto { - get dependencies(): Array - get blocks(): Array -} -export type DependenciesBlockDTO = DependenciesBlockDto - export class DependenciesDto { get fileDependencies(): Array get addedFileDependencies(): Array @@ -139,6 +133,11 @@ export class JsContextModuleFactoryBeforeResolveData { set recursive(recursive: boolean) } +export class JsDependenciesBlock { + get dependencies(): Array + get blocks(): Array +} + export class JsDependency { get type(): string get category(): string @@ -194,7 +193,7 @@ export class ModuleDto { get factoryMeta(): JsFactoryMeta | undefined get type(): string get layer(): string | undefined - get blocks(): Array + get blocks(): Array size(ty?: string | undefined | null): number get modules(): ModuleDTO[] | undefined } diff --git a/crates/node_binding/src/lib.rs b/crates/node_binding/src/lib.rs index 356a0a6d939..d49a51d2a38 100644 --- a/crates/node_binding/src/lib.rs +++ b/crates/node_binding/src/lib.rs @@ -11,7 +11,7 @@ use std::sync::Mutex; use compiler::{Compiler, CompilerState, CompilerStateGuard}; use napi::bindgen_prelude::*; use rspack_binding_options::BuiltinPlugin; -use rspack_core::{Compilation, PluginExt}; +use rspack_core::PluginExt; use rspack_error::Diagnostic; use rspack_fs_node::{AsyncNodeWritableFileSystem, ThreadsafeNodeFS}; @@ -171,7 +171,7 @@ impl Rspack { Ok(unsafe { s.compiler.as_mut().get_unchecked_mut() }) })?; - self.cleanup_last_compilation(&compiler.compilation); + self.cleanup_last_compilation(); // SAFETY: // 1. `Compiler` is pinned and stored on the heap. @@ -182,8 +182,8 @@ impl Rspack { ) } - fn cleanup_last_compilation(&self, compilation: &Compilation) { - JsCompilationWrapper::cleanup(compilation.id()); + fn cleanup_last_compilation(&self) { + JsCompilationWrapper::cleanup_last_compilation(); } } diff --git a/crates/rspack_binding_options/src/options/raw_split_chunks/raw_split_chunk_cache_group_test.rs b/crates/rspack_binding_options/src/options/raw_split_chunks/raw_split_chunk_cache_group_test.rs index 19e7d67572c..0f828d893cc 100644 --- a/crates/rspack_binding_options/src/options/raw_split_chunks/raw_split_chunk_cache_group_test.rs +++ b/crates/rspack_binding_options/src/options/raw_split_chunks/raw_split_chunk_cache_group_test.rs @@ -29,7 +29,7 @@ impl FromNapiValue for JsCacheGroupTestCtx { impl<'a> From> for JsCacheGroupTestCtx { fn from(value: CacheGroupTestFnCtx<'a>) -> Self { JsCacheGroupTestCtx { - module: ModuleDTOWrapper::new(value.module.identifier(), value.compilation), + module: ModuleDTOWrapper::new(value.module, value.compilation), } } } diff --git a/crates/rspack_binding_values/src/chunk_graph.rs b/crates/rspack_binding_values/src/chunk_graph.rs index ba56dc94b01..c35769d5845 100644 --- a/crates/rspack_binding_values/src/chunk_graph.rs +++ b/crates/rspack_binding_values/src/chunk_graph.rs @@ -17,7 +17,7 @@ pub fn get_chunk_modules(js_chunk_ukey: u32, compilation: &JsCompilation) -> Vec return modules .iter() - .map(|module| ModuleDTOWrapper::new(module.identifier(), compilation)) + .map(|module| ModuleDTOWrapper::new(module.as_ref(), compilation)) .collect::>(); } diff --git a/crates/rspack_binding_values/src/chunk_group.rs b/crates/rspack_binding_values/src/chunk_group.rs index f61f125aa00..3f6f970fd4e 100644 --- a/crates/rspack_binding_values/src/chunk_group.rs +++ b/crates/rspack_binding_values/src/chunk_group.rs @@ -53,9 +53,12 @@ impl JsChunkGroup { .origins() .iter() .map(|origin| JsChunkGroupOrigin { - module: origin - .module_id - .map(|module_id| ModuleDTOWrapper::new(module_id, compilation)), + module: origin.module_id.map(|module_id| { + let module = compilation + .module_by_identifier(&module_id) + .unwrap_or_else(|| panic!("failed to retrieve module by id: {}", module_id)); + ModuleDTOWrapper::new(module.as_ref(), compilation) + }), request: origin.request.clone(), }) .collect::>(), diff --git a/crates/rspack_binding_values/src/compilation/mod.rs b/crates/rspack_binding_values/src/compilation/mod.rs index aeec7ac623f..1fa59c6052e 100644 --- a/crates/rspack_binding_values/src/compilation/mod.rs +++ b/crates/rspack_binding_values/src/compilation/mod.rs @@ -15,7 +15,6 @@ use rspack_core::get_chunk_group_from_ukey; use rspack_core::rspack_sources::BoxSource; use rspack_core::AssetInfo; use rspack_core::ChunkUkey; -use rspack_core::CompilationId; use rspack_core::ModuleIdentifier; use rspack_error::Diagnostic; use rspack_napi::napi::bindgen_prelude::*; @@ -142,8 +141,12 @@ impl JsCompilation { .get_module_graph() .modules() .keys() - .cloned() - .map(|module_id| ModuleDTOWrapper::new(module_id, self.0)) + .filter_map(|module_id| { + self + .0 + .module_by_identifier(module_id) + .map(|module| ModuleDTOWrapper::new(module.as_ref(), self.0)) + }) .collect::>() } @@ -153,7 +156,12 @@ impl JsCompilation { .0 .built_modules .iter() - .map(|module_id| ModuleDTOWrapper::new(*module_id, self.0)) + .filter_map(|module_id| { + self + .0 + .module_by_identifier(module_id) + .map(|module| ModuleDTOWrapper::new(module.as_ref(), self.0)) + }) .collect::>() } @@ -567,19 +575,8 @@ impl JsCompilation { } } -#[derive(Default)] -struct CompilationInstanceRefs(RefCell>); - -impl Drop for CompilationInstanceRefs { - fn drop(&mut self) { - // cleanup references to be executed in cases of panic or unexpected termination - let mut refs = self.0.borrow_mut(); - refs.drain(); - } -} - thread_local! { - static COMPILATION_INSTANCE_REFS: CompilationInstanceRefs = Default::default(); + static COMPILATION_INSTANCE_REF: RefCell> = Default::default(); } // The difference between JsCompilationWrapper and JsCompilation is: @@ -601,42 +598,29 @@ impl JsCompilationWrapper { }) } - pub fn cleanup(compilation_id: CompilationId) { - COMPILATION_INSTANCE_REFS.with(|ref_cell| { - let mut refs = ref_cell.0.borrow_mut(); - refs.remove(&compilation_id); + pub fn cleanup_last_compilation() { + COMPILATION_INSTANCE_REF.with(|ref_cell| { + let _ = ref_cell.borrow_mut().take(); }); - ModuleDTOWrapper::cleanup(compilation_id); + ModuleDTOWrapper::cleanup_last_compilation(); } } impl ToNapiValue for JsCompilationWrapper { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { - COMPILATION_INSTANCE_REFS.with(|ref_cell| { - let mut env_wrapper = Env::from_raw(env); - let mut refs = ref_cell.0.borrow_mut(); - let compilation_id = val.0.id(); - let mut vacant = false; - let napi_value = match refs.entry(compilation_id) { - std::collections::hash_map::Entry::Occupied(entry) => { - let r = entry.get(); - ToNapiValue::to_napi_value(env, r) - } - std::collections::hash_map::Entry::Vacant(entry) => { - vacant = true; + COMPILATION_INSTANCE_REF.with(|ref_cell| { + let mut one_shot_ref = ref_cell.borrow_mut(); + match &*one_shot_ref { + Some(r) => ToNapiValue::to_napi_value(env, r), + None => { + let env_wrapper = Env::from_raw(env); let instance = JsCompilation(val.0).into_instance(env_wrapper)?; let napi_value = ToNapiValue::to_napi_value(env, instance)?; let r = OneShotRef::new(env, napi_value)?; - let r = entry.insert(r); - ToNapiValue::to_napi_value(env, r) + *one_shot_ref = Some(r); + Ok(napi_value) } - }; - if vacant { - // cleanup references to be executed when the JS thread exits normally - let _ = env_wrapper - .add_env_cleanup_hook((), move |_| JsCompilationWrapper::cleanup(compilation_id)); } - napi_value }) } } diff --git a/crates/rspack_binding_values/src/module.rs b/crates/rspack_binding_values/src/module.rs index 3ca26b58527..5df3220df5e 100644 --- a/crates/rspack_binding_values/src/module.rs +++ b/crates/rspack_binding_values/src/module.rs @@ -3,14 +3,12 @@ use std::{cell::RefCell, sync::Arc}; use napi_derive::napi; use rspack_collections::IdentifierMap; use rspack_core::{ - AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, Compilation, CompilationId, - CompilerModuleContext, DependenciesBlock, Module, ModuleGraph, ModuleIdentifier, - RuntimeModuleStage, SourceType, + AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, Compilation, CompilerModuleContext, + DependenciesBlock, Module, ModuleGraph, RuntimeModuleStage, SourceType, }; use rspack_napi::{napi::bindgen_prelude::*, threadsafe_function::ThreadsafeFunction, OneShotRef}; use rspack_plugin_runtime::RuntimeModuleFromJs; use rspack_util::source_map::SourceMapKind; -use rustc_hash::FxHashMap as HashMap; use super::{JsCompatSource, ToJsCompatSource}; use crate::{JsChunk, JsCodegenerationResults, JsDependency}; @@ -22,16 +20,19 @@ pub struct JsFactoryMeta { } #[napi] -pub struct DependenciesBlockDTO { +pub struct JsDependenciesBlock { block_id: AsyncDependenciesBlockIdentifier, compilation: &'static Compilation, } -impl DependenciesBlockDTO { - pub fn new( - block_id: AsyncDependenciesBlockIdentifier, - compilation: &'static Compilation, - ) -> Self { +impl JsDependenciesBlock { + pub fn new(block_id: AsyncDependenciesBlockIdentifier, compilation: &Compilation) -> Self { + let compilation = unsafe { + std::mem::transmute::<&rspack_core::Compilation, &'static rspack_core::Compilation>( + compilation, + ) + }; + Self { block_id, compilation, @@ -49,7 +50,7 @@ impl DependenciesBlockDTO { } #[napi] -impl DependenciesBlockDTO { +impl JsDependenciesBlock { #[napi(getter)] pub fn dependencies(&self) -> Vec { let module_graph = self.compilation.get_module_graph(); @@ -66,52 +67,38 @@ impl DependenciesBlockDTO { } #[napi(getter)] - pub fn blocks(&self) -> Vec { + pub fn blocks(&self) -> Vec { let module_graph = self.compilation.get_module_graph(); let block = self.block(&module_graph); let blocks = block.get_blocks(); blocks .iter() .cloned() - .map(|block_id| DependenciesBlockDTO::new(block_id, self.compilation)) + .map(|block_id| JsDependenciesBlock::new(block_id, self.compilation)) .collect::>() } } #[napi] pub struct ModuleDTO { - pub(crate) module_id: ModuleIdentifier, + pub(crate) module: &'static dyn Module, pub(crate) compilation: &'static Compilation, } impl ModuleDTO { - pub fn new(module_id: ModuleIdentifier, compilation: &'static Compilation) -> Self { + pub fn new(module: &'static dyn Module, compilation: &'static Compilation) -> Self { Self { - module_id, + module, compilation, } } - - fn module(&self) -> &dyn Module { - self - .compilation - .module_by_identifier(&self.module_id) - .unwrap_or_else(|| { - panic!( - "Cannot access module with id = {}. It might have been dropped on the Rust side.", - self.module_id - ) - }) - .as_ref() - } } #[napi] impl ModuleDTO { #[napi(getter)] pub fn context(&self) -> Either { - let module = self.module(); - match module.get_context() { + match self.module.get_context() { Some(ctx) => Either::A(ctx.to_string()), None => Either::B(()), } @@ -119,8 +106,7 @@ impl ModuleDTO { #[napi(getter)] pub fn original_source(&self) -> Either { - let module = self.module(); - match module.original_source() { + match self.module.original_source() { Some(source) => match source.to_js_compat_source().ok() { Some(s) => Either::A(s), None => Either::B(()), @@ -131,8 +117,7 @@ impl ModuleDTO { #[napi(getter)] pub fn resource(&self) -> Either { - let module = self.module(); - match module.try_as_normal_module() { + match self.module.try_as_normal_module() { Ok(normal_module) => Either::A(normal_module.resource_resolved_data().resource.to_string()), Err(_) => Either::B(()), } @@ -140,14 +125,12 @@ impl ModuleDTO { #[napi(getter)] pub fn module_identifier(&self) -> &str { - let module = self.module(); - module.identifier().as_str() + self.module.identifier().as_str() } #[napi(getter)] pub fn name_for_condition(&self) -> Either { - let module = self.module(); - match module.name_for_condition() { + match self.module.name_for_condition() { Some(s) => Either::A(s.to_string()), None => Either::B(()), } @@ -155,8 +138,7 @@ impl ModuleDTO { #[napi(getter)] pub fn request(&self) -> Either<&str, ()> { - let module = self.module(); - match module.try_as_normal_module() { + match self.module.try_as_normal_module() { Ok(normal_module) => Either::A(normal_module.request()), Err(_) => Either::B(()), } @@ -164,8 +146,7 @@ impl ModuleDTO { #[napi(getter)] pub fn user_request(&self) -> Either<&str, ()> { - let module = self.module(); - match module.try_as_normal_module() { + match self.module.try_as_normal_module() { Ok(normal_module) => Either::A(normal_module.user_request()), Err(_) => Either::B(()), } @@ -173,8 +154,7 @@ impl ModuleDTO { #[napi(getter)] pub fn raw_request(&self) -> Either<&str, ()> { - let module = self.module(); - match module.try_as_normal_module() { + match self.module.try_as_normal_module() { Ok(normal_module) => Either::A(normal_module.raw_request()), Err(_) => Either::B(()), } @@ -182,8 +162,7 @@ impl ModuleDTO { #[napi(getter)] pub fn factory_meta(&self) -> Either { - let module = self.module(); - match module.try_as_normal_module() { + match self.module.try_as_normal_module() { Ok(normal_module) => match normal_module.factory_meta() { Some(meta) => Either::A(JsFactoryMeta { side_effect_free: meta.side_effect_free, @@ -196,46 +175,46 @@ impl ModuleDTO { #[napi(getter)] pub fn get_type(&self) -> &str { - let module = self.module(); - module.module_type().as_str() + self.module.module_type().as_str() } #[napi(getter)] pub fn layer(&self) -> Either<&String, ()> { - let module = self.module(); - match module.get_layer() { + match self.module.get_layer() { Some(layer) => Either::A(layer), None => Either::B(()), } } #[napi(getter)] - pub fn blocks(&self) -> Vec { - let module = self.module(); - let blocks = module.get_blocks(); + pub fn blocks(&self) -> Vec { + let blocks = self.module.get_blocks(); blocks .iter() .cloned() - .map(|block_id| DependenciesBlockDTO::new(block_id, self.compilation)) + .map(|block_id| JsDependenciesBlock::new(block_id, self.compilation)) .collect::>() } #[napi] pub fn size(&self, ty: Option) -> f64 { - let module = self.module(); let ty = ty.map(|s| SourceType::from(s.as_str())); - module.size(ty.as_ref(), self.compilation) + self.module.size(ty.as_ref(), self.compilation) } #[napi(getter, ts_return_type = "ModuleDTO[] | undefined")] pub fn modules(&self) -> Either, ()> { - let module = self.module(); - match module.try_as_concatenated_module() { + match self.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)) + .filter_map(|inner_module_info| { + self + .compilation + .module_by_identifier(&inner_module_info.id) + .map(|module| ModuleDTOWrapper::new(module.as_ref(), self.compilation)) + }) .collect::>(); Either::A(inner_modules) } @@ -246,11 +225,8 @@ impl ModuleDTO { type ModuleInstanceRefs = IdentifierMap; -#[derive(Default)] -struct ModuleInstanceRefsByCompilationId(RefCell>); - thread_local! { - static MODULE_INSTANCE_REFS: ModuleInstanceRefsByCompilationId = Default::default(); + static MODULE_INSTANCE_REFS: RefCell = RefCell::new(IdentifierMap::default()); } // The difference between ModuleDTOWrapper and ModuleDTO is: @@ -258,12 +234,14 @@ thread_local! { // // This means that when transferring a ModuleDTO from Rust to JS, you must use ModuleDTOWrapper instead. pub struct ModuleDTOWrapper { - pub module_id: ModuleIdentifier, + pub module: &'static dyn Module, pub compilation: &'static Compilation, } impl ModuleDTOWrapper { - pub fn new(module_id: ModuleIdentifier, compilation: &Compilation) -> Self { + pub fn new(module: &dyn Module, compilation: &Compilation) -> Self { + let module = unsafe { std::mem::transmute::<&dyn Module, &'static dyn Module>(module) }; + // SAFETY: // 1. `Compiler` is stored on the heap and pinned in binding crate. // 2. `Compilation` outlives `JsCompilation` and `Compiler` outlives `Compilation`. @@ -274,15 +252,15 @@ impl ModuleDTOWrapper { ) }; Self { - module_id, + module, compilation, } } - pub fn cleanup(compilation_id: CompilationId) { + pub fn cleanup_last_compilation() { MODULE_INSTANCE_REFS.with(|refs| { - let mut refs_by_compilation_id = refs.0.borrow_mut(); - refs_by_compilation_id.remove(&compilation_id) + let mut refs = refs.borrow_mut(); + let _ = refs.drain(); }); } } @@ -290,23 +268,15 @@ impl ModuleDTOWrapper { impl ToNapiValue for ModuleDTOWrapper { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { MODULE_INSTANCE_REFS.with(|refs| { - let mut refs_by_compilation_id = refs.0.borrow_mut(); - let entry = refs_by_compilation_id.entry(val.compilation.id()); - let refs = match entry { - std::collections::hash_map::Entry::Occupied(entry) => entry.into_mut(), - std::collections::hash_map::Entry::Vacant(entry) => { - let refs = IdentifierMap::default(); - entry.insert(refs) - } - }; - match refs.entry(val.module_id) { + let mut refs = refs.borrow_mut(); + match refs.entry(val.module.identifier()) { std::collections::hash_map::Entry::Occupied(entry) => { let r = entry.get(); ToNapiValue::to_napi_value(env, r) } std::collections::hash_map::Entry::Vacant(entry) => { let instance = - ModuleDTO::new(val.module_id, val.compilation).into_instance(Env::from_raw(env))?; + ModuleDTO::new(val.module, val.compilation).into_instance(Env::from_raw(env))?; let napi_value = ToNapiValue::to_napi_value(env, instance)?; let r = entry.insert(OneShotRef::new(env, napi_value)?); ToNapiValue::to_napi_value(env, r) diff --git a/crates/rspack_napi/src/js_values/one_shot_value_ref.rs b/crates/rspack_napi/src/js_values/one_shot_value_ref.rs index fd4ff2fc538..d7bf35974f9 100644 --- a/crates/rspack_napi/src/js_values/one_shot_value_ref.rs +++ b/crates/rspack_napi/src/js_values/one_shot_value_ref.rs @@ -1,38 +1,70 @@ -use napi::bindgen_prelude::ToNapiValue; -use napi::sys::{self, napi_env, napi_value}; -use napi::Result; +use std::cell::RefCell; +use std::ptr; +use std::rc::Rc; -use crate::Ref; +use napi::bindgen_prelude::{check_status, ToNapiValue}; +use napi::sys::{self, napi_env, napi_value}; +use napi::{Env, Result}; // A RAII (Resource Acquisition Is Initialization) style wrapper around `Ref` that ensures the // reference is unreferenced when it goes out of scope. This struct maintains a single reference // count and automatically cleans up when it is dropped. pub struct OneShotRef { env: napi_env, - inner: Ref, + raw_ref: sys::napi_ref, + cleanup_flag: Rc>, } impl OneShotRef { pub fn new(env: napi_env, value: napi_value) -> Result { - let inner = Ref::new(env, value, 1)?; - Ok(Self { env, inner }) + let mut raw_ref = ptr::null_mut(); + check_status!(unsafe { sys::napi_create_reference(env, value, 1, &mut raw_ref) })?; + + // cleanup references to be executed when the JS thread exits normally + let cleanup_flag = Rc::new(RefCell::new(false)); + let mut env_wrapper = unsafe { Env::from_raw(env) }; + let _ = env_wrapper.add_env_cleanup_hook(cleanup_flag.clone(), move |cleanup_flag| { + if !*cleanup_flag.borrow() { + *cleanup_flag.borrow_mut() = true; + unsafe { sys::napi_delete_reference(env, raw_ref) }; + } + }); + + Ok(Self { + env, + raw_ref, + cleanup_flag, + }) } } impl Drop for OneShotRef { fn drop(&mut self) { - let _ = self.inner.unref(self.env); + if !*self.cleanup_flag.borrow() { + *self.cleanup_flag.borrow_mut() = true; + unsafe { sys::napi_delete_reference(self.env, self.raw_ref) }; + } } } impl ToNapiValue for &OneShotRef { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { - unsafe { ToNapiValue::to_napi_value(env, &val.inner) } + let mut result = ptr::null_mut(); + check_status!( + unsafe { sys::napi_get_reference_value(env, val.raw_ref, &mut result) }, + "Failed to get reference value" + )?; + Ok(result) } } impl ToNapiValue for &mut OneShotRef { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { - unsafe { ToNapiValue::to_napi_value(env, &val.inner) } + let mut result = ptr::null_mut(); + check_status!( + unsafe { sys::napi_get_reference_value(env, val.raw_ref, &mut result) }, + "Failed to get reference value" + )?; + Ok(result) } } diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 5719a7aa287..9706807fe14 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -17,7 +17,6 @@ import type { Callback } from '@rspack/lite-tapable'; import { cleanupGlobalTrace } from '@rspack/binding'; import { Compiler as Compiler_2 } from '..'; import { default as default_2 } from './util/hash'; -import type { DependenciesBlockDTO } from '@rspack/binding'; import { RawEvalDevToolModulePluginOptions as EvalDevToolModulePluginOptions } from '@rspack/binding'; import { EventEmitter } from 'events'; import { ExternalObject } from '@rspack/binding'; @@ -42,6 +41,7 @@ import { JsCompilation } from '@rspack/binding'; import type { JsContextModuleFactoryAfterResolveData } from '@rspack/binding'; import type { JsContextModuleFactoryBeforeResolveData } from '@rspack/binding'; import type { JsCreateData } from '@rspack/binding'; +import type { JsDependenciesBlock } from '@rspack/binding'; import { JsDependency } from '@rspack/binding'; import { JsDependencyMut } from '@rspack/binding'; import type { JsFactoryMeta } from '@rspack/binding'; @@ -1253,11 +1253,14 @@ export type Dependencies = Name[]; // @public (undocumented) class DependenciesBlock { - constructor(binding: DependenciesBlockDTO); // (undocumented) - get blocks(): DependenciesBlock[]; + static __from_binding(binding: JsDependenciesBlock): DependenciesBlock; + // (undocumented) + static __to_binding(block: DependenciesBlock): JsDependenciesBlock; // (undocumented) - get dependencies(): Dependency[]; + readonly blocks: DependenciesBlock[]; + // (undocumented) + readonly dependencies: Dependency[]; } // @public (undocumented) @@ -7528,8 +7531,8 @@ export const rspackOptions: z.ZodObject<{ maxEntrypointSize?: number | undefined; }>, z.ZodLiteral]>>; }, "strict", z.ZodTypeAny, { - context?: string | undefined; dependencies?: string[] | undefined; + context?: string | undefined; module?: { parser?: { javascript?: { @@ -8127,8 +8130,8 @@ export const rspackOptions: z.ZodObject<{ devServer?: DevServer | undefined; bail?: boolean | undefined; }, { - context?: string | undefined; dependencies?: string[] | undefined; + context?: string | undefined; module?: { parser?: { javascript?: { diff --git a/packages/rspack/src/DependenciesBlock.ts b/packages/rspack/src/DependenciesBlock.ts index 7879c43ebd7..4ae6fbea569 100644 --- a/packages/rspack/src/DependenciesBlock.ts +++ b/packages/rspack/src/DependenciesBlock.ts @@ -1,18 +1,36 @@ -import type { DependenciesBlockDTO } from "@rspack/binding"; +import type { JsDependenciesBlock } from "@rspack/binding"; import { Dependency } from "./Dependency"; export class DependenciesBlock { - #binding: DependenciesBlockDTO; + #binding: JsDependenciesBlock; - constructor(binding: DependenciesBlockDTO) { - this.#binding = binding; + declare readonly dependencies: Dependency[]; + declare readonly blocks: DependenciesBlock[]; + + static __from_binding(binding: JsDependenciesBlock): DependenciesBlock { + return new DependenciesBlock(binding); } - get dependencies(): Dependency[] { - return this.#binding.dependencies.map(d => Dependency.__from_binding(d)); + static __to_binding(block: DependenciesBlock): JsDependenciesBlock { + return block.#binding; } - get blocks(): DependenciesBlock[] { - return this.#binding.blocks.map(b => new DependenciesBlock(b)); + private constructor(binding: JsDependenciesBlock) { + this.#binding = binding; + + Object.defineProperties(this, { + dependencies: { + enumerable: true, + get(): Dependency[] { + return binding.dependencies.map(d => Dependency.__from_binding(d)); + } + }, + blocks: { + enumerable: true, + get(): DependenciesBlock[] { + return binding.blocks.map(b => DependenciesBlock.__from_binding(b)); + } + } + }); } } diff --git a/packages/rspack/src/Module.ts b/packages/rspack/src/Module.ts index 92fc75c7eaf..398e0b427c4 100644 --- a/packages/rspack/src/Module.ts +++ b/packages/rspack/src/Module.ts @@ -302,7 +302,7 @@ export class Module { get blocks(): DependenciesBlock[] { if ("blocks" in this.#inner) { - return this.#inner.blocks.map(b => new DependenciesBlock(b)); + return this.#inner.blocks.map(b => DependenciesBlock.__from_binding(b)); } return []; }