@@ -8,7 +8,7 @@ use turbo_tasks_fs::{FileContent, FileLine, FileLinesContent, rope::Rope};
88use turbopack_core:: {
99 asset:: { Asset , AssetContent } ,
1010 output:: OutputAsset ,
11- source_map:: { GenerateSourceMap , OriginalToken , SourceMap , SyntheticToken , Token } ,
11+ source_map:: { GenerateSourceMap , OriginalToken , SourceMap , Token } ,
1212} ;
1313
1414use crate :: compressed_size:: compressed_size_bytes;
@@ -111,7 +111,8 @@ pub async fn split_output_asset_into_parts(
111111 let start_line = start_line. min ( lines. len ( ) as u32 - 1 ) ;
112112 let end_line = end_line. min ( lines. len ( ) as u32 - 1 ) ;
113113 if start_line == end_line {
114- return end_column - start_column;
114+ // TODO: Figure out why start is larger than end sometimes
115+ return end_column. saturating_sub ( start_column) ;
115116 }
116117 let mut len = lines[ start_line as usize ] . len ( ) as u32 - start_column + 1 ;
117118 for line in & lines[ start_line as usize + 1 ..end_line as usize ] {
@@ -139,17 +140,6 @@ pub async fn split_output_asset_into_parts(
139140 lines,
140141 } ) ;
141142 entry. real_size += size;
142-
143- // Check if the new range is adjacent to the last range and merge if so
144- if let Some ( last_range) = entry. ranges . last_mut ( )
145- && last_range. line == chunk_part_range. line
146- && last_range. end_column == chunk_part_range. start_column
147- && chunk_part_range. end_column >= chunk_part_range. start_column
148- {
149- last_range. end_column = chunk_part_range. end_column ;
150- return ;
151- }
152-
153143 entry. ranges . push ( chunk_part_range) ;
154144 }
155145
@@ -171,98 +161,144 @@ pub async fn split_output_asset_into_parts(
171161 entry. unaccounted_size += unaccounted;
172162 }
173163
164+ fn end_current_mapping (
165+ source : RcStr ,
166+ current_line : u32 ,
167+ start_column : u32 ,
168+ next_line : u32 ,
169+ next_column : u32 ,
170+ lines : & [ FileLine ] ,
171+ chunk_parts : & mut FxIndexMap < RcStr , ChunkPart > ,
172+ lines_vc : ResolvedVc < FileLinesContent > ,
173+ ) -> State {
174+ let mapping_end_column = end_of_mapping_column ( current_line, next_line, next_column, lines) ;
175+ let len = mapping_end_column. saturating_sub ( start_column) ;
176+ add_chunk_part_range (
177+ source. clone ( ) ,
178+ ChunkPartRange {
179+ line : current_line,
180+ start_column,
181+ end_column : mapping_end_column,
182+ } ,
183+ len,
184+ chunk_parts,
185+ lines_vc,
186+ ) ;
187+ State :: AfterMapping {
188+ source,
189+ generated_line : current_line,
190+ current_generated_column : mapping_end_column,
191+ }
192+ }
193+
194+ fn should_extend_mapping (
195+ state : & State ,
196+ new_source : & RcStr ,
197+ new_line : u32 ,
198+ new_column : u32 ,
199+ ) -> bool {
200+ if let State :: InMapping {
201+ source,
202+ generated_line,
203+ end_column,
204+ ..
205+ } = state
206+ {
207+ // Extend if same source and line, and columns are adjacent or overlapping
208+ // end_column <= new_column handles both adjacent (equal) and overlapping cases
209+ source == new_source && * generated_line == new_line && * end_column <= new_column
210+ } else {
211+ false
212+ }
213+ }
214+
174215 enum State {
175216 StartOfFile ,
176217 InMapping {
177218 source : RcStr ,
178- current_generated_line : u32 ,
179- current_generated_column : u32 ,
219+ generated_line : u32 ,
220+ start_column : u32 ,
221+ end_column : u32 ,
180222 } ,
181223 AfterMapping {
182224 source : RcStr ,
183- current_generated_line : u32 ,
225+ generated_line : u32 ,
184226 current_generated_column : u32 ,
185227 } ,
186228 }
187229
188230 let mut state: State = State :: StartOfFile ;
189231
190232 for token in source_map. tokens ( ) {
191- // First end the previous mapping if we were in one
192- let end_info = if let State :: InMapping {
193- ref source,
194- current_generated_line,
195- current_generated_column,
196- } = state
197- {
198- let ( Token :: Original ( OriginalToken {
199- generated_line,
200- generated_column,
201- ..
202- } )
203- | Token :: Synthetic ( SyntheticToken {
204- generated_line,
205- generated_column,
206- ..
207- } ) ) = token;
208- let mapping_end_column = end_of_mapping_column (
209- current_generated_line,
210- generated_line,
211- generated_column,
212- lines,
213- ) ;
214- // TODO: Handle this better
215- let len = mapping_end_column. saturating_sub ( current_generated_column) ;
216- Some ( (
217- source. clone ( ) ,
218- ChunkPartRange {
219- line : current_generated_line,
220- start_column : current_generated_column,
221- end_column : mapping_end_column,
222- } ,
223- len,
224- current_generated_line,
225- mapping_end_column,
226- ) )
227- } else {
228- None
229- } ;
230-
231- if let Some ( ( source, range, len, line, col) ) = end_info {
232- add_chunk_part_range ( source. clone ( ) , range, len, & mut chunk_parts, lines_vc) ;
233- state = State :: AfterMapping {
234- source,
235- current_generated_line : line,
236- current_generated_column : col,
237- } ;
238- }
239-
240233 if let Token :: Original ( OriginalToken {
241234 original_file,
242235 generated_line,
243236 generated_column,
244237 ..
245238 } ) = token
246239 {
240+ // Check if we can extend the current mapping
241+ if should_extend_mapping ( & state, & original_file, generated_line, generated_column) {
242+ // Same source and line with adjacent columns - update end to next token position
243+ if let State :: InMapping {
244+ source,
245+ generated_line : current_line,
246+ start_column,
247+ ..
248+ } = state
249+ {
250+ state = State :: InMapping {
251+ source,
252+ generated_line : current_line,
253+ start_column,
254+ end_column : generated_column,
255+ } ;
256+ continue ;
257+ }
258+ }
259+
260+ // End the current mapping if we're in one
261+ if let State :: InMapping {
262+ source,
263+ generated_line : current_line,
264+ start_column,
265+ ..
266+ } = state
267+ {
268+ state = end_current_mapping (
269+ source,
270+ current_line,
271+ start_column,
272+ generated_line,
273+ generated_column,
274+ lines,
275+ & mut chunk_parts,
276+ lines_vc,
277+ ) ;
278+ }
279+
247280 // Start a new mapping and put the unaccounted part in between somewhere
281+ // Set end_column to start_column initially; it will be updated when we see the next
282+ // token
248283 match replace (
249284 & mut state,
250285 State :: InMapping {
251286 source : original_file. clone ( ) ,
252- current_generated_line : generated_line,
253- current_generated_column : generated_column,
287+ generated_line,
288+ start_column : generated_column,
289+ end_column : generated_column,
254290 } ,
255291 ) {
256292 State :: InMapping { .. } => {
257293 unreachable ! ( ) ;
258294 }
259295 State :: AfterMapping {
260296 source,
261- current_generated_line ,
297+ generated_line ,
262298 current_generated_column,
263299 } => {
264300 let len = len_between (
265- current_generated_line ,
301+ generated_line ,
266302 current_generated_column,
267303 generated_line,
268304 generated_column,
@@ -295,30 +331,21 @@ pub async fn split_output_asset_into_parts(
295331 // End the current token at end of file
296332 if let State :: InMapping {
297333 ref source,
298- current_generated_line,
299- current_generated_column,
334+ generated_line,
335+ start_column,
336+ ..
300337 } = state
301338 {
302- let mapping_end_column =
303- end_of_mapping_column ( current_generated_line, last_line, last_column, lines) ;
304- // TODO: Handle this better
305- let len = mapping_end_column. saturating_sub ( current_generated_column) ;
306- add_chunk_part_range (
339+ state = end_current_mapping (
307340 source. clone ( ) ,
308- ChunkPartRange {
309- line : current_generated_line,
310- start_column : current_generated_column,
311- end_column : mapping_end_column,
312- } ,
313- len,
341+ generated_line,
342+ start_column,
343+ last_line,
344+ last_column,
345+ lines,
314346 & mut chunk_parts,
315347 lines_vc,
316348 ) ;
317- state = State :: AfterMapping {
318- source : source. clone ( ) ,
319- current_generated_line,
320- current_generated_column : mapping_end_column,
321- } ;
322349 }
323350
324351 match state {
@@ -327,11 +354,11 @@ pub async fn split_output_asset_into_parts(
327354 }
328355 State :: AfterMapping {
329356 source,
330- current_generated_line ,
357+ generated_line ,
331358 current_generated_column,
332359 } => {
333360 let len = len_between (
334- current_generated_line ,
361+ generated_line ,
335362 current_generated_column,
336363 last_line,
337364 last_column,
0 commit comments