diff --git a/.vscode/settings.json b/.vscode/settings.json index 6d07ace19b6..a08a0c167a9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -42,5 +42,6 @@ "tokio", "ukey", "Ukey" - ] + ], + "rust-analyzer.checkOnSave": true } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index cfea26dd7cb..c740cddfb52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3763,6 +3763,7 @@ dependencies = [ "rspack_plugin_real_content_hash", "rspack_plugin_remove_duplicate_modules", "rspack_plugin_remove_empty_chunks", + "rspack_plugin_rsdoctor", "rspack_plugin_runtime", "rspack_plugin_runtime_chunk", "rspack_plugin_schemes", @@ -4670,6 +4671,7 @@ version = "0.2.0" dependencies = [ "async-trait", "cow-utils", + "futures", "indexmap 2.7.0", "rayon", "rspack_collections", diff --git a/Cargo.toml b/Cargo.toml index 87dc583b462..c4e8e338321 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -168,6 +168,7 @@ rspack_plugin_progress = { version = "0.2.0", path = "crates/rsp rspack_plugin_real_content_hash = { version = "0.2.0", path = "crates/rspack_plugin_real_content_hash" } rspack_plugin_remove_duplicate_modules = { version = "0.2.0", path = "crates/rspack_plugin_remove_duplicate_modules" } rspack_plugin_remove_empty_chunks = { version = "0.2.0", path = "crates/rspack_plugin_remove_empty_chunks" } +rspack_plugin_rsdoctor = { version = "0.2.0", path = "crates/rspack_plugin_rsdoctor" } rspack_plugin_runtime = { version = "0.2.0", path = "crates/rspack_plugin_runtime" } rspack_plugin_runtime_chunk = { version = "0.2.0", path = "crates/rspack_plugin_runtime_chunk" } rspack_plugin_schemes = { version = "0.2.0", path = "crates/rspack_plugin_schemes" } diff --git a/crates/rspack_binding_values/Cargo.toml b/crates/rspack_binding_values/Cargo.toml index 5e2e48e2779..fd00b9bdd5a 100644 --- a/crates/rspack_binding_values/Cargo.toml +++ b/crates/rspack_binding_values/Cargo.toml @@ -75,6 +75,7 @@ rspack_plugin_progress = { workspace = true } rspack_plugin_real_content_hash = { workspace = true } rspack_plugin_remove_duplicate_modules = { workspace = true } rspack_plugin_remove_empty_chunks = { workspace = true } +rspack_plugin_rsdoctor = { workspace = true } rspack_plugin_runtime = { workspace = true } rspack_plugin_runtime_chunk = { workspace = true } rspack_plugin_schemes = { workspace = true } diff --git a/crates/rspack_binding_values/src/plugins/mod.rs b/crates/rspack_binding_values/src/plugins/mod.rs index b8015e2e9c4..392a1d77057 100644 --- a/crates/rspack_binding_values/src/plugins/mod.rs +++ b/crates/rspack_binding_values/src/plugins/mod.rs @@ -1,6 +1,8 @@ mod context_replacement; mod js_loader; +mod rsdoctor; pub use context_replacement::*; pub(super) use js_loader::{JsLoaderRspackPlugin, JsLoaderRunner}; pub mod buildtime_plugins; +pub use rsdoctor::*; diff --git a/crates/rspack_binding_values/src/plugins/rsdoctor/data.rs b/crates/rspack_binding_values/src/plugins/rsdoctor/data.rs new file mode 100644 index 00000000000..bb281b87d67 --- /dev/null +++ b/crates/rspack_binding_values/src/plugins/rsdoctor/data.rs @@ -0,0 +1,314 @@ +use napi_derive::napi; +use rspack_plugin_rsdoctor::{ + RsdoctorAsset, RsdoctorChunk, RsdoctorChunkGraph, RsdoctorDependency, RsdoctorEntrypoint, + RsdoctorExportInfo, RsdoctorModule, RsdoctorModuleGraph, RsdoctorModuleGraphModule, + RsdoctorModuleSource, RsdoctorSideEffect, RsdoctorSourcePosition, RsdoctorSourceRange, + RsdoctorStatement, RsdoctorVariable, +}; + +#[napi(object)] +pub struct JsRsdoctorModule { + pub ukey: i32, + pub identifier: String, + pub path: String, + pub is_entry: bool, + pub kind: String, + pub layer: Option, + pub dependencies: Vec, + pub imported: Vec, + pub modules: Vec, + pub chunks: Vec, +} + +impl From for JsRsdoctorModule { + fn from(value: RsdoctorModule) -> Self { + JsRsdoctorModule { + ukey: value.ukey as i32, + identifier: value.identifier.to_string(), + path: value.path, + is_entry: value.is_entry, + kind: value.kind.into(), + layer: value.layer, + dependencies: value.dependencies.into_iter().map(|d| d as i32).collect(), + imported: value.imported.into_iter().map(|d| d as i32).collect(), + modules: value.modules.into_iter().map(|d| d as i32).collect(), + chunks: value.chunks.into_iter().map(|d| d as i32).collect(), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorDependency { + pub ukey: i32, + pub kind: String, + pub request: String, + pub module: i32, + pub dependency: i32, +} + +impl From for JsRsdoctorDependency { + fn from(value: RsdoctorDependency) -> Self { + JsRsdoctorDependency { + ukey: value.ukey as i32, + kind: value.kind.to_string(), + request: value.request, + module: value.module as i32, + dependency: value.dependency as i32, + } + } +} + +#[napi(object)] +pub struct JsRsdoctorChunk { + pub ukey: i32, + pub name: String, + pub initial: bool, + pub entry: bool, + pub assets: Vec, + pub dependencies: Vec, + pub imported: Vec, +} + +impl From for JsRsdoctorChunk { + fn from(value: RsdoctorChunk) -> Self { + JsRsdoctorChunk { + ukey: value.ukey as i32, + name: value.name, + initial: value.initial, + entry: value.entry, + assets: value.assets.into_iter().map(|d| d as i32).collect(), + dependencies: value.dependencies.into_iter().map(|d| d as i32).collect(), + imported: value.imported.into_iter().map(|d| d as i32).collect(), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorEntrypoint { + pub ukey: i32, + pub name: String, + pub chunks: Vec, +} + +impl From for JsRsdoctorEntrypoint { + fn from(value: RsdoctorEntrypoint) -> Self { + JsRsdoctorEntrypoint { + ukey: value.ukey as i32, + name: value.name, + chunks: value.chunks.into_iter().map(|d| d as i32).collect(), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorAsset { + pub ukey: i32, + pub path: String, + pub chunks: Vec, +} + +impl From for JsRsdoctorAsset { + fn from(value: RsdoctorAsset) -> Self { + JsRsdoctorAsset { + ukey: value.ukey as i32, + path: value.path, + chunks: value.chunks.into_iter().map(|d| d as i32).collect(), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorModuleSource { + pub source_size: i32, + pub transform_size: i32, + pub source: Option, + pub source_map: Option, +} + +impl From for JsRsdoctorModuleSource { + fn from(value: RsdoctorModuleSource) -> Self { + JsRsdoctorModuleSource { + source_size: value.source_size as i32, + transform_size: value.transform_size as i32, + source: value.source, + source_map: value.source_map, + } + } +} + +#[napi(object)] +pub struct JsRsdoctorModuleGraphModule { + pub ukey: i32, + pub module: i32, + pub exports: Vec, + pub side_effects: Vec, + pub variables: Vec, + pub dynamic: bool, +} + +impl From for JsRsdoctorModuleGraphModule { + fn from(value: RsdoctorModuleGraphModule) -> Self { + JsRsdoctorModuleGraphModule { + ukey: value.ukey as i32, + module: value.module as i32, + exports: value.exports.into_iter().map(|d| d as i32).collect(), + side_effects: value.side_effects.into_iter().map(|d| d as i32).collect(), + variables: value.variables.into_iter().map(|d| d as i32).collect(), + dynamic: value.dynamic, + } + } +} + +#[napi(object)] +pub struct JsRsdoctorSideEffect { + pub ukey: i32, + pub name: String, + pub origin_name: Option, + pub module: i32, + pub identifier: JsRsdoctorStatement, + pub is_name_space: bool, + pub from_dependency: Option, + pub exports: Vec, + pub variable: Option, +} + +impl From for JsRsdoctorSideEffect { + fn from(value: RsdoctorSideEffect) -> Self { + JsRsdoctorSideEffect { + ukey: value.ukey as i32, + name: value.name, + origin_name: value.origin_name, + module: value.module as i32, + identifier: value.identifier.into(), + is_name_space: value.is_name_space, + from_dependency: value.from_dependency.map(|d| d as i32), + exports: value.exports.into_iter().map(|d| d as i32).collect(), + variable: value.variable.map(|d| d as i32), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorVariable { + pub ukey: i32, + pub name: String, + pub module: i32, + pub used_info: String, + pub identififer: JsRsdoctorStatement, + pub exported: Option, +} + +impl From for JsRsdoctorVariable { + fn from(value: RsdoctorVariable) -> Self { + JsRsdoctorVariable { + ukey: value.ukey as i32, + name: value.name, + module: value.module as i32, + used_info: value.used_info, + identififer: value.identififer.into(), + exported: value.exported.map(|d| d as i32), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorExportInfo { + pub ukey: i32, + pub name: String, + pub from: Option, + pub variable: Option, + pub identifier: Option, + pub side_effects: Vec, +} + +impl From for JsRsdoctorExportInfo { + fn from(value: RsdoctorExportInfo) -> Self { + JsRsdoctorExportInfo { + ukey: value.ukey as i32, + name: value.name, + from: value.from.map(|d| d as i32), + variable: value.variable.map(|d| d as i32), + identifier: value.identifier.map(|i| i.into()), + side_effects: value.side_effects.into_iter().map(|d| d as i32).collect(), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorStatement { + pub module: i32, + pub source_position: Option, + pub transformed_position: JsRsdoctorSourceRange, +} + +impl From for JsRsdoctorStatement { + fn from(value: RsdoctorStatement) -> Self { + JsRsdoctorStatement { + module: value.module as i32, + source_position: value.source_position.map(|p| p.into()), + transformed_position: value.transformed_position.into(), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorSourceRange { + pub start: JsRsdoctorSourcePosition, + pub end: Option, +} + +impl From for JsRsdoctorSourceRange { + fn from(value: RsdoctorSourceRange) -> Self { + JsRsdoctorSourceRange { + start: value.start.into(), + end: value.end.map(|p| p.into()), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorSourcePosition { + pub line: Option, + pub column: Option, + pub index: Option, +} + +impl From for JsRsdoctorSourcePosition { + fn from(value: RsdoctorSourcePosition) -> Self { + JsRsdoctorSourcePosition { + line: value.line.map(|l| l as i32), + column: value.column.map(|c| c as i32), + index: value.index.map(|i| i as i32), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorModuleGraph { + pub modules: Vec, + pub dependencies: Vec, +} + +impl From for JsRsdoctorModuleGraph { + fn from(value: RsdoctorModuleGraph) -> Self { + JsRsdoctorModuleGraph { + modules: value.modules.into_iter().map(|m| m.into()).collect(), + dependencies: value.dependencies.into_iter().map(|d| d.into()).collect(), + } + } +} + +#[napi(object)] +pub struct JsRsdoctorChunkGraph { + pub chunks: Vec, + pub entrypoints: Vec, +} + +impl From for JsRsdoctorChunkGraph { + fn from(value: RsdoctorChunkGraph) -> Self { + JsRsdoctorChunkGraph { + chunks: value.chunks.into_iter().map(|c| c.into()).collect(), + entrypoints: value.entrypoints.into_iter().map(|e| e.into()).collect(), + } + } +} diff --git a/crates/rspack_binding_values/src/plugins/rsdoctor/mod.rs b/crates/rspack_binding_values/src/plugins/rsdoctor/mod.rs new file mode 100644 index 00000000000..737443b927f --- /dev/null +++ b/crates/rspack_binding_values/src/plugins/rsdoctor/mod.rs @@ -0,0 +1,5 @@ +mod data; +mod options; + +pub use data::*; +pub use options::*; diff --git a/crates/rspack_binding_values/src/plugins/rsdoctor/options.rs b/crates/rspack_binding_values/src/plugins/rsdoctor/options.rs new file mode 100644 index 00000000000..b352d7dc7e4 --- /dev/null +++ b/crates/rspack_binding_values/src/plugins/rsdoctor/options.rs @@ -0,0 +1,51 @@ +use std::sync::Arc; + +use derive_more::Debug; +use futures::future::BoxFuture; +use napi::bindgen_prelude::*; +use napi_derive::napi; +use rspack_error::Result; +use rspack_napi::threadsafe_function::ThreadsafeFunction; +use rspack_plugin_rsdoctor::{ + RsdoctorChunkGraph, RsdoctorModuleGraph, RsdoctorPluginOptions, SendChunkGraph, SendModuleGraph, +}; + +use super::{JsRsdoctorChunkGraph, JsRsdoctorModuleGraph}; + +pub type RawSendModuleGraphFn = ThreadsafeFunction; +pub type RawSendChunkGraphFn = ThreadsafeFunction; + +#[napi(object, object_to_js = false)] +pub struct RawRsdoctorPluginOptions { + #[napi(ts_type = "(moduleGraph: JsRsdoctorModuleGraph) => Promise")] + pub on_module_graph: Option, + #[napi(ts_type = "(chunkGraph: JsRsdoctorChunkGraph) => Promise")] + pub on_chunk_graph: Option, +} + +impl From for RsdoctorPluginOptions { + fn from(value: RawRsdoctorPluginOptions) -> Self { + let on_module_graph = value.on_module_graph.map(|func| -> SendModuleGraph { + Arc::new( + move |module_graph: RsdoctorModuleGraph| -> BoxFuture<'static, Result<()>> { + let f = func.clone(); + Box::pin(async move { f.call(module_graph.into()).await }) + }, + ) as _ + }); + + let on_chunk_graph = value.on_chunk_graph.map(|func| -> SendChunkGraph { + Arc::new( + move |chunk_graph: RsdoctorChunkGraph| -> BoxFuture<'static, Result<()>> { + let f = func.clone(); + Box::pin(async move { f.call(chunk_graph.into()).await }) + }, + ) as _ + }); + + Self { + on_module_graph, + on_chunk_graph, + } + } +} diff --git a/crates/rspack_plugin_rsdoctor/Cargo.toml b/crates/rspack_plugin_rsdoctor/Cargo.toml index ddadd69c401..9eee00670df 100644 --- a/crates/rspack_plugin_rsdoctor/Cargo.toml +++ b/crates/rspack_plugin_rsdoctor/Cargo.toml @@ -10,6 +10,7 @@ version = "0.2.0" [dependencies] async-trait = { workspace = true } cow-utils = { workspace = true } +futures = { workspace = true } indexmap = { workspace = true } rayon = { workspace = true } rspack_collections = { workspace = true } diff --git a/crates/rspack_plugin_rsdoctor/src/chunk_graph.rs b/crates/rspack_plugin_rsdoctor/src/chunk_graph.rs index a54237aa493..b9f8dd0d492 100644 --- a/crates/rspack_plugin_rsdoctor/src/chunk_graph.rs +++ b/crates/rspack_plugin_rsdoctor/src/chunk_graph.rs @@ -2,16 +2,14 @@ use std::sync::{atomic::AtomicUsize, Arc}; use indexmap::IndexMap; use rayon::iter::{IntoParallelRefIterator, ParallelBridge, ParallelIterator}; -use rspack_core::{ - Chunk, ChunkGraph, ChunkGroupByUkey, ChunkIdsArtifact, ChunkUkey, Compilation, CompilationAsset, -}; +use rspack_core::{Chunk, ChunkGraph, ChunkGroupByUkey, ChunkUkey, CompilationAsset}; use rspack_core::{ChunkByUkey, ChunkGroupUkey}; use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; -use crate::data::{ - ChunkUkey as RsdoctorChunkUkey, EntrypointUkey as RsdoctorEntrypointUkey, RsdoctorEntrypoint, +use crate::{ + AssetUkey as RsdoctorAssetUkey, ChunkUkey as RsdoctorChunkUkey, + EntrypointUkey as RsdoctorEntrypointUkey, RsdoctorAsset, RsdoctorChunk, RsdoctorEntrypoint, }; -use crate::data::{RsdoctorAsset, RsdoctorChunk}; pub fn collect_chunks( chunks: &HashMap<&ChunkUkey, &Chunk>, @@ -105,11 +103,42 @@ pub fn collect_chunk_dependencies( .collect::>() } +pub fn collect_entrypoints( + entrypoints: &IndexMap, + rsd_chunks: &HashMap, + chunk_group_by_ukey: &ChunkGroupByUkey, +) -> HashMap { + entrypoints + .par_iter() + .map(|(name, ukey)| { + let cg = chunk_group_by_ukey.get(ukey); + let chunks = cg + .map(|cg| { + cg.chunks + .iter() + .filter_map(|c| rsd_chunks.get(c).map(|c| c.ukey)) + .collect::>() + }) + .unwrap_or_default(); + + ( + ukey.to_owned(), + RsdoctorEntrypoint { + ukey: ukey.as_u32() as RsdoctorEntrypointUkey, + name: name.to_string(), + chunks, + // assets, + }, + ) + }) + .collect::>() +} + pub fn collect_assets( assets: &HashMap, - rsd_chunks: &HashMap, chunk_by_ukey: &ChunkByUkey, ) -> HashMap { + let asset_ukey_counter: Arc = Arc::new(AtomicUsize::new(0)); let mut compilation_file_to_chunks: HashMap<&String, Vec<&ChunkUkey>> = HashMap::default(); for (chunk_ukey, chunk) in chunk_by_ukey.iter() { for file in chunk.files() { @@ -126,16 +155,15 @@ pub fn collect_assets( .map(|chunks| { chunks .iter() - .filter_map(|c| rsd_chunks.get(c).map(|c| c.ukey)) + .map(|c| c.as_u32() as RsdoctorChunkUkey) .collect::>() }) .unwrap_or_default(); ( path.to_string(), RsdoctorAsset { - ukey: 0, + ukey: asset_ukey_counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed), path: path.to_string(), - content: Default::default(), chunks, }, ) @@ -143,33 +171,26 @@ pub fn collect_assets( .collect::>() } -pub fn collect_entrypoints( - entrypoints: &IndexMap, - rsd_chunks: &HashMap, - chunk_group_by_ukey: &ChunkGroupByUkey, -) -> HashMap { - entrypoints - .par_iter() - .map(|(name, ukey)| { - let cg = chunk_group_by_ukey.get(ukey); - let chunks = cg - .map(|cg| { - cg.chunks - .iter() - .filter_map(|c| rsd_chunks.get(c).map(|c| c.ukey)) - .collect::>() +pub fn collect_chunk_assets( + rsd_assets: &HashMap, + chunk_by_ukey: &ChunkByUkey, +) -> HashMap> { + chunk_by_ukey + .keys() + .par_bridge() + .map(|chunk_ukey| { + let rsd_chunk_ukey = chunk_ukey.as_u32() as RsdoctorChunkUkey; + let assets = rsd_assets + .iter() + .filter_map(|(_, asset)| { + if asset.chunks.contains(&rsd_chunk_ukey) { + Some(asset.ukey) + } else { + None + } }) - .unwrap_or_default(); - - ( - ukey.to_owned(), - RsdoctorEntrypoint { - ukey: ukey.as_u32() as RsdoctorEntrypointUkey, - name: name.to_string(), - chunks, - // assets, - }, - ) + .collect::>(); + (rsd_chunk_ukey, assets) }) .collect::>() } diff --git a/crates/rspack_plugin_rsdoctor/src/data.rs b/crates/rspack_plugin_rsdoctor/src/data.rs index 05f90dc1858..02209db90eb 100644 --- a/crates/rspack_plugin_rsdoctor/src/data.rs +++ b/crates/rspack_plugin_rsdoctor/src/data.rs @@ -7,11 +7,24 @@ pub enum ModuleKind { Concatenated, } +impl From for String { + fn from(value: ModuleKind) -> Self { + match value { + ModuleKind::Normal => "normal".to_string(), + ModuleKind::Concatenated => "concatenated".to_string(), + } + } +} + pub type ModuleUkey = usize; pub type DependencyUkey = usize; pub type ChunkUkey = usize; pub type AssetUkey = usize; pub type EntrypointUkey = usize; +pub type ModuleGraphModuleUkey = usize; +pub type ExportInfoUkey = usize; +pub type VariableUkey = usize; +pub type SideEffectUkey = usize; pub struct RsdoctorModule { pub ukey: ModuleUkey, @@ -53,7 +66,6 @@ pub struct RsdoctorEntrypoint { pub struct RsdoctorAsset { pub ukey: AssetUkey, pub path: String, - pub content: String, pub chunks: HashSet, } @@ -63,3 +75,69 @@ pub struct RsdoctorModuleSource { pub source: Option, pub source_map: Option, } + +pub struct RsdoctorModuleGraphModule { + pub ukey: ModuleGraphModuleUkey, + pub module: ModuleUkey, + pub exports: Vec, + pub side_effects: Vec, + pub variables: Vec, + pub dynamic: bool, +} + +pub struct RsdoctorSideEffect { + pub ukey: SideEffectUkey, + pub name: String, + pub origin_name: Option, + pub module: ModuleUkey, + pub identifier: RsdoctorStatement, + pub is_name_space: bool, + pub from_dependency: Option, + pub exports: Vec, + pub variable: Option, +} + +pub struct RsdoctorVariable { + pub ukey: VariableUkey, + pub name: String, + pub module: ModuleUkey, + pub used_info: String, + pub identififer: RsdoctorStatement, + pub exported: Option, +} + +pub struct RsdoctorExportInfo { + pub ukey: ExportInfoUkey, + pub name: String, + pub from: Option, + pub variable: Option, + pub identifier: Option, + pub side_effects: Vec, +} + +pub struct RsdoctorStatement { + pub module: ModuleUkey, + pub source_position: Option, + pub transformed_position: RsdoctorSourceRange, +} + +pub struct RsdoctorSourceRange { + pub start: RsdoctorSourcePosition, + pub end: Option, +} + +pub struct RsdoctorSourcePosition { + pub line: Option, + pub column: Option, + pub index: Option, +} + +pub struct RsdoctorModuleGraph { + pub modules: Vec, + pub dependencies: Vec, +} + +pub struct RsdoctorChunkGraph { + pub chunks: Vec, + pub entrypoints: Vec, +} diff --git a/crates/rspack_plugin_rsdoctor/src/lib.rs b/crates/rspack_plugin_rsdoctor/src/lib.rs index 3dc3aeb59ce..1b5e05b3ffd 100644 --- a/crates/rspack_plugin_rsdoctor/src/lib.rs +++ b/crates/rspack_plugin_rsdoctor/src/lib.rs @@ -3,4 +3,5 @@ mod data; mod module_graph; mod plugin; -pub use plugin::RsdoctorPlugin; +pub use data::*; +pub use plugin::{RsdoctorPlugin, RsdoctorPluginOptions, SendChunkGraph, SendModuleGraph}; diff --git a/crates/rspack_plugin_rsdoctor/src/module_graph.rs b/crates/rspack_plugin_rsdoctor/src/module_graph.rs index 9d228633fba..e288497ed7d 100644 --- a/crates/rspack_plugin_rsdoctor/src/module_graph.rs +++ b/crates/rspack_plugin_rsdoctor/src/module_graph.rs @@ -8,7 +8,7 @@ use rspack_core::{ }; use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; -use crate::data::{ +use crate::{ ChunkUkey, ModuleKind, ModuleUkey, RsdoctorDependency, RsdoctorModule, RsdoctorModuleSource, }; diff --git a/crates/rspack_plugin_rsdoctor/src/plugin.rs b/crates/rspack_plugin_rsdoctor/src/plugin.rs index 737965aff8a..197a9aa180a 100644 --- a/crates/rspack_plugin_rsdoctor/src/plugin.rs +++ b/crates/rspack_plugin_rsdoctor/src/plugin.rs @@ -1,38 +1,44 @@ +use std::future::Future; +use std::pin::Pin; use std::sync::Arc; -use std::{borrow::Cow, sync::atomic::AtomicUsize}; use async_trait::async_trait; -use rayon::iter::{IntoParallelRefIterator, ParallelBridge, ParallelIterator}; -use rspack_collections::Identifier; +use futures::future::BoxFuture; use rspack_core::{ - concatenated_module, ApplyContext, Chunk, Compilation, CompilationAfterCodeGeneration, - CompilationAfterProcessAssets, CompilationChunkIds, CompilationFinishModules, - CompilationModuleIds, CompilationOptimizeChunkModules, CompilationOptimizeChunks, - CompilationOptimizeModules, CompilerOptions, DependencyType, Module, Plugin, PluginContext, + ApplyContext, Compilation, CompilationAfterCodeGeneration, CompilationAfterProcessAssets, + CompilationOptimizeChunkModules, CompilationOptimizeChunks, CompilerOptions, Plugin, + PluginContext, }; use rspack_error::Result; use rspack_hook::{plugin, plugin_hook}; -use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; +use rustc_hash::FxHashMap as HashMap; -use crate::chunk_graph::{collect_chunk_dependencies, collect_chunks, collect_entrypoints}; +use crate::chunk_graph::{ + collect_assets, collect_chunk_assets, collect_chunk_dependencies, collect_chunks, + collect_entrypoints, +}; use crate::module_graph::{ collect_concatenated_modules, collect_module_dependencies, collect_module_sources, collect_modules, }; +use crate::{RsdoctorChunkGraph, RsdoctorModuleGraph}; -type HandlerFn = Arc) -> Result<()> + Send + Sync>; +pub type SendModuleGraph = + Arc BoxFuture<'static, Result<()>> + Send + Sync>; +pub type SendChunkGraph = + Arc BoxFuture<'static, Result<()>> + Send + Sync>; #[derive(Default)] pub struct RsdoctorPluginOptions { - module_graph_cb: Option, - chunk_graph_cb: Option, + pub on_module_graph: Option, + pub on_chunk_graph: Option, } impl std::fmt::Debug for RsdoctorPluginOptions { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("RsdoctorPluginOptions") - .field("module_graph_cb", &self.module_graph_cb.is_some()) - .field("chunk_graph_cb", &self.chunk_graph_cb.is_some()) + .field("on_module_graph", &self.on_module_graph.is_some()) + .field("on_chunk_graph", &self.on_chunk_graph.is_some()) .finish() } } @@ -135,7 +141,10 @@ fn after_code_generation(&self, compilation: &mut Compilation) -> Result<()> { #[plugin_hook(CompilationAfterProcessAssets for RsdoctorPlugin)] async fn after_process_asssets(&self, compilation: &mut Compilation) -> Result<()> { - // TODO: send compilation.assets to the js + let chunk_by_ukey = &compilation.chunk_by_ukey; + let rsd_assets = collect_assets(&compilation.assets(), chunk_by_ukey); + let rsd_chunk_assets = collect_chunk_assets(&rsd_assets, chunk_by_ukey); + // TODO: send rsd_chunk_assets and rsd_assets to the js Ok(()) }