From 11003c6fb50d58a4fe0da11ad17a0cc2d357ec0c Mon Sep 17 00:00:00 2001 From: ahabhgk Date: Tue, 24 Dec 2024 15:25:22 +0800 Subject: [PATCH] fix --- .gitignore | 2 +- .../src/artifacts/cgm_hash_artifact.rs | 28 ++ .../cgm_runtime_requirement_artifact.rs | 33 ++ .../src/artifacts/code_generation_results.rs | 343 ++++++++++++++++++ crates/rspack_core/src/artifacts/mod.rs | 25 ++ .../side_effects_do_optimize_artifact.rs | 19 + 6 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 crates/rspack_core/src/artifacts/cgm_hash_artifact.rs create mode 100644 crates/rspack_core/src/artifacts/cgm_runtime_requirement_artifact.rs create mode 100644 crates/rspack_core/src/artifacts/code_generation_results.rs create mode 100644 crates/rspack_core/src/artifacts/mod.rs create mode 100644 crates/rspack_core/src/artifacts/side_effects_do_optimize_artifact.rs diff --git a/.gitignore b/.gitignore index d6d457a334da..b0c5fbecbfae 100644 --- a/.gitignore +++ b/.gitignore @@ -190,7 +190,7 @@ esbuild.cpuprofile !packages/rspack-test-tools/tests/treeShakingCases/node_modules # Binding artifacts -artifacts +/artifacts/ # Node Addons npm/**/*.node diff --git a/crates/rspack_core/src/artifacts/cgm_hash_artifact.rs b/crates/rspack_core/src/artifacts/cgm_hash_artifact.rs new file mode 100644 index 000000000000..5b010dde7a6b --- /dev/null +++ b/crates/rspack_core/src/artifacts/cgm_hash_artifact.rs @@ -0,0 +1,28 @@ +use rspack_collections::IdentifierMap; +use rspack_hash::RspackHashDigest; + +use crate::{ModuleIdentifier, RuntimeSpec, RuntimeSpecMap}; + +#[derive(Debug, Default)] +pub struct CgmHashArtifact { + module_to_hashes: IdentifierMap>, +} + +impl CgmHashArtifact { + pub fn is_empty(&self) -> bool { + self.module_to_hashes.is_empty() + } + + pub fn get(&self, module: &ModuleIdentifier, runtime: &RuntimeSpec) -> Option<&RspackHashDigest> { + let hashes = self.module_to_hashes.get(module)?; + hashes.get(runtime) + } + + pub fn set_hashes(&mut self, module: ModuleIdentifier, hashes: RuntimeSpecMap) { + self.module_to_hashes.insert(module, hashes); + } + + pub fn remove(&mut self, module: &ModuleIdentifier) -> Option> { + self.module_to_hashes.remove(module) + } +} diff --git a/crates/rspack_core/src/artifacts/cgm_runtime_requirement_artifact.rs b/crates/rspack_core/src/artifacts/cgm_runtime_requirement_artifact.rs new file mode 100644 index 000000000000..01bf78064949 --- /dev/null +++ b/crates/rspack_core/src/artifacts/cgm_runtime_requirement_artifact.rs @@ -0,0 +1,33 @@ +use rspack_collections::IdentifierMap; + +use crate::{ModuleIdentifier, RuntimeGlobals, RuntimeSpec, RuntimeSpecMap}; + +#[derive(Debug, Default)] +pub struct CgmRuntimeRequirementsArtifact { + module_to_runtime_requirements: IdentifierMap>, +} + +impl CgmRuntimeRequirementsArtifact { + pub fn is_empty(&self) -> bool { + self.module_to_runtime_requirements.is_empty() + } + + pub fn get(&self, module: &ModuleIdentifier, runtime: &RuntimeSpec) -> Option<&RuntimeGlobals> { + let requirements = self.module_to_runtime_requirements.get(module)?; + requirements.get(runtime) + } + + pub fn set_runtime_requirements( + &mut self, + module: ModuleIdentifier, + runtime_requirements_map: RuntimeSpecMap, + ) { + self + .module_to_runtime_requirements + .insert(module, runtime_requirements_map); + } + + pub fn remove(&mut self, module: &ModuleIdentifier) -> Option> { + self.module_to_runtime_requirements.remove(module) + } +} diff --git a/crates/rspack_core/src/artifacts/code_generation_results.rs b/crates/rspack_core/src/artifacts/code_generation_results.rs new file mode 100644 index 000000000000..68ef01bd5725 --- /dev/null +++ b/crates/rspack_core/src/artifacts/code_generation_results.rs @@ -0,0 +1,343 @@ +use std::collections::hash_map::Entry; +use std::hash::Hash; +use std::ops::{Deref, DerefMut}; +use std::sync::atomic::AtomicU32; + +use anymap::CloneAny; +use rspack_collections::IdentifierMap; +use rspack_hash::{HashDigest, HashFunction, HashSalt, RspackHash, RspackHashDigest}; +use rspack_sources::BoxSource; +use rspack_util::atom::Atom; +use rustc_hash::{FxHashMap as HashMap, FxHashSet}; +use serde::Serialize; + +use crate::{ + AssetInfo, ChunkInitFragments, ConcatenationScope, ModuleIdentifier, PublicPath, RuntimeGlobals, + RuntimeMode, RuntimeSpec, RuntimeSpecMap, SourceType, +}; + +#[derive(Clone, Debug)] +pub struct CodeGenerationDataUrl { + inner: String, +} + +impl CodeGenerationDataUrl { + pub fn new(inner: String) -> Self { + Self { inner } + } + + pub fn inner(&self) -> &str { + &self.inner + } +} + +#[derive(Clone, Debug)] +pub struct CodeGenerationDataFilename { + filename: String, + public_path: PublicPath, +} + +impl CodeGenerationDataFilename { + pub fn new(filename: String, public_path: PublicPath) -> Self { + Self { + filename, + public_path, + } + } + + pub fn filename(&self) -> &str { + &self.filename + } + + pub fn public_path(&self) -> &PublicPath { + &self.public_path + } +} + +#[derive(Clone, Debug)] +pub struct CodeGenerationDataAssetInfo { + inner: AssetInfo, +} + +impl CodeGenerationDataAssetInfo { + pub fn new(inner: AssetInfo) -> Self { + Self { inner } + } + + pub fn inner(&self) -> &AssetInfo { + &self.inner + } +} + +#[derive(Clone, Debug)] +pub struct CodeGenerationDataTopLevelDeclarations { + inner: FxHashSet, +} + +impl CodeGenerationDataTopLevelDeclarations { + pub fn new(inner: FxHashSet) -> Self { + Self { inner } + } + + pub fn inner(&self) -> &FxHashSet { + &self.inner + } +} + +#[derive(Clone, Debug)] +pub struct CodeGenerationExportsFinalNames { + inner: HashMap, +} + +impl CodeGenerationExportsFinalNames { + pub fn new(inner: HashMap) -> Self { + Self { inner } + } + + pub fn inner(&self) -> &HashMap { + &self.inner + } +} + +#[derive(Debug, Default, Clone)] +pub struct CodeGenerationData { + inner: anymap::Map, +} + +impl Deref for CodeGenerationData { + type Target = anymap::Map; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for CodeGenerationData { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +#[derive(Debug, Default, Clone)] +pub struct CodeGenerationResult { + pub inner: HashMap, + /// [definition in webpack](https://github.com/webpack/webpack/blob/4b4ca3bb53f36a5b8fc6bc1bd976ed7af161bd80/lib/Module.js#L75) + pub data: CodeGenerationData, + pub chunk_init_fragments: ChunkInitFragments, + pub runtime_requirements: RuntimeGlobals, + pub hash: Option, + pub id: CodeGenResultId, + pub concatenation_scope: Option, +} + +impl CodeGenerationResult { + pub fn with_javascript(mut self, generation_result: BoxSource) -> Self { + self.inner.insert(SourceType::JavaScript, generation_result); + self + } + + pub fn with_css(mut self, generation_result: BoxSource) -> Self { + self.inner.insert(SourceType::Css, generation_result); + self + } + + pub fn with_asset(mut self, generation_result: BoxSource) -> Self { + self.inner.insert(SourceType::Asset, generation_result); + self + } + + pub fn inner(&self) -> &HashMap { + &self.inner + } + + pub fn get(&self, source_type: &SourceType) -> Option<&BoxSource> { + self.inner.get(source_type) + } + + pub fn add(&mut self, source_type: SourceType, generation_result: BoxSource) { + let result = self.inner.insert(source_type, generation_result); + debug_assert!(result.is_none()); + } + + pub fn set_hash( + &mut self, + hash_function: &HashFunction, + hash_digest: &HashDigest, + hash_salt: &HashSalt, + ) { + let mut hasher = RspackHash::with_salt(hash_function, hash_salt); + for (source_type, source) in &self.inner { + source_type.hash(&mut hasher); + source.hash(&mut hasher); + } + self.chunk_init_fragments.hash(&mut hasher); + self.runtime_requirements.hash(&mut hasher); + self.hash = Some(hasher.digest(hash_digest)); + } +} + +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)] +pub struct CodeGenResultId(u32); + +impl Default for CodeGenResultId { + fn default() -> Self { + Self(CODE_GEN_RESULT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed)) + } +} + +pub static CODE_GEN_RESULT_ID: AtomicU32 = AtomicU32::new(0); + +#[derive(Debug, Default, Clone)] +pub struct CodeGenerationResults { + module_generation_result_map: HashMap, + map: IdentifierMap>, +} + +impl CodeGenerationResults { + pub fn is_empty(&self) -> bool { + self.module_generation_result_map.is_empty() && self.map.is_empty() + } + + pub fn get_one(&self, module_identifier: &ModuleIdentifier) -> Option<&CodeGenerationResult> { + self + .map + .get(module_identifier) + .and_then(|spec| match spec.mode { + RuntimeMode::Empty => None, + RuntimeMode::SingleEntry => spec + .single_value + .and_then(|result_id| self.module_generation_result_map.get(&result_id)), + RuntimeMode::Map => spec + .map + .values() + .next() + .and_then(|result_id| self.module_generation_result_map.get(result_id)), + }) + } + + pub fn insert( + &mut self, + module_identifier: ModuleIdentifier, + codegen_res: CodeGenerationResult, + runtimes: impl IntoIterator, + ) { + let codegen_res_id = codegen_res.id; + self + .module_generation_result_map + .insert(codegen_res_id, codegen_res); + for runtime in runtimes { + self.add(module_identifier, runtime, codegen_res_id); + } + } + + pub fn remove(&mut self, module_identifier: &ModuleIdentifier) -> Option<()> { + let runtime_map = self.map.remove(module_identifier)?; + for result in runtime_map.get_values() { + self.module_generation_result_map.remove(result)?; + } + Some(()) + } + + pub fn get( + &self, + module_identifier: &ModuleIdentifier, + runtime: Option<&RuntimeSpec>, + ) -> &CodeGenerationResult { + if let Some(entry) = self.map.get(module_identifier) { + if let Some(runtime) = runtime { + entry + .get(runtime) + .and_then(|m| { + self.module_generation_result_map.get(m) + }) + .unwrap_or_else(|| { + panic!( + "Failed to code generation result for {module_identifier} with runtime {runtime:?} \n {entry:?}" + ) + }) + } else { + if entry.size() > 1 { + let results = entry.get_values(); + if results.len() != 1 { + panic!( + "No unique code generation entry for unspecified runtime for {module_identifier} ", + ); + } + + return results + .first() + .copied() + .and_then(|m| self.module_generation_result_map.get(m)) + .unwrap_or_else(|| panic!("Expected value exists")); + } + + entry + .get_values() + .first() + .copied() + .and_then(|m| self.module_generation_result_map.get(m)) + .unwrap_or_else(|| panic!("Expected value exists")) + } + } else { + panic!( + "No code generation entry for {} (existing entries: {:?})", + module_identifier, + self.map.keys().collect::>() + ) + } + } + + pub fn add( + &mut self, + module_identifier: ModuleIdentifier, + runtime: RuntimeSpec, + result: CodeGenResultId, + ) { + match self.map.entry(module_identifier) { + Entry::Occupied(mut record) => { + record.get_mut().set(runtime, result); + } + Entry::Vacant(record) => { + let mut spec_map = RuntimeSpecMap::default(); + spec_map.set(runtime, result); + record.insert(spec_map); + } + }; + } + + pub fn get_runtime_requirements( + &self, + module_identifier: &ModuleIdentifier, + runtime: Option<&RuntimeSpec>, + ) -> RuntimeGlobals { + self.get(module_identifier, runtime).runtime_requirements + } + + #[allow(clippy::unwrap_in_result)] + pub fn get_hash( + &self, + module_identifier: &ModuleIdentifier, + runtime: Option<&RuntimeSpec>, + ) -> Option<&RspackHashDigest> { + let code_generation_result = self.get(module_identifier, runtime); + + code_generation_result.hash.as_ref() + } + + pub fn into_inner( + self, + ) -> ( + IdentifierMap>, + HashMap, + ) { + (self.map, self.module_generation_result_map) + } +} + +#[derive(Debug)] +pub struct CodeGenerationJob { + pub module: ModuleIdentifier, + pub hash: RspackHashDigest, + pub runtime: RuntimeSpec, + pub runtimes: Vec, +} diff --git a/crates/rspack_core/src/artifacts/mod.rs b/crates/rspack_core/src/artifacts/mod.rs new file mode 100644 index 000000000000..487e11ed0fed --- /dev/null +++ b/crates/rspack_core/src/artifacts/mod.rs @@ -0,0 +1,25 @@ +use rspack_collections::{IdentifierMap, IdentifierSet, UkeyMap}; +use rspack_error::Diagnostic; + +use crate::{ + chunk_graph_chunk::ChunkId, ChunkHashesResult, ChunkRenderResult, ChunkUkey, ModuleId, + RuntimeGlobals, +}; + +mod cgm_hash_artifact; +mod cgm_runtime_requirement_artifact; +mod code_generation_results; +mod side_effects_do_optimize_artifact; + +pub use cgm_hash_artifact::*; +pub use cgm_runtime_requirement_artifact::*; +pub use code_generation_results::*; +pub use side_effects_do_optimize_artifact::*; + +pub type AsyncModulesArtifact = IdentifierSet; +pub type DependenciesDiagnosticsArtifact = IdentifierMap>; +pub type ModuleIdsArtifact = IdentifierMap; +pub type ChunkIdsArtifact = UkeyMap; +pub type CgcRuntimeRequirementsArtifact = UkeyMap; +pub type ChunkHashesArtifact = UkeyMap; +pub type ChunkRenderArtifact = UkeyMap; diff --git a/crates/rspack_core/src/artifacts/side_effects_do_optimize_artifact.rs b/crates/rspack_core/src/artifacts/side_effects_do_optimize_artifact.rs new file mode 100644 index 000000000000..af7c0d827351 --- /dev/null +++ b/crates/rspack_core/src/artifacts/side_effects_do_optimize_artifact.rs @@ -0,0 +1,19 @@ +use rspack_collections::UkeyMap; +use rspack_util::atom::Atom; + +use crate::{DependencyId, ExportInfo, ModuleIdentifier}; + +#[derive(Debug, Clone)] +pub struct SideEffectsDoOptimize { + pub ids: Vec, + pub target_module: ModuleIdentifier, + pub need_move_target: Option, +} + +#[derive(Debug, Clone)] +pub struct SideEffectsDoOptimizeMoveTarget { + pub export_info: ExportInfo, + pub target_export: Option>, +} + +pub type SideEffectsOptimizeArtifact = UkeyMap;