Skip to content
Merged
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
1 change: 0 additions & 1 deletion mordant-baseline.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"bare_bool_args:src/ast/lib.rs" = 1

[bun_bundler]
"bare_bool_args:src/bundler/Chunk.rs" = 1
"defaulted_failure:src/bundler/bundle_v2.rs" = 2
"narrowed_two_ways:src/bundler/bundle_v2.rs" = 1

Expand Down
92 changes: 68 additions & 24 deletions src/bundler/Chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,52 @@ pub struct CodeResult {
pub(crate) shifts: Vec<source_map::SourceMapShifts>,
}

/// What the paths `code()` writes over a chunk's references to other outputs
/// are relative to. A public path makes them outdir-relative either way.
Comment thread
robobun marked this conversation as resolved.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ReferencePathStyle {
/// The directory of the chunk being emitted, as in esbuild.
ImporterRelative,
/// The outdir, wherever the emitting chunk lands (`bun build --compile`).
OutdirRelative,
}

impl ReferencePathStyle {
/// An executable loads every chunk from one virtual root, except for the
/// browser chunks a server build emits for its HTML imports: those are
/// served over HTTP.
Comment thread
robobun marked this conversation as resolved.
pub(crate) fn for_chunk(chunk: &Chunk, compile: bool) -> ReferencePathStyle {
if compile
&& !chunk
.flags
.contains(Flags::IS_BROWSER_CHUNK_FROM_SERVER_BUILD)
{
ReferencePathStyle::OutdirRelative
} else {
ReferencePathStyle::ImporterRelative
}
}
}

/// Whether `code()` records how far each path it writes moves the text after it
/// (`CodeResult::shifts`, which the chunk's source map is corrected with) and
/// appends the `//# debugId` comment. Only wanted for a chunk that gets a map.
Comment thread
robobun marked this conversation as resolved.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SourceMapShiftTracking {
Disabled,
Enabled,
}

impl SourceMapShiftTracking {
pub(crate) fn for_source_map(source_map: options::SourceMapOption) -> SourceMapShiftTracking {
if source_map == options::SourceMapOption::None {
SourceMapShiftTracking::Disabled
} else {
SourceMapShiftTracking::Enabled
}
}
}

