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
4 changes: 1 addition & 3 deletions src/analytics/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,7 @@ pub mod features {
// attached to the single definition.
}

pub use features::{
Formatter as FeaturesFormatter, PACKED_FEATURES_LIST, PackedFeatures, packed_features,
};
pub use features::{PACKED_FEATURES_LIST, PackedFeatures, packed_features};

/// Enforced at the macro definition site; kept as a `const fn`
/// for documentation / debug assertions.
Expand Down
1 change: 0 additions & 1 deletion src/bundler/Graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ bun_collections::multi_array_columns! {
bitflags::bitflags! {
#[derive(Default, Clone, Copy, PartialEq, Eq)]
pub struct InputFileFlags: u8 {
const IS_PLUGIN_FILE = 1 << 0;
/// Set when a barrel-eligible file has `export * from` this file.
const IS_EXPORT_STAR_TARGET = 1 << 1;
}
Expand Down
1 change: 0 additions & 1 deletion src/bundler/ParseTask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ pub(crate) struct ResultError {
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Step {
Pending,
ReadFile,
Parse,
Resolve,
}
Expand Down
2 changes: 1 addition & 1 deletion src/bundler/ThreadPool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//!
//! `Worker::create` / `initialize_transpiler` build the per-worker
//! `Transpiler` via `Transpiler::for_worker` (per-field deep clone — no
//! bitwise struct copy); the `linker.resolver` backref is wired by
//! bitwise struct copy); the self-referential `linker` backrefs are wired by
//! `Transpiler::wire_after_move` once the value is at its final address.

use core::mem::{ManuallyDrop, MaybeUninit};
Expand Down
3 changes: 0 additions & 3 deletions src/bundler/bundle_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4351,8 +4351,6 @@ pub mod bv2_impl {
this.free_list.push(code.source_code);
std::borrow::Cow::Borrowed(source_code)
};
this.graph.input_files.items_flags_mut()[load.source_index.get() as usize]
.insert(crate::Graph::InputFileFlags::IS_PLUGIN_FILE);
let parse_task = load.parse_task_mut();
parse_task.loader = Some(code.loader);
parse_task.contents_or_fd = parse_task::ContentsOrFd::Contents(source_code);
Expand Down Expand Up @@ -7175,7 +7173,6 @@ pub mod bv2_impl {
} else {
let step_name = match err.step {
crate::parse_task::Step::Pending => "pending",
crate::parse_task::Step::ReadFile => "read_file",
crate::parse_task::Step::Parse => "parse",
crate::parse_task::Step::Resolve => "resolve",
};
Expand Down
44 changes: 2 additions & 42 deletions src/bundler/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::io::Write as _;

use bun_ast::Log;
use bun_ast::{ImportKind, ImportRecord, ImportRecordFlags, ImportRecordTag};
use bun_collections::HashMap;
use bun_paths::{self, SEP};
// two `fs` shapes are in play here. `bun_resolver::fs` (`Fs`) holds
// the singleton `FileSystem` / `DirnameStore`; `bun_paths::fs` (`PFs`) defines
Expand All @@ -13,8 +12,8 @@ use bun_paths::{self, SEP};
// `import_record.path` via `PFs::Path` so the field assignment unifies.
use bun_core::strings;
use bun_paths::fs as PFs;
use bun_resolver as resolver;
use bun_resolver::fs as Fs;
use bun_resolver::{self as resolver, Resolver};
use bun_sys::Fd;
use bun_url::URL;

Expand All @@ -24,12 +23,6 @@ use crate::transpiler::{
BunPluginTarget, ParseResult, PluginResolver, PluginRunner, ResolveQueue, ResolveResults,
};

type HashedFileNameMap = HashMap<u64, &'static [u8]>;

// Matches `Transpiler::IS_CACHE_ENABLED`; inlined so `get_hashed_filename`
// doesn't need a `Transpiler` handle.
const IS_CACHE_ENABLED: bool = false;

pub struct Linker {
// arena field dropped — global mimalloc (callers pass `bun.default_allocator`)
// `Transpiler` owns these values directly and also owns `linker:
Expand All @@ -41,9 +34,7 @@ pub struct Linker {
pub(crate) fs: *mut Fs::FileSystem,
pub log: *mut Log,
pub(crate) resolve_queue: *mut ResolveQueue,
pub resolver: *mut Resolver<'static>,
pub(crate) resolve_results: *mut ResolveResults,
pub(crate) hashed_filenames: HashedFileNameMap,

pub plugin_runner: Option<*mut dyn PluginResolver>,
}
Expand Down Expand Up @@ -237,7 +228,6 @@ impl Linker {
log: *mut Log,
resolve_queue: *mut ResolveQueue,
options: *mut BundleOptions<'static>,
resolver: *mut Resolver<'static>,
resolve_results: *mut ResolveResults,
fs: *mut Fs::FileSystem,
) -> Self {
Expand All @@ -249,9 +239,7 @@ impl Linker {
fs,
log,
resolve_queue,
resolver,
resolve_results,
hashed_filenames: HashedFileNameMap::default(),
plugin_runner: None,
}
}
Expand All @@ -266,14 +254,12 @@ impl Linker {
log: *mut Log,
resolve_queue: *mut ResolveQueue,
options: *mut BundleOptions<'static>,
resolver: *mut Resolver<'static>,
resolve_results: *mut ResolveResults,
fs: *mut Fs::FileSystem,
) {
self.log = log;
self.resolve_queue = resolve_queue;
self.options = options;
self.resolver = resolver;
self.resolve_results = resolve_results;
self.fs = fs;
}
Expand Down Expand Up @@ -318,35 +304,9 @@ impl Linker {
file_path: &PFs::Path<'_>,
fd: Option<Fd>,
) -> crate::Result<&'static [u8]> {
if IS_CACHE_ENABLED {
let hashed = bun_wyhash::hash(file_path.text);
if let Some(v) = self.hashed_filenames.get(&hashed) {
return Ok(*v);
}
}

let modkey = self.get_mod_key(file_path, fd)?;
// `ModKey::hash_name` writes into a caller-supplied buffer (1 KiB)
// and returns a borrow of it; `dupe` copies the bytes into the
// process-lifetime interner to satisfy this fn's `'static` return.
// Note: `IS_CACHE_ENABLED` is a hard `const false` (see above), so
// the `hashed_filenames` cache never dedups — every call interns a
// fresh copy for the life of the process. Accepted: the `'static`
// return contract forces a copy anyway, and the alternative (the old
// threadlocal slice return) was unsound. `dupe` also aborts on OOM
// where the old path propagated `?` — consistent with the
// `bun.handleOom` idiom for interner allocations.
// Spec passes `file_path.text` even though the param is named
// `basename`; preserved verbatim.
let mut hash_name_buf = [0u8; 1024];
let hash_name = dupe(modkey.hash_name(file_path.text, &mut hash_name_buf)?);

if IS_CACHE_ENABLED {
let hashed = bun_wyhash::hash(file_path.text);
self.hashed_filenames.insert(hashed, hash_name);
}

Ok(hash_name)
Ok(dupe(modkey.hash_name(file_path.text, &mut hash_name_buf)?))
}

/// This modifies the Ast in-place! It resolves import records and
Expand Down
8 changes: 0 additions & 8 deletions src/bundler/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1529,14 +1529,6 @@ impl<'a> BundleOptions<'a> {
b"react-refresh",
];

#[inline]
pub(crate) fn css_import_behavior(&self) -> api::CssInJsBehavior {
match self.target {
Target::Browser => api::CssInJsBehavior::AutoOnimportcss,
_ => api::CssInJsBehavior::Facade,
}
}

pub(crate) fn load_defines(
&mut self,
arena: &bun_alloc::Arena,
Expand Down
29 changes: 6 additions & 23 deletions src/bundler/transpiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,6 @@ impl<'a> Transpiler<'a> {
core::ptr::null_mut(),
core::ptr::null_mut(),
core::ptr::null_mut(),
core::ptr::null_mut(),
from.fs,
),
env: from.env,
Expand All @@ -378,7 +377,6 @@ impl<'a> Transpiler<'a> {
log,
core::ptr::addr_of_mut!(self.resolve_queue),
core::ptr::addr_of_mut!(self.options).cast(),
core::ptr::addr_of_mut!(self.resolver).cast(),
core::ptr::addr_of_mut!(*self.resolve_results),
self.fs,
);
Expand Down Expand Up @@ -669,22 +667,15 @@ impl<'a> Transpiler<'a> {
/// Initialize `self.linker` with back-pointers into this `Transpiler`,
/// optionally auto-configuring JSX from the nearest `tsconfig.json`.
pub fn configure_linker_with_auto_jsx(&mut self, auto_jsx: bool) {
// `Linker::init` dropped its `arena` arg (linker.rs:172
// — global mimalloc). `crate::linker::Linker` stores raw pointers
// so `&mut self.options` etc. coerce directly. Self-reference is
// load-bearing — `linker.link()` reads back through these into the
// owning `Transpiler` — hence raw `*mut`, not `&'a mut` (would alias
// `&mut self` on every call).
// `.cast()` on the `options`/`resolver` pointers erases the
// `<'a>` lifetime parameter — `Linker` stores them as
// `*mut BundleOptions` / `*mut Resolver` with an (implicit) distinct
// lifetime. The linker never
// outlives its owning `Transpiler<'a>`.
// `crate::linker::Linker` stores raw back-pointers into the owning
// `Transpiler`; `linker.link()` reads back through them, so they are
// `*mut` (a `&'a mut` would alias `&mut self` on every call). The
// `.cast()` on `options` erases `<'a>` to the `'static` the field is
// typed at; the linker never outlives its owning `Transpiler<'a>`.
Comment thread
robobun marked this conversation as resolved.
self.linker = crate::linker::Linker::init(
self.log,
core::ptr::addr_of_mut!(self.resolve_queue),
core::ptr::addr_of_mut!(self.options).cast(),
core::ptr::addr_of_mut!(self.resolver).cast(),
core::ptr::addr_of_mut!(*self.resolve_results),
self.fs,
);
Expand Down Expand Up @@ -1267,10 +1258,7 @@ impl<'a> Transpiler<'a> {
// Construct directly into the caller-owned storage instead of building a
// stack temporary and returning it. All fallible work is done; every
// field below is written exactly once. `Linker::init` gets null
// back-pointers — `core::mem::zeroed()` is NOT a
// valid analogue (`Linker.hashed_filenames: HashMap` carries a `NonNull`
// niche, so all-zeroes is instant UB); the value fields get their proper
// defaults and `configure_linker_with_auto_jsx` overwrites the
// back-pointers; `configure_linker_with_auto_jsx` overwrites the
// self-referential pointers before any deref.
let p = dst.as_mut_ptr();
// SAFETY: `dst` is an exclusively-borrowed, currently-uninitialised
Expand Down Expand Up @@ -1300,7 +1288,6 @@ impl<'a> Transpiler<'a> {
core::ptr::null_mut(),
core::ptr::null_mut(),
core::ptr::null_mut(),
core::ptr::null_mut(),
fs,
));
core::ptr::addr_of_mut!((*p).env).write(env_loader);
Expand Down Expand Up @@ -2397,12 +2384,10 @@ impl<'a> Transpiler<'a> {
let opts = js_printer::Options {
bundling: false,
require_ref: Some(ast.require_ref),
css_import_behavior: self.options.css_import_behavior(),
source_map_handler: source_map_context,
minify_whitespace: self.options.minify_whitespace,
minify_syntax: self.options.minify_syntax,
minify_identifiers: self.options.minify_identifiers,
transform_only: self.options.transform_only,
import_meta_ref: ast.import_meta_ref,
print_dce_annotations: self.options.emit_dce_annotations,
runtime_transpiler_cache,
Expand Down Expand Up @@ -2476,12 +2461,10 @@ impl<'a> Transpiler<'a> {
let opts = js_printer::Options {
bundling: false,
require_ref: Some(ast.require_ref),
css_import_behavior: self.options.css_import_behavior(),
source_map_handler: source_map_context,
minify_whitespace: self.options.minify_whitespace,
minify_syntax: self.options.minify_syntax,
minify_identifiers: self.options.minify_identifiers,
transform_only: self.options.transform_only,
module_type: if IS_BUN && self.options.transform_only {
// this is for when using `bun build --no-bundle`
// it should copy what was passed for the cli
Expand Down
32 changes: 2 additions & 30 deletions src/js_parser/p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ pub struct P<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> {
pub(crate) top_level_await_keyword: bun_ast::Range,
pub(crate) fn_or_arrow_data_parse: FnOrArrowDataParse,
pub(crate) fn_or_arrow_data_visit: FnOrArrowDataVisit,
pub(crate) fn_only_data_visit: FnOnlyDataVisit<'a>,
pub(crate) fn_only_data_visit: FnOnlyDataVisit,
pub(crate) allocated_names: List<'a, &'a [u8]>,
// allocated_names: ListManaged(string) = ListManaged(string).init(bun.default_allocator),
// allocated_names_pool: ?*AllocatedNamesPool.Node = null,
Expand Down Expand Up @@ -4313,11 +4313,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
r: bun_ast::Range,
detail: &[u8],
) -> Result<(), crate::Error> {
let can_be_transformed = feature == StrictModeFeature::ForInVarInit;
let text: &'a [u8] = match feature {
StrictModeFeature::WithStatement => b"With statements",
StrictModeFeature::DeleteBareName => b"\"delete\" of a bare identifier",
StrictModeFeature::ForInVarInit => b"Variable initializers within for-in loops",
StrictModeFeature::EvalOrArguments => bun_alloc::arena_format!(
in self.arena,
"Declarations with the name \"{}\"",
Expand All @@ -4332,9 +4328,6 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
)
.into_bump_str()
.as_bytes(),
StrictModeFeature::LegacyOctalLiteral => b"Legacy octal literals",
StrictModeFeature::LegacyOctalEscape => b"Legacy octal escape sequences",
StrictModeFeature::IfElseFunctionStmt => b"Function declarations inside if statements",
};

let scope = self.current_scope();
Expand Down Expand Up @@ -4375,7 +4368,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
notes,
format_args!("{} cannot be used in strict mode", bstr::BStr::new(text)),
);
} else if !can_be_transformed && self.is_strict_mode_output_format() {
} else if self.is_strict_mode_output_format() {
self.log().add_range_error_fmt(
Some(self.source),
r,
Expand Down Expand Up @@ -5239,27 +5232,6 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
}

pub(crate) fn value_for_this(&mut self, loc: bun_ast::Loc) -> Option<Expr> {
// Substitute "this" if we're inside a static class property initializer
if self
.fn_only_data_visit
.should_replace_this_with_class_name_ref
{
// class_name_ref is `Option<&'a Cell<Ref>>` (arena slot owned by the enclosing
// `visit_class` frame); copy the Ref out so the field borrow is released before
// record_usage/new_expr.
if let Some(r) = self.fn_only_data_visit.class_name_ref.map(|c| c.get()) {
self.record_usage(r);
return Some(self.new_expr(
E::Identifier {
ref_: r,
..Default::default()
},
loc,
));
}
}

// oroigianlly was !=- modepassthrough
if !self.fn_only_data_visit.is_this_nested {
// In the REPL, top-level `this` must evaluate to the global object
// (matching Node's `> this` and `deno repl > this`). The REPL wraps
Expand Down
28 changes: 1 addition & 27 deletions src/js_parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,14 +1173,8 @@ pub struct ParsedPath<'a> {

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum StrictModeFeature {
WithStatement,
DeleteBareName,
ForInVarInit,
EvalOrArguments,
ReservedWord,
LegacyOctalLiteral,
LegacyOctalEscape,
IfElseFunctionStmt,
}

#[derive(Clone, Copy)]
Expand Down Expand Up @@ -1386,27 +1380,7 @@ pub struct FnOrArrowDataVisit {
/// restored on the call stack around code that parses nested functions (but not
/// nested arrow functions).
#[derive(Default)]
pub struct FnOnlyDataVisit<'a> {
/// This is a reference to the enclosing class name if there is one. It's used
/// to implement "this" and "super" references. A name is automatically generated
/// if one is missing so this will always be present inside a class body.
///
/// `&Cell<Ref>` (not `&mut Ref`): the visit pass needs to
/// both share this slot into nested `fn_only_data_visit` frames *and* read/write
/// it from the enclosing `visit_class` frame. `Cell` gives shared interior
/// mutability for the `Copy` `Ref` payload with zero `unsafe`.
pub(crate) class_name_ref: Option<&'a core::cell::Cell<Ref>>,

/// If true, we're inside a static class context where "this" expressions
/// should be replaced with the class name.
pub(crate) should_replace_this_with_class_name_ref: bool,

/// If we're inside an async arrow function and async functions are not
/// supported, then we will have to convert that arrow function to a generator
/// function. That means references to "arguments" inside the arrow function
/// will have to reference a captured variable instead of the real variable.
pub(crate) is_inside_async_arrow_fn: bool,

pub struct FnOnlyDataVisit {
/// If false, the value for "this" is the top-level module scope "this" value.
/// That means it's "undefined" for ECMAScript modules and "exports" for
/// CommonJS modules. We track this information so that we can substitute the
Expand Down
Loading
Loading