11use std:: cmp:: Ordering ;
22
33use crate :: chunk_graph:: ChunkGraph ;
4+ use arcstr:: ArcStr ;
45use itertools:: Itertools ;
56use oxc:: index:: IndexVec ;
67use rolldown_common:: { Chunk , ChunkIdx , ChunkKind , Module , ModuleIdx , OutputFormat } ;
@@ -12,7 +13,7 @@ use super::GenerateStage;
1213
1314impl < ' a > GenerateStage < ' a > {
1415 #[ tracing:: instrument( level = "debug" , skip_all) ]
15- pub fn generate_chunks ( & mut self ) -> ChunkGraph {
16+ pub async fn generate_chunks ( & mut self ) -> anyhow :: Result < ChunkGraph > {
1617 if matches ! ( self . options. format, OutputFormat :: Iife ) {
1718 let user_defined_entry_count =
1819 self . link_output . entries . iter ( ) . filter ( |entry| entry. kind . is_user_defined ( ) ) . count ( ) ;
@@ -63,18 +64,47 @@ impl<'a> GenerateStage<'a> {
6364 ) ;
6465 } ) ;
6566
67+ let mut module_to_assigned: IndexVec < ModuleIdx , bool > =
68+ oxc:: index:: index_vec![ false ; self . link_output. module_table. modules. len( ) ] ;
69+
6670 // 1. Assign modules to corresponding chunks
6771 // 2. Create shared chunks to store modules that belong to multiple chunks.
6872 for normal_module in self . link_output . module_table . modules . iter ( ) . filter_map ( Module :: as_ecma) {
6973 if !normal_module. is_included {
7074 continue ;
7175 }
7276
77+ if module_to_assigned[ normal_module. idx ] {
78+ continue ;
79+ }
80+ module_to_assigned[ normal_module. idx ] = true ;
81+
7382 let bits = & module_to_bits[ normal_module. idx ] ;
7483 debug_assert ! (
7584 !bits. is_empty( ) ,
7685 "Empty bits means the module is not reachable, so it should bail out with `is_included: false` {:?}" , normal_module. stable_id
7786 ) ;
87+
88+ let mut manual_chunk_by_name = FxHashMap :: default ( ) ;
89+
90+ if let Some ( manual_chunks) = & self . options . advanced_chunks {
91+ if let Some ( matched) = ( manual_chunks) ( & normal_module. id ) . await ? {
92+ let chunk_name = ArcStr :: from ( matched. name ) ;
93+ if let Some ( chunk_idx) = manual_chunk_by_name. get ( & chunk_name) . copied ( ) {
94+ let chunk: & mut Chunk = & mut chunk_graph. chunk_table [ chunk_idx] ;
95+ chunk. bits . union ( bits) ;
96+ chunk_graph. add_module_to_chunk ( normal_module. idx , chunk_idx) ;
97+ } else {
98+ let chunk =
99+ Chunk :: new ( Some ( chunk_name. clone ( ) ) , bits. clone ( ) , vec ! [ ] , ChunkKind :: Common ) ;
100+ let chunk_id = chunk_graph. add_chunk ( chunk) ;
101+ chunk_graph. add_module_to_chunk ( normal_module. idx , chunk_id) ;
102+ manual_chunk_by_name. insert ( chunk_name, chunk_id) ;
103+ }
104+ continue ;
105+ }
106+ }
107+
78108 if let Some ( chunk_id) = bits_to_chunk. get ( bits) . copied ( ) {
79109 chunk_graph. add_module_to_chunk ( normal_module. idx , chunk_id) ;
80110 } else {
@@ -196,7 +226,7 @@ impl<'a> GenerateStage<'a> {
196226 chunk_graph. sorted_chunk_idx_vec = sorted_chunk_idx_vec;
197227 chunk_graph. entry_module_to_entry_chunk = entry_module_to_entry_chunk;
198228
199- chunk_graph
229+ Ok ( chunk_graph)
200230 }
201231
202232 fn determine_reachable_modules_for_entry (
0 commit comments