1mod after_seal;
2mod assign_runtime_ids;
3pub mod build_chunk_graph;
4pub mod build_module_graph;
5mod chunk_ids;
6mod code_generation;
7mod create_chunk_assets;
8mod create_hash;
9mod create_module_assets;
10mod create_module_hashes;
11mod finish_make;
12mod finish_module_graph;
13mod finish_modules;
14mod make;
15mod module_ids;
16mod optimize_chunk_modules;
17mod optimize_chunks;
18mod optimize_code_generation;
19mod optimize_dependencies;
20mod optimize_modules;
21mod optimize_tree;
22mod process_assets;
23mod run_passes;
24mod runtime_requirements;
25mod seal;
26use std::{
27 collections::{VecDeque, hash_map},
28 fmt::{self, Debug},
29 hash::{BuildHasherDefault, Hash},
30 mem,
31 sync::{
32 Arc,
33 atomic::{AtomicBool, AtomicU32, Ordering},
34 },
35};
36
37use atomic_refcell::AtomicRefCell;
38use dashmap::DashSet;
39use futures::future::BoxFuture;
40use indexmap::IndexMap;
41use itertools::Itertools;
42use rayon::prelude::*;
43use rspack_cacheable::{
44 cacheable,
45 with::{AsOption, AsPreset},
46};
47use rspack_collections::{
48 DatabaseItem, IdentifierDashMap, IdentifierMap, IdentifierSet, UkeyMap, UkeySet,
49};
50use rspack_error::{Diagnostic, Result, ToStringResultToRspackResultExt};
51use rspack_fs::{IntermediateFileSystem, ReadableFileSystem, WritableFileSystem};
52use rspack_hash::{RspackHash, RspackHashDigest};
53use rspack_hook::define_hook;
54use rspack_paths::{ArcPath, ArcPathIndexSet, ArcPathSet};
55use rspack_sources::BoxSource;
56use rspack_tasks::CompilerContext;
57#[cfg(allocative)]
58use rspack_util::allocative;
59use rspack_util::{itoa, tracing_preset::TRACING_BENCH_TARGET};
60use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet, FxHasher};
61use tracing::instrument;
62use ustr::Ustr;
63
64use crate::{
65 AsyncModulesArtifact, BindingCell, BoxDependency, BoxModule, BuildChunkGraphArtifact, CacheCount,
66 CacheOptions, CgcRuntimeRequirementsArtifact, CgmHashArtifact, CgmRuntimeRequirementsArtifact,
67 Chunk, ChunkByUkey, ChunkContentHash, ChunkGraph, ChunkGroupByUkey, ChunkGroupUkey,
68 ChunkHashesArtifact, ChunkKind, ChunkNamedIdArtifact, ChunkRenderArtifact,
69 ChunkRenderCacheArtifact, ChunkRenderResult, ChunkUkey, CodeGenerateCacheArtifact,
70 CodeGenerationJob, CodeGenerationResult, CodeGenerationResults, CompilationLogger,
71 CompilationLogging, CompilerOptions, CompilerPlatform, ConcatenationScope,
72 DependenciesDiagnosticsArtifact, DependencyCodeGeneration, DependencyTemplate,
73 DependencyTemplateType, DependencyType, DerefOption, Entry, EntryData, EntryOptions,
74 EntryRuntime, Entrypoint, ExecuteModuleId, Filename, ImportPhase, ImportVarMap,
75 ImportedByDeferModulesArtifact, MemoryGCStorage, ModuleFactory, ModuleGraph,
76 ModuleGraphCacheArtifact, ModuleIdentifier, ModuleIdsArtifact, ModuleStaticCacheArtifact,
77 PathData, ProcessRuntimeRequirementsCacheArtifact, ResolverFactory, RuntimeGlobals,
78 RuntimeKeyMap, RuntimeMode, RuntimeModule, RuntimeSpec, RuntimeSpecMap, RuntimeTemplate,
79 SharedPluginDriver, SideEffectsOptimizeArtifact, SourceType, Stats, ValueCacheVersions,
80 compilation::build_module_graph::{
81 BuildModuleGraphArtifact, ModuleExecutor, UpdateParam, update_module_graph,
82 },
83 compiler::{CompilationRecords, CompilerId},
84 get_runtime_key,
85 incremental::{self, Incremental, IncrementalPasses, Mutation},
86 is_source_equal, to_identifier,
87};
88
89define_hook!(CompilationAddEntry: Series(compilation: &mut Compilation, entry_name: Option<&str>));
90define_hook!(CompilationBuildModule: Series(compiler_id: CompilerId, compilation_id: CompilationId, module: &mut BoxModule),tracing=false);
91define_hook!(CompilationRevokedModules: Series(compilation: &Compilation, revoked_modules: &IdentifierSet));
92define_hook!(CompilationStillValidModule: Series(compiler_id: CompilerId, compilation_id: CompilationId, module: &mut BoxModule));
93define_hook!(CompilationSucceedModule: Series(compiler_id: CompilerId, compilation_id: CompilationId, module: &mut BoxModule),tracing=false);
94define_hook!(CompilationExecuteModule:
95 Series(module: &ModuleIdentifier, runtime_modules: &IdentifierSet, code_generation_results: &BindingCell<CodeGenerationResults>, execute_module_id: &ExecuteModuleId));
96define_hook!(CompilationFinishModules: Series(compilation: &mut Compilation, async_modules_artifact: &mut AsyncModulesArtifact));
97define_hook!(CompilationSeal: Series(compilation: &mut Compilation));
98define_hook!(CompilationConcatenationScope: SeriesBail(compilation: &Compilation, curr_module: ModuleIdentifier) -> ConcatenationScope);
99define_hook!(CompilationOptimizeDependencies: SeriesBail(compilation: &Compilation, side_effects_optimize_artifact: &mut SideEffectsOptimizeArtifact, build_module_graph_artifact: &mut BuildModuleGraphArtifact,
100 diagnostics: &mut Vec<Diagnostic>) -> bool);
101define_hook!(CompilationOptimizeModules: SeriesBail(compilation: &Compilation, diagnostics: &mut Vec<Diagnostic>) -> bool);
102define_hook!(CompilationAfterOptimizeModules: Series(compilation: &Compilation));
103define_hook!(CompilationOptimizeChunks: SeriesBail(compilation: &mut Compilation) -> bool);
104define_hook!(CompilationOptimizeTree: Series(compilation: &Compilation));
105define_hook!(CompilationOptimizeChunkModules: SeriesBail(compilation: &mut Compilation) -> bool);
106define_hook!(CompilationModuleIds: Series(compilation: &Compilation, module_ids: &mut ModuleIdsArtifact, diagnostics: &mut Vec<Diagnostic>));
107define_hook!(CompilationChunkIds: Series(compilation: &Compilation, chunk_by_ukey: &mut ChunkByUkey, named_chunk_ids_artifact: &mut ChunkNamedIdArtifact, diagnostics: &mut Vec<Diagnostic>));
108define_hook!(CompilationRuntimeModule: Series(compilation: &Compilation, module: &ModuleIdentifier, chunk: &ChunkUkey, runtime_modules: &mut IdentifierMap<Box<dyn RuntimeModule>>));
109define_hook!(CompilationAdditionalModuleRuntimeRequirements: Series(compilation: &Compilation, module_identifier: &ModuleIdentifier, runtime_requirements: &mut RuntimeGlobals),tracing=false);
110define_hook!(CompilationRuntimeRequirementInModule: SeriesBail(compilation: &Compilation, module_identifier: &ModuleIdentifier, all_runtime_requirements: &RuntimeGlobals, runtime_requirements: &RuntimeGlobals, runtime_requirements_mut: &mut RuntimeGlobals),tracing=false);
111define_hook!(CompilationAdditionalChunkRuntimeRequirements: Series(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, runtime_requirements: &mut RuntimeGlobals));
112define_hook!(CompilationRuntimeRequirementInChunk: SeriesBail(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, all_runtime_requirements: &RuntimeGlobals, runtime_requirements: &RuntimeGlobals, runtime_requirements_mut: &mut RuntimeGlobals));
113define_hook!(CompilationAdditionalTreeRuntimeRequirements: Series(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, runtime_requirements: &mut RuntimeGlobals));
114define_hook!(CompilationRuntimeRequirementInTree: SeriesBail(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, all_runtime_requirements: &RuntimeGlobals, runtime_requirements: &RuntimeGlobals, runtime_requirements_mut: &mut RuntimeGlobals));
115define_hook!(CompilationOptimizeCodeGeneration: Series(compilation: &Compilation, build_module_graph_artifact: &mut BuildModuleGraphArtifact, diagnostics: &mut Vec<Diagnostic>));
116define_hook!(CompilationAfterCodeGeneration: Series(compilation: &Compilation, diagnostics: &mut Vec<Diagnostic>));
117define_hook!(CompilationChunkHash: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, hasher: &mut RspackHash),tracing=false);
118define_hook!(CompilationContentHash: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, hashes: &mut HashMap<SourceType, RspackHash>));
119define_hook!(CompilationDependentFullHash: SeriesBail(compilation: &Compilation, chunk_ukey: &ChunkUkey) -> bool);
120define_hook!(CompilationRenderManifest: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, manifest: &mut Vec<RenderManifestEntry>, diagnostics: &mut Vec<Diagnostic>),tracing=false);
121define_hook!(CompilationChunkAsset: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, filename: &str));
122define_hook!(CompilationProcessAssets: Series(compilation: &mut Compilation));
123define_hook!(CompilationAfterProcessAssets: Series(compilation: &Compilation, diagnostics: &mut Vec<Diagnostic>));
124define_hook!(CompilationAfterSeal: Series(compilation: &Compilation),tracing=true);
125
126#[derive(Debug, Default)]
127pub struct CompilationHooks {
128 pub add_entry: CompilationAddEntryHook,
129 pub build_module: CompilationBuildModuleHook,
130 pub revoked_modules: CompilationRevokedModulesHook,
131 pub concatenation_scope: CompilationConcatenationScopeHook,
132 pub still_valid_module: CompilationStillValidModuleHook,
133 pub succeed_module: CompilationSucceedModuleHook,
134 pub execute_module: CompilationExecuteModuleHook,
135 pub finish_modules: CompilationFinishModulesHook,
136 pub seal: CompilationSealHook,
137 pub optimize_dependencies: CompilationOptimizeDependenciesHook,
138 pub optimize_modules: CompilationOptimizeModulesHook,
139 pub after_optimize_modules: CompilationAfterOptimizeModulesHook,
140 pub optimize_chunks: CompilationOptimizeChunksHook,
141 pub optimize_tree: CompilationOptimizeTreeHook,
142 pub optimize_chunk_modules: CompilationOptimizeChunkModulesHook,
143 pub module_ids: CompilationModuleIdsHook,
144 pub chunk_ids: CompilationChunkIdsHook,
145 pub runtime_module: CompilationRuntimeModuleHook,
146 pub additional_module_runtime_requirements: CompilationAdditionalModuleRuntimeRequirementsHook,
147 pub runtime_requirement_in_module: CompilationRuntimeRequirementInModuleHook,
148 pub additional_chunk_runtime_requirements: CompilationAdditionalChunkRuntimeRequirementsHook,
149 pub runtime_requirement_in_chunk: CompilationRuntimeRequirementInChunkHook,
150 pub additional_tree_runtime_requirements: CompilationAdditionalTreeRuntimeRequirementsHook,
151 pub runtime_requirement_in_tree: CompilationRuntimeRequirementInTreeHook,
152 pub optimize_code_generation: CompilationOptimizeCodeGenerationHook,
153 pub after_code_generation: CompilationAfterCodeGenerationHook,
154 pub chunk_hash: CompilationChunkHashHook,
155 pub content_hash: CompilationContentHashHook,
156 pub dependent_full_hash: CompilationDependentFullHashHook,
157 pub render_manifest: CompilationRenderManifestHook,
158 pub chunk_asset: CompilationChunkAssetHook,
159 pub process_assets: CompilationProcessAssetsHook,
160 pub after_process_assets: CompilationAfterProcessAssetsHook,
161 pub after_seal: CompilationAfterSealHook,
162}
163
164#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
165#[cfg_attr(allocative, derive(allocative::Allocative))]
166pub struct CompilationId(pub u32);
167
168impl CompilationId {
169 pub fn new() -> Self {
170 Self(COMPILATION_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
171 }
172}
173
174impl Default for CompilationId {
175 fn default() -> Self {
176 Self::new()
177 }
178}
179
180static COMPILATION_ID: AtomicU32 = AtomicU32::new(0);
181
182#[derive(Debug)]
186pub struct Compilation {
187 id: CompilationId,
189 compiler_id: CompilerId,
190 pub hot_index: u32,
196 pub records: Option<CompilationRecords>,
197 pub options: Arc<CompilerOptions>,
198 pub platform: Arc<CompilerPlatform>,
199 pub entries: Entry,
200 pub global_entry: EntryData,
201 pub dependency_factories: HashMap<DependencyType, Arc<dyn ModuleFactory>>,
202 pub dependency_templates: HashMap<DependencyTemplateType, Arc<dyn DependencyTemplate>>,
203 pub runtime_modules: IdentifierMap<Box<dyn RuntimeModule>>,
204 pub runtime_modules_hash: IdentifierMap<RspackHashDigest>,
205 pub runtime_modules_code_generation_source: IdentifierMap<BoxSource>,
206 pub chunk_graph: ChunkGraph,
207 pub chunk_by_ukey: ChunkByUkey,
208 pub chunk_group_by_ukey: ChunkGroupByUkey,
209 pub entrypoints: IndexMap<String, ChunkGroupUkey>,
210 pub async_entrypoints: Vec<ChunkGroupUkey>,
211 assets: CompilationAssets,
212 assets_related_in: HashMap<String, HashSet<String>>,
213 pub emitted_assets: DashSet<String, BuildHasherDefault<FxHasher>>,
214 diagnostics: Vec<Diagnostic>,
215 logging: CompilationLogging,
216 pub plugin_driver: SharedPluginDriver,
217 pub buildtime_plugin_driver: SharedPluginDriver,
218 pub resolver_factory: Arc<ResolverFactory>,
219 pub loader_resolver_factory: Arc<ResolverFactory>,
220 pub named_chunks: HashMap<String, ChunkUkey>,
221 pub named_chunk_groups: HashMap<String, ChunkGroupUkey>,
222 pub runtime_template: RuntimeTemplate,
223
224 pub async_modules_artifact: Arc<AtomicRefCell<AsyncModulesArtifact>>,
226 pub dependencies_diagnostics_artifact: Arc<AtomicRefCell<DependenciesDiagnosticsArtifact>>,
228 pub side_effects_optimize_artifact: DerefOption<SideEffectsOptimizeArtifact>,
230 pub module_ids_artifact: ModuleIdsArtifact,
232 pub named_chunk_ids_artifact: ChunkNamedIdArtifact,
234 pub code_generation_results: BindingCell<CodeGenerationResults>,
236 pub cgm_hash_artifact: CgmHashArtifact,
238 pub cgm_runtime_requirements_artifact: CgmRuntimeRequirementsArtifact,
240 pub cgc_runtime_requirements_artifact: CgcRuntimeRequirementsArtifact,
242 pub chunk_hashes_artifact: ChunkHashesArtifact,
244 pub chunk_render_artifact: ChunkRenderArtifact,
246 pub module_graph_cache_artifact: ModuleGraphCacheArtifact,
248 pub module_static_cache_artifact: ModuleStaticCacheArtifact,
250 pub chunk_render_cache_artifact: ChunkRenderCacheArtifact,
252 pub code_generate_cache_artifact: CodeGenerateCacheArtifact,
254 pub process_runtime_requirements_cache_artifact: ProcessRuntimeRequirementsCacheArtifact,
256 pub imported_by_defer_modules_artifact: ImportedByDeferModulesArtifact,
257
258 pub code_generated_modules: IdentifierSet,
259 pub build_time_executed_modules: IdentifierSet,
260 pub build_chunk_graph_artifact: BuildChunkGraphArtifact,
261 pub incremental: Incremental,
262
263 pub hash: Option<RspackHashDigest>,
264
265 pub file_dependencies: ArcPathIndexSet,
266 pub context_dependencies: ArcPathIndexSet,
267 pub missing_dependencies: ArcPathIndexSet,
268 pub build_dependencies: ArcPathIndexSet,
269
270 pub value_cache_versions: ValueCacheVersions,
271
272 import_var_map: IdentifierDashMap<RuntimeKeyMap<ImportVarMap>>,
273
274 pub module_executor: Option<ModuleExecutor>,
276 in_finish_make: AtomicBool,
277
278 pub modified_files: ArcPathSet,
279 pub removed_files: ArcPathSet,
280 pub build_module_graph_artifact: DerefOption<BuildModuleGraphArtifact>,
281 pub input_filesystem: Arc<dyn ReadableFileSystem>,
282
283 pub intermediate_filesystem: Arc<dyn IntermediateFileSystem>,
284 pub output_filesystem: Arc<dyn WritableFileSystem>,
285
286 pub is_rebuild: bool,
290 pub compiler_context: Arc<CompilerContext>,
291}
292
293impl Compilation {
294 pub const OPTIMIZE_CHUNKS_STAGE_BASIC: i32 = -10;
295 pub const OPTIMIZE_CHUNKS_STAGE_DEFAULT: i32 = 0;
296 pub const OPTIMIZE_CHUNKS_STAGE_ADVANCED: i32 = 10;
297
298 pub const PROCESS_ASSETS_STAGE_ADDITIONAL: i32 = -2000;
299 pub const PROCESS_ASSETS_STAGE_PRE_PROCESS: i32 = -1000;
300 pub const PROCESS_ASSETS_STAGE_DERIVED: i32 = -200;
301 pub const PROCESS_ASSETS_STAGE_ADDITIONS: i32 = -100;
302 pub const PROCESS_ASSETS_STAGE_OPTIMIZE: i32 = 100;
303 pub const PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT: i32 = 200;
304 pub const PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY: i32 = 300;
305 pub const PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE: i32 = 400;
306 pub const PROCESS_ASSETS_STAGE_DEV_TOOLING: i32 = 500;
307 pub const PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE: i32 = 700;
308 pub const PROCESS_ASSETS_STAGE_SUMMARIZE: i32 = 1000;
309 pub const PROCESS_ASSETS_STAGE_OPTIMIZE_HASH: i32 = 2500;
310 pub const PROCESS_ASSETS_STAGE_AFTER_OPTIMIZE_HASH: i32 = 2600;
311 pub const PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER: i32 = 3000;
312 pub const PROCESS_ASSETS_STAGE_ANALYSE: i32 = 4000;
313 pub const PROCESS_ASSETS_STAGE_REPORT: i32 = 5000;
314
315 #[allow(clippy::too_many_arguments)]
316 pub fn new(
317 compiler_id: CompilerId,
318 options: Arc<CompilerOptions>,
319 platform: Arc<CompilerPlatform>,
320 plugin_driver: SharedPluginDriver,
321 buildtime_plugin_driver: SharedPluginDriver,
322 resolver_factory: Arc<ResolverFactory>,
323 loader_resolver_factory: Arc<ResolverFactory>,
324 records: Option<CompilationRecords>,
325 incremental: Incremental,
326 module_executor: Option<ModuleExecutor>,
327 modified_files: ArcPathSet,
328 removed_files: ArcPathSet,
329 input_filesystem: Arc<dyn ReadableFileSystem>,
330 intermediate_filesystem: Arc<dyn IntermediateFileSystem>,
331 output_filesystem: Arc<dyn WritableFileSystem>,
332 is_rebuild: bool,
333 compiler_context: Arc<CompilerContext>,
334 ) -> Self {
335 Self {
336 id: CompilationId::new(),
337 compiler_id,
338 hot_index: 0,
339 runtime_template: RuntimeTemplate::new(options.clone()),
340 records,
341 options: options.clone(),
342 platform,
343 dependency_factories: Default::default(),
344 dependency_templates: Default::default(),
345 runtime_modules: Default::default(),
346 runtime_modules_hash: Default::default(),
347 runtime_modules_code_generation_source: Default::default(),
348 chunk_by_ukey: Default::default(),
349 chunk_group_by_ukey: Default::default(),
350 entries: Default::default(),
351 global_entry: Default::default(),
352 chunk_graph: Default::default(),
353 entrypoints: Default::default(),
354 async_entrypoints: Default::default(),
355 assets: Default::default(),
356 assets_related_in: Default::default(),
357 emitted_assets: Default::default(),
358 diagnostics: Default::default(),
359 logging: Default::default(),
360 plugin_driver,
361 buildtime_plugin_driver,
362 resolver_factory,
363 loader_resolver_factory,
364 named_chunks: Default::default(),
365 named_chunk_groups: Default::default(),
366
367 async_modules_artifact: Arc::new(AtomicRefCell::new(AsyncModulesArtifact::default())),
368 imported_by_defer_modules_artifact: Default::default(),
369 dependencies_diagnostics_artifact: Arc::new(AtomicRefCell::new(
370 DependenciesDiagnosticsArtifact::default(),
371 )),
372 side_effects_optimize_artifact: DerefOption::new(Default::default()),
373 module_ids_artifact: Default::default(),
374 named_chunk_ids_artifact: Default::default(),
375 code_generation_results: Default::default(),
376 cgm_hash_artifact: Default::default(),
377 cgm_runtime_requirements_artifact: Default::default(),
378 cgc_runtime_requirements_artifact: Default::default(),
379 chunk_hashes_artifact: Default::default(),
380 chunk_render_artifact: Default::default(),
381 module_graph_cache_artifact: Default::default(),
382 module_static_cache_artifact: Default::default(),
383 code_generated_modules: Default::default(),
384 chunk_render_cache_artifact: ChunkRenderCacheArtifact::new(MemoryGCStorage::new(
385 match &options.cache {
386 CacheOptions::Memory { max_generations } => max_generations.unwrap_or(1),
387 CacheOptions::Disabled => 0, },
389 )),
390 code_generate_cache_artifact: CodeGenerateCacheArtifact::new(&options),
391 process_runtime_requirements_cache_artifact: ProcessRuntimeRequirementsCacheArtifact::new(
392 &options,
393 ),
394 build_time_executed_modules: Default::default(),
395 incremental,
396 build_chunk_graph_artifact: Default::default(),
397
398 hash: None,
399
400 file_dependencies: Default::default(),
401 context_dependencies: Default::default(),
402 missing_dependencies: Default::default(),
403 build_dependencies: Default::default(),
404
405 value_cache_versions: ValueCacheVersions::default(),
406
407 import_var_map: IdentifierDashMap::default(),
408
409 module_executor,
410 in_finish_make: AtomicBool::new(false),
411
412 build_module_graph_artifact: DerefOption::new(BuildModuleGraphArtifact::default()),
413 modified_files,
414 removed_files,
415 input_filesystem,
416
417 intermediate_filesystem,
418 output_filesystem,
419 is_rebuild,
420 compiler_context,
421 }
422 }
423
424 pub fn id(&self) -> CompilationId {
425 self.id
426 }
427
428 pub fn compiler_id(&self) -> CompilerId {
429 self.compiler_id
430 }
431
432 pub fn recover_module_graph_to_new_compilation(&mut self, new_compilation: &mut Compilation) {
433 self
434 .build_module_graph_artifact
435 .get_module_graph_mut()
436 .reset();
437 std::mem::swap(
438 &mut self.build_module_graph_artifact,
439 &mut new_compilation.build_module_graph_artifact,
440 );
441 }
442 pub fn swap_build_module_graph_artifact(&mut self, make_artifact: &mut BuildModuleGraphArtifact) {
443 self.build_module_graph_artifact.swap(make_artifact);
444 }
445 pub fn get_module_graph(&self) -> &ModuleGraph {
446 self.build_module_graph_artifact.get_module_graph()
447 }
448
449 pub fn module_by_identifier(&self, identifier: &ModuleIdentifier) -> Option<&BoxModule> {
451 if self.build_module_graph_artifact.is_none() {
452 return None;
453 }
454 if let Some(module) = self.get_module_graph().module_by_identifier(identifier) {
455 return Some(module);
456 };
457
458 self
459 .build_module_graph_artifact
460 .get_module_graph()
461 .module_by_identifier(identifier)
462 }
463 pub fn get_module_graph_mut(&mut self) -> &mut ModuleGraph {
464 self.build_module_graph_artifact.get_module_graph_mut()
465 }
466
467 pub fn file_dependencies(
468 &self,
469 ) -> (
470 impl Iterator<Item = &ArcPath>,
471 impl Iterator<Item = &ArcPath>,
472 impl Iterator<Item = &ArcPath>,
473 ) {
474 let all_files = self
475 .build_module_graph_artifact
476 .file_dependencies
477 .files()
478 .chain(&self.file_dependencies);
479 let added_files = self
480 .build_module_graph_artifact
481 .file_dependencies
482 .added_files()
483 .chain(&self.file_dependencies);
484 let removed_files = self
485 .build_module_graph_artifact
486 .file_dependencies
487 .removed_files();
488 (all_files, added_files, removed_files)
489 }
490
491 pub fn context_dependencies(
492 &self,
493 ) -> (
494 impl Iterator<Item = &ArcPath>,
495 impl Iterator<Item = &ArcPath>,
496 impl Iterator<Item = &ArcPath>,
497 ) {
498 let all_files = self
499 .build_module_graph_artifact
500 .context_dependencies
501 .files()
502 .chain(&self.context_dependencies);
503 let added_files = self
504 .build_module_graph_artifact
505 .context_dependencies
506 .added_files()
507 .chain(&self.file_dependencies);
508 let removed_files = self
509 .build_module_graph_artifact
510 .context_dependencies
511 .removed_files();
512 (all_files, added_files, removed_files)
513 }
514
515 pub fn missing_dependencies(
516 &self,
517 ) -> (
518 impl Iterator<Item = &ArcPath>,
519 impl Iterator<Item = &ArcPath>,
520 impl Iterator<Item = &ArcPath>,
521 ) {
522 let all_files = self
523 .build_module_graph_artifact
524 .missing_dependencies
525 .files()
526 .chain(&self.missing_dependencies);
527 let added_files = self
528 .build_module_graph_artifact
529 .missing_dependencies
530 .added_files()
531 .chain(&self.file_dependencies);
532 let removed_files = self
533 .build_module_graph_artifact
534 .missing_dependencies
535 .removed_files();
536 (all_files, added_files, removed_files)
537 }
538
539 pub fn build_dependencies(
540 &self,
541 ) -> (
542 impl Iterator<Item = &ArcPath>,
543 impl Iterator<Item = &ArcPath>,
544 impl Iterator<Item = &ArcPath>,
545 ) {
546 let all_files = self
547 .build_module_graph_artifact
548 .build_dependencies
549 .files()
550 .chain(&self.build_dependencies);
551 let added_files = self
552 .build_module_graph_artifact
553 .build_dependencies
554 .added_files()
555 .chain(&self.file_dependencies);
556 let removed_files = self
557 .build_module_graph_artifact
558 .build_dependencies
559 .removed_files();
560 (all_files, added_files, removed_files)
561 }
562
563 pub fn get_import_var(
565 &self,
566 module: ModuleIdentifier,
567 target_module: Option<&BoxModule>,
568 user_request: &str,
569 phase: ImportPhase,
570 runtime: Option<&RuntimeSpec>,
571 ) -> String {
572 let mut runtime_map = self.import_var_map.entry(module).or_default();
573 let import_var_map_of_module = runtime_map
574 .entry(
575 runtime
576 .map(|r| get_runtime_key(r).clone())
577 .unwrap_or_default(),
578 )
579 .or_default();
580 let len = import_var_map_of_module.len();
581 let is_deferred = phase.is_defer()
582 && !target_module
583 .map(|m| m.build_meta().has_top_level_await)
584 .unwrap_or_default();
585
586 match import_var_map_of_module.entry((target_module.map(|m| m.identifier()), is_deferred)) {
587 hash_map::Entry::Occupied(occ) => occ.get().clone(),
588 hash_map::Entry::Vacant(vac) => {
589 let mut b = itoa::Buffer::new();
590 let import_var = format!(
591 "{}__rspack_{}import_{}",
592 to_identifier(user_request),
593 match phase {
594 ImportPhase::Evaluation => "",
595 ImportPhase::Source => "",
596 ImportPhase::Defer => "DEFERRED_",
597 },
598 b.format(len)
599 );
600 vac.insert(import_var.clone());
601 import_var
602 }
603 }
604 }
605
606 pub async fn add_entry(&mut self, entry: BoxDependency, options: EntryOptions) -> Result<()> {
607 let entry_id = *entry.id();
608 let entry_name: Option<String> = options.name.clone();
609 self
610 .build_module_graph_artifact
611 .get_module_graph_mut()
612 .add_dependency(entry);
613 if let Some(name) = &entry_name {
614 if let Some(data) = self.entries.get_mut(name) {
615 data.dependencies.push(entry_id);
616 data.options.merge(options)?;
617 } else {
618 let data = EntryData {
619 dependencies: vec![entry_id],
620 include_dependencies: vec![],
621 options,
622 };
623 self.entries.insert(name.to_owned(), data);
624 }
625 } else {
626 self.global_entry.dependencies.push(entry_id);
627 }
628
629 self
630 .plugin_driver
631 .clone()
632 .compilation_hooks
633 .add_entry
634 .call(self, entry_name.as_deref())
635 .await?;
636
637 Ok(())
638 }
639
640 pub async fn add_entry_batch(&mut self, args: Vec<(BoxDependency, EntryOptions)>) -> Result<()> {
641 for (entry, options) in args {
642 self.add_entry(entry, options).await?;
643 }
644
645 let make_artifact = self.build_module_graph_artifact.take();
646 self.build_module_graph_artifact.replace(
647 update_module_graph(
648 self,
649 make_artifact,
650 vec![UpdateParam::BuildEntry(
651 self
652 .entries
653 .values()
654 .flat_map(|item| item.all_dependencies())
655 .chain(self.global_entry.all_dependencies())
656 .copied()
657 .collect(),
658 )],
659 )
660 .await?,
661 );
662 Ok(())
663 }
664
665 pub async fn add_include(&mut self, args: Vec<(BoxDependency, EntryOptions)>) -> Result<()> {
666 if !self.in_finish_make.load(Ordering::Acquire) {
667 return Err(rspack_error::Error::error(
668 "You can only call `add_include` during the finish make stage".into(),
669 ));
670 }
671
672 for (entry, options) in args {
673 let entry_id = *entry.id();
674 self
675 .build_module_graph_artifact
676 .get_module_graph_mut()
677 .add_dependency(entry);
678 if let Some(name) = options.name.clone() {
679 if let Some(data) = self.entries.get_mut(&name) {
680 data.include_dependencies.push(entry_id);
681 } else {
682 let data = EntryData {
683 dependencies: vec![],
684 include_dependencies: vec![entry_id],
685 options,
686 };
687 self.entries.insert(name, data);
688 }
689 } else {
690 self.global_entry.include_dependencies.push(entry_id);
691 }
692 }
693
694 let make_artifact = self.build_module_graph_artifact.take();
697 self.build_module_graph_artifact.replace(
698 update_module_graph(
699 self,
700 make_artifact,
701 vec![UpdateParam::BuildEntry(
702 self
703 .entries
704 .values()
705 .flat_map(|item| item.all_dependencies())
706 .chain(self.global_entry.all_dependencies())
707 .copied()
708 .collect(),
709 )],
710 )
711 .await?,
712 );
713 Ok(())
714 }
715
716 fn set_asset_info(
717 &mut self,
718 name: &str,
719 new_info: Option<&AssetInfo>,
720 old_info: Option<&AssetInfo>,
721 ) {
722 if let Some(old_info) = old_info
723 && let Some(source_map) = &old_info.related.source_map
724 && let Some(entry) = self.assets_related_in.get_mut(source_map)
725 {
726 entry.remove(name);
727 }
728 if let Some(new_info) = new_info
729 && let Some(source_map) = new_info.related.source_map.clone()
730 {
731 let entry = self.assets_related_in.entry(source_map).or_default();
732 entry.insert(name.to_string());
733 }
734 }
735
736 pub fn update_asset(
737 &mut self,
738 filename: &str,
739 updater: impl FnOnce(
740 BoxSource,
741 BindingCell<AssetInfo>,
742 ) -> Result<(BoxSource, BindingCell<AssetInfo>)>,
743 ) -> Result<()> {
744 let assets = &mut self.assets;
745
746 let (old_info, new_source, new_info) = match assets.remove(filename) {
747 Some(CompilationAsset {
748 source: Some(source),
749 info: old_info,
750 }) => {
751 let (new_source, new_info) = updater(source, old_info.clone())?;
752 (old_info, new_source, new_info)
753 }
754 _ => {
755 return Err(rspack_error::error!(
756 "Called Compilation.updateAsset for not existing filename {}",
757 filename
758 ));
759 }
760 };
761 self.set_asset_info(filename, Some(&new_info), Some(&old_info));
762 self.assets.insert(
763 filename.to_owned(),
764 CompilationAsset {
765 source: Some(new_source),
766 info: new_info,
767 },
768 );
769 Ok(())
770 }
771 #[instrument("Compilation:emit_asset",skip_all, fields(filename = filename))]
772 pub fn emit_asset(&mut self, filename: String, asset: CompilationAsset) {
773 if let Some(mut original) = self.assets.remove(&filename)
774 && let Some(original_source) = &original.source
775 && let Some(asset_source) = asset.get_source()
776 {
777 let is_source_equal = is_source_equal(original_source, asset_source);
778 if !is_source_equal {
779 tracing::error!(
780 "Emit Duplicate Filename({}), is_source_equal: {:?}",
781 filename,
782 is_source_equal
783 );
784 self.push_diagnostic(
785 rspack_error::error!(
786 "Conflict: Multiple assets emit different content to the same filename {}{}",
787 filename,
788 ""
790 )
791 .into(),
792 );
793 self.set_asset_info(&filename, Some(asset.get_info()), None);
794 self.assets.insert(filename, asset);
795 return;
796 }
797 self.set_asset_info(&filename, Some(asset.get_info()), Some(original.get_info()));
798 original.info = asset.info;
799 self.assets.insert(filename, original);
800 } else {
801 self.set_asset_info(&filename, Some(asset.get_info()), None);
802 self.assets.insert(filename, asset);
803 }
804 }
805
806 pub fn delete_asset(&mut self, filename: &str) {
807 if let Some(asset) = self.assets.remove(filename) {
808 self.set_asset_info(filename, None, Some(asset.get_info()));
809
810 if let Some(source_map) = &asset.info.related.source_map {
811 self.delete_asset(source_map);
812 }
813 self.chunk_by_ukey.iter_mut().for_each(|(_, chunk)| {
814 chunk.remove_file(filename);
815 chunk.remove_auxiliary_file(filename);
816 });
817 }
818 }
819
820 pub fn rename_asset(&mut self, filename: &str, new_name: String) {
821 if let Some(asset) = self.assets.remove(filename) {
822 if let Some(related_in_info) = self.assets_related_in.get(filename) {
824 for name in related_in_info {
825 if let Some(asset) = self.assets.get_mut(name) {
826 asset.get_info_mut().related.source_map = Some(new_name.clone());
827 }
828 }
829 }
830 self.set_asset_info(filename, None, Some(asset.get_info()));
831 self.set_asset_info(&new_name, Some(asset.get_info()), None);
832
833 self.assets.insert(new_name.clone(), asset);
834
835 self.chunk_by_ukey.iter_mut().for_each(|(_, chunk)| {
836 if chunk.remove_file(filename) {
837 chunk.add_file(new_name.clone());
838 }
839
840 if chunk.remove_auxiliary_file(filename) {
841 chunk.add_auxiliary_file(new_name.clone());
842 }
843 });
844 }
845 }
846
847 pub fn par_rename_assets(&mut self, renames: Vec<(String, String)>) {
852 self
853 .chunk_by_ukey
854 .values_mut()
855 .par_bridge()
856 .for_each(|chunk| {
857 for (old_name, new_name) in renames.iter() {
858 if chunk.remove_file(old_name) {
859 chunk.add_file(new_name.clone());
860 }
861
862 if chunk.remove_auxiliary_file(old_name) {
863 chunk.add_auxiliary_file(new_name.clone());
864 }
865 }
866 });
867
868 for (old_name, new_name) in renames {
869 if let Some(asset) = self.assets.remove(&old_name) {
870 if let Some(related_in_info) = self.assets_related_in.get(&old_name) {
872 for related_in_name in related_in_info {
873 if let Some(asset) = self.assets.get_mut(related_in_name) {
874 asset.get_info_mut().related.source_map = Some(new_name.clone());
875 }
876 }
877 }
878 self.set_asset_info(&old_name, None, Some(asset.get_info()));
879 self.set_asset_info(&new_name, Some(asset.get_info()), None);
880
881 self.assets.insert(new_name, asset);
882 }
883 }
884 }
885
886 pub fn assets(&self) -> &CompilationAssets {
887 &self.assets
888 }
889
890 pub fn assets_mut(&mut self) -> &mut CompilationAssets {
891 &mut self.assets
892 }
893
894 pub fn entrypoints(&self) -> &IndexMap<String, ChunkGroupUkey> {
895 &self.entrypoints
896 }
897
898 pub fn push_diagnostic(&mut self, diagnostic: Diagnostic) {
899 self.diagnostics.push(diagnostic);
900 }
901
902 pub fn extend_diagnostics(&mut self, diagnostics: impl IntoIterator<Item = Diagnostic>) {
903 self.diagnostics.extend(diagnostics);
904 }
905
906 pub fn diagnostics(&self) -> &[Diagnostic] {
907 &self.diagnostics
908 }
909
910 pub fn diagnostics_mut(&mut self) -> &mut Vec<Diagnostic> {
911 &mut self.diagnostics
912 }
913
914 pub fn get_errors(&self) -> impl Iterator<Item = &Diagnostic> {
915 self.diagnostics.iter().filter(|d| d.is_error())
916 }
917
918 pub fn get_errors_sorted(&self) -> impl Iterator<Item = &Diagnostic> {
925 let get_offset = |d: &Diagnostic| {
926 d.labels
927 .as_ref()
928 .and_then(|l| l.first())
929 .map(|l| l.offset)
930 .unwrap_or_default()
931 };
932 self
933 .get_errors()
934 .sorted_by(|a, b| match a.module_identifier.cmp(&b.module_identifier) {
935 std::cmp::Ordering::Equal => get_offset(a).cmp(&get_offset(b)),
936 other => other,
937 })
938 }
939
940 pub fn get_warnings(&self) -> impl Iterator<Item = &Diagnostic> {
941 self.diagnostics.iter().filter(|d| d.is_warn())
942 }
943
944 pub fn get_warnings_sorted(&self) -> impl Iterator<Item = &Diagnostic> {
951 let get_offset = |d: &Diagnostic| {
952 d.labels
953 .as_ref()
954 .and_then(|l| l.first())
955 .map(|l| l.offset)
956 .unwrap_or_default()
957 };
958 self
959 .get_warnings()
960 .sorted_by(|a, b| match a.module_identifier.cmp(&b.module_identifier) {
961 std::cmp::Ordering::Equal => get_offset(a).cmp(&get_offset(b)),
962 other => other,
963 })
964 }
965
966 pub fn get_logging(&self) -> &CompilationLogging {
967 &self.logging
968 }
969
970 pub fn get_stats(&self) -> Stats<'_> {
971 Stats::new(self)
972 }
973
974 pub fn add_named_chunk(
975 name: String,
976 chunk_by_ukey: &mut ChunkByUkey,
977 named_chunks: &mut HashMap<String, ChunkUkey>,
978 ) -> (ChunkUkey, bool) {
979 let existed_chunk_ukey = named_chunks.get(&name);
980 if let Some(chunk_ukey) = existed_chunk_ukey {
981 assert!(chunk_by_ukey.contains(chunk_ukey));
982 (*chunk_ukey, false)
983 } else {
984 let chunk = Chunk::new(Some(name.clone()), ChunkKind::Normal);
985 let ukey = chunk.ukey();
986 named_chunks.insert(name, ukey);
987 chunk_by_ukey.entry(ukey).or_insert_with(|| chunk);
988 (ukey, true)
989 }
990 }
991
992 pub fn add_chunk(chunk_by_ukey: &mut ChunkByUkey) -> ChunkUkey {
993 let chunk = Chunk::new(None, ChunkKind::Normal);
994 let ukey = chunk.ukey();
995 chunk_by_ukey.add(chunk);
996 ukey
997 }
998
999 pub async fn rebuild_module<T>(
1000 &mut self,
1001 module_identifiers: IdentifierSet,
1002 f: impl Fn(Vec<&BoxModule>) -> T,
1003 ) -> Result<T> {
1004 let artifact = self.build_module_graph_artifact.take();
1005
1006 self.module_graph_cache_artifact.unfreeze();
1008
1009 self.build_module_graph_artifact.replace(
1010 update_module_graph(
1011 self,
1012 artifact,
1013 vec![UpdateParam::ForceBuildModules(module_identifiers.clone())],
1014 )
1015 .await?,
1016 );
1017
1018 let module_graph = self.get_module_graph();
1019 Ok(f(module_identifiers
1020 .into_iter()
1021 .filter_map(|id| module_graph.module_by_identifier(&id))
1022 .collect::<Vec<_>>()))
1023 }
1024
1025 pub fn entry_modules(&self) -> IdentifierSet {
1026 let module_graph = self.get_module_graph();
1027 self
1028 .entries
1029 .values()
1030 .flat_map(|item| item.all_dependencies())
1031 .chain(self.global_entry.all_dependencies())
1032 .filter_map(|dep_id| {
1033 module_graph
1036 .module_identifier_by_dependency_id(dep_id)
1037 .copied()
1038 })
1039 .collect()
1040 }
1041
1042 pub fn entrypoint_by_name(&self, name: &str) -> &Entrypoint {
1043 let ukey = self.entrypoints.get(name).expect("entrypoint not found");
1044 self.chunk_group_by_ukey.expect_get(ukey)
1045 }
1046
1047 pub fn entrypoint_by_name_mut(&mut self, name: &str) -> &mut Entrypoint {
1048 let ukey = self.entrypoints.get(name).expect("entrypoint not found");
1049 self.chunk_group_by_ukey.expect_get_mut(ukey)
1050 }
1051
1052 pub fn get_chunk_graph_entries(&self) -> impl Iterator<Item = ChunkUkey> + use<'_> {
1053 let entries = self.entrypoints.values().map(|entrypoint_ukey| {
1054 let entrypoint = self.chunk_group_by_ukey.expect_get(entrypoint_ukey);
1055 entrypoint.get_runtime_chunk(&self.chunk_group_by_ukey)
1056 });
1057 let async_entries = self.async_entrypoints.iter().map(|entrypoint_ukey| {
1058 let entrypoint = self.chunk_group_by_ukey.expect_get(entrypoint_ukey);
1059 entrypoint.get_runtime_chunk(&self.chunk_group_by_ukey)
1060 });
1061 entries.chain(async_entries)
1062 }
1063 pub fn add_runtime_module(
1064 &mut self,
1065 chunk_ukey: &ChunkUkey,
1066 mut module: Box<dyn RuntimeModule>,
1067 ) -> Result<()> {
1068 let chunk = self.chunk_by_ukey.expect_get(chunk_ukey);
1070 let runtime_module_identifier = ModuleIdentifier::from(format!(
1071 "{}/{}",
1072 get_runtime_key(chunk.runtime()),
1073 module.identifier()
1074 ));
1075 module.attach(*chunk_ukey);
1076
1077 self.chunk_graph.add_module(runtime_module_identifier);
1078 self.runtime_template.add_templates(module.template());
1079 self
1080 .chunk_graph
1081 .connect_chunk_and_module(*chunk_ukey, runtime_module_identifier);
1082 self
1083 .chunk_graph
1084 .connect_chunk_and_runtime_module(*chunk_ukey, runtime_module_identifier);
1085
1086 self
1087 .runtime_modules
1088 .insert(runtime_module_identifier, module);
1089
1090 Ok(())
1091 }
1092
1093 pub fn get_hash(&self) -> Option<&str> {
1094 self
1095 .hash
1096 .as_ref()
1097 .map(|hash| hash.rendered(self.options.output.hash_digest_length))
1098 }
1099
1100 pub async fn get_path<'b, 'a: 'b>(
1101 &'a self,
1102 filename: &Filename,
1103 mut data: PathData<'b>,
1104 ) -> Result<String> {
1105 if data.hash.is_none() {
1106 data.hash = self.get_hash();
1107 }
1108 filename.render(data, None).await
1109 }
1110
1111 pub async fn get_path_with_info<'b, 'a: 'b>(
1112 &'a self,
1113 filename: &Filename,
1114 mut data: PathData<'b>,
1115 info: &mut AssetInfo,
1116 ) -> Result<String> {
1117 if data.hash.is_none() {
1118 data.hash = self.get_hash();
1119 }
1120 let path = filename.render(data, Some(info)).await?;
1121 Ok(path)
1122 }
1123
1124 pub async fn get_asset_path(&self, filename: &Filename, data: PathData<'_>) -> Result<String> {
1125 filename.render(data, None).await
1126 }
1127
1128 pub async fn get_asset_path_with_info(
1129 &self,
1130 filename: &Filename,
1131 data: PathData<'_>,
1132 ) -> Result<(String, AssetInfo)> {
1133 let mut info = AssetInfo::default();
1134 let path = filename.render(data, Some(&mut info)).await?;
1135 Ok((path, info))
1136 }
1137
1138 pub fn get_logger(&self, name: impl Into<String>) -> CompilationLogger {
1139 CompilationLogger::new(name.into(), self.logging.clone())
1140 }
1141
1142 pub fn set_dependency_factory(
1143 &mut self,
1144 dependency_type: DependencyType,
1145 module_factory: Arc<dyn ModuleFactory>,
1146 ) {
1147 self
1148 .dependency_factories
1149 .insert(dependency_type, module_factory);
1150 }
1151
1152 pub fn get_dependency_factory(&self, dependency: &BoxDependency) -> Arc<dyn ModuleFactory> {
1153 let dependency_type = dependency.dependency_type();
1154 self
1155 .dependency_factories
1156 .get(dependency_type)
1157 .unwrap_or_else(|| {
1158 panic!(
1159 "No module factory available for dependency type: {}, resourceIdentifier: {:?}",
1160 dependency_type,
1161 dependency.resource_identifier()
1162 )
1163 })
1164 .clone()
1165 }
1166
1167 pub fn set_dependency_template(
1168 &mut self,
1169 template_type: DependencyTemplateType,
1170 template: Arc<dyn DependencyTemplate>,
1171 ) {
1172 self.dependency_templates.insert(template_type, template);
1173 }
1174
1175 pub fn get_dependency_template(
1176 &self,
1177 dep: &dyn DependencyCodeGeneration,
1178 ) -> Option<Arc<dyn DependencyTemplate>> {
1179 dep
1180 .dependency_template()
1181 .and_then(|template_type| self.dependency_templates.get(&template_type).cloned())
1182 }
1183}
1184
1185pub type CompilationAssets = HashMap<String, CompilationAsset>;
1186
1187#[cacheable]
1188#[derive(Debug, Clone)]
1189pub struct CompilationAsset {
1190 #[cacheable(with=AsOption<AsPreset>)]
1191 pub source: Option<BoxSource>,
1192 pub info: BindingCell<AssetInfo>,
1193}
1194
1195impl From<BoxSource> for CompilationAsset {
1196 fn from(value: BoxSource) -> Self {
1197 Self::new(Some(value), Default::default())
1198 }
1199}
1200
1201impl CompilationAsset {
1202 pub fn new(source: Option<BoxSource>, info: AssetInfo) -> Self {
1203 Self {
1204 source,
1205 info: BindingCell::from(info),
1206 }
1207 }
1208
1209 pub fn get_source(&self) -> Option<&BoxSource> {
1210 self.source.as_ref()
1211 }
1212
1213 pub fn set_source(&mut self, source: Option<BoxSource>) {
1214 self.source = source;
1215 }
1216
1217 pub fn get_info(&self) -> &AssetInfo {
1218 &self.info
1219 }
1220
1221 pub fn get_info_mut(&mut self) -> &mut AssetInfo {
1222 &mut self.info
1223 }
1224
1225 pub fn set_info(&mut self, info: AssetInfo) {
1226 self.info = BindingCell::from(info);
1227 }
1228}
1229
1230#[cacheable]
1231#[derive(Debug, Default, Clone)]
1232pub struct AssetInfo {
1233 pub immutable: Option<bool>,
1235 pub minimized: Option<bool>,
1237 pub full_hash: HashSet<String>,
1239 pub chunk_hash: HashSet<String>,
1241 pub content_hash: HashSet<String>,
1245 pub source_filename: Option<String>,
1247 pub copied: Option<bool>,
1249 pub development: Option<bool>,
1253 pub hot_module_replacement: Option<bool>,
1255 pub javascript_module: Option<bool>,
1257 pub related: AssetInfoRelated,
1259 pub version: String,
1262 pub css_unused_idents: Option<HashSet<String>>,
1264 pub is_over_size_limit: Option<bool>,
1266 pub asset_type: ManifestAssetType,
1268
1269 #[cacheable(with=AsPreset)]
1273 pub extras: serde_json::Map<String, serde_json::Value>,
1274}
1275
1276impl AssetInfo {
1277 pub fn with_development(mut self, v: Option<bool>) -> Self {
1278 self.development = v;
1279 self
1280 }
1281
1282 pub fn with_hot_module_replacement(mut self, v: Option<bool>) -> Self {
1283 self.hot_module_replacement = v;
1284 self
1285 }
1286
1287 pub fn with_content_hashes(mut self, v: HashSet<String>) -> Self {
1288 self.content_hash = v;
1289 self
1290 }
1291
1292 pub fn with_version(mut self, v: String) -> Self {
1293 self.version = v;
1294 self
1295 }
1296
1297 pub fn with_asset_type(mut self, v: ManifestAssetType) -> Self {
1298 self.asset_type = v;
1299 self
1300 }
1301
1302 pub fn set_full_hash(&mut self, v: String) {
1303 self.full_hash.insert(v);
1304 }
1305
1306 pub fn set_content_hash(&mut self, v: String) {
1307 self.content_hash.insert(v);
1308 }
1309
1310 pub fn set_chunk_hash(&mut self, v: String) {
1311 self.chunk_hash.insert(v);
1312 }
1313
1314 pub fn set_immutable(&mut self, v: Option<bool>) {
1315 self.immutable = v;
1316 }
1317
1318 pub fn set_source_filename(&mut self, v: String) {
1319 self.source_filename = Some(v);
1320 }
1321
1322 pub fn set_javascript_module(&mut self, v: bool) {
1323 self.javascript_module = Some(v);
1324 }
1325
1326 pub fn set_css_unused_idents(&mut self, v: HashSet<String>) {
1327 self.css_unused_idents = Some(v);
1328 }
1329
1330 pub fn set_is_over_size_limit(&mut self, v: bool) {
1331 self.is_over_size_limit = Some(v);
1332 }
1333 pub fn merge_another_asset(&mut self, another: AssetInfo) {
1339 self.minimized = another.minimized;
1341
1342 self.source_filename = another.source_filename.or(self.source_filename.take());
1343 self.version = another.version;
1344 self.related.merge_another(another.related);
1345
1346 self.chunk_hash.extend(another.chunk_hash);
1348 self.content_hash.extend(another.content_hash);
1349 self.extras.extend(another.extras);
1350 self.javascript_module = another.javascript_module.or(self.javascript_module.take());
1355 self.immutable = another.immutable.or(self.immutable);
1356 self.development = another.development.or(self.development);
1357 self.hot_module_replacement = another
1358 .hot_module_replacement
1359 .or(self.hot_module_replacement);
1360 self.is_over_size_limit = another.is_over_size_limit.or(self.is_over_size_limit);
1361 }
1362}
1363
1364#[cacheable]
1365#[derive(Debug, Default, Clone)]
1366pub struct AssetInfoRelated {
1367 pub source_map: Option<String>,
1368}
1369
1370impl AssetInfoRelated {
1371 pub fn merge_another(&mut self, another: AssetInfoRelated) {
1372 if let Some(source_map) = another.source_map {
1373 self.source_map = Some(source_map);
1374 }
1375 }
1376}
1377
1378pub fn assign_depths<'a>(
1381 assign_map: &mut IdentifierMap<usize>,
1382 modules: impl Iterator<Item = &'a ModuleIdentifier>,
1383 outgoings: &IdentifierMap<Vec<ModuleIdentifier>>,
1384) {
1385 let mut q = VecDeque::new();
1387 for item in modules {
1388 q.push_back((*item, 0));
1389 }
1390 while let Some((id, depth)) = q.pop_front() {
1391 match assign_map.entry(id) {
1392 hash_map::Entry::Occupied(_) => {
1393 continue;
1394 }
1395 hash_map::Entry::Vacant(vac) => {
1396 vac.insert(depth);
1397 }
1398 };
1399 for con in outgoings.get(&id).expect("should have outgoings").iter() {
1400 q.push_back((*con, depth + 1));
1401 }
1402 }
1403}
1404
1405pub fn set_depth_if_lower(
1406 module_id: ModuleIdentifier,
1407 depth: usize,
1408 assign_map: &mut IdentifierMap<usize>,
1409) -> bool {
1410 let Some(&cur_depth) = assign_map.get(&module_id) else {
1411 assign_map.insert(module_id, depth);
1412 return true;
1413 };
1414 if cur_depth > depth {
1415 assign_map.insert(module_id, depth);
1416 return true;
1417 }
1418 false
1419}
1420
1421#[derive(Debug, Clone)]
1422pub struct RenderManifestEntry {
1423 pub source: BoxSource,
1424 pub filename: String,
1425 pub has_filename: bool, pub info: AssetInfo,
1427 pub auxiliary: bool,
1428}
1429
1430#[cacheable]
1431#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
1432pub enum ManifestAssetType {
1433 #[default]
1434 Unknown,
1435 Asset,
1436 Css,
1437 JavaScript,
1438 Wasm,
1439 Custom(#[cacheable(with=AsPreset)] Ustr),
1440}
1441
1442impl fmt::Display for ManifestAssetType {
1443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1444 match self {
1445 ManifestAssetType::Unknown => write!(f, "unknown"),
1446 ManifestAssetType::Asset => write!(f, "asset"),
1447 ManifestAssetType::Css => write!(f, "css"),
1448 ManifestAssetType::JavaScript => write!(f, "javascript"),
1449 ManifestAssetType::Wasm => write!(f, "wasm"),
1450 ManifestAssetType::Custom(custom) => write!(f, "{custom}"),
1451 }
1452 }
1453}
1454
1455impl From<String> for ManifestAssetType {
1456 fn from(value: String) -> Self {
1457 match value.as_str() {
1458 "unknown" => ManifestAssetType::Unknown,
1459 "asset" => ManifestAssetType::Asset,
1460 "css" => ManifestAssetType::Css,
1461 "javascript" => ManifestAssetType::JavaScript,
1462 "wasm" => ManifestAssetType::Wasm,
1463 _ => ManifestAssetType::Custom(value.into()),
1464 }
1465 }
1466}