Skip to content
Closed
43 changes: 25 additions & 18 deletions src/bundler/Chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,8 @@ impl IntermediateOutput {
let additional_files = graph.input_files.items_additional_files();
let unique_key_for_additional_files =
graph.input_files.items_unique_key_for_additional_file();
let mut relative_platform_buf = bun_paths::path_buffer_pool::get();
let mut file_path_buf = bun_paths::path_buffer_pool::get();
let mut relative_spill: Vec<u8> = Vec::new();
let mut file_path_posix: Vec<u8> = Vec::new();
match self {
IntermediateOutput::Pieces(pieces) => {
let entry_point_chunks_for_scb = linker_graph.files.items_entry_point_chunk_index();
Expand Down Expand Up @@ -803,16 +803,25 @@ impl IntermediateOutput {
QueryKind::None => unreachable!(),
};

// Normalize exactly like the write pass below, so
// the counted and the written lengths agree.
Comment thread
robobun marked this conversation as resolved.
let file_path: &[u8] = {
file_path_posix.clear();
file_path_posix.extend_from_slice(file_path);
bun_paths::resolve_path::platform_to_posix_in_place::<u8>(
&mut file_path_posix,
);
&file_path_posix
};
let cheap_normalizer = cheap_prefix_normalizer(
import_prefix,
if use_outdir_relative_path {
file_path
} else {
bun_paths::resolve_path::relative_platform_buf::<
bun_paths::resolve_path::relative_platform_spill::<
bun_paths::platform::Posix,
false,
>(
&mut relative_platform_buf[..], from_chunk_dir, file_path
&mut relative_spill, from_chunk_dir, file_path
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
);
Expand Down Expand Up @@ -978,28 +987,26 @@ impl IntermediateOutput {
_ => unreachable!(),
};

// normalize windows paths to '/'
// The source slices are reachable only
// through `&Graph` / `&[Chunk]` here; materialising `&mut` from a
// shared-provenance pointer is UB regardless of whether the write
// happens. Copy into a pooled scratch buffer and normalise that.
// normalize windows paths to '/', in a scratch copy: the
// source slices are only reachable through `&Graph` /
// `&[Chunk]` here, so they cannot be normalized in place.
Comment thread
robobun marked this conversation as resolved.
let file_path: &[u8] = {
let n = file_path.len();
let dst = &mut file_path_buf[..n];
dst.copy_from_slice(file_path);
bun_paths::resolve_path::platform_to_posix_in_place::<u8>(dst);
dst
file_path_posix.clear();
file_path_posix.extend_from_slice(file_path);
bun_paths::resolve_path::platform_to_posix_in_place::<u8>(
&mut file_path_posix,
);
&file_path_posix
};
let cheap_normalizer = cheap_prefix_normalizer(
import_prefix,
if use_outdir_relative_path {
file_path
} else {
bun_paths::resolve_path::relative_platform_buf::<
bun_paths::resolve_path::relative_platform_spill::<
bun_paths::platform::Posix,
false,
>(
&mut relative_platform_buf[..], from_chunk_dir, file_path
&mut relative_spill, from_chunk_dir, file_path
)
},
);
Expand Down
9 changes: 6 additions & 3 deletions src/bundler/HTMLImportManifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use bun_collections::VecExt;
use bun_core::strings;
use bun_io::{FmtAdapter, Write};
use bun_js_printer::Encoding;
use bun_paths::resolve_path::relative_normalized;
use bun_paths::resolve_path::relative_normalized_spill;
use bun_resolver::fs::FileSystem;

use crate::Graph::Graph;
Expand Down Expand Up @@ -197,6 +197,7 @@ pub(crate) fn write<W: Write + ?Sized>(
// Use the server-side public path here.
let public_path: &[u8] = &options.public_path;
let mut temp_buffer: Vec<u8> = Vec::new();
let mut relative_spill: Vec<u8> = Vec::new();

for ch in chunks.iter() {
if ch.entry_point.source_index() == browser_source_index && ch.entry_point.is_entry_point()
Expand Down Expand Up @@ -253,7 +254,8 @@ pub(crate) fn write<W: Write + ?Sized>(
let input: &[u8] = if !ch.entry_point.is_entry_point() {
b""
} else {
let path_for_key = relative_normalized::<bun_paths::platform::Posix, false>(
let path_for_key = relative_normalized_spill::<bun_paths::platform::Posix>(
&mut relative_spill,
root_dir,
sources[ch.entry_point.source_index() as usize].path.text,
);
Expand Down Expand Up @@ -308,7 +310,8 @@ pub(crate) fn write<W: Write + ?Sized>(
}
first = false;

let path_for_key = relative_normalized::<bun_paths::platform::Posix, false>(
let path_for_key = relative_normalized_spill::<bun_paths::platform::Posix>(
&mut relative_spill,
root_dir,
sources[source_index.get() as usize].path.text,
);
Expand Down
8 changes: 5 additions & 3 deletions src/bundler/LinkerContext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2485,10 +2485,12 @@ impl<'a> LinkerContext<'a> {
let path = &parse_graph.additional_output_files
[*output_file_id as usize]
.dest_path;
hash.write(bun_paths::resolve_path::relative_platform::<
let mut spill = Vec::new();
hash.write(bun_paths::resolve_path::relative_platform_spill::<
bun_paths::resolve_path::platform::Posix,
false,
>(from_chunk_dir, path));
>(
&mut spill, from_chunk_dir, path
));
}
}
crate::chunk::QueryKind::Chunk => out.push(piece.query.index()),
Expand Down
93 changes: 41 additions & 52 deletions src/bundler/bundle_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2525,11 +2525,13 @@ pub mod bv2_impl {

if path.pretty.as_ptr() == path.text.as_ptr() {
// TODO: outbase
let rel = bun_paths::resolve_path::relative_platform::<
let mut spill = Vec::new();
let rel = bun_paths::resolve_path::relative_platform_spill::<
bun_paths::resolve_path::platform::Loose,
false,
>(
bun_resolver::fs::FileSystem::get().top_level_dir, path.text
&mut spill,
bun_resolver::fs::FileSystem::get().top_level_dir,
path.text,
Comment thread
robobun marked this conversation as resolved.
);
// SAFETY: arena outlives the bundle pass; raw-pointer detour erases the
// `&self` lifetime so the resulting `&'static [u8]` doesn't pin `self`.
Expand Down Expand Up @@ -4297,14 +4299,16 @@ pub mod bv2_impl {

let output_path: Box<[u8]> = {
// TODO: outbase
let pathname =
Fs::PathName::init(bun_paths::resolve_path::relative_platform::<
let mut spill = Vec::new();
let pathname = Fs::PathName::init(
bun_paths::resolve_path::relative_platform_spill::<
bun_paths::resolve_path::platform::Loose,
false,
>(
&mut spill,
&self.transpiler.options.root_dir,
source.path.text,
));
),
);

template.placeholder.name = pathname.base.to_vec().into_boxed_slice();
template.placeholder.dir = pathname.dir.to_vec().into_boxed_slice();
Expand Down Expand Up @@ -6566,12 +6570,6 @@ pub mod bv2_impl {
import_record.source_index = Index::INVALID;

if let Some(entry) = dev_server.is_file_cached(path.text, bake_graph) {
let rel = bun_paths::resolve_path::relative_platform::<
bun_paths::resolve_path::platform::Loose,
false,
>(
self.transpiler.fs().top_level_dir, path.text
);
if loader == Loader::Html && entry.kind == bake_types::CacheKind::Asset
{
// Overload `path.text` to point to the final URL
Expand All @@ -6597,8 +6595,6 @@ pub mod bv2_impl {
};
import_record.path.is_disabled = false;
} else {
import_record.path.text = path.text;
import_record.path.pretty = rel;
import_record.path = path_as_static(
&self
.path_with_pretty_initialized(path, target)
Expand Down Expand Up @@ -7687,9 +7683,6 @@ pub mod bv2_impl {
) -> crate::Result<bun_paths::fs::Path<'static>> {
use crate::bun_fs::PathResolverExt as _;
use crate::bun_node_fallbacks;
use bun_io::Write as _;

let mut buf = bun_paths::path_buffer_pool::get();

let is_node = path.namespace == b"node";
if is_node
Expand All @@ -7699,49 +7692,45 @@ pub mod bv2_impl {
return Ok(*path);
}

if path.is_file() || is_node {
let mut buf2 = bun_paths::path_buffer_pool::get();
let rel = bun_paths::resolve_path::relative_platform_buf::<
// `pretty` is a display path never handed to the filesystem, so it is
// not bounded by MAX_PATH_BYTES; `dupe_alloc_fix_pretty` copies it into `bump`.
Comment thread
robobun marked this conversation as resolved.
let ssr_prefix: &[u8] = if target == options::Target::ServerComponentsSsr {
b"ssr:"
} else {
b""
};
let mut spill = Vec::new();
let mut prefixed = Vec::new();
let mut path_clone: crate::bun_fs::Path<'_> = *path;
path_clone.pretty = if path.is_file() || is_node {
let rel = bun_paths::resolve_path::relative_platform_spill::<
bun_paths::resolve_path::platform::Loose,
false,
>(&mut **buf2, top_level_dir, path.text);
let mut path_clone: crate::bun_fs::Path<'_> = *path;
if target == options::Target::ServerComponentsSsr {
let mut fbs = bun_io::FixedBufferStream::new_mut(&mut buf.0[..]);
let _ = fbs.write_all(b"ssr:");
let _ = fbs.write_all(rel);
let written = fbs.pos;
path_clone.pretty = &buf.0[..written];
>(&mut spill, top_level_dir, path.text);
if ssr_prefix.is_empty() {
rel
} else {
path_clone.pretty = rel;
prefixed = [ssr_prefix, rel].concat();
&prefixed
}
path_clone.dupe_alloc_fix_pretty(bump).map_err(Into::into)
} else {
let mut path_clone: crate::bun_fs::Path<'_> = *path;
let mut fbs = bun_io::FixedBufferStream::new_mut(&mut buf.0[..]);
if target == options::Target::ServerComponentsSsr {
let _ = fbs.write_all(b"ssr:");
}
let _ = write_escaped_namespace(&mut fbs, path_clone.namespace);
let _ = fbs.write_all(b":");
let _ = fbs.write_all(path_clone.text);
let written = fbs.pos;
path_clone.pretty = &buf.0[..written];
path_clone.dupe_alloc_fix_pretty(bump).map_err(Into::into)
}
prefixed.reserve(ssr_prefix.len() + path.namespace.len() + 1 + path.text.len());
prefixed.extend_from_slice(ssr_prefix);
push_escaped_namespace(&mut prefixed, path.namespace);
prefixed.extend_from_slice(b":");
prefixed.extend_from_slice(path.text);
&prefixed
};
path_clone.dupe_alloc_fix_pretty(bump).map_err(Into::into)
}

fn write_escaped_namespace<W: bun_io::Write + ?Sized>(
w: &mut W,
slice: &[u8],
) -> bun_io::Result {
let mut rest = slice;
fn push_escaped_namespace(out: &mut Vec<u8>, namespace: &[u8]) {
let mut rest = namespace;
while let Some(i) = strings::index_of_char(rest, b':') {
w.write_all(&rest[..i as usize])?;
w.write_all(b"::")?;
out.extend_from_slice(&rest[..i as usize]);
out.extend_from_slice(b"::");
rest = &rest[i as usize + 1..];
}
w.write_all(rest)
out.extend_from_slice(rest);
}

#[repr(u8)]
Expand Down
9 changes: 3 additions & 6 deletions src/bundler/linker_context/generateChunksInParallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ pub(crate) fn generate_chunks_in_parallel<const IS_DEV_SERVER: bool>(
// so the sourceMappingURL resolves relative to the HTML
// file rather than a JS file next to the .map. Point at
// the .map path relative to the HTML chunk's directory.
let mut relative_platform_buf = path::path_buffer_pool::get();
let mut relative_spill: Vec<u8> = Vec::new();
let [a, b]: [&[u8]; 2] = if !c.options.public_path.is_empty() {
cheap_prefix_normalizer(
c.options.public_path,
Expand Down Expand Up @@ -743,13 +743,10 @@ pub(crate) fn generate_chunks_in_parallel<const IS_DEV_SERVER: bool>(
if html_dir.is_empty() {
&source_map_final_rel_path
} else {
path::resolve_path::relative_platform_buf::<
path::resolve_path::relative_platform_spill::<
path::platform::Posix,
false,
>(
&mut relative_platform_buf[..],
html_dir,
&source_map_final_rel_path,
&mut relative_spill, html_dir, &source_map_final_rel_path
)
},
)
Expand Down
16 changes: 11 additions & 5 deletions src/bundler/transpiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2631,7 +2631,10 @@ impl<'a> Transpiler<'a> {
return crate::linker::dupe(_entry);
}

let entry = fs.relative_to(entry);
let mut rel_spill = Vec::new();
let entry = bun_paths::resolve_path::relative_platform_spill::<
bun_paths::resolve_path::platform::Auto,
>(&mut rel_spill, fs.top_level_dir, entry);

if !strings::starts_with(entry, b"./") {
// Entry point paths without a leading "./" are interpreted as package
Expand Down Expand Up @@ -2898,7 +2901,10 @@ impl<'a> Transpiler<'a> {
let mut file_path = Fs::Path::init(file_path_text);

let top_level_dir = self.fs().top_level_dir;
let rel = bun_paths::resolve_path::relative(top_level_dir, file_path_text);
let mut rel_spill = Vec::new();
let rel = bun_paths::resolve_path::relative_platform_spill::<
bun_paths::resolve_path::platform::Auto,
>(&mut rel_spill, top_level_dir, file_path_text);
file_path.pretty = crate::linker::dupe(rel);

let mut output_file = options::OutputFile::zero_value();
Expand Down Expand Up @@ -3069,10 +3075,10 @@ impl<'a> Transpiler<'a> {
loader: options::Loader,
output: &[u8],
) -> Box<[u8]> {
let rel_to_root = bun_paths::resolve_path::relative_platform::<
let mut rel_spill = Vec::new();
let rel_to_root = bun_paths::resolve_path::relative_platform_spill::<
bun_paths::resolve_path::platform::Loose,
false,
>(&self.options.root_dir, file_path_text);
>(&mut rel_spill, &self.options.root_dir, file_path_text);
let pathname = Fs::PathName::init(rel_to_root);

let ext: &[u8] = if loader == options::Loader::Css {
Expand Down
Loading
Loading