Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/bundler/linker_context/MetafileBuilder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,9 @@ pub(crate) fn generate(c: &mut LinkerContext, chunks: &mut [Chunk]) -> crate::Re
}
}

// Write inputs
let mut source_index: u32 = 0;
while (source_index as usize) < sources.len() {
// (defer-style increment moved to end of loop body)
let si = source_index;
source_index += 1;
let source_index = si;
// Write inputs in `reachable_files` order, as esbuild does: source indices are random.
for source_index in c.graph.reachable_files.slice() {
let source_index = source_index.get();

if !seen_sources.is_set(source_index as usize) {
continue;
Expand Down Expand Up @@ -421,6 +417,17 @@ pub(crate) fn generate(c: &mut LinkerContext, chunks: &mut [Chunk]) -> crate::Re
j.push_static(b"\n }");
}

if cfg!(debug_assertions) {
for source_index in c.graph.reachable_files.slice() {
seen_sources.unset(source_index.get() as usize);
}
debug_assert_eq!(
seen_sources.count(),
0,
"a chunk holds a file that is not in reachable_files"
);
}

j.push_static(b"\n },\n \"outputs\": {");

let mut first_output = true;
Expand Down
23 changes: 7 additions & 16 deletions src/bundler/linker_context/computeChunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,7 @@ pub(crate) fn compute_chunks<'a>(
}
}

// Sort the chunks for determinism. This matters because we use chunk indices
// as sorting keys in a few places.
// Order the chunks for determinism: a chunk index is a sort key and a hash input in a few places.
let mut sorted_chunks: Vec<Chunk> = 'sort_chunks: {
let mut sorted_chunks = Vec::<Chunk>::init_capacity(
js_chunks.count() + css_chunks.count() + html_chunks.count(),
Expand Down Expand Up @@ -512,22 +511,14 @@ pub(crate) fn compute_chunks<'a>(
}

if css_chunks.count() > 0 {
let sorted_css_keys: &mut [u64] = temp.alloc_slice_copy(css_chunks.keys());
index_sort::sort_slice_unstable_by(sorted_css_keys, |a, b| a.cmp(b));

// A map from the index in `css_chunks` to it's final index in `sorted_chunks`
let remapped_css_indexes: &mut [u32] =
temp.alloc_slice_fill_copy(css_chunks.count(), 0u32);

// Use sorted_chunks.len as the starting index because HTML chunks
// may be interleaved with JS chunks, so js_chunks.count() would be
// incorrect when HTML entry points are present.
for (sorted_index, &key) in (sorted_chunks.len() as usize..).zip(sorted_css_keys.iter())
{
let index = css_chunks.get_index(&key).expect("unreachable");
let owned = core::mem::take(&mut css_chunks.values_mut()[index]);
sorted_chunks.append_assume_capacity(owned);
remapped_css_indexes[index] = u32::try_from(sorted_index).expect("int cast");
let first_css_chunk = u32::try_from(sorted_chunks.len()).expect("int cast");

// CSS chunks keep entry point order, the insertion order of `css_chunks`: a key is a hash, not an order.
for css_chunk in css_chunks.values_mut() {
sorted_chunks.append_assume_capacity(core::mem::take(css_chunk));
}

// Update all affected JS chunks to point at the correct CSS chunk index.
Expand All @@ -536,7 +527,7 @@ pub(crate) fn compute_chunks<'a>(
&mut sorted_chunks.slice_mut()[js_index as usize].content
{
for idx in js.css_chunks.iter_mut() {
*idx = remapped_css_indexes[*idx as usize];
*idx += first_css_chunk;
}
}
}
Expand Down
Loading
Loading