From f02087a1523e64ad588c4d3071307b2b6a415c4c Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Fri, 28 Aug 2026 03:36:33 +0000 Subject: [PATCH 1/6] Remove dead code from bun_css, bun_react_compiler, bun_jsc, and smaller crates Delete code that nothing reaches. The workspace denies dead_code, but these items are pub, trait impls, write-only fields, or branches behind an option that no caller sets. bun_css: the CSS-modules export and reference tables, Config.dashed_idents, DashedIdentReference.from, Pattern::write_to_string*, Segment::Name, the analyze_dependencies printer option with Dependency, ImportDependency, UrlDependency, DependencyOptions, Printer.{dependencies,remove_imports}, Printer::get_import_records, Url::is_absolute, and PrinterErrorKind::ambiguous_url_in_custom_property. bun_react_compiler: the logger event types (LoggerEvent, OrderedLogItem, DebugLogEntry, CompilerErrorDetailInfo, LoggerSuggestionInfo, LoggerSuggestionOp, CompilerErrorItemInfo, LoggerSourceLocation, LoggerPosition), the events, ordered_log and renames fields of CompileOutput with their producers, count_memo_blocks, the logged_severity methods, and never-constructed enum variants. Smaller crates: RefCounted::debug_name and its macro key, HasLength impls for [u8], &str and &String, the unused tcc Error and OutputFormat variants, the unused to_*_error_instance helpers in bun_jsc, WeakRefType::PostgreSQLQueryClient, five RedisError variants with their four ERR_REDIS_INVALID_* codes, IntoOptionalData for &mut Data, the notImplementedIssue codegen rule, and 54 stale declarations in src/js/builtins.d.ts. Add a source lint that pins the module-level #![allow(dead_code)] and dead-code analysis is a deliberate change. --- src/CLAUDE.md | 2 +- src/bun_core/comptime_string_map.rs | 21 -- src/bun_core_macros/lib.rs | 23 +- src/codegen/replacements.ts | 4 - src/css/css_modules.rs | 287 +----------------- src/css/css_parser.rs | 41 +-- src/css/dependencies.rs | 71 +---- src/css/error.rs | 10 - src/css/lib.rs | 2 - src/css/printer.rs | 160 ++-------- src/css/properties/animation.rs | 19 -- src/css/properties/background.rs | 2 - src/css/properties/css_modules.rs | 21 -- src/css/properties/custom.rs | 69 +---- src/css/properties/masking.rs | 6 - src/css/rules/import.rs | 24 +- src/css/rules/mod.rs | 24 -- src/css/values/ident.rs | 82 +---- src/css/values/image.rs | 35 +-- src/css/values/url.rs | 73 ----- src/js/builtins.d.ts | 54 ---- src/js_parser/react_compiler_host.rs | 1 - src/jsc/EncodedSlice.rs | 8 - src/jsc/Weak.rs | 1 - src/jsc/bindings/ErrorCode.ts | 4 - src/jsc/bindings/Weak.cpp | 10 +- src/jsc/bun_string_jsc.rs | 8 - src/ptr/ref_count.rs | 32 -- src/react_compiler/codegen.rs | 82 ----- src/react_compiler/collections.rs | 22 -- src/react_compiler/compile_result.rs | 185 +---------- src/react_compiler/diagnostics/mod.rs | 37 +-- src/react_compiler/hir/environment.rs | 14 - src/react_compiler/hir/reactive.rs | 10 - src/react_compiler/hir/type_config.rs | 1 - src/react_compiler/imports.rs | 4 - src/react_compiler/lowering/hir_builder.rs | 11 - src/react_compiler/pipeline.rs | 11 +- src/react_compiler/program.rs | 26 +- .../bun/subprocess/SubprocessPipeReader.rs | 1 - src/runtime/api/js_bundle_completion_task.rs | 1 - src/runtime/server/HTMLBundle.rs | 2 - src/runtime/valkey_jsc/protocol_jsc.rs | 5 - src/sql_jsc/shared/SQLDataCell.rs | 8 +- src/tcc_sys/tcc.rs | 21 -- src/valkey/valkey_protocol.rs | 5 - .../source-lints/module-lint-escapes.json | 20 ++ .../source-lints/module-lint-escapes.test.ts | 100 ++++++ 48 files changed, 189 insertions(+), 1471 deletions(-) create mode 100644 test/internal/source-lints/module-lint-escapes.json create mode 100644 test/internal/source-lints/module-lint-escapes.test.ts diff --git a/src/CLAUDE.md b/src/CLAUDE.md index 07f756cdb786..2ed935850b71 100644 --- a/src/CLAUDE.md +++ b/src/CLAUDE.md @@ -138,7 +138,7 @@ ASCII literals / `&'static` ASCII tables, bytes already validated as ASCII, or bytes that really are Latin-1; `utf16(units)`. `String::to_encoded_slice()` borrows any `String` as one; `EncodedSlice::to_utf8() -> Utf8Bytes<'a>`; `bun_jsc::EncodedSliceJsc` adds -`to_js`, `to_{,type_,range_,syntax_}error_instance`, `to_json_object`, and +`to_js`, `to_{,syntax_}error_instance`, `to_json_object`, and `to_external_value` / `external` (hand a globally-allocated buffer to JSC). Bytes → JS string: `bun_string_jsc::create_utf8_for_js(global, bytes)?` diff --git a/src/bun_core/comptime_string_map.rs b/src/bun_core/comptime_string_map.rs index 4eed3362f804..803a2654a76b 100644 --- a/src/bun_core/comptime_string_map.rs +++ b/src/bun_core/comptime_string_map.rs @@ -44,13 +44,6 @@ pub trait HasLength { fn length(&self) -> usize; } -impl HasLength for [u8] { - #[inline] - fn length(&self) -> usize { - self.len() - } -} - impl HasLength for &[u8] { #[inline] fn length(&self) -> usize { @@ -58,20 +51,6 @@ impl HasLength for &[u8] { } } -impl HasLength for &str { - #[inline] - fn length(&self) -> usize { - self.len() - } -} - -impl HasLength for &crate::String { - #[inline] - fn length(&self) -> usize { - crate::String::length(self) - } -} - /// Lookup for large maps, which store their keys as data instead of as an /// inlined compare tree: keys are sorted by `(len, bytes)` and concatenated /// into `blob`; `buckets[len]` is `(blob offset, first sorted position)` of diff --git a/src/bun_core_macros/lib.rs b/src/bun_core_macros/lib.rs index 352a3c61f11b..d22b0800c509 100644 --- a/src/bun_core_macros/lib.rs +++ b/src/bun_core_macros/lib.rs @@ -467,7 +467,6 @@ pub fn derive_thread_safe_ref_counted(input: TokenStream) -> TokenStream { // Struct-level attribute: // #[ref_count(destroy = )] — `unsafe fn(*mut Self)`; default is // `drop(::bun_core::heap::take(this))` -// #[ref_count(debug_name = "Name")] — overrides `RefCounted::debug_name()` // // Field selection follows the shared `find_ref_count_field` rules (a // `#[ref_count]`-annotated field, else a field literally named `ref_count`). @@ -478,13 +477,9 @@ pub fn derive_thread_safe_ref_counted(input: TokenStream) -> TokenStream { // migrated structs keep their own bespoke `ref_`/`r#ref`/`deref` thin // wrappers — emitting inherent fns here would collide. -/// Parse the struct-level `#[ref_count(destroy = …, debug_name = "…")]` -/// attribute (both keys optional, either order). -fn parse_ref_count_attrs( - attrs: &[syn::Attribute], -) -> Result<(Option, Option), syn::Error> { +/// Parse the struct-level `#[ref_count(destroy = …)]` attribute (optional). +fn parse_ref_count_attrs(attrs: &[syn::Attribute]) -> Result, syn::Error> { let mut destroy = None; - let mut debug_name = None; for a in attrs { if !a.path().is_ident("ref_count") { continue; @@ -494,16 +489,13 @@ fn parse_ref_count_attrs( if meta.path.is_ident("destroy") { destroy = Some(meta.value()?.parse::()?); Ok(()) - } else if meta.path.is_ident("debug_name") { - debug_name = Some(meta.value()?.parse::()?); - Ok(()) } else { Err(meta.error("unknown ref_count attribute key")) } })?; } } - Ok((destroy, debug_name)) + Ok(destroy) } /// `#[derive(RefCounted)]` — see module comment above. @@ -526,7 +518,7 @@ pub fn derive_ref_counted(input: TokenStream) -> TokenStream { Ok(f) => f, Err(e) => return e.to_compile_error().into(), }; - let (destroy, debug_name) = match parse_ref_count_attrs(&input.attrs) { + let destroy = match parse_ref_count_attrs(&input.attrs) { Ok(v) => v, Err(e) => return e.to_compile_error().into(), }; @@ -544,16 +536,9 @@ pub fn derive_ref_counted(input: TokenStream) -> TokenStream { drop(unsafe { ::bun_core::heap::take(this) }); }, }; - let debug_name_impl = debug_name.map(|lit| { - quote! { - #[inline] - fn debug_name() -> &'static str { #lit } - } - }); quote! { impl #impl_g ::bun_ptr::RefCounted for #name #ty_g #where_g { - #debug_name_impl #[inline] unsafe fn get_ref_count(this: *mut Self) -> *mut ::bun_ptr::RefCount { // SAFETY: caller contract — `this` points to a live Self. diff --git a/src/codegen/replacements.ts b/src/codegen/replacements.ts index 3aaf4f3132c0..c41eccba4410 100644 --- a/src/codegen/replacements.ts +++ b/src/codegen/replacements.ts @@ -40,10 +40,6 @@ for (let id = 0; id < jsclasses.length; id++) { // These rules are run on the entire file, including within strings. export const globalReplacements: ReplacementRule[] = [ - { - from: /\bnotImplementedIssue\(\s*([0-9]+)\s*,\s*((?:"[^"]*"|'[^']+'))\s*\)/g, - toRaw: "__intrinsic__makeTypeError(`${$2} is not implemented yet. See https://github.com/oven-sh/bun/issues/$1`)", - }, { from: /\bnotImplementedIssueFn\(\s*([0-9]+)\s*,\s*((?:"[^"]*"|'[^']+'))\s*\)/g, toRaw: diff --git a/src/css/css_modules.rs b/src/css/css_modules.rs index 314c1e569e9e..02a8982c9c71 100644 --- a/src/css/css_modules.rs +++ b/src/css/css_modules.rs @@ -1,21 +1,13 @@ use core::fmt::Arguments; use bun_alloc::Arena as Bump; -use bun_alloc::{ArenaVec as BumpVec, ArenaVecExt as _}; -use bun_collections::ArrayHashMap; +use bun_alloc::ArenaVec as BumpVec; use crate as css; -// ───────────────────────────────────────────────────────────────────────── -// `reference_dashed`'s `dest.importRecord()` lookup is hoisted to the caller (see the comment -// on the method) to satisfy Rust borrowck (caller holds `&mut dest.css_module`). -// ───────────────────────────────────────────────────────────────────────── pub struct CssModule<'a> { pub(crate) config: &'a Config, - pub(crate) sources: &'a Vec>, pub(crate) hashes: BumpVec<'a, &'a [u8]>, - pub(crate) exports_by_source_index: BumpVec<'a, CssModuleExports<'a>>, - pub(crate) references: &'a mut CssModuleReferences<'a>, } impl<'a> CssModule<'a> { @@ -24,7 +16,6 @@ impl<'a> CssModule<'a> { config: &'a Config, sources: &'a Vec>, project_root: Option<&[u8]>, - references: &'a mut CssModuleReferences<'a>, ) -> CssModule<'a> { // TODO: this is BAAAAAAAAAAD we are going to remove it let hashes = 'hashes: { @@ -53,122 +44,7 @@ impl<'a> CssModule<'a> { } break 'hashes hashes; }; - let exports_by_source_index = 'exports_by_source_index: { - let mut exports_by_source_index = BumpVec::with_capacity_in(sources.len(), bump); - for _ in 0..sources.len() { - exports_by_source_index.push(CssModuleExports::default()); - } - break 'exports_by_source_index exports_by_source_index; - }; - CssModule { - config, - sources, - references, - hashes, - exports_by_source_index, - } - } - - pub(crate) fn get_reference(&mut self, bump: &'a Bump, name: &'a [u8], source_index: u32) { - // bun_collections::ArrayHashMap::get_or_put requires `V: Default` - // (CssModuleExport can't be Default — BumpVec field), so use the - // entry()-API instead. - use bun_collections::array_hash_map::MapEntry; - match self.exports_by_source_index[source_index as usize].entry(name) { - MapEntry::Occupied(mut o) => { - o.get_mut().is_referenced = true; - } - MapEntry::Vacant(v) => { - v.insert(CssModuleExport { - name: self.config.pattern.write_to_string( - bump, - BumpVec::new_in(bump), - self.hashes[source_index as usize], - self.sources[source_index as usize].as_ref(), - name, - ), - is_referenced: true, - }); - } - } - } - - // This does not take `&mut Printer`: the only - // caller (`DashedIdentReference::to_css`) already holds a `&mut` borrow of - // `dest.css_module` (which *is* `self`), so threading `&mut Printer` in - // here would alias. The caller pre-resolves the import-record path and - // hands it down as `specifier_path`; the fallible `importRecord` lookup - // therefore lives at the call site, which is why this no longer returns - // `Result<_, PrintErr>`. - pub(crate) fn reference_dashed( - &mut self, - bump: &'a Bump, - name: &'a [u8], - from: Option, - specifier_path: Option<&'a [u8]>, - source_index: u32, - ) -> Option<&'a [u8]> { - use css::css_properties::css_modules::Specifier; - let (reference, key): (CssModuleReference<'a>, &'a [u8]) = match from { - Some(Specifier::Global) => return Some(&name[2..]), - Some(Specifier::ImportRecordIndex(_)) => { - let path = specifier_path - .expect("specifier_path required for Specifier::ImportRecordIndex"); - ( - CssModuleReference::Dependency { - name: &name[2..], - specifier: path, - }, - path, - ) - } - None => { - // Local export. Mark as used. - // `CssModuleExport` cannot be `Default` (BumpVec field), - // so use the `entry()` API like `get_reference` above. - use bun_collections::array_hash_map::MapEntry; - match self.exports_by_source_index[source_index as usize].entry(name) { - MapEntry::Occupied(mut o) => { - o.get_mut().is_referenced = true; - } - MapEntry::Vacant(v) => { - let mut res = BumpVec::new_in(bump); - res.extend_from_slice(b"--"); - v.insert(CssModuleExport { - name: self.config.pattern.write_to_string( - bump, - res, - self.hashes[source_index as usize], - self.sources[source_index as usize].as_ref(), - &name[2..], - ), - is_referenced: true, - }); - } - } - return None; - } - }; - - let the_hash = hash( - bump, - format_args!( - "{}_{}_{}", - bstr::BStr::new(self.hashes[source_index as usize]), - bstr::BStr::new(name), - bstr::BStr::new(key) - ), - false, - ); - - // Build `--{the_hash}` as a bump Vec — a plain concat - // (`bumpalo::Vec` lacks `io::Write`, and no formatting is needed). - let mut k = BumpVec::with_capacity_in(2 + the_hash.len(), bump); - k.extend_from_slice(b"--"); - k.extend_from_slice(the_hash); - let _ = self.references.put(k.into_bump_slice(), reference); - - Some(the_hash) + CssModule { config, hashes } } pub(crate) fn handle_composes( @@ -195,50 +71,6 @@ impl<'a> CssModule<'a> { Ok(()) } - - pub(crate) fn add_dashed(&mut self, bump: &'a Bump, local: &'a [u8], source_index: u32) { - use bun_collections::array_hash_map::MapEntry; - if let MapEntry::Vacant(v) = - self.exports_by_source_index[source_index as usize].entry(local) - { - v.insert(CssModuleExport { - // todo_stuff.depth - name: self.config.pattern.write_to_string_with_prefix( - bump, - b"--", - self.hashes[source_index as usize], - self.sources[source_index as usize].as_ref(), - &local[2..], - ), - is_referenced: false, - }); - } - } - - pub(crate) fn add_local( - &mut self, - bump: &'a Bump, - exported: &'a [u8], - local: &'a [u8], - source_index: u32, - ) { - use bun_collections::array_hash_map::MapEntry; - if let MapEntry::Vacant(v) = - self.exports_by_source_index[source_index as usize].entry(exported) - { - v.insert(CssModuleExport { - // todo_stuff.depth - name: self.config.pattern.write_to_string( - bump, - BumpVec::new_in(bump), - self.hashes[source_index as usize], - self.sources[source_index as usize].as_ref(), - local, - ), - is_referenced: false, - }); - } - } } /// Configuration for CSS modules. @@ -247,9 +79,6 @@ pub struct Config { /// Default is `[hash]_[local]`. pub(crate) pattern: Pattern, - /// Whether to rename dashed identifiers, e.g. custom properties. - pub(crate) dashed_idents: bool, - /// Whether to scope animation names. /// Default is `true`. pub(crate) animation: bool, @@ -263,7 +92,6 @@ impl Default for Config { fn default() -> Self { Self { pattern: Pattern::default(), - dashed_idents: false, animation: true, custom_idents: true, } @@ -290,89 +118,21 @@ impl Default for Pattern { impl Pattern { /// Write the substituted pattern to a destination. - pub(crate) fn write( - &self, - hash_: &[u8], - path: &[u8], - local: &[u8], - mut writefn: impl FnMut(&[u8], /* replace_dots: */ bool), - ) { + pub(crate) fn write(&self, hash_: &[u8], local: &[u8], mut writefn: impl FnMut(&[u8])) { for segment in self.segments.slice() { match segment { Segment::Literal(s) => { - writefn(s, false); - } - Segment::Name => { - let stem = bun_paths::stem(path); - if bun_core::index_of(stem, b".").is_some() { - writefn(stem, true); - } else { - writefn(stem, false); - } + writefn(s); } Segment::Local => { - writefn(local, false); + writefn(local); } Segment::Hash => { - writefn(hash_, false); + writefn(hash_); } } } } - - pub(crate) fn write_to_string_with_prefix<'a>( - &self, - bump: &'a Bump, - prefix: &'static [u8], - hash_: &[u8], - path: &[u8], - local: &[u8], - ) -> &'a [u8] { - let mut res: BumpVec<'a, u8> = BumpVec::new_in(bump); - self.write(hash_, path, local, |slice: &[u8], replace_dots: bool| { - res.extend_from_slice(prefix); - if replace_dots { - let start = res.len(); - res.extend_from_slice(slice); - let end = res.len(); - for c in &mut res[start..end] { - if *c == b'.' { - *c = b'-'; - } - } - return; - } - res.extend_from_slice(slice); - }); - res.into_bump_slice() - } - - pub(crate) fn write_to_string<'a>( - &self, - _bump: &'a Bump, - res_: BumpVec<'a, u8>, - hash_: &[u8], - path: &[u8], - local: &[u8], - ) -> &'a [u8] { - let mut res = res_; - self.write(hash_, path, local, |slice: &[u8], replace_dots: bool| { - if replace_dots { - let start = res.len(); - res.extend_from_slice(slice); - let end = res.len(); - for c in &mut res[start..end] { - if *c == b'.' { - *c = b'-'; - } - } - return; - } - res.extend_from_slice(slice); - }); - - res.into_bump_slice() - } } /// A segment in a CSS modules class name pattern. @@ -383,9 +143,6 @@ pub enum Segment { /// A literal string segment. Literal(&'static [u8]), - /// The base file name. - Name, - /// The original class name. Local, @@ -393,40 +150,10 @@ pub enum Segment { Hash, } -/// A map of exported names to values. -pub type CssModuleExports<'a> = ArrayHashMap<&'a [u8], CssModuleExport<'a>>; - -/// A map of placeholders to references. -pub type CssModuleReferences<'a> = ArrayHashMap<&'a [u8], CssModuleReference<'a>>; - -/// An exported value from a CSS module. -pub struct CssModuleExport<'a> { - /// The local (compiled) name for this export. - pub name: &'a [u8], - /// Whether the export is referenced in this file. - pub(crate) is_referenced: bool, -} - -/// A referenced name within a CSS module, e.g. via the `composes` property. -/// -/// See [CssModuleExport](CssModuleExport). -pub enum CssModuleReference<'a> { - /// A reference to an export in a different file. - Dependency { - /// The name to reference within the dependency. - name: &'a [u8], - /// The dependency specifier for the referenced file. - /// - /// import record idx - specifier: &'a [u8], - }, -} - /// LAYERING: canonical implementation lives in `bun_base64::wyhash_url_safe` /// (a leaf crate) so `bun_bundler::LinkerContext::mangle_local_css` can call /// the *same* hasher without depending on `bun_css`. Re-export here so -/// in-crate callers (`dependencies.rs`, `rules/import.rs`) keep the -/// `css_modules::hash` path. +/// in-crate callers keep the `css_modules::hash` path. #[inline] pub(crate) fn hash<'a>(bump: &'a Bump, args: Arguments<'_>, at_start: bool) -> &'a [u8] { bun_base64::wyhash_url_safe(bump, args, at_start) diff --git a/src/css/css_parser.rs b/src/css/css_parser.rs index b10599d0a71d..29fa9876cd0c 100644 --- a/src/css/css_parser.rs +++ b/src/css/css_parser.rs @@ -23,11 +23,8 @@ type SymbolList = Vec; use bun_ast::{ImportKind, ImportRecord}; pub use crate::compat::{self, Feature}; -pub use crate::css_modules::{ - self, Config as CssModuleConfig, CssModule, CssModuleExports, CssModuleReference, - CssModuleReferences, -}; -pub use crate::dependencies::{self, Dependency}; +pub use crate::css_modules::{self, Config as CssModuleConfig, CssModule}; +pub use crate::dependencies; pub use crate::error::{ self as errors_, BasicParseError, BasicParseErrorKind, Err, ErrorLocation, MinifyErr, MinifyError, MinifyErrorKind, ParseError, ParserError, PrinterError, PrinterErrorKind, @@ -2483,43 +2480,17 @@ mod stylesheet_impl { } if let Some(config) = &self.options.css_modules { - let mut references = CssModuleReferences::default(); - let references_ptr: *mut CssModuleReferences<'_> = &raw mut references; - // SAFETY: `'bump`-erasure — `Printer<'a>` stores `CssModule<'a>` which - // holds `&'a mut CssModuleReferences<'a>`; tying the borrow to `'a` - // (the printer's whole lifetime) makes the local `references` - // unmovable. Detach the borrow here and re-attach by clearing - // `printer.css_module` before moving `references` out below. - // Re-thread once `Printer<'a>` / `CssModule<'a>` split borrow vs. - // arena lifetimes (see rules/mod.rs `decl_block_static`). - let references_mut: &mut CssModuleReferences<'_> = unsafe { &mut *references_ptr }; printer.css_module = Some(CssModule::new( printer.arena, config, &self.sources, project_root, - references_mut, )); - - // `css_module` holds a pointer-detached `&mut references`; clear - // it before any return out of the frame that owns `references`. - if let Err(e) = self.rules.to_css(printer) { - printer.css_module = None; - return Err(e); - } - if let Err(e) = printer.newline() { - printer.css_module = None; - return Err(e); - } - - printer.css_module = None; - - return Ok(()); - } else { - self.rules.to_css(printer)?; - printer.newline()?; - return Ok(()); } + + self.rules.to_css(printer)?; + printer.newline()?; + Ok(()) } pub fn to_css<'a>( diff --git a/src/css/dependencies.rs b/src/css/dependencies.rs index f0682860c504..634588961abc 100644 --- a/src/css/dependencies.rs +++ b/src/css/dependencies.rs @@ -1,21 +1,7 @@ -//! CSS dependency tracking — `@import` and `url()` references collected during printing. +//! Source locations recorded for `url()` and `composes` values during parsing. use crate::SourceLocation; -/// Options for `analyze_dependencies` in `PrinterOptions`. -pub struct DependencyOptions { - /// Whether to remove `@import` rules. - pub(crate) remove_imports: bool, -} - -/// A dependency. -pub enum Dependency { - /// An `@import` dependency. - Import(ImportDependency), - /// A `url()` dependency. - Url(UrlDependency), -} - /// A line and column position within a source file. #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct Location { @@ -33,58 +19,3 @@ impl Location { } } } - -/// An `@import` dependency. -pub struct ImportDependency { - /// The placeholder that the URL was replaced with. - // Lifetime: arena-allocated by `css_modules::hash`. - pub(crate) placeholder: *const [u8], -} - -impl ImportDependency { - pub(crate) fn new<'bump>( - bump: &'bump bun_alloc::Arena, - rule: &crate::css_rules::import::ImportRule, - filename: &[u8], - ) -> ImportDependency { - let placeholder = crate::css_modules::hash( - bump, - format_args!( - "{}_{}", - bstr::BStr::new(filename), - bstr::BStr::new(rule.url) - ), - false, - ); - - ImportDependency { - placeholder: std::ptr::from_ref::<[u8]>(placeholder), - } - } -} - -/// A `url()` dependency. -pub struct UrlDependency { - /// The placeholder that the URL was replaced with. - // Lifetime: arena-allocated by `css_modules::hash`. - pub(crate) placeholder: *const [u8], -} - -impl UrlDependency { - pub(crate) fn new<'bump>( - bump: &'bump bun_alloc::Arena, - url: &crate::values::url::Url, - filename: &[u8], - import_records: &[bun_ast::ImportRecord], - ) -> UrlDependency { - let theurl: &[u8] = import_records[url.import_record_idx as usize].path.pretty; - let placeholder = crate::css_modules::hash( - bump, - format_args!("{}_{}", bstr::BStr::new(filename), bstr::BStr::new(theurl)), - false, - ); - UrlDependency { - placeholder: std::ptr::from_ref::<[u8]>(placeholder), - } - } -} diff --git a/src/css/error.rs b/src/css/error.rs index bcefd472d809..154e9fe5756e 100644 --- a/src/css/error.rs +++ b/src/css/error.rs @@ -204,11 +204,6 @@ impl fmt::Display for ErrorLocation { /// A printer error type. #[allow(non_camel_case_types)] pub enum PrinterErrorKind { - /// An ambiguous relative `url()` was encountered in a custom property declaration. - ambiguous_url_in_custom_property { - /// The ambiguous URL. - url: Str, - }, /// A [std::fmt::Error](std::fmt::Error) was encountered in the underlying destination. fmt_error, /// The CSS modules `composes` property cannot be used within nested rules. @@ -231,11 +226,6 @@ pub enum PrinterErrorKind { impl fmt::Display for PrinterErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::ambiguous_url_in_custom_property { url } => write!( - f, - "Ambiguous relative URL '{}' in custom property declaration", - bs(*url) - ), Self::fmt_error => f.write_str("Formatting error occurred"), Self::invalid_composes_nesting => { f.write_str("The 'composes' property cannot be used within nested rules") diff --git a/src/css/lib.rs b/src/css/lib.rs index 37250736276b..7c55aab7ceb4 100644 --- a/src/css/lib.rs +++ b/src/css/lib.rs @@ -179,8 +179,6 @@ impl core::error::Error for PrintErr {} /// signal (the *kind* lives in `Printer.error_kind`). pub(crate) type PrintResult = core::result::Result; -pub use dependencies::Dependency; - // Re-export the hub types at the crate root so `bun_css::Foo` paths resolve // for css_jsc / bundler. pub use css_parser::{ diff --git a/src/css/printer.rs b/src/css/printer.rs index c37427280041..747bc363889c 100644 --- a/src/css/printer.rs +++ b/src/css/printer.rs @@ -22,14 +22,6 @@ pub struct PrinterOptions<'a> { pub project_root: Option<&'a [u8]>, /// Targets to output the CSS for. pub targets: Targets, - /// Whether to analyze dependencies (i.e. `@import` and `url()`). - /// If true, the dependencies are returned as part of the - /// [ToCssResult](super::stylesheet::ToCssResult). - /// - /// When enabled, `@import` and `url()` dependencies - /// are replaced with hashed placeholders that can be replaced with the final - /// urls later (after bundling). - pub analyze_dependencies: Option, /// A mapping of pseudo classes to replace with class names that can be applied /// from JavaScript. Useful for polyfills, for example. pub pseudo_classes: Option>, @@ -48,7 +40,6 @@ impl<'a> PrinterOptions<'a> { browsers: None, ..Targets::default() }, - analyze_dependencies: None, pseudo_classes: None, } } @@ -131,8 +122,6 @@ pub struct Printer<'a> { pub(crate) skip_prefixed_nested_rules: bool, pub(crate) in_calc: bool, pub(crate) css_module: Option>, - pub(crate) dependencies: Option>, - pub(crate) remove_imports: bool, /// A mapping of pseudo classes to replace with class names that can be applied /// from JavaScript. Useful for polyfills, for example. pub(crate) pseudo_classes: Option>, @@ -262,7 +251,7 @@ impl<'a> Printer<'a> { Err(PrintErr::CSSPrintError) } - // deinit() dropped — scratchbuf/dependencies are arena-backed + // deinit() dropped — scratchbuf is an arena-backed // BumpVec<'a, _>; freed in bulk by `arena.reset()`. No explicit Drop impl needed. /// If `import_records` is null, then the printer will error when it encounters code that relies on import records (urls()) @@ -280,16 +269,6 @@ impl<'a> Printer<'a> { dest, minify: options.minify, targets: options.targets, - dependencies: if options.analyze_dependencies.is_some() { - Some(BumpVec::new_in(arena)) - } else { - None - }, - remove_imports: options - .analyze_dependencies - .as_ref() - .map(|d| d.remove_imports) - .unwrap_or(false), pseudo_classes: options.pseudo_classes, import_info, scratchbuf, @@ -315,14 +294,6 @@ impl<'a> Printer<'a> { } } - #[inline] - pub(crate) fn get_import_records(&mut self) -> PrintResult<&'a [ImportRecord]> { - if let Some(info) = &self.import_info { - return Ok(info.import_records); - } - Err(self.add_no_import_record_error()) - } - #[inline] pub(crate) fn import_record(&mut self, import_record_idx: u32) -> PrintResult<&ImportRecord> { if let Some(info) = &self.import_info { @@ -506,16 +477,6 @@ impl<'a> Printer<'a> { Ok(()) } - fn replace_dots<'b>(arena: &'b Bump, s: &[u8]) -> &'b mut [u8] { - let str_ = arena.alloc_slice_copy(s); - for b in str_.iter_mut() { - if *b == b'.' { - *b = b'-'; - } - } - str_ - } - pub(crate) fn write_ident_or_ref( &mut self, ident: css_values::ident::IdentOrRef, @@ -555,51 +516,31 @@ impl<'a> Printer<'a> { // Copy the `'a`-lifetime references out of `css_module` up front so // the closure can hold the sole `&mut self`. let source_index = self.loc.source_index as usize; - let arena = self.arena; - let (config, hash, source): (&'a css::css_modules::Config, &'a [u8], &'a [u8]) = { + let (config, hash): (&'a css::css_modules::Config, &'a [u8]) = { let m = self.css_module.as_ref().unwrap(); - let sources: &'a Vec> = m.sources; - ( - m.config, - m.hashes[source_index], - sources[source_index].as_ref(), - ) + (m.config, m.hashes[source_index]) }; let mut first = true; let mut err: Option = None; - config - .pattern - .write(hash, source, ident, |s1: &[u8], replace_dots: bool| { - if err.is_some() { - return; - } - // PERF: stack fallback? - let s: &[u8] = if !replace_dots { - s1 - } else { - Printer::replace_dots(arena, s1) - }; - self.col += u32::try_from(s.len()).expect("int cast"); - let r = if first { - first = false; - css::serializer::serialize_identifier(s, self) - } else { - css::serializer::serialize_name(s, self) - }; - if r.is_err() { - err = Some(PrintErr::CSSPrintError); - } - }); + config.pattern.write(hash, ident, |s: &[u8]| { + if err.is_some() { + return; + } + self.col += u32::try_from(s.len()).expect("int cast"); + let r = if first { + first = false; + css::serializer::serialize_identifier(s, self) + } else { + css::serializer::serialize_name(s, self) + }; + if r.is_err() { + err = Some(PrintErr::CSSPrintError); + } + }); if let Some(e) = err { return Err(e); } - - let src_idx = self.loc.source_index; - self.css_module - .as_mut() - .unwrap() - .add_local(arena, ident, ident, src_idx); return Ok(()); } } @@ -607,70 +548,9 @@ impl<'a> Printer<'a> { self.serialize_identifier(ident) } - pub(crate) fn write_dashed_ident( - &mut self, - ident: &DashedIdent, - is_declaration: bool, - ) -> PrintResult<()> { + pub(crate) fn write_dashed_ident(&mut self, ident: &DashedIdent) -> PrintResult<()> { self.write_str(b"--")?; - - // NOTE: cannot use `ident.v()` here — `add_dashed` requires `&'a [u8]` - // (arena lifetime), but the safe accessor ties the borrow to `&ident`. - // SAFETY: DashedIdent.v is an arena-owned slice valid for `'a`. - let ident_v: &'a [u8] = unsafe { crate::arena_str(ident.v) }; - - let dashed_idents = match &self.css_module { - Some(m) => m.config.dashed_idents, - None => false, - }; - if dashed_idents { - // Same borrowck reshape as `write_ident`. - let source_index = self.loc.source_index as usize; - let arena = self.arena; - let (config, hash, source): (&'a css::css_modules::Config, &'a [u8], &'a [u8]) = { - let m = self.css_module.as_ref().unwrap(); - let sources: &'a Vec> = m.sources; - ( - m.config, - m.hashes[source_index], - sources[source_index].as_ref(), - ) - }; - - let mut err: Option = None; - config.pattern.write( - hash, - source, - &ident_v[2..], - |s1: &[u8], replace_dots: bool| { - if err.is_some() { - return; - } - let s: &[u8] = if !replace_dots { - s1 - } else { - Printer::replace_dots(arena, s1) - }; - self.col += u32::try_from(s.len()).expect("int cast"); - if css::serializer::serialize_name(s, self).is_err() { - err = Some(PrintErr::CSSPrintError); - } - }, - ); - if let Some(e) = err { - return Err(e); - } - - if is_declaration { - let src_idx = self.loc.source_index; - self.css_module - .as_mut() - .unwrap() - .add_dashed(arena, ident_v, src_idx); - } - } - - self.serialize_name(&ident_v[2..]) + self.serialize_name(&ident.v()[2..]) } /// Write a single character to the underlying destination. diff --git a/src/css/properties/animation.rs b/src/css/properties/animation.rs index dfe3f6d08df8..c5a8a76f8b82 100644 --- a/src/css/properties/animation.rs +++ b/src/css/properties/animation.rs @@ -336,30 +336,11 @@ impl AnimationName { match self { AnimationName::None => return dest.write_str("none"), AnimationName::Ident(s) => { - // SAFETY: arena-owned slice valid for 'bump. - let name: &[u8] = unsafe { crate::arena_str(s.v) }; - if css_module_animation_enabled { - // reshaped for borrowck — capture arena/source_index - // before borrowing dest.css_module mutably. - let arena = dest.arena; - let source_index = dest.loc.source_index; - if let Some(css_module) = &mut dest.css_module { - css_module.get_reference(arena, name, source_index); - } - } return s.to_css_with_options(dest, css_module_animation_enabled); } AnimationName::String(s) => { // SAFETY: arena-owned slice valid for 'bump. let name: &[u8] = unsafe { crate::arena_str(*s) }; - if css_module_animation_enabled { - // reshaped for borrowck - let arena = dest.arena; - let source_index = dest.loc.source_index; - if let Some(css_module) = &mut dest.css_module { - css_module.get_reference(arena, name, source_index); - } - } // CSS-wide keywords and `none` cannot remove quotes if strings::eql_case_insensitive_ascii_check_length(name, b"none") diff --git a/src/css/properties/background.rs b/src/css/properties/background.rs index 71fd71f72bcf..15ec932dcb33 100644 --- a/src/css/properties/background.rs +++ b/src/css/properties/background.rs @@ -14,8 +14,6 @@ use bun_alloc::Arena as Bump; use bun_alloc::ArenaVecExt as _; /// A value for the [background](https://www.w3.org/TR/css-backgrounds-3/#background) shorthand property. -// Clone derive gated on `Image` gaining `Clone` upstream. -#[cfg_attr(any(), derive(Clone))] pub struct Background { /// The background image. pub(crate) image: Image, diff --git a/src/css/properties/css_modules.rs b/src/css/properties/css_modules.rs index 981ed3fa47a3..3f8f26fae9d6 100644 --- a/src/css/properties/css_modules.rs +++ b/src/css/properties/css_modules.rs @@ -8,7 +8,6 @@ use crate::css_values::ident::{CustomIdent, CustomIdentList}; use crate::dependencies::Location; use bun_alloc::Arena; // bumpalo::Bump re-export (CSS is an AST/arena crate) -use bun_wyhash::Wyhash; /// A value for the [composes](https://github.com/css-modules/css-modules/#dependencies) property from CSS modules. pub struct Composes { @@ -124,16 +123,6 @@ pub enum Specifier { ImportRecordIndex(u32), } -// `generics::CssEql` so the `Option` blanket (used by -// `DashedIdentReference::eql` in values/ident.rs) resolves. Forwards to the -// inherent `eql` below. -impl crate::generics::CssEql for Specifier { - #[inline] - fn eql(&self, other: &Self) -> bool { - Specifier::eql(*self, *other) - } -} - impl Specifier { pub fn eql(lhs: Self, rhs: Self) -> bool { match (lhs, rhs) { @@ -178,14 +167,4 @@ impl Specifier { // Variants are `Copy`; the deep clone is the value itself. self } - - pub(crate) fn hash(self, hasher: &mut Wyhash) { - match self { - Specifier::Global => hasher.update(&0u32.to_ne_bytes()), - Specifier::ImportRecordIndex(i) => { - hasher.update(&1u32.to_ne_bytes()); - hasher.update(&i.to_ne_bytes()); - } - } - } } diff --git a/src/css/properties/custom.rs b/src/css/properties/custom.rs index ff887d55c14a..c1072ed620e7 100644 --- a/src/css/properties/custom.rs +++ b/src/css/properties/custom.rs @@ -61,36 +61,6 @@ mod ext { /// Inline of `Url::to_css`. pub(super) fn url_to_css(this: &Url, dest: &mut Printer) -> PrintResult<()> { - let dep: Option = if dest.dependencies.is_some() { - // `get_import_records` borrows &mut *dest, so capture - // arena/filename first. - let arena = dest.arena; - // SAFETY: filename borrows the printer arena/options which outlive `dest`. - let filename: &[u8] = unsafe { &*std::ptr::from_ref::<[u8]>(dest.filename()) }; - let records = dest.get_import_records()?; - Some(dependencies::UrlDependency::new( - arena, this, filename, records, - )) - } else { - None - }; - - // If adding dependencies, always write url() with quotes so that the placeholder can - // be replaced without escaping more easily. Quotes may be removed later during minification. - if let Some(d) = dep { - dest.write_str("url(")?; - // SAFETY: placeholder borrows the printer arena. - let placeholder = unsafe { crate::arena_str(d.placeholder) }; - dest.serialize_string(placeholder)?; - dest.write_char(b')')?; - - if let Some(dependencies) = &mut dest.dependencies { - dependencies.push(crate::Dependency::Url(d)); - } - - return Ok(()); - } - let import_record = dest.import_record(this.import_record_idx)?; let is_internal = import_record.tag.is_internal(); // `get_import_record_url` reborrows &mut *dest, so capture @@ -128,15 +98,10 @@ mod ext { Ok(()) } - /// Forwarder to `DashedIdentReference::parse_with_options`. Honors - /// `options.css_modules.dashed_idents` and parses the - /// `from ` suffix when enabled. + /// Forwarder to `DashedIdentReference::parse`. #[inline] - pub(super) fn dashed_ident_ref_parse( - input: &mut Parser, - options: &ParserOptions, - ) -> Result { - DashedIdentReference::parse_with_options(input, options) + pub(super) fn dashed_ident_ref_parse(input: &mut Parser) -> Result { + DashedIdentReference::parse(input) } /// Forwarder to `DashedIdentReference::to_css`. @@ -316,20 +281,6 @@ impl TokenList { has_whitespace = false; } TokenOrValue::Url(url) => { - if dest.dependencies.is_some() - && is_custom_property - && !url.is_absolute(dest.get_import_records()?) - { - let pretty = std::ptr::from_ref::<[u8]>( - dest.get_import_records()?[url.import_record_idx as usize] - .path - .pretty, - ); - return dest.new_error( - css::PrinterErrorKind::ambiguous_url_in_custom_property { url: pretty }, - Some(url.loc), - ); - } ext::url_to_css(url, dest)?; has_whitespace = false; } @@ -364,7 +315,7 @@ impl TokenList { has_whitespace = false; } TokenOrValue::DashedIdent(v) => { - dest.write_dashed_ident(v, true)?; + dest.write_dashed_ident(v)?; has_whitespace = false; } TokenOrValue::AnimationName(v) => { @@ -1065,7 +1016,7 @@ impl Variable { // deinit(): body only freed owned `TokenList` field — handled by `Drop`. fn parse(input: &mut Parser, options: &ParserOptions, depth: usize) -> Result { - let name = ext::dashed_ident_ref_parse(input, options)?; + let name = ext::dashed_ident_ref_parse(input)?; let fallback = if input.try_parse(|i| i.expect_comma()).is_ok() { Some(TokenList::parse(input, options, depth)?) @@ -1197,9 +1148,7 @@ impl EnvironmentVariableName { return Ok(EnvironmentVariableName::Ua(ua)); } - if let Ok(dashed) = - input.try_parse(|i| ext::dashed_ident_ref_parse(i, &ParserOptions::default(None))) - { + if let Ok(dashed) = input.try_parse(ext::dashed_ident_ref_parse) { return Ok(EnvironmentVariableName::Custom(dashed)); } @@ -1565,11 +1514,7 @@ pub enum CustomPropertyName { impl CustomPropertyName { pub fn to_css(&self, dest: &mut Printer) -> PrintResult<()> { match self { - CustomPropertyName::Custom(custom) => { - // DashedIdent.toCss → dest.writeDashedIdent(ident, true), - // which applies CSS-Modules dashed-ident renaming. - dest.write_dashed_ident(custom, true) - } + CustomPropertyName::Custom(custom) => dest.write_dashed_ident(custom), CustomPropertyName::Unknown(unknown) => { // SAFETY: arena-owned slice valid for printer lifetime. let v = unsafe { crate::arena_str(unknown.v) }; diff --git a/src/css/properties/masking.rs b/src/css/properties/masking.rs index 5672a93631d7..ce897a8123dc 100644 --- a/src/css/properties/masking.rs +++ b/src/css/properties/masking.rs @@ -108,9 +108,6 @@ pub enum MaskType { } /// A value for the [mask](https://www.w3.org/TR/css-masking-1/#the-mask) shorthand property. -// Debug/Clone/PartialEq derives gated on `Image`/`Position`/ -// `BackgroundSize`/`BackgroundRepeat` gaining those derives upstream. -#[cfg_attr(any(), derive(Debug, Clone, PartialEq))] #[derive(DeepClone, CssEql)] pub struct Mask { /// The mask image. @@ -279,9 +276,6 @@ pub enum MaskBorderMode { } /// A value for the [mask-border](https://www.w3.org/TR/css-masking-1/#the-mask-border) shorthand property. -// Debug/Clone/PartialEq derives gated on `Image`/`Rect<_>` gaining -// those derives upstream. -#[cfg_attr(any(), derive(Debug, Clone, PartialEq))] #[derive(DeepClone, CssEql)] pub struct MaskBorder { /// The mask image. diff --git a/src/css/rules/import.rs b/src/css/rules/import.rs index df95395a0989..7fe614a86a94 100644 --- a/src/css/rules/import.rs +++ b/src/css/rules/import.rs @@ -1,4 +1,3 @@ -use crate as css; use crate::css_rules::Location; use crate::css_rules::layer::LayerName; use crate::css_rules::supports::SupportsCondition; @@ -205,32 +204,11 @@ impl ImportRule { } pub fn to_css(&self, dest: &mut Printer) -> Result<(), PrintErr> { - let dep: Option = if dest.dependencies.is_some() { - Some(css::dependencies::ImportDependency::new( - dest.arena, - self, - dest.filename(), - )) - } else { - None - }; - // #[cfg(feature = "sourcemap")] // dest.add_mapping(self.loc); dest.write_str("@import ")?; - if let Some(d) = dep { - // SAFETY: `placeholder` is arena-allocated by `css_modules::hash` - // and outlives this print call. - let placeholder = unsafe { crate::arena_str(d.placeholder) }; - dest.serialize_string(placeholder)?; - - if let Some(deps) = &mut dest.dependencies { - deps.push(css::Dependency::Import(d)); - } - } else { - dest.serialize_string(self.url)?; - } + dest.serialize_string(self.url)?; if let Some(lyr) = &self.layer { dest.write_str(" layer")?; diff --git a/src/css/rules/mod.rs b/src/css/rules/mod.rs index d3bacb092d95..29efcb187c88 100644 --- a/src/css/rules/mod.rs +++ b/src/css/rules/mod.rs @@ -437,30 +437,6 @@ impl CssRuleList { continue; } - // Skip @import rules if collecting dependencies. - if let CssRule::Import(import_rule) = rule - && dest.remove_imports - { - let dep = if dest.dependencies.is_some() { - Some(css::dependencies::Dependency::Import( - css::dependencies::ImportDependency::new( - dest.arena, - import_rule, - dest.filename(), - ), - )) - } else { - None - }; - - if let Some(deps) = dest.dependencies.as_mut() { - if let Some(d) = dep { - deps.push(d); - } - continue; - } - } - if first { first = false; } else { diff --git a/src/css/values/ident.rs b/src/css/values/ident.rs index 3cd4b213261b..ddc171302bf9 100644 --- a/src/css/values/ident.rs +++ b/src/css/values/ident.rs @@ -1,5 +1,4 @@ use crate::SmallList; -use crate::css_parser as css; use crate::css_parser::{CssResult, Parser, PrintErr, Printer, Token}; use bun_ast::Ref; @@ -68,108 +67,39 @@ macro_rules! arena_slice_newtype { } // ───────────────────────── DashedIdentReference ────────────────────────── -// `properties::css_modules::Specifier` is real (parse/to_css/eql/hash); the -// `from` field below uses it directly. `parse_with_options` honors -// `ParserOptions.css_modules.dashed_idents`. `to_css` resolves the -// import-record path up front and hands it to `CssModule::reference_dashed` -// (borrowck — see the comment on that method). /// A CSS [``](https://www.w3.org/TR/css-values-4/#dashed-idents) reference. /// /// Dashed idents are used in cases where an identifier can be either author defined _or_ CSS-defined. /// Author defined idents must start with two dash characters ("--") or parsing will fail. -/// -/// In CSS modules, when the `dashed_idents` option is enabled, the identifier may be followed by the -/// `from` keyword and an argument indicating where the referenced identifier is declared (e.g. a filename). #[derive(Debug, Clone, Copy)] pub struct DashedIdentReference { /// The referenced identifier. pub(crate) ident: DashedIdent, - /// CSS modules extension: the filename where the variable is defined. - /// Only enabled when the CSS modules `dashed_idents` option is turned on. - pub(crate) from: Option, } impl DashedIdentReference { pub(crate) fn eql(&self, rhs: &Self) -> bool { - // Field-wise over `ident` and `from`. use crate::generics::CssEql; - self.ident.eql(&rhs.ident) && self.from.eql(&rhs.from) + self.ident.eql(&rhs.ident) } pub(crate) fn hash(&self, hasher: &mut Wyhash) { self.ident.hash(hasher); - if let Some(from) = &self.from { - from.hash(hasher); - } } pub(crate) fn deep_clone(&self, _bump: &bun_alloc::Arena) -> Self { - // Both fields are `Copy` (arena-slice pointer + tagged enum of Copy payloads). + // `ident` is `Copy` (arena-slice pointer). *self } - pub(crate) fn parse_with_options( - input: &mut Parser, - options: &css::ParserOptions, - ) -> CssResult { + pub(crate) fn parse(input: &mut Parser) -> CssResult { let ident = DashedIdent::parse(input)?; - let from = if options - .css_modules - .as_ref() - .is_some_and(|m| m.dashed_idents) - { - if input - .try_parse(|i| i.expect_ident_matching(b"from")) - .is_ok() - { - Some(crate::properties::css_modules::Specifier::parse(input)?) - } else { - None - } - } else { - None - }; - Ok(DashedIdentReference { ident, from }) + Ok(DashedIdentReference { ident }) } pub(crate) fn to_css(&self, dest: &mut Printer) -> Result<(), PrintErr> { - let dashed_idents = match &dest.css_module { - Some(m) => m.config.dashed_idents, - None => false, - }; - if dashed_idents { - // NOTE: cannot use `self.ident.v()` here — `reference_dashed` requires - // `&'a [u8]` (arena lifetime), but the safe accessor ties the borrow - // to `&self`. Raw deref yields the unbounded arena borrow. - // SAFETY: arena-owned slice; see `DashedIdent::v`. - let ident_v = unsafe { crate::arena_str(self.ident.v) }; - let source_index = dest.loc.source_index; - let bump = dest.arena; - // Borrowck forbids handing - // `dest` to a method on `dest.css_module`, so resolve the path - // here and pass the slice down. The `?` propagates the - // `import_record` error path. - use crate::properties::css_modules::Specifier; - let specifier_path: Option<&[u8]> = match &self.from { - Some(Specifier::ImportRecordIndex(idx)) => { - Some(dest.import_record(*idx)?.path.text) - } - _ => None, - }; - let name = dest.css_module.as_mut().unwrap().reference_dashed( - bump, - ident_v, - self.from, - specifier_path, - source_index, - ); - if let Some(name) = name { - dest.write_str(b"--")?; - return dest.serialize_name(name); - } - } - dest.write_dashed_ident(&self.ident, false) + dest.write_dashed_ident(&self.ident) } } @@ -196,7 +126,7 @@ impl DashedIdent { } pub fn to_css(&self, dest: &mut Printer) -> Result<(), PrintErr> { - dest.write_dashed_ident(self, true) + dest.write_dashed_ident(self) } } diff --git a/src/css/values/image.rs b/src/css/values/image.rs index 91d7c8c9572f..ac8acf2ab6f2 100644 --- a/src/css/values/image.rs +++ b/src/css/values/image.rs @@ -1,6 +1,5 @@ use crate as css; use crate::css_parser::CssResult as Result; -use crate::dependencies::UrlDependency; use crate::generics::DeepClone as _; use crate::values::color::ColorFallbackKind; use crate::values::gradient::Gradient; @@ -427,35 +426,11 @@ impl ImageSetOption { let Image::Url(url) = &self.image else { unreachable!() }; - let dep_: Option = if dest.dependencies.is_some() { - // Hoist `get_import_records` (mut borrow) out of the - // arg list so `filename()` (shared borrow) can run; result is `&'a _`. - let import_records = dest.get_import_records()?; - Some(UrlDependency::new( - dest.arena, - url, - dest.filename(), - import_records, - )) - } else { - None - }; - - if let Some(dep) = dep_ { - // SAFETY: placeholder borrows the printer arena. - let placeholder = unsafe { crate::arena_str(dep.placeholder) }; - dest.serialize_string(placeholder)?; - if let Some(dependencies) = &mut dest.dependencies { - // Vec::push aborts on OOM by default. - dependencies.push(css::Dependency::Url(dep)); - } - } else { - let record_url = dest.get_import_record_url(url.import_record_idx)?; - // SAFETY: `record_url` borrows arena-backed `import_info` data - // valid for the printer's `'a`; detach so `dest` is reusable. - let record_url: &[u8] = unsafe { &*std::ptr::from_ref::<[u8]>(record_url) }; - dest.serialize_string(record_url)?; - } + let record_url = dest.get_import_record_url(url.import_record_idx)?; + // SAFETY: `record_url` borrows arena-backed `import_info` data + // valid for the printer's `'a`; detach so `dest` is reusable. + let record_url: &[u8] = unsafe { &*std::ptr::from_ref::<[u8]>(record_url) }; + dest.serialize_string(record_url)?; } else { self.image.to_css(dest)?; } diff --git a/src/css/values/url.rs b/src/css/values/url.rs index 8c228fa0af53..93dd7f64fa03 100644 --- a/src/css/values/url.rs +++ b/src/css/values/url.rs @@ -1,9 +1,6 @@ use crate::css_parser as css; use css::{CssResult, PrintErr, Printer}; -use bun_ast::ImportRecord; -use bun_core::strings; - /// A CSS [url()](https://www.w3.org/TR/css-values-4/#urls) value and its source location. pub struct Url { /// The url string. @@ -25,77 +22,7 @@ impl Url { }) } - /// Returns whether the URL is absolute, and not relative. - pub(crate) fn is_absolute(&self, import_records: &[ImportRecord]) -> bool { - let url: &[u8] = import_records[self.import_record_idx as usize].path.pretty; - - // Quick checks. If the url starts with '.', it is relative. - if strings::starts_with_char(url, b'.') { - return false; - } - - // If the url starts with '/' it is absolute. - if strings::starts_with_char(url, b'/') { - return true; - } - - // If the url starts with '#' we have a fragment URL. - // These are resolved relative to the document rather than the CSS file. - // https://drafts.csswg.org/css-values-4/#local-urls - if strings::starts_with_char(url, b'#') { - return true; - } - - // Otherwise, we might have a scheme. These must start with an ascii alpha character. - // https://url.spec.whatwg.org/#scheme-start-state - if url.is_empty() || !url[0].is_ascii_alphabetic() { - return false; - } - - // https://url.spec.whatwg.org/#scheme-state - for &c in url { - match c { - b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'+' | b'-' | b'.' => {} - b':' => return true, - _ => break, - } - } - - false - } - pub fn to_css(&self, dest: &mut Printer) -> Result<(), PrintErr> { - use crate::dependencies::UrlDependency; - let dep: Option = if dest.dependencies.is_some() { - // `get_import_records` (mut borrow) is hoisted out of the arg - // list so `filename()` (shared borrow) can run; result is `&'a _`. - let import_records = dest.get_import_records()?; - Some(UrlDependency::new( - dest.arena, - self, - dest.filename(), - import_records, - )) - } else { - None - }; - - // If adding dependencies, always write url() with quotes so that the placeholder can - // be replaced without escaping more easily. Quotes may be removed later during minification. - if let Some(d) = dep { - dest.write_str("url(")?; - // SAFETY: placeholder borrows the printer arena. - let placeholder = unsafe { crate::arena_str(d.placeholder) }; - dest.serialize_string(placeholder)?; - dest.write_char(b')')?; - - if let Some(dependencies) = &mut dest.dependencies { - dependencies.push(crate::Dependency::Url(d)); - } - - return Ok(()); - } - let import_record = dest.import_record(self.import_record_idx)?; let is_internal = import_record .flags diff --git a/src/js/builtins.d.ts b/src/js/builtins.d.ts index 2868ed044e67..494cf009bbc3 100644 --- a/src/js/builtins.d.ts +++ b/src/js/builtins.d.ts @@ -192,8 +192,6 @@ declare function $putInternalField * - [WebKit - `emit_intrinsic_newArrayWithSize`](https://github.com/oven-sh/WebKit/blob/e1a802a2287edfe7f4046a9dd8307c8b59f5d816/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp#L2317) */ declare function $newArrayWithSize(size: number): T[]; -declare const $ModuleFetch: number; -declare const $ModuleLink: number; declare const $proxyFieldTarget: TODO; declare const $proxyFieldHandler: TODO; declare const $processBindingConstants: { @@ -206,56 +204,16 @@ declare const $asyncContext: InternalFieldObject<[ReadonlyArray | undefined // We define our intrinsics in ./BunBuiltinNames.h. Some of those are globals. -declare var $_events: TODO; -declare function $addAbortAlgorithmToSignal(signal: AbortSignal, algorithm: () => void): TODO; -declare function $autoAllocateChunkSize(): TODO; -declare function $basename(): TODO; -declare function $body(): TODO; declare function $bunNativePtr(): TODO; -declare function $cancel(): TODO; -declare function $close(): TODO; -declare function $code(): TODO; declare function $createFIFO(): TODO; -declare function $createUninitializedArrayBuffer(size: number): ArrayBuffer; declare function $data(): TODO; -declare function $decode(): TODO; -declare function $dirname(): TODO; -declare function $encoding(): TODO; -declare function $end(): TODO; -declare function $errno(): TODO; -declare function $extname(): TODO; -declare function $fatal(): TODO; -declare function $format(): TODO; declare function $esmNamespaceForCjs(key: string): any | undefined; declare function $esmRegistryDelete(key: string): boolean; declare function $esmRegistryEvaluatedKeys(): string[]; declare function $esmLoadSync(key: string): any; declare function $get(): TODO; -declare function $handleEvent(): TODO; -declare function $headers(): TODO; -declare function $highWaterMark(): TODO; -declare function $host(): TODO; -declare function $hostname(): TODO; -declare function $ignoreBOM(): TODO; -declare function $importer(): TODO; declare function $internalRequire(id: string, parent: JSCommonJSModule): TODO; -declare function $isAbortSignal(signal: unknown): signal is AbortSignal; -declare function $isAbsolute(): TODO; -declare function $join(): TODO; -declare function $main(): TODO; -declare function $makeDOMException(): TODO; -declare function $makeGetterTypeError(className: string, prop: string): Error; -declare function $method(): TODO; -declare function $normalize(): TODO; -declare function $parse(): TODO; -declare function $path(): TODO; -declare function $port(): TODO; declare function $pull(): TODO; -declare function $read(): TODO; -declare function $readable(): TODO; -declare function $removeAbortAlgorithmFromSignal(signal: AbortSignal, algorithmIdentifier: number): TODO; -declare function $redirect(): TODO; -declare function $relative(): TODO; declare function $require(): TODO; declare function $requireESM(path: string): any; declare const $requireMap: Map; @@ -270,18 +228,9 @@ declare function $resolveSync( parentModule?: JSCommonJSModule, resolveFilenameOptions?: unknown, ): string; -declare function $self(): TODO; declare function $size(): TODO; declare function $start(): TODO; -declare function $status(): TODO; -declare function $stream(): TODO; -declare function $syscall(): TODO; -declare function $toNamespacedPath(): TODO; -declare function $url(): TODO; -declare function $writable(): TODO; declare function $write(): TODO; -declare function $writer(): TODO; -declare function $written(): TODO; declare function $createCommonJSModule( id: string, @@ -300,7 +249,6 @@ declare function $overridableRequire(this: JSCommonJSModule, id: string): any; // The following I cannot find any definitions of, but they are functional. declare function $toLength(length: number): number; declare function $isTypedArrayView(obj: unknown): obj is ArrayBufferView | DataView | Uint8Array; -declare function $setStateToMax(target: any, state: number): void; /** @deprecated, use new TypeError instead */ declare function $makeTypeError(message: string): TypeError; @@ -352,8 +300,6 @@ declare const $LoaderIdToLabel: Array; declare const $LoaderLabelToId: Record; // not a builtin, but a build-time macro of our own -/** Returns a not implemented error that points to a github issue. */ -declare function notImplementedIssue(issueNumber: number, description: string): Error; /** Return a function that throws a not implemented error that points to a github issue */ declare function notImplementedIssueFn(issueNumber: number, description: string): (...args: any[]) => never; diff --git a/src/js_parser/react_compiler_host.rs b/src/js_parser/react_compiler_host.rs index 161ba27d2fc0..28546f045e2f 100644 --- a/src/js_parser/react_compiler_host.rs +++ b/src/js_parser/react_compiler_host.rs @@ -61,7 +61,6 @@ impl<'a, const TS: bool, const SCAN_ONLY: bool> bun_react_compiler::Host K::Jsxs => JSXImport::Jsxs, K::JsxDEV => JSXImport::JsxDEV, K::Fragment => JSXImport::Fragment, - K::CreateElement => JSXImport::CreateElement, }; let p = &mut *self.p; match p.jsx_imports.get_with_tag(kind) { diff --git a/src/jsc/EncodedSlice.rs b/src/jsc/EncodedSlice.rs index 13b27d4d647c..1e851867a38f 100644 --- a/src/jsc/EncodedSlice.rs +++ b/src/jsc/EncodedSlice.rs @@ -55,9 +55,7 @@ fn error_instance(slice: &EncodedSlice<'_>, global: &JSGlobalObject, kind: Error /// JSC conversions for `bun_core::EncodedSlice`. pub trait EncodedSliceJsc: Sized { fn to_error_instance(&self, global: &JSGlobalObject) -> JSValue; - fn to_type_error_instance(&self, global: &JSGlobalObject) -> JSValue; fn to_syntax_error_instance(&self, global: &JSGlobalObject) -> JSValue; - fn to_range_error_instance(&self, global: &JSGlobalObject) -> JSValue; fn to_dom_exception_instance(&self, global: &JSGlobalObject, code: DOMExceptionCode) -> JSValue; /// Copies into a GC-managed `JSString` (or hands over an external value @@ -85,15 +83,9 @@ impl EncodedSliceJsc for EncodedSlice<'_> { fn to_error_instance(&self, global: &JSGlobalObject) -> JSValue { error_instance(self, global, ErrorKind::Error) } - fn to_type_error_instance(&self, global: &JSGlobalObject) -> JSValue { - error_instance(self, global, ErrorKind::TypeError) - } fn to_syntax_error_instance(&self, global: &JSGlobalObject) -> JSValue { error_instance(self, global, ErrorKind::SyntaxError) } - fn to_range_error_instance(&self, global: &JSGlobalObject) -> JSValue { - error_instance(self, global, ErrorKind::RangeError) - } fn to_dom_exception_instance( &self, global: &JSGlobalObject, diff --git a/src/jsc/Weak.rs b/src/jsc/Weak.rs index 33a84ec916e9..b71f017510a5 100644 --- a/src/jsc/Weak.rs +++ b/src/jsc/Weak.rs @@ -9,7 +9,6 @@ use crate::{JSGlobalObject, JSValue}; pub enum WeakRefType { None = 0, FetchResponse = 1, - PostgreSQLQueryClient = 2, } bun_opaque::opaque_ffi! { diff --git a/src/jsc/bindings/ErrorCode.ts b/src/jsc/bindings/ErrorCode.ts index 0b284d02de3e..c676adbd787a 100644 --- a/src/jsc/bindings/ErrorCode.ts +++ b/src/jsc/bindings/ErrorCode.ts @@ -275,17 +275,13 @@ const errors: ErrorCodeMapping = [ ["ERR_REDIS_CONNECTION_CLOSED", Error, "RedisError"], ["ERR_REDIS_CONNECTION_TIMEOUT", Error, "RedisError"], ["ERR_REDIS_IDLE_TIMEOUT", Error, "RedisError"], - ["ERR_REDIS_INVALID_ARGUMENT", Error, "RedisError"], - ["ERR_REDIS_INVALID_ARRAY", Error, "RedisError"], ["ERR_REDIS_INVALID_BULK_STRING", Error, "RedisError"], ["ERR_REDIS_INVALID_COMMAND", Error, "RedisError"], ["ERR_REDIS_INVALID_DATABASE", Error, "RedisError"], - ["ERR_REDIS_INVALID_ERROR_STRING", Error, "RedisError"], ["ERR_REDIS_INVALID_INTEGER", Error, "RedisError"], ["ERR_REDIS_INVALID_PASSWORD", Error, "RedisError"], ["ERR_REDIS_INVALID_RESPONSE", Error, "RedisError"], ["ERR_REDIS_INVALID_RESPONSE_TYPE", Error, "RedisError"], - ["ERR_REDIS_INVALID_SIMPLE_STRING", Error, "RedisError"], ["ERR_REDIS_INVALID_STATE", Error, "RedisError"], ["ERR_REDIS_INVALID_USERNAME", Error, "RedisError"], ["ERR_REDIS_TLS_NOT_AVAILABLE", Error, "RedisError"], diff --git a/src/jsc/bindings/Weak.cpp b/src/jsc/bindings/Weak.cpp index 68ab951730fd..c8e3455df68a 100644 --- a/src/jsc/bindings/Weak.cpp +++ b/src/jsc/bindings/Weak.cpp @@ -9,13 +9,11 @@ namespace Bun { enum class WeakRefType : uint32_t { None = 0, FetchResponse = 1, - PostgreSQLQueryClient = 2, }; // clang-format off #define FOR_EACH_WEAK_REF_TYPE(macro) \ - macro(FetchResponse) \ - macro(PostgreSQLQueryClient) + macro(FetchResponse) // clang-format on @@ -34,9 +32,6 @@ class WeakRefOwner : public JSC::WeakHandleOwner { case WeakRefType::FetchResponse: Bun__FetchResponse_finalize(context); break; - case WeakRefType::PostgreSQLQueryClient: - // Bun__PostgreSQLQueryClient_finalize(context); - break; default: break; } @@ -60,9 +55,6 @@ static JSC::WeakHandleOwner* getWeakRefOwner(WeakRefType type) case WeakRefType::FetchResponse: { return getWeakRefOwner(); } - case WeakRefType::PostgreSQLQueryClient: { - return getWeakRefOwner(); - } default: { RELEASE_ASSERT_NOT_REACHED(); } diff --git a/src/jsc/bun_string_jsc.rs b/src/jsc/bun_string_jsc.rs index 7874020393c6..ba28105924f2 100644 --- a/src/jsc/bun_string_jsc.rs +++ b/src/jsc/bun_string_jsc.rs @@ -60,8 +60,6 @@ pub trait StringJsc { /// atomized, a borrowed `EncodedSlice` copied. fn to_error_instance(&self, global: &JSGlobalObject) -> JSValue; fn to_type_error_instance(&self, global: &JSGlobalObject) -> JSValue; - fn to_syntax_error_instance(&self, global: &JSGlobalObject) -> JSValue; - fn to_range_error_instance(&self, global: &JSGlobalObject) -> JSValue; } impl StringJsc for String { #[track_caller] @@ -110,12 +108,6 @@ impl StringJsc for String { fn to_type_error_instance(&self, global: &JSGlobalObject) -> JSValue { error_instance(self, global, ErrorKind::TypeError) } - fn to_syntax_error_instance(&self, global: &JSGlobalObject) -> JSValue { - error_instance(self, global, ErrorKind::SyntaxError) - } - fn to_range_error_instance(&self, global: &JSGlobalObject) -> JSValue { - error_instance(self, global, ErrorKind::RangeError) - } } /// JSC conversions for `bun_core::Utf8WithString`. diff --git a/src/ptr/ref_count.rs b/src/ptr/ref_count.rs index 646a5f68866e..50130e219136 100644 --- a/src/ptr/ref_count.rs +++ b/src/ptr/ref_count.rs @@ -15,26 +15,8 @@ use bun_core::ThreadLock; // Host-type traits (field projection + destructor) // ────────────────────────────────────────────────────────────────────────── -/// `bun.meta.typeBaseName` — strip the module path (and the path inside any -/// leading generic segment) from a `core::any::type_name` string, returning a -/// subslice so the result stays `&'static str`. -/// `"a::b::Foo"` → `"Foo"`. -fn type_base_name(name: &'static str) -> &'static str { - let bytes = name.as_bytes(); - let end = bun_core::strings::index_of_char_usize(bytes, b'<').unwrap_or(bytes.len()); - match bun_core::strings::last_index_of(&bytes[..end], b"::") { - Some(i) => &name[i + 2..], - None => name, - } -} - /// Implemented by types that embed a [`RefCount`] field. pub trait RefCounted: Sized { - /// Defaults to the type basename. - fn debug_name() -> &'static str { - type_base_name(core::any::type_name::()) - } - /// Locate the embedded `RefCount` field. /// /// # Safety @@ -57,11 +39,6 @@ pub trait RefCounted: Sized { /// Implemented by types that embed a [`ThreadSafeRefCount`] field. pub trait ThreadSafeRefCounted: Sized { - /// Defaults to the type basename. - fn debug_name() -> &'static str { - type_base_name(core::any::type_name::()) - } - /// Locate the embedded `ThreadSafeRefCount` field. /// /// # Safety @@ -966,13 +943,4 @@ mod tests { } assert_eq!(drops(), before + 1); } - - // ── helpers ─────────────────────────────────────────────────────────── - - #[test] - fn type_base_name_strips_module_path() { - assert_eq!(type_base_name("a::b::Foo"), "Foo"); - assert_eq!(type_base_name("a::b::Foo"), "Foo"); - assert_eq!(type_base_name("Foo"), "Foo"); - } } diff --git a/src/react_compiler/codegen.rs b/src/react_compiler/codegen.rs index 7b67a32344b2..dc82fbbf80a4 100644 --- a/src/react_compiler/codegen.rs +++ b/src/react_compiler/codegen.rs @@ -42,7 +42,6 @@ use crate::hir::{ ObjectPropertyType, ParamPattern, Pattern, Place, PlaceOrSpread, PrimitiveValue, PropertyLiteral, ScopeId, }; -use crate::reactive_scopes::visitors::{ReactiveFunctionVisitor, visit_reactive_function}; use crate::reactive_scopes::{ build_reactive_function, prune_hoisted_contexts, prune_unused_labels, prune_unused_lvalues, rename_variables, @@ -61,25 +60,9 @@ pub struct CodegenFunction { pub(crate) generator: bool, pub(crate) is_async: bool, pub(crate) memo_slots_used: u32, - pub(crate) memo_blocks: u32, - pub(crate) memo_values: u32, - pub(crate) pruned_memo_blocks: u32, - pub(crate) pruned_memo_values: u32, pub(crate) outlined: Vec, } -impl std::fmt::Debug for CodegenFunction { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("CodegenFunction") - .field("memo_slots_used", &self.memo_slots_used) - .field("memo_blocks", &self.memo_blocks) - .field("memo_values", &self.memo_values) - .field("pruned_memo_blocks", &self.pruned_memo_blocks) - .field("pruned_memo_values", &self.pruned_memo_values) - .finish() - } -} - pub struct OutlinedFunction { pub(crate) func: CodegenFunction, #[cfg(any(debug_assertions, bun_asan, feature = "fixtures"))] @@ -505,9 +488,6 @@ fn codegen_reactive_function( } } - let (memo_blocks, memo_values, pruned_memo_blocks, pruned_memo_values) = - count_memo_blocks(func, cx.env); - let id = func.id.as_ref().map(|name| { let r = cx.cg.ref_for_name(store_str(name.as_bytes())); LocRef { @@ -526,10 +506,6 @@ fn codegen_reactive_function( generator: func.generator, is_async: func.is_async, memo_slots_used: cx.next_cache_index, - memo_blocks, - memo_values, - pruned_memo_blocks, - pruned_memo_values, outlined: Vec::new(), }) } @@ -2991,64 +2967,6 @@ fn codegen_dependency( Ok(object) } -// ============================================================================= -// CountMemoBlockVisitor -// ============================================================================= - -struct CountMemoBlockVisitor<'a> { - env: &'a Environment, -} - -struct CountMemoBlockState { - memo_blocks: u32, - memo_values: u32, - pruned_memo_blocks: u32, - pruned_memo_values: u32, -} - -impl<'a> ReactiveFunctionVisitor for CountMemoBlockVisitor<'a> { - type State = CountMemoBlockState; - - fn env(&self) -> &Environment { - self.env - } - - fn visit_scope(&self, scope_block: &ReactiveScopeBlock, state: &mut CountMemoBlockState) { - state.memo_blocks += 1; - let scope = &self.env.scopes[scope_block.scope.0 as usize]; - state.memo_values += scope.declarations.len() as u32; - self.traverse_scope(scope_block, state); - } - - fn visit_pruned_scope( - &self, - scope_block: &PrunedReactiveScopeBlock, - state: &mut CountMemoBlockState, - ) { - state.pruned_memo_blocks += 1; - let scope = &self.env.scopes[scope_block.scope.0 as usize]; - state.pruned_memo_values += scope.declarations.len() as u32; - self.traverse_pruned_scope(scope_block, state); - } -} - -fn count_memo_blocks(func: &ReactiveFunction, env: &Environment) -> (u32, u32, u32, u32) { - let visitor = CountMemoBlockVisitor { env }; - let mut state = CountMemoBlockState { - memo_blocks: 0, - memo_values: 0, - pruned_memo_blocks: 0, - pruned_memo_values: 0, - }; - visit_reactive_function(func, &visitor, &mut state); - ( - state.memo_blocks, - state.memo_values, - state.pruned_memo_blocks, - state.pruned_memo_values, - ) -} - // ============================================================================= // Operator conversions // ============================================================================= diff --git a/src/react_compiler/collections.rs b/src/react_compiler/collections.rs index 54a3a32fa318..2a8d0923557c 100644 --- a/src/react_compiler/collections.rs +++ b/src/react_compiler/collections.rs @@ -32,7 +32,6 @@ pub type FxHashSet = std::collections::HashSet; type Inner = ArrayHashMap; pub(crate) type Entry<'a, K, V> = MapEntry<'a, K, V, AutoContext, AstAlloc>; -pub use bun_collections::array_hash_map::{OccupiedEntry, VacantEntry}; // ────────────────────────────────────────────────────────────────────────── // IndexMap @@ -195,7 +194,6 @@ impl Iterator for IntoIter { self.keys.size_hint() } } -impl ExactSizeIterator for IntoIter {} impl IntoIterator for IndexMap { type Item = (K, V); @@ -217,13 +215,6 @@ impl<'a, K, V> IntoIterator for &'a IndexMap { } } -impl PartialEq for IndexMap { - fn eq(&self, other: &Self) -> bool { - self.len() == other.len() && self.iter().all(|(k, v)| other.get(k) == Some(v)) - } -} -impl Eq for IndexMap {} - // ────────────────────────────────────────────────────────────────────────── // IndexSet // ────────────────────────────────────────────────────────────────────────── @@ -310,12 +301,6 @@ impl FromIterator for IndexSet { } } -impl From<[K; N]> for IndexSet { - fn from(arr: [K; N]) -> Self { - Self::from_iter(arr) - } -} - impl IntoIterator for IndexSet { type Item = K; type IntoIter = alloc::vec::IntoIter; @@ -332,13 +317,6 @@ impl<'a, K> IntoIterator for &'a IndexSet { } } -impl PartialEq for IndexSet { - fn eq(&self, other: &Self) -> bool { - self.len() == other.len() && self.iter().all(|k| other.contains(k)) - } -} -impl Eq for IndexSet {} - // ────────────────────────────────────────────────────────────────────────── // IdMap // ────────────────────────────────────────────────────────────────────────── diff --git a/src/react_compiler/compile_result.rs b/src/react_compiler/compile_result.rs index 5241f5aa5f7d..1073f64d31ac 100644 --- a/src/react_compiler/compile_result.rs +++ b/src/react_compiler/compile_result.rs @@ -1,61 +1,6 @@ //! Port of `react_compiler/entrypoint/compile_result.rs`. -#![allow( - unreachable_pub, - reason = "ported types consumed by sibling stubs not yet wired" -)] - -use crate::diagnostics::{CompilerError, SourceLocation}; - -/// Source location with index and filename fields for logger event serialization. -/// Matches the Babel SourceLocation format that the TS compiler emits in logger events. -#[derive(Debug, Clone)] -pub struct LoggerSourceLocation { - pub start: LoggerPosition, - pub end: LoggerPosition, - pub filename: Option, - pub identifier_name: Option, -} - -#[derive(Debug, Clone)] -pub struct LoggerPosition { - pub line: u32, - pub column: u32, - pub index: Option, -} - -impl LoggerSourceLocation { - /// Create from a diagnostics SourceLocation, adding index and filename. - pub fn from_loc( - loc: &SourceLocation, - filename: Option<&str>, - start_index: Option, - end_index: Option, - ) -> Self { - Self { - start: LoggerPosition { - line: loc.start.line, - column: loc.start.column, - index: start_index, - }, - end: LoggerPosition { - line: loc.end.line, - column: loc.end.column, - index: end_index, - }, - filename: filename.map(|s| s.to_string()), - identifier_name: None, - } - } -} - -/// A variable rename from lowering, serialized for the JS shim. -#[derive(Debug, Clone)] -pub struct BindingRenameInfo { - pub original: String, - pub renamed: String, - pub declaration_start: u32, -} +use crate::diagnostics::CompilerError; /// Main result type returned by the compile function. /// @@ -65,131 +10,9 @@ pub enum CompileOutput { /// No components/hooks found, or all opted out. Unchanged, /// At least one function was compiled; bodies were rewritten in place. - Changed { - diagnostics: Vec, - events: Vec, - ordered_log: Vec, - /// Bindings the lowerer renamed; the caller must patch references in - /// the surrounding (uncompiled) scope. - renames: Vec, - }, - /// `panic_threshold` escalated a compile error to fatal. Carries the logger - /// events emitted for earlier functions in the file so the caller can flush - /// them before throwing. - Error { - error: CompilerError, - events: Vec, - ordered_log: Vec, - }, + Changed { diagnostics: Vec }, + /// `panic_threshold` escalated a compile error to fatal. + Error { error: CompilerError }, } pub struct CompileDiagnostic {} - -/// An item in the ordered log, which can be either a logger event or a debug entry. -#[derive(Debug, Clone)] -#[allow( - clippy::large_enum_variant, - reason = "LoggerEvent is from vendored react_compiler_hir; boxing would diverge from upstream's by-value shape" -)] -pub enum OrderedLogItem { - Event { event: LoggerEvent }, - Debug { entry: DebugLogEntry }, -} - -/// Serializable error detail — flat plain object matching the TS -/// `formatDetailForLogging()` output. All fields are direct properties. -#[derive(Debug, Clone)] -pub struct CompilerErrorDetailInfo { - pub category: String, - pub reason: String, - pub description: Option, - pub severity: String, - pub suggestions: Option>, - pub details: Option>, - pub loc: Option, -} - -/// Serializable suggestion info for logger events. -#[derive(Debug, Clone)] -pub struct LoggerSuggestionInfo { - pub description: String, - pub op: LoggerSuggestionOp, - pub range: (usize, usize), - pub text: Option, -} - -/// Numeric enum matching TS `CompilerSuggestionOperation`. -/// Serialized as the numeric discriminant (0-3), not the variant name. -#[derive(Debug, Clone, Copy)] -pub enum LoggerSuggestionOp { - InsertBefore = 0, - InsertAfter = 1, - Remove = 2, - Replace = 3, -} - -/// Individual error or hint item within a CompilerErrorDetailInfo. -#[derive(Debug, Clone)] -pub struct CompilerErrorItemInfo { - pub kind: String, - pub loc: Option, - /// Serialized as `null` when None (not omitted), matching TS behavior. - pub message: Option, -} - -/// Debug log entry for debugLogIRs support. -/// Currently only supports the 'debug' variant (string values). -#[derive(Debug, Clone)] -pub struct DebugLogEntry { - pub kind: &'static str, - pub name: String, - pub value: String, -} - -impl DebugLogEntry { - pub fn new(name: impl Into, value: impl Into) -> Self { - Self { - kind: "debug", - name: name.into(), - value: value.into(), - } - } -} - -/// Logger events emitted during compilation. -/// These are returned to JS for the logger callback. -#[derive(Debug, Clone)] -pub enum LoggerEvent { - CompileSuccess { - fn_loc: Option, - fn_name: Option, - memo_slots: u32, - memo_blocks: u32, - memo_values: u32, - pruned_memo_blocks: u32, - pruned_memo_values: u32, - }, - CompileError { - detail: CompilerErrorDetailInfo, - fn_loc: Option, - }, - /// Serializes as `kind: "CompileError"` (same tag as `CompileError`); this - /// variant exists only to force fnLoc-before-detail field order. - CompileErrorWithLoc { - fn_loc: LoggerSourceLocation, - detail: CompilerErrorDetailInfo, - }, - CompileSkip { - fn_loc: Option, - reason: String, - loc: Option, - }, - CompileUnexpectedThrow { - fn_loc: Option, - data: String, - }, - PipelineError { - fn_loc: Option, - data: String, - }, -} diff --git a/src/react_compiler/diagnostics/mod.rs b/src/react_compiler/diagnostics/mod.rs index 8735c033f472..11070d88d713 100644 --- a/src/react_compiler/diagnostics/mod.rs +++ b/src/react_compiler/diagnostics/mod.rs @@ -2,7 +2,6 @@ clippy::disallowed_types, clippy::disallowed_methods, unreachable_pub, - dead_code, reason = "ported from facebook/react react_compiler_diagnostics; uses std collections by design" )] #![allow( @@ -44,8 +43,6 @@ pub enum ErrorCategory { UnsupportedSyntax, Config, Gating, - Suppression, - FBT, } /// Error severity levels @@ -73,26 +70,11 @@ impl ErrorCategory { _ => ErrorSeverity::Error, } } - - /// The severity to use in logged output, matching the TS compiler's - /// `getRuleForCategory()`. This may differ from the internal `severity()` - /// used for panicThreshold logic. In particular, `PreserveManualMemo` is - /// `Warning` internally (so it doesn't trigger panicThreshold throws) but - /// `Error` in logged output (matching TS behavior). - pub fn logged_severity(&self) -> ErrorSeverity { - match self { - ErrorCategory::PreserveManualMemo => ErrorSeverity::Error, - _ => self.severity(), - } - } } /// Suggestion operations for auto-fixes #[derive(Debug, Clone)] pub enum CompilerSuggestionOperation { - InsertBefore, - InsertAfter, - Remove, Replace, } @@ -102,7 +84,7 @@ pub struct CompilerSuggestion { pub op: CompilerSuggestionOperation, pub range: (usize, usize), pub description: String, - pub text: Option, // None for Remove operations + pub text: Option, } /// Source location (matches Babel's SourceLocation format) @@ -170,10 +152,6 @@ impl CompilerDiagnostic { self.category.severity() } - pub fn logged_severity(&self) -> ErrorSeverity { - self.category.logged_severity() - } - pub fn with_detail(mut self, detail: CompilerDiagnosticDetail) -> Self { self.details.push(detail); self @@ -247,10 +225,6 @@ impl CompilerErrorDetail { pub fn severity(&self) -> ErrorSeverity { self.category.severity() } - - pub fn logged_severity(&self) -> ErrorSeverity { - self.category.logged_severity() - } } /// Aggregate compiler error - can contain multiple diagnostics. @@ -282,13 +256,6 @@ impl CompilerErrorOrDiagnostic { } } - pub fn logged_severity(&self) -> ErrorSeverity { - match self { - Self::Diagnostic(d) => d.logged_severity(), - Self::ErrorDetail(d) => d.logged_severity(), - } - } - pub fn category(&self) -> ErrorCategory { match self { Self::Diagnostic(d) => d.category, @@ -412,8 +379,6 @@ impl std::fmt::Display for CompilerError { } } -impl std::error::Error for CompilerError {} - pub fn format_category_heading(category: ErrorCategory) -> &'static str { match category { ErrorCategory::EffectDependencies diff --git a/src/react_compiler/hir/environment.rs b/src/react_compiler/hir/environment.rs index 7a4ada868b1b..2b628b38a02f 100644 --- a/src/react_compiler/hir/environment.rs +++ b/src/react_compiler/hir/environment.rs @@ -21,15 +21,6 @@ use crate::hir::object_shape::default_mutating_hook; use crate::hir::object_shape::default_nonmutating_hook; use crate::hir::*; -/// A variable rename from lowering: the binding at `declaration_start` position -/// was renamed from `original` to `renamed`. -#[derive(Debug, Clone, Copy)] -pub struct BindingRename { - pub original: StoreStr, - pub renamed: StoreStr, - pub declaration_start: u32, -} - /// Output mode for the compiler, mirrored from the entrypoint's CompilerOutputMode. /// Stored on Environment so pipeline passes can access it. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -72,10 +63,6 @@ pub struct Environment { pub instrument_gating_name: Option, pub hook_guard_name: Option, - // Renames: tracks variable renames from lowering (original_name → new_name) - // keyed by binding declaration position, for applying back to the Babel AST. - pub renames: HirVec, - // Node IDs of identifiers that are actual references to bindings. // Used by codegen to filter type annotation renames — only rename identifiers // whose node_id is in this set (type labels like ObjectTypeIndexer params @@ -189,7 +176,6 @@ impl Environment { instrument_fn_name: None, instrument_gating_name: None, hook_guard_name: None, - renames: AstAlloc::vec(), reference_node_ids: HashSet::new(), hoisted_identifiers: HashSet::new(), validate_preserve_existing_memoization_guarantees: config diff --git a/src/react_compiler/hir/reactive.rs b/src/react_compiler/hir/reactive.rs index 7e45747f551e..cc8c8d729206 100644 --- a/src/react_compiler/hir/reactive.rs +++ b/src/react_compiler/hir/reactive.rs @@ -131,16 +131,6 @@ pub enum ReactiveTerminalTargetKind { Unlabeled, } -impl std::fmt::Display for ReactiveTerminalTargetKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ReactiveTerminalTargetKind::Implicit => write!(f, "implicit"), - ReactiveTerminalTargetKind::Labeled => write!(f, "labeled"), - ReactiveTerminalTargetKind::Unlabeled => write!(f, "unlabeled"), - } - } -} - #[derive(Debug, Clone)] pub enum ReactiveTerminal { Break { diff --git a/src/react_compiler/hir/type_config.rs b/src/react_compiler/hir/type_config.rs index adb720181dc0..bb65130d842c 100644 --- a/src/react_compiler/hir/type_config.rs +++ b/src/react_compiler/hir/type_config.rs @@ -38,7 +38,6 @@ pub enum ValueReason { HookReturn, Global, JsxCaptured, - StoreLocal, ReactiveFunctionArgument, Other, } diff --git a/src/react_compiler/imports.rs b/src/react_compiler/imports.rs index 70adc8751221..3a64f98ef155 100644 --- a/src/react_compiler/imports.rs +++ b/src/react_compiler/imports.rs @@ -42,9 +42,6 @@ pub(crate) struct ProgramContext { pub(crate) instrument_gating_name: Option, pub(crate) hook_guard_name: Option, - // Variable renames from lowering, to be applied back to the Babel AST - pub(crate) renames: Vec, - // Internal state known_referenced_names: IndexSet, imports: IndexMap<&'static str, IndexMap<&'static str, NonLocalImportSpecifier>>, @@ -68,7 +65,6 @@ impl ProgramContext { instrument_fn_name: None, instrument_gating_name: None, hook_guard_name: None, - renames: Vec::new(), known_referenced_names: IndexSet::new(), imports: IndexMap::new(), } diff --git a/src/react_compiler/lowering/hir_builder.rs b/src/react_compiler/lowering/hir_builder.rs index e0a08e3bc45c..54e5bacfcec8 100644 --- a/src/react_compiler/lowering/hir_builder.rs +++ b/src/react_compiler/lowering/hir_builder.rs @@ -917,17 +917,6 @@ impl<'h> HirBuilder<'h> { } else { StoreStr::new(bun_ast::data_store_dupe_str(candidate.as_bytes())) }; - if candidate != name { - if let Some(start) = loc.as_ref().and_then(|l| l.start.index) { - self.env - .renames - .push(crate::hir::environment::BindingRename { - original: stored_name, - renamed: stored_candidate, - declaration_start: start, - }); - } - } let id = self.env.next_identifier_id(); self.env.identifiers[id.0 as usize].name = Some(IdentifierName::Named(stored_candidate)); diff --git a/src/react_compiler/pipeline.rs b/src/react_compiler/pipeline.rs index 8844745854a8..dd497eaa446e 100644 --- a/src/react_compiler/pipeline.rs +++ b/src/react_compiler/pipeline.rs @@ -11,9 +11,9 @@ //! //! Upstream's `ProgramContext` carries `timing` / `debug_enabled` / //! `log_debug` / `log_event`; the Bun port's [`ProgramContext`] does not (Bun -//! has no Babel-shim debug surface), so the per-pass timing and -//! `log_debug(DebugLogEntry::new(...))` calls are dropped. The pass *sequence* -//! and gating predicates are kept byte-identical with upstream. +//! has no Babel-shim debug surface), so the per-pass timing and debug log +//! calls are dropped. The pass *sequence* and gating predicates are kept +//! byte-identical with upstream. #![allow( clippy::disallowed_types, @@ -154,11 +154,6 @@ pub(crate) fn compile_fn( lowering::lower(func, fn_name, &*host, &mut env, import_bindings) )?; - // Copy renames from lowering to context (keep on env for codegen to apply to type annotations) - if !env.renames.is_empty() { - context.renames.extend(env.renames.iter().cloned()); - } - // Upstream `lower()` ends with `if (builder.errors.hasAnyErrors()) return Err(...)` // before `builder.build()`, so any error recorded during lowering — Todo // (throw-in-try, var, …), Syntax, or Invariant — short-circuits the diff --git a/src/react_compiler/program.rs b/src/react_compiler/program.rs index 239248ca496e..effb2b236acf 100644 --- a/src/react_compiler/program.rs +++ b/src/react_compiler/program.rs @@ -48,7 +48,6 @@ pub enum JsxImportKind { Jsxs, JsxDEV, Fragment, - CreateElement, } /// Parser-side state the React Compiler needs. Implemented by `P` at the @@ -1015,11 +1014,7 @@ fn handle_error( .any(|d| d.category() == ErrorCategory::Config); if should_panic || is_config_error { - Some(CompileOutput::Error { - error: err, - events: Vec::new(), - ordered_log: Vec::new(), - }) + Some(CompileOutput::Error { error: err }) } else { None } @@ -1374,9 +1369,6 @@ pub fn finish( } else { CompileOutput::Changed { diagnostics: state.diagnostics, - events: Vec::new(), - ordered_log: Vec::new(), - renames: convert_renames(&state.context.renames), } }; } @@ -1386,21 +1378,5 @@ pub fn finish( CompileOutput::Changed { diagnostics: state.diagnostics, - events: Vec::new(), - ordered_log: Vec::new(), - renames: convert_renames(&state.context.renames), } } - -fn convert_renames( - renames: &[crate::hir::environment::BindingRename], -) -> Vec { - renames - .iter() - .map(|r| crate::compile_result::BindingRenameInfo { - original: bun_core::BStr::new(r.original.slice()).to_string(), - renamed: bun_core::BStr::new(r.renamed.slice()).to_string(), - declaration_start: r.declaration_start, - }) - .collect() -} diff --git a/src/runtime/api/bun/subprocess/SubprocessPipeReader.rs b/src/runtime/api/bun/subprocess/SubprocessPipeReader.rs index 0f18b54cc349..42c96194c14d 100644 --- a/src/runtime/api/bun/subprocess/SubprocessPipeReader.rs +++ b/src/runtime/api/bun/subprocess/SubprocessPipeReader.rs @@ -28,7 +28,6 @@ pub enum State { // Intrusive, single-thread ref-count; `deinit` runs when the last ref drops. #[derive(bun_ptr::RefCounted)] -#[ref_count(debug_name = "PipeReader")] pub struct PipeReader { pub(crate) reader: IOReader, // Backref to owning Subprocess; cleared in detach()/onReaderDone()/onReaderError(). diff --git a/src/runtime/api/js_bundle_completion_task.rs b/src/runtime/api/js_bundle_completion_task.rs index b2104423d778..48682b83905d 100644 --- a/src/runtime/api/js_bundle_completion_task.rs +++ b/src/runtime/api/js_bundle_completion_task.rs @@ -46,7 +46,6 @@ use crate::server::html_bundle; /// See module doc for the layering rationale. #[derive(bun_ptr::RefCounted)] -#[ref_count(debug_name = "JSBundleCompletionTask")] pub struct JSBundleCompletionTask { // NOTE: this should arguably be a thread-safe refcount, but it is the plain // (non-atomic) `RefCount` — a pre-existing discrepancy. See the diff --git a/src/runtime/server/HTMLBundle.rs b/src/runtime/server/HTMLBundle.rs index 4d55bc40ec52..a6593e5527bf 100644 --- a/src/runtime/server/HTMLBundle.rs +++ b/src/runtime/server/HTMLBundle.rs @@ -39,7 +39,6 @@ use debug_scope::HTMLBundle as debug; // HTMLBundle can be owned by JavaScript as well as any number of Server instances, // hence the ref count alongside the JS wrapper. #[derive(bun_ptr::RefCounted)] -#[ref_count(debug_name = "HTMLBundle")] pub struct HTMLBundle { ref_count: RefCount, pub global: bun_ptr::BackRef, @@ -143,7 +142,6 @@ pub(crate) type HTMLBundleRoute = Route; // `JSBundleCompletionTask` while a prior `&Route` may still be on the // stack — `&mut self` would alias (UB); `&self` + `UnsafeCell` is sound. #[derive(bun_ptr::RefCounted)] -#[ref_count(debug_name = "HTMLBundleRoute")] pub struct Route { pub(crate) bundle: RefPtr, /// One HTMLBundle.Route can be specified multiple times diff --git a/src/runtime/valkey_jsc/protocol_jsc.rs b/src/runtime/valkey_jsc/protocol_jsc.rs index 9f46eae38afb..47ca4411dbea 100644 --- a/src/runtime/valkey_jsc/protocol_jsc.rs +++ b/src/runtime/valkey_jsc/protocol_jsc.rs @@ -20,23 +20,18 @@ pub(crate) fn valkey_error_to_js( RedisError::ConnectionClosed => JscError::REDIS_CONNECTION_CLOSED, RedisError::InvalidResponse => JscError::REDIS_INVALID_RESPONSE, RedisError::InvalidBulkString => JscError::REDIS_INVALID_BULK_STRING, - RedisError::InvalidArray => JscError::REDIS_INVALID_ARRAY, RedisError::InvalidInteger => JscError::REDIS_INVALID_INTEGER, - RedisError::InvalidSimpleString => JscError::REDIS_INVALID_SIMPLE_STRING, - RedisError::InvalidErrorString => JscError::REDIS_INVALID_ERROR_STRING, RedisError::InvalidDouble | RedisError::InvalidBoolean | RedisError::InvalidNull | RedisError::InvalidMap | RedisError::InvalidSet - | RedisError::InvalidBigNumber | RedisError::InvalidVerbatimString | RedisError::InvalidBlobError | RedisError::InvalidAttribute | RedisError::InvalidPush => JscError::REDIS_INVALID_RESPONSE, RedisError::AuthenticationFailed => JscError::REDIS_AUTHENTICATION_FAILED, RedisError::InvalidCommand => JscError::REDIS_INVALID_COMMAND, - RedisError::InvalidArgument => JscError::REDIS_INVALID_ARGUMENT, RedisError::UnsupportedProtocol => JscError::REDIS_INVALID_RESPONSE, RedisError::InvalidResponseType => JscError::REDIS_INVALID_RESPONSE_TYPE, RedisError::ConnectionTimeout => JscError::REDIS_CONNECTION_TIMEOUT, diff --git a/src/sql_jsc/shared/SQLDataCell.rs b/src/sql_jsc/shared/SQLDataCell.rs index f1c8ce9aceac..277ea617613b 100644 --- a/src/sql_jsc/shared/SQLDataCell.rs +++ b/src/sql_jsc/shared/SQLDataCell.rs @@ -468,7 +468,7 @@ impl SQLDataCell { } } -/// Coercion helper for `raw()` call sites. Lets callers pass `&Data`, `&mut Data`, +/// Coercion helper for `raw()` call sites. Lets callers pass `&Data`, /// `Option<&Data>`, or `Option<&mut Data>` without wrapping. pub trait IntoOptionalData<'a> { fn into_optional_data(self) -> Option<&'a Data>; @@ -479,12 +479,6 @@ impl<'a> IntoOptionalData<'a> for &'a Data { Some(self) } } -impl<'a> IntoOptionalData<'a> for &'a mut Data { - #[inline] - fn into_optional_data(self) -> Option<&'a Data> { - Some(&*self) - } -} impl<'a> IntoOptionalData<'a> for Option<&'a Data> { #[inline] fn into_optional_data(self) -> Option<&'a Data> { diff --git a/src/tcc_sys/tcc.rs b/src/tcc_sys/tcc.rs index 0a95ffe74e7b..5113a031ebe1 100644 --- a/src/tcc_sys/tcc.rs +++ b/src/tcc_sys/tcc.rs @@ -66,12 +66,6 @@ tcc_externs! { } const TCC_OUTPUT_MEMORY: c_int = 1; -const TCC_OUTPUT_EXE: c_int = 2; -// NOTE: vendor/tinycc/libtcc.h defines OBJ=3, DLL=4 (Bun's fork swapped vs upstream); -// match libtcc.h here. -const TCC_OUTPUT_OBJ: c_int = 3; -const TCC_OUTPUT_DLL: c_int = 4; -const TCC_OUTPUT_PREPROCESS: c_int = 5; #[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error, strum::IntoStaticStr)] pub enum Error { @@ -84,20 +78,13 @@ pub enum Error { // output #[error("InvalidOutputType")] InvalidOutputType, - #[error("SyntaxError")] - SyntaxError, #[error("InvalidLibraryPath")] InvalidLibraryPath, #[error("InvalidSymbol")] InvalidSymbol, - #[error("ExecError")] - ExecError, /// Could not get a symbol for some reason #[error("RelocationError")] RelocationError, - // Returned by `output_file`. - #[error("OutputError")] - OutputError, #[error(transparent)] Alloc(#[from] bun_alloc::AllocError), } @@ -108,14 +95,6 @@ pub enum OutputFormat { /// Output will be run in memory #[default] Memory = TCC_OUTPUT_MEMORY as _, - /// Executable file - Exe = TCC_OUTPUT_EXE as _, - /// Dynamic library - Dll = TCC_OUTPUT_DLL as _, - /// Object file - Obj = TCC_OUTPUT_OBJ as _, - /// Only preprocess - Preprocess = TCC_OUTPUT_PREPROCESS as _, } // Nominal type for some registered symbol. Used to force pointer-cast usage without diff --git a/src/valkey/valkey_protocol.rs b/src/valkey/valkey_protocol.rs index 9ea0a4862802..f2d01c2d2cae 100644 --- a/src/valkey/valkey_protocol.rs +++ b/src/valkey/valkey_protocol.rs @@ -6,16 +6,12 @@ use bstr::BStr; pub enum RedisError { AuthenticationFailed, ConnectionClosed, - InvalidArgument, - InvalidArray, InvalidAttribute, - InvalidBigNumber, InvalidBlobError, InvalidBoolean, InvalidBulkString, InvalidCommand, InvalidDouble, - InvalidErrorString, InvalidInteger, InvalidMap, InvalidNull, @@ -23,7 +19,6 @@ pub enum RedisError { InvalidResponse, InvalidResponseType, InvalidSet, - InvalidSimpleString, InvalidVerbatimString, JSError, OutOfMemory, diff --git a/test/internal/source-lints/module-lint-escapes.json b/test/internal/source-lints/module-lint-escapes.json new file mode 100644 index 000000000000..897bdad4cc41 --- /dev/null +++ b/test/internal/source-lints/module-lint-escapes.json @@ -0,0 +1,20 @@ +{ + "src/install/windows-shim/main.rs": 1, + "src/jsc/cpp.rs": 1, + "src/react_compiler/diagnostics/mod.rs": 1, + "src/react_compiler/hir/mod.rs": 1, + "src/react_compiler/inference/mod.rs": 1, + "src/react_compiler/optimization/mod.rs": 1, + "src/react_compiler/reactive_scopes/mod.rs": 1, + "src/react_compiler/ssa/mod.rs": 1, + "src/react_compiler/typeinference/mod.rs": 1, + "src/react_compiler/utils/mod.rs": 1, + "src/react_compiler/validation/mod.rs": 1, + "src/runtime/api/bun/h2/connection.rs": 1, + "src/runtime/api/bun/h2/flow_control.rs": 1, + "src/runtime/api/bun/h2/hpack.rs": 1, + "src/runtime/api/bun/h2/settings.rs": 1, + "src/runtime/api/bun/h2/stream.rs": 1, + "src/runtime/api/bun/h2/wire.rs": 1, + "src/runtime/generated_classes.rs": 1 +} diff --git a/test/internal/source-lints/module-lint-escapes.test.ts b/test/internal/source-lints/module-lint-escapes.test.ts new file mode 100644 index 000000000000..93f70b5c0c9a --- /dev/null +++ b/test/internal/source-lints/module-lint-escapes.test.ts @@ -0,0 +1,100 @@ +// Inventory of module-level `#![allow(dead_code)]` / `#![allow(unreachable_pub)]` +// escapes in the Rust sources. +// +// The workspace compiles with `dead_code = "deny"` and `unreachable_pub = "deny"`, +// so an item nothing uses fails the build, and a `pub` item has to be imported +// by another crate. A module-level `#![allow(...)]` for either lint switches +// that analysis off for the whole file: every item in it can go dead without a +// compile error, and `pub` stops meaning "another crate uses this". The +// sibling `dead-code-escapes.test.ts` pins the item-level escapes; this file +// pins the module-level ones, per file, so a new opt-out is a deliberate +// change to this inventory and a file that drops its opt-out updates it. +// +// If this test fails because a count went UP: prefer deleting the dead items +// (or narrowing `pub` to `pub(crate)`) over adding the module-level escape. If +// the escape is justified (a codegen surface, a port that is wired up in +// stages), update the inventory by running +// `bun ./test/internal/source-lints/module-lint-escapes.test.ts --write`. +// +// If it fails because a count went DOWN: you removed an escape. Update the +// inventory the same way so it stays accurate. + +import { file } from "bun"; +import { describe, test } from "bun:test"; +import { realpathSync } from "fs"; +import path from "path"; +import { globAllSources } from "../../../scripts/glob-sources.ts"; + +// A module-level `#![allow(...)]`, including one that rustfmt wrapped across +// several lines. `[^\]]*` cannot cross a `]`, so a match never spans from one +// attribute into the next. +const MODULE_ALLOW = /#!\[\s*allow\(([^\]]*)\)\s*\]/g; +// The lint names inside the attribute. `\b` keeps `clippy::dead_code`-style +// paths from matching only when the segment is the bare rustc lint. +const ESCAPED_LINT = /(? = await Bun.file(import.meta.dir + "/module-lint-escapes.json").json(); + +const root = path.resolve(import.meta.dir, "..", "..", ".."); +const rustSources = globAllSources().rust.filter(p => p.endsWith(".rs")); + +// Only count files tracked in HEAD, for the same reason as +// dead-code-escapes.test.ts: stray `.rs` files a branch deletes can come back +// during a `git stash` round-trip, and they must not fail the ratchet. +const tracked: Set | null = (() => { + const r = Bun.spawnSync({ + cmd: ["git", "-C", root, "ls-tree", "-r", "--name-only", "-z", "HEAD"], + stdout: "pipe", + stderr: "ignore", + }); + if (!r.success) return null; + return new Set(r.stdout.toString().split("\0").filter(Boolean)); +})(); + +const counts: Record = {}; +for (const abs of rustSources) { + const source = path.relative(root, abs).replaceAll(path.sep, "/"); + // `src/cli` is a symlink into `src/runtime/cli`; count each file once + // under its canonical path. + if (path.relative(root, realpathSync(abs)).replaceAll(path.sep, "/") !== source) continue; + if (tracked !== null && !tracked.has(source)) continue; + const content = await file(abs).text(); + // Strip full-line `//` comments first so a commented-out escape stays ignored. + const stripped = content.replace(/^\s*\/\/.*$/gm, ""); + let n = 0; + for (const [, lints] of stripped.matchAll(MODULE_ALLOW)) { + if (ESCAPED_LINT.test(lints)) n++; + } + if (n > 0) counts[source] = n; +} + +if (process.argv.includes("--write")) { + // `bun ./test/internal/source-lints/module-lint-escapes.test.ts --write`: + // regenerate the inventory from the current tree. + const sorted = Object.fromEntries(Object.entries(counts).sort(([a], [b]) => (a < b ? -1 : 1))); + await Bun.write(import.meta.dir + "/module-lint-escapes.json", JSON.stringify(sorted, null, 2) + "\n"); + console.log(`Wrote ${Object.keys(sorted).length} files to module-lint-escapes.json`); + process.exit(0); +} + +describe("module-level #![allow(dead_code)] / #![allow(unreachable_pub)] escapes", () => { + const files = new Set([...Object.keys(limits), ...Object.keys(counts)]); + for (const source of [...files].sort()) { + const limit = limits[source] ?? 0; + const count = counts[source] ?? 0; + test(`${source} (${limit})`, () => { + if (count > limit) { + throw new Error( + `${source} has ${count} module-level dead_code/unreachable_pub escapes, up from ${limit}.\n` + + `A module-level escape hides every dead item in the file from the compiler. Delete the dead items or use pub(crate) instead.\n` + + `If the escape is justified, update the inventory with \`bun ./test/internal/source-lints/module-lint-escapes.test.ts\`.`, + ); + } else if (count < limit) { + throw new Error( + `${source} has ${count} module-level dead_code/unreachable_pub escapes, down from ${limit}.\n` + + `Update the inventory with \`bun ./test/internal/source-lints/module-lint-escapes.test.ts\`.`, + ); + } + }); + } +}); From 89fa00e1bcaabf26fe4ecd13ea5cee58d8eb8354 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Fri, 28 Aug 2026 04:01:52 +0000 Subject: [PATCH 2/6] module-lint-escapes: name the --write flag in the failure messages --- test/internal/source-lints/module-lint-escapes.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/internal/source-lints/module-lint-escapes.test.ts b/test/internal/source-lints/module-lint-escapes.test.ts index 93f70b5c0c9a..b5315b3f1970 100644 --- a/test/internal/source-lints/module-lint-escapes.test.ts +++ b/test/internal/source-lints/module-lint-escapes.test.ts @@ -87,12 +87,12 @@ describe("module-level #![allow(dead_code)] / #![allow(unreachable_pub)] escapes throw new Error( `${source} has ${count} module-level dead_code/unreachable_pub escapes, up from ${limit}.\n` + `A module-level escape hides every dead item in the file from the compiler. Delete the dead items or use pub(crate) instead.\n` + - `If the escape is justified, update the inventory with \`bun ./test/internal/source-lints/module-lint-escapes.test.ts\`.`, + `If the escape is justified, update the inventory with \`bun ./test/internal/source-lints/module-lint-escapes.test.ts --write\`.`, ); } else if (count < limit) { throw new Error( `${source} has ${count} module-level dead_code/unreachable_pub escapes, down from ${limit}.\n` + - `Update the inventory with \`bun ./test/internal/source-lints/module-lint-escapes.test.ts\`.`, + `Update the inventory with \`bun ./test/internal/source-lints/module-lint-escapes.test.ts --write\`.`, ); } }); From f90bdbcdd6bb53c966ec00797959cdeb219b9b0b Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Fri, 28 Aug 2026 04:02:39 +0000 Subject: [PATCH 3/6] react_compiler: shorten the pipeline module doc --- src/react_compiler/pipeline.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/react_compiler/pipeline.rs b/src/react_compiler/pipeline.rs index dd497eaa446e..0c51c4ab5f22 100644 --- a/src/react_compiler/pipeline.rs +++ b/src/react_compiler/pipeline.rs @@ -9,11 +9,9 @@ //! //! Port of `react_compiler/entrypoint/pipeline.rs` — see DESIGN.md. //! -//! Upstream's `ProgramContext` carries `timing` / `debug_enabled` / -//! `log_debug` / `log_event`; the Bun port's [`ProgramContext`] does not (Bun -//! has no Babel-shim debug surface), so the per-pass timing and debug log -//! calls are dropped. The pass *sequence* and gating predicates are kept -//! byte-identical with upstream. +//! Bun has no Babel-shim debug surface, so upstream's per-pass timing and +//! debug log calls are not ported. The pass sequence and gating predicates +//! match upstream. #![allow( clippy::disallowed_types, From 1ac5d1945d6b48a1d5f7c45c580ebbbd039fc801 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Fri, 28 Aug 2026 04:04:06 +0000 Subject: [PATCH 4/6] react_compiler: drop the pipeline module doc paragraph about unported debug logging --- src/react_compiler/pipeline.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/react_compiler/pipeline.rs b/src/react_compiler/pipeline.rs index 0c51c4ab5f22..20581e1e8dff 100644 --- a/src/react_compiler/pipeline.rs +++ b/src/react_compiler/pipeline.rs @@ -8,10 +8,6 @@ //! Analogous to TS `Pipeline.ts` (`compileFn` → `run` → `runWithEnvironment`). //! //! Port of `react_compiler/entrypoint/pipeline.rs` — see DESIGN.md. -//! -//! Bun has no Babel-shim debug surface, so upstream's per-pass timing and -//! debug log calls are not ported. The pass sequence and gating predicates -//! match upstream. #![allow( clippy::disallowed_types, From a023e2016f7717b4eb535184b9df2a2f5c69ab95 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Fri, 28 Aug 2026 04:17:27 +0000 Subject: [PATCH 5/6] hawk.toml: drop the override for the removed WeakRefType::PostgreSQLQueryClient --- hawk.toml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/hawk.toml b/hawk.toml index a70d0ab48b5e..3c51c93f8a44 100644 --- a/hawk.toml +++ b/hawk.toml @@ -444,14 +444,6 @@ kind = "enum_variant" level = "expect" reason = "external code table: regular-expression flag bits shared with JSC" -[[override]] -lint = "hawk::dead_public" -crate = "bun_jsc" -item = "weak::WeakRefType::PostgreSQLQueryClient" -kind = "enum_variant" -level = "expect" -reason = "external code table: weak-ref type numbering shared with JSC" - [[override]] lint = "hawk::dead_public" crate = "bun_runtime" From 6d7ad0465d40d37fda569d0ff6608556a1293037 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Fri, 28 Aug 2026 04:41:09 +0000 Subject: [PATCH 6/6] ci: retrigger