// We don't need an allocator vtable here yet. `()` is kept as a token for the
// caller's `Option<&DynAlloc>` plumbing; the actual
// allocation goes through `alloc_buf` (global mimalloc) regardless. Real
Expand Down Expand Up @@ -549,35 +595,33 @@ impl IntermediateOutput {
// Accept both `&mut usize` and
// `Option<&mut usize>` so call sites spelled either way compile.
display_size: impl Into<Option<&'d mut usize>>,
force_absolute_path: bool,
enable_source_map_shifts: bool,
reference_path_style: ReferencePathStyle,
shift_tracking: SourceMapShiftTracking,
) -> Result<CodeResult, AllocError> {
let display_size: Option<&mut usize> = display_size.into();
// switch (enable_source_map_shifts) { inline else => |b| ... }
if enable_source_map_shifts {
self.code_with_source_map_shifts::<true>(
match shift_tracking {
SourceMapShiftTracking::Enabled => self.code_with_source_map_shifts::<true>(
allocator_to_use,
parse_graph,
linker_graph,
import_prefix,
chunk,
chunks,
display_size,
force_absolute_path,
reference_path_style,
None,
)
} else {
self.code_with_source_map_shifts::<false>(
),
SourceMapShiftTracking::Disabled => self.code_with_source_map_shifts::<false>(
allocator_to_use,
parse_graph,
linker_graph,
import_prefix,
chunk,
chunks,
display_size,
force_absolute_path,
reference_path_style,
None,
)
),
}
}

Expand All @@ -598,35 +642,34 @@ impl IntermediateOutput {
// Accept both `&mut usize` and
// `Option<&mut usize>` so call sites spelled either way compile.
display_size: impl Into<Option<&'d mut usize>>,
force_absolute_path: bool,
enable_source_map_shifts: bool,
reference_path_style: ReferencePathStyle,
shift_tracking: SourceMapShiftTracking,
standalone_chunk_contents: &[Option<Box<[u8]>>],
) -> Result<CodeResult, AllocError> {
let display_size: Option<&mut usize> = display_size.into();
if enable_source_map_shifts {
self.code_with_source_map_shifts::<true>(
match shift_tracking {
SourceMapShiftTracking::Enabled => self.code_with_source_map_shifts::<true>(
allocator_to_use,
parse_graph,
linker_graph,
import_prefix,
chunk,
chunks,
display_size,
force_absolute_path,
reference_path_style,
Some(standalone_chunk_contents),
)
} else {
self.code_with_source_map_shifts::<false>(
),
SourceMapShiftTracking::Disabled => self.code_with_source_map_shifts::<false>(
allocator_to_use,
parse_graph,
linker_graph,
import_prefix,
chunk,
chunks,
display_size,
force_absolute_path,
reference_path_style,
Some(standalone_chunk_contents),
)
),
}
}

Expand All @@ -641,7 +684,7 @@ impl IntermediateOutput {
chunk: &Chunk,
chunks: &[Chunk],
display_size: Option<&mut usize>,
force_absolute_path: bool,
reference_path_style: ReferencePathStyle,
standalone_chunk_contents: Option<&[Option<Box<[u8]>>]>,
) -> Result<CodeResult, AllocError> {
// `Graph.input_files` SoA accessors live in `Graph::InputFileColumns`;
Expand Down Expand Up @@ -682,8 +725,9 @@ impl IntermediateOutput {
// esbuild's `pathBetweenChunks`: with a public path configured, every
// reference is `publicPath + outdir-relative path`. Importer-relative
// paths would escape the prefix from chunks in subdirectories.
let use_outdir_relative_path =
from_chunk_dir.is_empty() || force_absolute_path || !import_prefix.is_empty();
let use_outdir_relative_path = from_chunk_dir.is_empty()
|| reference_path_style == ReferencePathStyle::OutdirRelative
|| !import_prefix.is_empty();

let urls_for_css: &[&[u8]] = if standalone_chunk_contents.is_some() {
graph.ast.items_url_for_css()
Expand Down
8 changes: 4 additions & 4 deletions src/bundler/linker_context/MetafileBuilder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use bun_ast::ExportsKind;
use bun_ast::ImportKind;
use bun_ast::ImportRecordFlags;

use crate::chunk::Content as ChunkContent;
use crate::chunk::{Content as ChunkContent, ReferencePathStyle, SourceMapShiftTracking};
use crate::options::Loader;
use crate::{Chunk, Index, LinkerContext};

Expand Down Expand Up @@ -446,9 +446,9 @@ pub(crate) fn generate(c: &mut LinkerContext, chunks: &mut [Chunk]) -> crate::Re
b"", // no import prefix for metafile
&chunks[0],
chunks,
None, // no display size
false, // not force absolute path
false, // no source map shifts
None, // no display size
ReferencePathStyle::ImporterRelative,
SourceMapShiftTracking::Disabled,
)?;

Ok(code_result.buffer)
Expand Down
26 changes: 11 additions & 15 deletions src/bundler/linker_context/generateChunksInParallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::Index;
use crate::analyze_transpiled_module;
use crate::analyze_transpiled_module::StringIDExt as _;
use crate::cheap_prefix_normalizer;
use crate::chunk::{ReferencePathStyle, SourceMapShiftTracking};
use crate::options;
use crate::options::Loader;

Expand Down Expand Up @@ -667,8 +668,8 @@ pub(crate) fn generate_chunks_in_parallel<const IS_DEV_SERVER: bool>(
&chunks[ci],
chunks,
&mut ds,
false,
sourcemap_option != SourceMapOption::None,
ReferencePathStyle::ImporterRelative,
SourceMapShiftTracking::for_source_map(sourcemap_option),
&scc,
)?;
chunks[ci].intermediate_output = intermediate_output;
Expand Down Expand Up @@ -899,29 +900,24 @@ pub(crate) fn generate_chunks_in_parallel<const IS_DEV_SERVER: bool>(
&chunks[chunk_index_in_chunks_list],
chunks,
&mut display_size,
false,
false,
ReferencePathStyle::ImporterRelative,
SourceMapShiftTracking::Disabled,
standalone_chunk_contents.as_deref().unwrap(),
)?
} else {
let force_abs = c.resolver().opts.compile
&& !chunks[chunk_index_in_chunks_list]
.flags
.contains(crate::chunk::Flags::IS_BROWSER_CHUNK_FROM_SERVER_BUILD);
let enable_sm = chunks[chunk_index_in_chunks_list]
.content
.sourcemap(c.options.source_maps)
!= SourceMapOption::None;
let chunk = &chunks[chunk_index_in_chunks_list];
intermediate_output.code(
None,
c.parse_graph(),
&c.graph,
public_path,
&chunks[chunk_index_in_chunks_list],
chunk,
chunks,
&mut display_size,
force_abs,
enable_sm,
ReferencePathStyle::for_chunk(chunk, c.resolver().opts.compile),
SourceMapShiftTracking::for_source_map(
chunk.content.sourcemap(c.options.source_maps),
),
)?
};
// Tail of the loop body needs `&mut chunk` (`output_source_map.finalize()`);
Expand Down
15 changes: 7 additions & 8 deletions src/bundler/linker_context/writeOutputFilesToDisk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bun_paths::{self as paths, PathBuffer};
use bun_wyhash::hash;

use crate::LinkerContext;
use crate::chunk::{Content, Flags as ChunkFlags};
use crate::chunk::{Content, Flags as ChunkFlags, ReferencePathStyle, SourceMapShiftTracking};
use crate::linker_context::output_file_list_builder::OutputFileList;
use crate::linker_context_mod::debug;
use crate::options::{self, Loader, OutputFile, SourceMapOption};
Expand Down Expand Up @@ -247,8 +247,8 @@ pub(crate) fn write_output_files_to_disk(
chunk,
chunks,
Some(&mut display_size),
false,
false,
ReferencePathStyle::ImporterRelative,
SourceMapShiftTracking::Disabled,
scc,
) {
Ok(r) => r,
Expand All @@ -265,11 +265,10 @@ pub(crate) fn write_output_files_to_disk(
chunk,
chunks,
Some(&mut display_size),
resolver_opts.compile
&& !chunk
.flags
.contains(ChunkFlags::IS_BROWSER_CHUNK_FROM_SERVER_BUILD),
chunk.content.sourcemap(c.options.source_maps) != SourceMapOption::None,
ReferencePathStyle::for_chunk(chunk, resolver_opts.compile),
SourceMapShiftTracking::for_source_map(
chunk.content.sourcemap(c.options.source_maps),
),
) {
Ok(r) => r,
Err(_e) => bun_core::Output::panic(format_args!(
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/bake/DevServer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4027,8 +4027,8 @@ pub(super) fn finalize_bundle(
// and `code()` only reads.
unsafe { ::core::slice::from_raw_parts(chunks_ptr, chunks_len) },
None,
false,
false,
bundler::chunk::ReferencePathStyle::ImporterRelative,
bundler::chunk::SourceMapShiftTracking::Disabled,
)?
};

Expand Down
6 changes: 6 additions & 0 deletions test/bake/dev/css.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ devTest("asset referenced in css", {
let backgroundImage = await c.style("body").backgroundImage;
assert(backgroundImage);
await dev.fetch(extractCssUrl(backgroundImage)).expectFile(imageFixtures.bun);
// The served stylesheet is the chunk with the asset reference resolved and
// nothing else: CSS never gets a source map, so no debugId trailer either.
const stylesheetHref = (await (await dev.fetch("/")).text()).match(/<link rel="stylesheet"[^>]*href="([^"]+)"/)![1];
const stylesheet = await (await dev.fetch(stylesheetHref)).text();
expect(stylesheet).toContain("background-image:");
expect(stylesheet).not.toContain("debugId");
await dev.write("bun.png", imageFixtures.bun2);
backgroundImage = await c.style("body").backgroundImage;
assert(backgroundImage);
Expand Down
Loading
Loading