diff --git a/src/ast/b.rs b/src/ast/b.rs index 68d4316f2ce..228bbc170a8 100644 --- a/src/ast/b.rs +++ b/src/ast/b.rs @@ -50,15 +50,12 @@ impl Default for B { } // ── Layout guards ───────────────────────────────────────────────────────── -// Three `StoreRef` variants (`#[repr(transparent)] NonNull`, 8-byte -// payload) + one ZST → 1-byte discriminant + 8-byte payload = 9, align(8) -// rounds to 16. `Binding` = `B` (16, align 8) + `Loc` (i32) → 20 → 24. -// Matches `expr::Data`/`stmt::Data`: every pointer payload is non-nullable, -// so `Option` packs into the same 16 bytes via the NonNull niche (and -// would continue to even under a future `#[repr(u8)]`, unlike the prior -// `*mut T` form which relied solely on spare-tag-value niche). -const _: () = assert!(core::mem::size_of::() == 16); -const _: () = assert!(core::mem::size_of::() == 24); +// Three `StoreRef` variants (8 B align 4) + one ZST → 1-byte discriminant +// + 8-byte payload = 9, align(4) rounds to 12. `Binding` = `B` (12, align 4) +// + `Loc` (i32) → 16. `Option` niche-packs via spare discriminant values. +const _: () = assert!(core::mem::size_of::() == 12); +const _: () = assert!(core::mem::align_of::() == 4); +const _: () = assert!(core::mem::size_of::() == 16); const _: () = assert!( core::mem::size_of::>() == core::mem::size_of::(), "B lost its niche — check for #[repr] or oversized inline payload" diff --git a/src/ast/e.rs b/src/ast/e.rs index 9b538ece2f3..772420a0fdd 100644 --- a/src/ast/e.rs +++ b/src/ast/e.rs @@ -41,7 +41,7 @@ impl Default for NameOfSymbol { pub struct Array { pub items: ExprNodeList, - pub comma_after_spread: Option, + pub comma_after_spread: crate::Loc, pub is_single_line: bool, pub is_parenthesized: bool, pub was_originally_macro: bool, @@ -51,7 +51,7 @@ impl Default for Array { fn default() -> Self { Self { items: bun_alloc::AstAlloc::vec(), - comma_after_spread: None, + comma_after_spread: crate::Loc::EMPTY, is_single_line: false, is_parenthesized: false, was_originally_macro: false, @@ -63,7 +63,7 @@ impl Default for Array { impl Array { pub const EMPTY: Array = Array { items: bun_alloc::AstAlloc::vec(), - comma_after_spread: None, + comma_after_spread: crate::Loc::EMPTY, is_single_line: false, is_parenthesized: false, was_originally_macro: false, @@ -688,9 +688,35 @@ impl JSXSpecialProp { } } +/// `packed(4)` lowers the alignment to 4 so `expr::Data` (and therefore `Expr`) +/// drop to align 4 and pack into 16 bytes; the `f64` stays a single scalar so +/// `.value()` is one `movsd`/`ldr`. The field is private because comparisons on +/// a packed `f64` field would require `&self.value` (an unaligned reference); +/// callers go through `value()` / `new()` which copy by value. #[derive(Clone, Copy)] +#[repr(C, packed(4))] pub struct Number { - pub value: f64, + value: f64, +} + +const _: () = assert!(core::mem::size_of::() == 8); +const _: () = assert!(core::mem::align_of::() == 4); + +impl Number { + #[inline(always)] + pub const fn new(value: f64) -> Self { + Number { value } + } + #[inline(always)] + pub const fn value(self) -> f64 { + self.value + } +} +impl From for Number { + #[inline] + fn from(v: f64) -> Self { + Number::new(v) + } } const DOUBLE_DIGIT: [&[u8]; 101] = [ @@ -722,7 +748,7 @@ impl Number { /// /// This can return `None` in wasm builds to avoid linking JSC pub fn to_string(self, bump: &Bump) -> Option { - Self::to_string_from_f64(self.value, bump) + Self::to_string_from_f64(self.value(), bump) } pub fn to_string_from_f64(value: f64, bump: &Bump) -> Option { @@ -794,7 +820,7 @@ impl Number { } pub fn to(self) -> T { - let clamped = self.value.trunc().max(0.0).min(T::MAX_AS_F64); + let clamped = self.value().trunc().max(0.0).min(T::MAX_AS_F64); T::from_f64(clamped) } @@ -832,7 +858,7 @@ impl BigInt { pub struct Object { pub properties: G::PropertyList, - pub comma_after_spread: Option, + pub comma_after_spread: crate::Loc, pub is_single_line: bool, pub is_parenthesized: bool, pub was_originally_macro: bool, @@ -843,7 +869,7 @@ impl Default for Object { fn default() -> Self { Self { properties: bun_alloc::AstAlloc::vec(), - comma_after_spread: None, + comma_after_spread: crate::Loc::EMPTY, is_single_line: false, is_parenthesized: false, was_originally_macro: false, @@ -922,7 +948,7 @@ pub struct RopeQuery<'a> { impl Object { pub const EMPTY: Object = Object { properties: bun_alloc::AstAlloc::vec(), - comma_after_spread: None, + comma_after_spread: crate::Loc::EMPTY, is_single_line: false, is_parenthesized: false, was_originally_macro: false, @@ -1585,12 +1611,7 @@ impl EString { // Ordering / equality / const-literal / rope-mutation helpers. // `string_z`/`to_zig_string` remain gated on `bun_core::ZStr` arena constructors. impl EString { - pub const CLASS: EString = EString::from_static(b"class"); pub const EMPTY: EString = EString::from_static(b""); - pub const TRUE: EString = EString::from_static(b"true"); - pub const FALSE: EString = EString::from_static(b"false"); - pub const NULL: EString = EString::from_static(b"null"); - pub const UNDEFINED: EString = EString::from_static(b"undefined"); pub fn is_identifier(&mut self, bump: &Bump) -> bool { if !self.is_utf8() { diff --git a/src/ast/expr.rs b/src/ast/expr.rs index be0f049a8b2..9fb7ca30a97 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -269,7 +269,7 @@ impl Expr { pub fn as_number(&self) -> Option { match self.data { - Data::ENumber(n) => Some(n.value), + Data::ENumber(n) => Some(n.value()), _ => None, } } @@ -1504,7 +1504,7 @@ impl Expr { } Data::ENumber(n) => { return Some(expr.at(E::Boolean { - value: n.value == 0.0 || n.value.is_nan(), + value: n.value() == 0.0 || n.value().is_nan(), })); } Data::EBigInt(b) => { @@ -1738,18 +1738,14 @@ pub enum Data { } // ── Layout guards ───────────────────────────────────────────────────────── -// The identifier-family flags are packed into `Ref`'s spare bits (see -// `E::Identifier` doc), so every inline payload is ≤ 8 bytes; with the -// repr(Rust) discriminant that rounds to 16. `Expr` = `Data` (16, align 8) + -// `Loc` (i32) → 20 → 24 after tail padding. -// -// The `Option` assert proves Rust's niche optimization fires: the enum -// has spare discriminant values (47 variants < 256, and every pointer variant -// contributes a NonNull niche), so `None` packs into an unused bit-pattern -// rather than adding a word. If a future variant adds `#[repr(C)]`/`#[repr(u32)]` -// or a nullable `*mut T` payload, this assert catches the size regression. -const _: () = assert!(core::mem::size_of::() == 16); // Do not increase the size of Expr -const _: () = assert!(core::mem::size_of::() == 24); +// Every payload — `StoreRef` and the inline identifier/`Number`/etc. +// structs — is ≤ 8 bytes at align 4, so `Data` = 1-byte discriminant + 8-byte +// payload → 12 at align 4. `Expr` = `Data` (12, align 4) + `Loc` (i32) → 16. +// `Option`/`Option` niche-pack via spare discriminant values +// (47 variants < 256); a `#[repr(C)]`/`#[repr(u32)]` on `Data` would break it. +const _: () = assert!(core::mem::size_of::() == 12); // Do not increase the size of Expr +const _: () = assert!(core::mem::align_of::() == 4); +const _: () = assert!(core::mem::size_of::() == 16); const _: () = assert!( core::mem::size_of::>() == core::mem::size_of::(), "expr::Data lost its niche — check for #[repr] or nullable-ptr payload" @@ -1758,16 +1754,23 @@ const _: () = assert!( core::mem::size_of::>() == core::mem::size_of::(), "Expr lost its niche — Option is used in G::Property/B::Property/etc." ); -// Inline-payload ceilings (regress any of these and `Data` grows past 16): +// Inline-payload ceilings (regress any of these and `Data` grows past 12). +// `align_of <= 4` is what keeps `Data` (and therefore `Expr`) at align 4. const _: () = assert!(core::mem::size_of::() == 8); +const _: () = assert!(core::mem::align_of::() == 4); const _: () = assert!(core::mem::size_of::() == 8); const _: () = assert!(core::mem::size_of::() == 8); const _: () = assert!(core::mem::size_of::() == 8); const _: () = assert!(core::mem::size_of::() <= 8); +const _: () = assert!(core::mem::align_of::() == 4); const _: () = assert!(core::mem::size_of::() <= 8); const _: () = assert!(core::mem::size_of::() <= 8); const _: () = assert!(core::mem::size_of::() <= 8); const _: () = assert!(core::mem::size_of::>() == core::mem::size_of::()); +// Heap-payload shrinks unlocked by the 12-byte StoreSlice: +const _: () = assert!(core::mem::size_of::() == 16); +const _: () = assert!(core::mem::size_of::() <= 32); +const _: () = assert!(core::mem::size_of::() == 16); // Field-style accessors (`data.e_string()`, `data.e_object()`). The match arms // in this file use these heavily; keeping them as inherent methods avoids @@ -2685,7 +2688,7 @@ impl Data { raw(hasher, e.value); } Data::ENumber(e) => { - raw(hasher, e.value); + raw(hasher, e.value()); } Data::EBigInt(e) => { hasher.update(&e.value); @@ -2990,9 +2993,9 @@ impl Data { Some(string_to_equivalent_number_value(str.slice8())) } Data::EBoolean(b) | Data::EBranchBoolean(b) => Some(if b.value { 1.0 } else { 0.0 }), - Data::ENumber(n) => Some(n.value), + Data::ENumber(n) => Some(n.value()), Data::EInlinedEnum(inlined) => match &inlined.value.data { - Data::ENumber(num) => Some(num.value), + Data::ENumber(num) => Some(num.value()), Data::EString(str) => { if str.next.is_some() { return None; @@ -3013,16 +3016,16 @@ impl Data { match self { Data::EBoolean(b) | Data::EBranchBoolean(b) => Some(if b.value { 1.0 } else { 0.0 }), Data::ENumber(n) => { - if n.value.is_finite() { - Some(n.value) + if n.value().is_finite() { + Some(n.value()) } else { None } } Data::EInlinedEnum(inlined) => match &inlined.value.data { Data::ENumber(num) => { - if num.value.is_finite() { - Some(num.value) + if num.value().is_finite() { + Some(num.value()) } else { None } @@ -3035,9 +3038,9 @@ impl Data { pub fn extract_numeric_value(&self) -> Option { match self { - Data::ENumber(n) => Some(n.value), + Data::ENumber(n) => Some(n.value()), Data::EInlinedEnum(inlined) => match &inlined.value.data { - Data::ENumber(num) => Some(num.value), + Data::ENumber(num) => Some(num.value()), _ => None, }, _ => None, @@ -3173,9 +3176,9 @@ impl Data { return Equality { ok: true, equal: if l.value { - num.value == 1.0 + num.value() == 1.0 } else { - num.value == 0.0 + num.value() == 0.0 }, ..Default::default() }; @@ -3189,7 +3192,7 @@ impl Data { Data::ENumber(r) => { return Equality { ok: true, - equal: l.value == r.value, + equal: l.value() == r.value(), ..Default::default() }; } @@ -3197,7 +3200,7 @@ impl Data { if let Data::ENumber(rn) = &r.value.data { return Equality { ok: true, - equal: l.value == rn.value, + equal: l.value() == rn.value(), ..Default::default() }; } @@ -3209,9 +3212,9 @@ impl Data { // "1 == true" is true // "0 == false" is true equal: if r.value { - l.value == 1.0 + l.value() == 1.0 } else { - l.value == 0.0 + l.value() == 0.0 }, ..Default::default() }; @@ -3277,10 +3280,10 @@ impl Data { Data::ENumber(r) => { if !K::STRICT { l.resolve_rope_if_needed(p.arena()); - if r.value == 0.0 && (l.is_blank() || l.eql_comptime(b"0")) { + if r.value() == 0.0 && (l.is_blank() || l.eql_comptime(b"0")) { return Equality::TRUE; } - if r.value == 1.0 && l.eql_comptime(b"1") { + if r.value() == 1.0 && l.eql_comptime(b"1") { return Equality::TRUE; } // the string could still equal 0 or 1 but it could be hex, binary, octal, ... diff --git a/src/ast/g.rs b/src/ast/g.rs index c17113ef0b5..8438a5522c8 100644 --- a/src/ast/g.rs +++ b/src/ast/g.rs @@ -280,7 +280,7 @@ pub struct Fn { // This was originally nullable, but doing so I believe caused a miscompilation // Specifically, the body was always null. pub body: FnBody, - pub arguments_ref: Option, + pub arguments_ref: Ref, pub flags: flags::FunctionSet, @@ -297,7 +297,7 @@ impl Default for Fn { loc: crate::Loc::EMPTY, stmts: StmtNodeList::EMPTY, }, - arguments_ref: None, + arguments_ref: Ref::NONE, flags: flags::FUNCTION_NONE, return_ts_metadata: TypeScript::Metadata::MNone, } diff --git a/src/ast/import_record.rs b/src/ast/import_record.rs index 95c4d2950ae..79e24904c1a 100644 --- a/src/ast/import_record.rs +++ b/src/ast/import_record.rs @@ -23,11 +23,6 @@ pub struct ImportRecord { pub source_index: Index, - /// Dead field: the only reader (`js_printer`'s `print_bundled_import`) - /// has been deleted. Always 0. Remove together with the `module_id: 0` initializers - /// in the parser/bundler/css constructors when those files are next touched. - pub module_id: u32, - /// The original import specifier as written in source code (e.g., "./foo.js"). /// This is preserved before resolution overwrites `path` with the resolved path. /// Used for metafile generation. diff --git a/src/ast/known_global.rs b/src/ast/known_global.rs index 1ee6ad149e8..07a3c2d6c95 100644 --- a/src/ast/known_global.rs +++ b/src/ast/known_global.rs @@ -194,7 +194,7 @@ impl KnownGlobal { } js_ast::expr::PrimitiveType::Number => { let val = match arg.data { - js_ast::ExprData::ENumber(num) => num.value, + js_ast::ExprData::ENumber(num) => num.value(), _ => return Some(Self::call_from_new(e, loc)), }; if diff --git a/src/ast/lib.rs b/src/ast/lib.rs index 52c5f00174f..858e72cfbd7 100644 --- a/src/ast/lib.rs +++ b/src/ast/lib.rs @@ -171,10 +171,20 @@ pub enum RefTag { /// into the user-bit lane, so for every `Ref` constructed via `new`/`init` /// the masking is a no-op and hashing is bit-identical to the pre-shrink /// layout — preserving output sha-identity. -#[repr(transparent)] +/// +/// `packed(4)` lowers the alignment to 4 without changing the single-scalar +/// representation, so `Ref` is still passed/returned in one register and +/// `self.0` is still one `mov`. The align-4 part is what lets the inline +/// identifier payloads — and therefore `expr::Data` and `Expr` — pack into 16 +/// bytes. All accessors take `self` by value (`Copy`), so the packed-field +/// reference restriction never applies. +#[repr(C, packed(4))] #[derive(Clone, Copy)] pub struct Ref(u64); +const _: () = assert!(core::mem::size_of::() == 8); +const _: () = assert!(core::mem::align_of::() == 4); + /// We mask to 31 bits for `source_index`, 28 for `inner_index`. pub type RefInt = u32; @@ -348,13 +358,19 @@ impl Ref { #[inline] pub const fn eql(self, other: Ref) -> bool { // User-bit lane is not part of identity — see type-level doc. - (self.0 & !Self::USER_BITS_MASK) == (other.0 & !Self::USER_BITS_MASK) + self.as_u64() == other.as_u64() } /// deprecated alias #[inline] pub const fn is_null(self) -> bool { self.is_empty() } + /// `Ref::NONE` → `None`, otherwise `Some(self)`. For sites that previously + /// stored `Option` and want option combinators on the sentinel form. + #[inline] + pub fn to_nullable(self) -> Option { + if self.is_empty() { None } else { Some(self) } + } } impl Default for Ref { diff --git a/src/ast/nodes.rs b/src/ast/nodes.rs index e6deded40dc..0a33f63a3c4 100644 --- a/src/ast/nodes.rs +++ b/src/ast/nodes.rs @@ -20,11 +20,21 @@ pub use crate::flags as Flags; // Thin `NonNull` newtype — `Copy`, `Deref`/`DerefMut`. The pointee lives // until the owning Store/arena is `reset()`; callers must not hold a `StoreRef` // across that boundary. +// +// `packed(4)` lowers the alignment to 4 without changing the single-scalar +// representation: still passed/returned in one register, `self.0` is one `mov`, +// and `Option>` keeps its `NonNull` niche. The align-4 part is what +// lets `expr::Data`/`stmt::Data` drop to align 4 and `Expr`/`Stmt`/`Binding` +// pack into 16 bytes. // ─────────────────────────────────────────────────────────────────────────── -#[repr(transparent)] +#[repr(C, packed(4))] pub struct StoreRef(NonNull); +const _: () = assert!(core::mem::size_of::>() == 8); +const _: () = assert!(core::mem::align_of::>() == 4); +const _: () = assert!(core::mem::size_of::>>() == 8); + // SAFETY: `StoreRef` is a thin pointer into a single-threaded bump arena. // We assert Send/Sync so payload types embedding `Option>` // (e.g. `E::EString::next`) can sit in `static` tables. Callers are @@ -97,7 +107,7 @@ impl Deref for StoreRef { #[inline] fn deref(&self) -> &T { // SAFETY: StoreRef invariant — points into a live Store/arena block. - unsafe { self.0.as_ref() } + unsafe { &*self.as_ptr() } } } impl DerefMut for StoreRef { @@ -106,20 +116,23 @@ impl DerefMut for StoreRef { // SAFETY: StoreRef invariant. AST nodes are mutated in-place during // visiting; no two `StoreRef` to the same node are deref'd `&mut` // simultaneously in single-threaded parser/visitor passes. - unsafe { self.0.as_mut() } + unsafe { &mut *self.as_ptr() } } } impl From> for StoreRef { #[inline] fn from(p: NonNull) -> Self { - StoreRef(p) + StoreRef::from_non_null(p) } } /// Pointer-identity comparison. impl PartialEq for StoreRef { #[inline] fn eq(&self, other: &Self) -> bool { - self.0 == other.0 + // Copy out of the packed field before comparing (`NonNull::eq` takes + // `&self`, which would require an unaligned reference). + let (a, b) = (self.0, other.0); + a == b } } impl Eq for StoreRef {} @@ -149,13 +162,19 @@ pub(crate) const fn empty_arena_str() -> ArenaStr { // already imposes. Avoids cascading `<'arena>` through `Expr`/`Stmt`/`Data` // (~100 types, 12 downstream crates) — that cascade is the follow-up round // once `StoreRef` itself carries `'arena`. +// Layout matches `StoreSlice`: `packed(4)` lowers `NonNull` to align 4 +// so the struct is 12 bytes instead of 16. The `u32` length keeps the 4 GB +// source-file limit explicit. #[derive(Copy, Clone)] -#[repr(C)] +#[repr(C, packed(4))] pub struct StoreStr { - ptr: core::ptr::NonNull, - len: usize, + ptr: NonNull, + len: u32, } +const _: () = assert!(core::mem::size_of::() == 12); +const _: () = assert!(core::mem::align_of::() == 4); + // SAFETY: same rationale as `StoreRef` — points into a single-threaded bump // arena. Asserted Send/Sync so payload types can sit in // `static` Prefill tables; callers must not actually share a Store across @@ -167,7 +186,7 @@ unsafe impl Sync for StoreStr {} impl StoreStr { pub const EMPTY: StoreStr = StoreStr { - ptr: core::ptr::NonNull::::dangling(), + ptr: NonNull::::dangling(), len: 0, }; @@ -176,11 +195,12 @@ impl StoreStr { /// (valid until the owning arena resets). #[inline] pub const fn new(s: &[u8]) -> Self { - match core::ptr::NonNull::new(s.as_ptr().cast_mut()) { - Some(ptr) => StoreStr { ptr, len: s.len() }, - // Only the (ptr=null, len=0) empty-slice edge needs this; Rust - // `&[u8]` never has a null ptr, but be defensive for const-eval. - None => StoreStr::EMPTY, + debug_assert!(s.len() <= u32::MAX as usize); + // SAFETY: `&[u8]` always has a non-null data pointer. + let ptr = unsafe { NonNull::new_unchecked(s.as_ptr().cast_mut()) }; + StoreStr { + ptr, + len: s.len() as u32, } } @@ -191,7 +211,7 @@ impl StoreStr { #[inline] pub const fn raw_len(self) -> usize { - self.len + self.len as usize } /// Re-borrow as `&[u8]`. Same safety contract as `StoreRef::get`: the @@ -203,18 +223,13 @@ impl StoreStr { // SAFETY: StoreStr invariant — `ptr` is non-null, points at `len` // initialized bytes valid for the arena lifetime (or `'static`); caller // must not outlive the owning arena (same as `StoreRef`). - unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len) } + unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) } } #[inline] pub fn as_raw(self) -> *const [u8] { - core::ptr::slice_from_raw_parts(self.ptr.as_ptr(), self.len) + core::ptr::slice_from_raw_parts(self.ptr.as_ptr(), self.len as usize) } - - // (former `from_raw(*const [u8])` removed — the StoreSlice migration is - // complete; `js_printer::renamer::NameStr` now constructs via the safe - // `StoreStr::new(&[u8])`, so the raw-fat-pointer back-door has no - // remaining callers.) } impl Default for StoreStr { @@ -311,16 +326,21 @@ impl core::fmt::Debug for StoreStr { // // Generalizes `StoreStr` to `[T]` for AST list fields (`E::Arrow.args`, // per-node `[Stmt]`/`[Expr]` views, …) that borrow from the parse arena. -// Same contract as `StoreRef`/`StoreStr`: safe `::new`, -// raw `NonNull` + `u32` length, `Deref`, valid until the -// owning arena resets. The `u32` length keeps the field at 12 bytes -// on 64-bit instead of 16 — relevant for hot AST nodes. -#[repr(C)] +// Same contract as `StoreRef`/`StoreStr`: safe `::new`, `Deref`, +// valid until the owning arena resets. +// +// Layout: `packed(4)` lowers `NonNull` to align 4 so the field is 12 bytes +// instead of 16. The pointer stays a single scalar (one `mov` to read), and the +// `u32` length keeps the 4 G-element ceiling explicit. +#[repr(C, packed(4))] pub struct StoreSlice { - ptr: core::ptr::NonNull, + ptr: NonNull, len: u32, } +const _: () = assert!(core::mem::size_of::>() == 12); +const _: () = assert!(core::mem::align_of::>() == 4); + // Manual Copy/Clone: derive would add a spurious `T: Copy` bound. impl Copy for StoreSlice {} impl Clone for StoreSlice { @@ -343,7 +363,7 @@ unsafe impl Sync for StoreSlice {} impl StoreSlice { pub const EMPTY: StoreSlice = StoreSlice { - ptr: core::ptr::NonNull::::dangling(), + ptr: NonNull::::dangling(), len: 0, }; @@ -353,12 +373,11 @@ impl StoreSlice { #[inline] pub const fn new(s: &[T]) -> Self { debug_assert!(s.len() <= u32::MAX as usize); - match core::ptr::NonNull::new(s.as_ptr().cast_mut()) { - Some(ptr) => StoreSlice { - ptr, - len: s.len() as u32, - }, - None => StoreSlice::EMPTY, + // SAFETY: `&[T]` always has a non-null data pointer. + let ptr = unsafe { NonNull::new_unchecked(s.as_ptr().cast_mut()) }; + StoreSlice { + ptr, + len: s.len() as u32, } } @@ -368,12 +387,11 @@ impl StoreSlice { #[inline] pub fn new_mut(s: &mut [T]) -> Self { debug_assert!(s.len() <= u32::MAX as usize); - match core::ptr::NonNull::new(s.as_mut_ptr()) { - Some(ptr) => StoreSlice { - ptr, - len: s.len() as u32, - }, - None => StoreSlice::EMPTY, + // SAFETY: `&mut [T]` always has a non-null data pointer. + let ptr = unsafe { NonNull::new_unchecked(s.as_mut_ptr()) }; + StoreSlice { + ptr, + len: s.len() as u32, } } @@ -554,17 +572,16 @@ pub enum AssignTarget { #[derive(Copy, Clone)] pub struct LocRef { pub loc: crate::Loc, - - // TODO: remove this optional and make Ref a function getter - // That will make this struct 128 bits instead of 192 bits and we can remove some heap allocations - pub ref_: Option, + pub ref_: Ref, } +const _: () = assert!(core::mem::size_of::() == 12); + impl Default for LocRef { fn default() -> Self { Self { loc: crate::Loc::EMPTY, - ref_: None, + ref_: Ref::NONE, } } } @@ -1065,7 +1082,7 @@ pub struct Part { /// value or not. This is only known during linking. So we defer adding /// a dependency on these imported symbols until we know whether the /// property access is an inlined enum value or not. - pub import_symbol_property_uses: PartSymbolPropertyUseMap, + pub import_symbol_property_uses: Option>, /// The indices of the other parts in this file that are needed if this part /// is needed. @@ -1120,7 +1137,7 @@ impl Default for Part { import_record_indices: PartImportRecordIndices::new_in(bun_alloc::AstAlloc), declared_symbols: DeclaredSymbolList::default(), symbol_uses: PartSymbolUseMap::default(), - import_symbol_property_uses: PartSymbolPropertyUseMap::default(), + import_symbol_property_uses: None, dependencies: Vec::new_in(bun_alloc::AstAlloc), can_be_removed_if_unused: false, force_tree_shaking: false, @@ -1177,8 +1194,8 @@ pub struct NamedImport { /// This field is used by the bundler to match imports with their corresponding /// exports and for error reporting when imports can't be resolved. pub alias: Option, - pub alias_loc: Option, - pub namespace_ref: Option, + pub alias_loc: crate::Loc, + pub namespace_ref: Ref, pub import_record_index: u32, /// If true, the alias refers to the entire export namespace object of a @@ -1197,8 +1214,8 @@ impl Default for NamedImport { Self { local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias: None, - alias_loc: None, - namespace_ref: None, + alias_loc: crate::Loc::EMPTY, + namespace_ref: Ref::NONE, import_record_index: 0, alias_is_star: false, is_exported: false, diff --git a/src/ast/runtime.rs b/src/ast/runtime.rs index 5778804b472..9a38c19f9c6 100644 --- a/src/ast/runtime.rs +++ b/src/ast/runtime.rs @@ -141,34 +141,34 @@ impl ServerComponentsMode { #[allow(non_snake_case)] #[derive(Default, Clone)] pub struct Imports { - pub __name: Option, - pub __require: Option, - pub __export: Option, - pub __reExport: Option, - pub __exportValue: Option, - pub __exportDefault: Option, + pub __name: Ref, + pub __require: Ref, + pub __export: Ref, + pub __reExport: Ref, + pub __exportValue: Ref, + pub __exportDefault: Ref, // __refreshRuntime: ?GeneratedSymbol = null, // __refreshSig: ?GeneratedSymbol = null, // $RefreshSig$ - pub __merge: Option, - pub __legacyDecorateClassTS: Option, - pub __legacyDecorateParamTS: Option, - pub __legacyMetadataTS: Option, - pub __publicField: Option, - pub __privateIn: Option, - pub __privateGet: Option, - pub __privateAdd: Option, - pub __privateSet: Option, - pub __privateMethod: Option, - pub __decoratorStart: Option, - pub __decoratorMetadata: Option, - pub __runInitializers: Option, - pub __decorateElement: Option, + pub __merge: Ref, + pub __legacyDecorateClassTS: Ref, + pub __legacyDecorateParamTS: Ref, + pub __legacyMetadataTS: Ref, + pub __publicField: Ref, + pub __privateIn: Ref, + pub __privateGet: Ref, + pub __privateAdd: Ref, + pub __privateSet: Ref, + pub __privateMethod: Ref, + pub __decoratorStart: Ref, + pub __decoratorMetadata: Ref, + pub __runInitializers: Ref, + pub __decorateElement: Ref, /// The `$$typeof` runtime import (`$$typeof` is not a valid Rust identifier). - pub dollar_dollar_typeof: Option, - pub __using: Option, - pub __callDispose: Option, - pub __jsonParse: Option, - pub __promiseAll: Option, + pub dollar_dollar_typeof: Ref, + pub __using: Ref, + pub __callDispose: Ref, + pub __jsonParse: Ref, + pub __promiseAll: Ref, } impl Imports { @@ -266,7 +266,7 @@ impl Imports { /// Index → field. #[inline] fn field(&self, i: usize) -> Option { - match i { + let r = match i { 0 => self.__name, 1 => self.__require, 2 => self.__export, @@ -292,12 +292,13 @@ impl Imports { 22 => self.__callDispose, 23 => self.__jsonParse, 24 => self.__promiseAll, - _ => None, - } + _ => return None, + }; + r.to_nullable() } #[inline] - fn field_mut(&mut self, i: usize) -> Option<&mut Option> { + fn field_mut(&mut self, i: usize) -> Option<&mut Ref> { match i { 0 => Some(&mut self.__name), 1 => Some(&mut self.__require), @@ -336,7 +337,7 @@ impl Imports { } /// Callers that know the key statically can read the field directly - /// (`imports.__foo.is_some()`); this is the runtime-keyed equivalent. + /// (`!imports.__foo.is_empty()`); this is the runtime-keyed equivalent. pub fn contains(&self, key: &[u8]) -> bool { Self::ALL .iter() @@ -359,7 +360,7 @@ impl Imports { pub fn put(&mut self, key: &[u8], ref_: Ref) { if let Some(i) = Self::ALL.iter().position(|&k| k == key) { if let Some(slot) = self.field_mut(i) { - *slot = Some(ref_); + *slot = ref_; } } } diff --git a/src/ast/s.rs b/src/ast/s.rs index 9bc85057c2d..545db597148 100644 --- a/src/ast/s.rs +++ b/src/ast/s.rs @@ -203,9 +203,9 @@ pub struct Import { /// the imported file. In this case StarLoc is nil. The NamespaceRef is used /// when converting this module to a CommonJS module. pub namespace_ref: Ref, - pub default_name: Option, // = None - pub items: StoreSlice, // arena-owned; = &[] - pub star_name_loc: Option, // = None + pub default_name: Option, // = None + pub items: StoreSlice, // arena-owned; = &[] + pub star_name_loc: crate::Loc, // = Loc::EMPTY pub import_record_index: u32, pub is_single_line: bool, // = false /// "import defer * as ns from 'path'" — the TC39 Deferred Module Evaluation @@ -220,7 +220,7 @@ impl Default for Import { namespace_ref: Ref::NONE, default_name: None, items: StoreSlice::EMPTY, - star_name_loc: None, + star_name_loc: crate::Loc::EMPTY, import_record_index: u32::MAX, is_single_line: false, phase_defer: false, diff --git a/src/ast/scope.rs b/src/ast/scope.rs index fe626fe87bc..dc987aeffea 100644 --- a/src/ast/scope.rs +++ b/src/ast/scope.rs @@ -33,7 +33,7 @@ pub struct Scope { pub generated: AstVec, // This is used to store the ref of the label symbol for ScopeLabel scopes. - pub label_ref: Option, + pub label_ref: Ref, pub label_stmt_is_loop: bool, // If a scope contains a direct eval() expression, then none of the symbols @@ -70,7 +70,7 @@ impl Scope { children: AstAlloc::vec(), members: MemberHashMap::new_in(AstAlloc), generated: AstAlloc::vec(), - label_ref: None, + label_ref: Ref::NONE, label_stmt_is_loop: false, contains_direct_eval: false, forbid_arguments: false, @@ -129,7 +129,7 @@ impl Scope { self.members.clear(); self.parent = None; self.id = 0; - self.label_ref = None; + self.label_ref = Ref::NONE; self.label_stmt_is_loop = false; self.contains_direct_eval = false; self.strict_mode = StrictModeKind::SloppyMode; diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 4d6df898f75..d4d1d034780 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -350,19 +350,16 @@ pub enum Data { } // ── Layout guards ───────────────────────────────────────────────────────── -// Every payload -// variant is either a `StoreRef` (`#[repr(transparent)] NonNull`, 8 bytes, -// niche-carrying) or a ZST, so the union is one pointer word and the repr(Rust) -// discriminant packs alongside it for `Data` = 16. `Stmt` = `Data` (16, align 8) -// + `Loc` (i32) → 20 → 24 after tail padding. The `Option` assert proves -// the niche fires (33 variants < 256 + every pointer variant contributes a -// NonNull niche), so `Option` / `Option` add no discriminant word. -// Adding `#[repr(C)]`/`#[repr(u8)]` to `Data` or a nullable `*mut T` payload -// would break this — the asserts catch it. -const _: () = assert!(core::mem::size_of::() == 16); +// Every payload variant is either a `StoreRef` (8 bytes, align 4) or a ZST, +// so `Data` = 1-byte discriminant + 8-byte payload → 12 at align 4. `Stmt` = +// `Data` (12, align 4) + `Loc` (i32) → 16. `Option`/`Option` +// niche-pack via spare discriminant values (33 variants < 256); a +// `#[repr(C)]`/`#[repr(u32)]` on `Data` would break it. +const _: () = assert!(core::mem::size_of::() == 12); +const _: () = assert!(core::mem::align_of::() == 4); const _: () = assert!( - core::mem::size_of::() <= 24, - "Expected Stmt to be <= 24 bytes" + core::mem::size_of::() == 16, + "Expected Stmt to be 16 bytes" ); const _: () = assert!( core::mem::size_of::>() == core::mem::size_of::(), diff --git a/src/ast/symbol.rs b/src/ast/symbol.rs index 08df9761b9c..6d29929d5f2 100644 --- a/src/ast/symbol.rs +++ b/src/ast/symbol.rs @@ -25,7 +25,13 @@ pub struct Symbol { /// mode, re-exported symbols are collapsed using MergeSymbols() and renamed /// symbols from other files that end up at this symbol must be able to tell /// if it has a namespace alias. - pub namespace_alias: Option, + /// + /// Boxed: this is `None` for the overwhelming majority of symbols, so we + /// pay 8 bytes inline instead of ~32. `AstBox` so the header lives in the + /// same spill heap as the rest of the per-file AST and is reclaimed on + /// reset (`Symbol` is held in `ArenaVec<'a, Symbol>`; `Drop` is not + /// guaranteed to run). + pub namespace_alias: Option>, /// Used by the parser for single pass parsing. /// @@ -73,19 +79,10 @@ pub struct Symbol { /// Do not use this directly. Use `nestedScopeSlot()` instead. pub nested_scope_slot: u32, - pub did_keep_name: bool, - - pub must_start_with_capital_letter_for_jsx: bool, - /// The kind of symbol. This is used to determine how to print the symbol /// and how to deal with conflicts, renaming, etc. pub kind: Kind, - /// Certain symbols must not be renamed or minified. For example, the - /// "arguments" variable is declared by the runtime for every function. - /// Renaming can also break any identifier used inside a "with" statement. - pub must_not_be_renamed: bool, - /// We automatically generate import items for property accesses off of /// namespace imports. This lets us remove the expensive namespace imports /// while bundling in many cases, replacing them with a cheap import item @@ -105,69 +102,113 @@ pub struct Symbol { /// undefined, which this status is also used for. pub import_item_status: ImportItemStatus, - /// --- Not actually used yet ----------------------------------------------- - /// Sometimes we lower private symbols even if they are supported. For example, - /// consider the following TypeScript code: - /// - /// class Foo { - /// #foo = 123 - /// bar = this.#foo - /// } - /// - /// If "useDefineForClassFields: false" is set in "tsconfig.json", then "bar" - /// must use assignment semantics instead of define semantics. We can compile - /// that to this code: - /// - /// class Foo { - /// constructor() { - /// this.#foo = 123; - /// this.bar = this.#foo; - /// } - /// #foo; - /// } - /// - /// However, we can't do the same for static fields: - /// - /// class Foo { - /// static #foo = 123 - /// static bar = this.#foo - /// } - /// - /// Compiling these static fields to something like this would be invalid: - /// - /// class Foo { - /// static #foo; - /// } - /// Foo.#foo = 123; - /// Foo.bar = Foo.#foo; - /// - /// Thus "#foo" must be lowered even though it's supported. Another case is - /// when we're converting top-level class declarations to class expressions - /// to avoid the TDZ and the class shadowing symbol is referenced within the - /// class body: - /// - /// class Foo { - /// static #foo = Foo - /// } - /// - /// This cannot be converted into something like this: - /// - /// var Foo = class { - /// static #foo; - /// }; - /// Foo.#foo = Foo; - /// - /// --- Not actually used yet ----------------------------------------------- - pub private_symbol_must_be_lowered: bool, + /// Packed boolean state — see [`SymbolFlags`]. Six former `bool` fields + /// collapsed into one byte. + pub flags: SymbolFlags, +} - pub remove_overwritten_function_declaration: bool, +bitflags::bitflags! { + #[derive(Copy, Clone, Eq, PartialEq, Default, Debug)] + pub struct SymbolFlags: u8 { + const DID_KEEP_NAME = 1 << 0; + + const MUST_START_WITH_CAPITAL_LETTER_FOR_JSX = 1 << 1; + + /// Certain symbols must not be renamed or minified. For example, the + /// "arguments" variable is declared by the runtime for every function. + /// Renaming can also break any identifier used inside a "with" statement. + const MUST_NOT_BE_RENAMED = 1 << 2; + + /// --- Not actually used yet ----------------------------------------------- + /// Sometimes we lower private symbols even if they are supported. For example, + /// consider the following TypeScript code: + /// + /// class Foo { + /// #foo = 123 + /// bar = this.#foo + /// } + /// + /// If "useDefineForClassFields: false" is set in "tsconfig.json", then "bar" + /// must use assignment semantics instead of define semantics. We can compile + /// that to this code: + /// + /// class Foo { + /// constructor() { + /// this.#foo = 123; + /// this.bar = this.#foo; + /// } + /// #foo; + /// } + /// + /// However, we can't do the same for static fields: + /// + /// class Foo { + /// static #foo = 123 + /// static bar = this.#foo + /// } + /// + /// Compiling these static fields to something like this would be invalid: + /// + /// class Foo { + /// static #foo; + /// } + /// Foo.#foo = 123; + /// Foo.bar = Foo.#foo; + /// + /// Thus "#foo" must be lowered even though it's supported. Another case is + /// when we're converting top-level class declarations to class expressions + /// to avoid the TDZ and the class shadowing symbol is referenced within the + /// class body: + /// + /// class Foo { + /// static #foo = Foo + /// } + /// + /// This cannot be converted into something like this: + /// + /// var Foo = class { + /// static #foo; + /// }; + /// Foo.#foo = Foo; + /// + /// --- Not actually used yet ----------------------------------------------- + const PRIVATE_SYMBOL_MUST_BE_LOWERED = 1 << 3; + + const REMOVE_OVERWRITTEN_FUNCTION_DECLARATION = 1 << 4; + + /// Used in HMR to decide when live binding code is needed. + const HAS_BEEN_ASSIGNED_TO = 1 << 5; + } +} + +macro_rules! symbol_flag_accessors { + ($($getter:ident, $setter:ident => $flag:ident;)*) => { + impl Symbol { + $( + #[inline] + pub fn $getter(&self) -> bool { + self.flags.contains(SymbolFlags::$flag) + } + #[inline] + pub fn $setter(&mut self, v: bool) { + self.flags.set(SymbolFlags::$flag, v) + } + )* + } + }; +} - /// Used in HMR to decide when live binding code is needed. - pub has_been_assigned_to: bool, +symbol_flag_accessors! { + did_keep_name, set_did_keep_name => DID_KEEP_NAME; + must_start_with_capital_letter_for_jsx, set_must_start_with_capital_letter_for_jsx => MUST_START_WITH_CAPITAL_LETTER_FOR_JSX; + must_not_be_renamed, set_must_not_be_renamed => MUST_NOT_BE_RENAMED; + private_symbol_must_be_lowered, set_private_symbol_must_be_lowered => PRIVATE_SYMBOL_MUST_BE_LOWERED; + remove_overwritten_function_declaration, set_remove_overwritten_function_declaration => REMOVE_OVERWRITTEN_FUNCTION_DECLARATION; + has_been_assigned_to, set_has_been_assigned_to => HAS_BEEN_ASSIGNED_TO; } -// The size of `Symbol` is not load-bearing (no FFI, no serialization), so -// there is intentionally no layout assert here. +const _: () = assert!(core::mem::size_of::>>() == 8); +const _: () = assert!(core::mem::size_of::() <= 48); const INVALID_CHUNK_INDEX: u32 = u32::MAX; pub const INVALID_NESTED_SCOPE_SLOT: u32 = u32::MAX; @@ -181,14 +222,9 @@ impl Default for Symbol { use_count_estimate: 0, chunk_index: AtomicU32::new(INVALID_CHUNK_INDEX), nested_scope_slot: INVALID_NESTED_SCOPE_SLOT, - did_keep_name: true, - must_start_with_capital_letter_for_jsx: false, kind: Kind::Other, - must_not_be_renamed: false, import_item_status: ImportItemStatus::None, - private_symbol_must_be_lowered: false, - remove_overwritten_function_declaration: false, - has_been_assigned_to: false, + flags: SymbolFlags::DID_KEEP_NAME, } } } @@ -230,7 +266,7 @@ impl Symbol { pub fn slot_namespace(&self) -> SlotNamespace { let kind = self.kind; - if kind == Kind::Unbound || self.must_not_be_renamed { + if kind == Kind::Unbound || self.must_not_be_renamed() { return SlotNamespace::MustNotBeRenamed; } @@ -380,9 +416,9 @@ pub type NestedList = Vec>; impl Symbol { pub fn merge_contents_with(&mut self, old: &mut Symbol) { self.use_count_estimate += old.use_count_estimate; - if old.must_not_be_renamed { + if old.must_not_be_renamed() { self.original_name = old.original_name; - self.must_not_be_renamed = true; + self.set_must_not_be_renamed(true); } // TODO: MustStartWithCapitalLetterForJSX diff --git a/src/bun_alloc/ast_alloc.rs b/src/bun_alloc/ast_alloc.rs index 894c5913993..fc896248eb2 100644 --- a/src/bun_alloc/ast_alloc.rs +++ b/src/bun_alloc/ast_alloc.rs @@ -328,6 +328,20 @@ pub struct AstAlloc; /// `Vec` whose backing buffer lives in the thread-local AST allocation state. pub type AstVec = Vec; +/// `Box` whose header lives in the thread-local AST allocation state. +/// `AstAlloc::deallocate` is a no-op, so the header is reclaimed by spill-heap +/// reset rather than `Drop` — same lifetime story as `AstVec`. As with any +/// arena-backed value, **`T::drop` is not guaranteed to run**: a `T` that owns +/// a global-heap allocation, refcount, or fd will leak it. Use only for +/// AST-lifetime payloads whose own storage is also `AstAlloc`/arena-backed. +pub type AstBox = Box; + +/// See [`AstBox`] for the drop-safety contract. +#[inline] +pub fn ast_box(value: T) -> AstBox { + Box::new_in(value, AstAlloc) +} + use crate::alloc_result; #[inline(always)] diff --git a/src/bun_alloc/lib.rs b/src/bun_alloc/lib.rs index 6b0489c612e..ddafb3a1bf8 100644 --- a/src/bun_alloc/lib.rs +++ b/src/bun_alloc/lib.rs @@ -511,7 +511,7 @@ pub use stack_fallback::{ArenaPtr, StackFallback}; pub mod mimalloc_arena; pub mod ast_alloc; -pub use ast_alloc::{AstAlloc, AstVec}; +pub use ast_alloc::{AstAlloc, AstBox, AstVec, ast_box}; mod hashbrown_bridge; /// Re-export so `bun_collections` can name the polyfill trait in /// `StringHashMap`'s `A` bound without taking its own direct dep on diff --git a/src/bundler/AstBuilder.rs b/src/bundler/AstBuilder.rs index 6b1a3b1612e..a88694b362a 100644 --- a/src/bundler/AstBuilder.rs +++ b/src/bundler/AstBuilder.rs @@ -73,7 +73,7 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { pub fn init(bump: &'bump Bump, source: &'a Source, hot_reloading: bool) -> Result { let scope: *mut Scope = bump.alloc(Scope { kind: ScopeKind::Entry, - label_ref: None, + label_ref: Ref::NONE, parent: None, ..Default::default() }); @@ -127,7 +127,7 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { self.current_scope_mut().children.ensure_unused_capacity(1); let scope: *mut Scope = self.bump.alloc(Scope { kind, - label_ref: None, + label_ref: Ref::NONE, parent: NonNull::new(self.current_scope).map(bun_ast::StoreRef::from), ..Default::default() }); @@ -176,7 +176,6 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { tag: Default::default(), loader: None, source_index: Default::default(), - module_id: 0, original_path: b"", flags: Default::default(), }); @@ -211,12 +210,13 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { let import_id: &[u8] = *import_id; // must be given '[N][]const u8' let ref_ = self.new_symbol(SymbolKind::Import, import_id)?; if self.hot_reloading { - self.get_symbol(ref_).namespace_alias = Some(G::NamespaceAlias { - namespace_ref, - alias: bun_ast::StoreStr::new(import_id), - import_record_index: record, - ..Default::default() - }); + self.get_symbol(ref_).namespace_alias = + Some(bun_alloc::ast_box(G::NamespaceAlias { + namespace_ref, + alias: bun_ast::StoreStr::new(import_id), + import_record_index: record, + ..Default::default() + })); } out_ref.write(self.new_expr(E::ImportIdentifier { ref_, @@ -225,7 +225,7 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { *clause = ClauseItem { name: LocRef { loc: Loc::EMPTY, - ref_: Some(ref_), + ref_, }, original_name: bun_ast::StoreStr::new(import_id), alias: bun_ast::StoreStr::new(import_id), @@ -264,7 +264,7 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { pub fn new_external_symbol(&mut self, name: &[u8]) -> Result { let ref_ = self.new_symbol(SymbolKind::Other, name)?; let sym = self.get_symbol(ref_); - sym.must_not_be_renamed = true; + sym.set_must_not_be_renamed(true); Ok(ref_) } @@ -364,13 +364,13 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { self.import_records_for_current_part .push(st.import_record_index); for item in st.items.slice() { - let ref_ = item.name.ref_.expect("infallible: ref bound"); + let ref_ = item.name.ref_; self.named_imports.put( ref_, bun_ast::NamedImport { alias: Some(item.alias), - alias_loc: Some(item.alias_loc), - namespace_ref: Some(st.namespace_ref), + alias_loc: item.alias_loc, + namespace_ref: st.namespace_ref, import_record_index: st.import_record_index, alias_is_star: false, is_exported: false, @@ -412,7 +412,7 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { } bun_ast::StmtData::SExportDefault(st) => { // ImportScanner: recordExport("default", default_name.ref) - let default_ref = st.default_name.ref_.expect("infallible: ref bound"); + let default_ref = st.default_name.ref_; self.record_export(st.default_name.loc, b"default", default_ref)?; // convertStmt: AstBuilder only emits the `.expr` arm // (`registerClientReference(...)`), which is not @@ -517,13 +517,13 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { self.import_records_for_current_part .push(st.import_record_index); for item in st.items.slice() { - let ref_ = item.name.ref_.expect("infallible: ref bound"); + let ref_ = item.name.ref_; self.named_imports.put( ref_, bun_ast::NamedImport { alias: Some(item.alias), - alias_loc: Some(item.name.loc), - namespace_ref: Some(st.namespace_ref), + alias_loc: item.name.loc, + namespace_ref: st.namespace_ref, import_record_index: st.import_record_index, alias_is_star: false, is_exported: false, @@ -539,7 +539,7 @@ impl<'a, 'bump> AstBuilder<'a, 'bump> { } } bun_ast::StmtData::SExportDefault(st) => { - let default_ref = st.default_name.ref_.expect("infallible: ref bound"); + let default_ref = st.default_name.ref_; self.record_export(st.default_name.loc, b"default", default_ref)?; } _ => {} diff --git a/src/bundler/HTMLScanner.rs b/src/bundler/HTMLScanner.rs index e13b69bc61f..233f38cb842 100644 --- a/src/bundler/HTMLScanner.rs +++ b/src/bundler/HTMLScanner.rs @@ -77,7 +77,6 @@ impl<'a> HTMLScanner<'a> { tag: ImportRecordTag::default(), loader: None, source_index: AstIndex::default(), - module_id: 0, original_path: b"", flags: ImportRecordFlags::default(), }; diff --git a/src/bundler/LinkerContext.rs b/src/bundler/LinkerContext.rs index 6bb2dec44cb..e262cd03ce9 100644 --- a/src/bundler/LinkerContext.rs +++ b/src/bundler/LinkerContext.rs @@ -3559,17 +3559,15 @@ impl<'a> LinkerContext<'a> { .get(&tracker.import_ref) .unwrap(); - if let Some(namespace_ref) = named_import.namespace_ref - && namespace_ref.is_valid() - { + if named_import.namespace_ref.is_valid() { if result.kind == MatchImportKind::Normal { result.kind = MatchImportKind::NormalAndNamespace; - result.namespace_ref = namespace_ref; + result.namespace_ref = named_import.namespace_ref; result.alias = named_import.alias.expect("infallible: alias present"); } else { result = MatchImport { kind: MatchImportKind::Namespace, - namespace_ref, + namespace_ref: named_import.namespace_ref, alias: named_import.alias.expect("infallible: alias present"), ..Default::default() }; @@ -3588,7 +3586,7 @@ impl<'a> LinkerContext<'a> { // `log_disjoint` returns the disjoint `Transpiler.log` backref. self.log_disjoint().add_range_warning_fmt( Some(source), - source.range_of_identifier(named_import.alias_loc.expect("infallible: alias present")), + source.range_of_identifier(named_import.alias_loc), format_args!( "Import \"{}\" will always be undefined because the file \"{}\" has no exports", bstr::BStr::new(alias), @@ -3607,12 +3605,7 @@ impl<'a> LinkerContext<'a> { .get(&tracker.import_ref) .unwrap(); - if named_import.namespace_ref.is_some() - && named_import - .namespace_ref - .expect("infallible: checked is_some") - .is_valid() - { + if named_import.namespace_ref.is_valid() { // SAFETY: `named_import` borrows `graph.ast`; the symbol slot is a // disjoint allocation, so no aliasing with this `&mut`. let symbol = unsafe { self.graph.symbol_mut(tracker.import_ref) }; @@ -3620,7 +3613,7 @@ impl<'a> LinkerContext<'a> { result.kind = MatchImportKind::NormalAndNamespace; result.namespace_ref = tracker.import_ref; result.alias = named_import.alias.expect("infallible: alias present"); - result.name_loc = named_import.alias_loc.unwrap_or(Loc::EMPTY); + result.name_loc = named_import.alias_loc; } } @@ -3630,12 +3623,7 @@ impl<'a> LinkerContext<'a> { [prev_source_index as usize] .get(&tracker.import_ref) .unwrap(); - if named_import.namespace_ref.is_some() - && named_import - .namespace_ref - .expect("infallible: checked is_some") - .is_valid() - { + if named_import.namespace_ref.is_valid() { if result.kind == MatchImportKind::Normal { result.kind = MatchImportKind::NormalAndNamespace; result.namespace_ref = next_tracker.import_ref; @@ -3663,9 +3651,7 @@ impl<'a> LinkerContext<'a> { let source = self.get_source(prev_source_index); let next_source = self.get_source(next_tracker.source_index.get()); - let r = source.range_of_identifier( - named_import.alias_loc.expect("infallible: alias present"), - ); + let r = source.range_of_identifier(named_import.alias_loc); // SAFETY: arena `*const [u8]` valid for the link pass. let alias = named_import .alias @@ -3914,11 +3900,11 @@ impl<'a> LinkerContext<'a> { // SAFETY: the mutated symbol slot is disjoint from `named_import` // (graph.ast SoA) and `result` (stack local). unsafe { self.graph.symbol_mut(import_ref) }.namespace_alias = - Some(G::NamespaceAlias { + Some(bun_alloc::ast_box(G::NamespaceAlias { namespace_ref: result.namespace_ref, alias: result.alias, ..Default::default() - }); + })); } MatchImportKind::NormalAndNamespace => { imports_to_bind @@ -3938,18 +3924,15 @@ impl<'a> LinkerContext<'a> { // SAFETY: one-shot field store after `imports_to_bind.put` (disjoint // map) has fully returned; no other live borrow aliases this symbol slot. unsafe { self.graph.symbol_mut(import_ref) }.namespace_alias = - Some(G::NamespaceAlias { + Some(bun_alloc::ast_box(G::NamespaceAlias { namespace_ref: result.namespace_ref, alias: result.alias, ..Default::default() - }); + })); } MatchImportKind::Cycle => { let source = self.get_source(source_index); - let r = lex::range_of_identifier( - source, - named_import.alias_loc.unwrap_or_default(), - ); + let r = lex::range_of_identifier(source, named_import.alias_loc); // SAFETY: arena `*const [u8]` valid for the link pass. let alias = named_import .alias @@ -3973,10 +3956,7 @@ impl<'a> LinkerContext<'a> { } MatchImportKind::Ambiguous => { let source = self.get_source(source_index); - let r = lex::range_of_identifier( - source, - named_import.alias_loc.unwrap_or_default(), - ); + let r = lex::range_of_identifier(source, named_import.alias_loc); // TODO: log locations of the ambiguous exports diff --git a/src/bundler/ParseTask.rs b/src/bundler/ParseTask.rs index 545163f457c..68ef0bd3b01 100644 --- a/src/bundler/ParseTask.rs +++ b/src/bundler/ParseTask.rs @@ -681,14 +681,9 @@ pub mod parse_worker { s.chunk_index.load(core::sync::atomic::Ordering::Relaxed), ), nested_scope_slot: s.nested_scope_slot, - did_keep_name: s.did_keep_name, - must_start_with_capital_letter_for_jsx: s.must_start_with_capital_letter_for_jsx, kind, - must_not_be_renamed: s.must_not_be_renamed, import_item_status, - private_symbol_must_be_lowered: s.private_symbol_must_be_lowered, - remove_overwritten_function_declaration: s.remove_overwritten_function_declaration, - has_been_assigned_to: s.has_been_assigned_to, + flags: s.flags, }); } out diff --git a/src/bundler/ServerComponentParseTask.rs b/src/bundler/ServerComponentParseTask.rs index e8a51b602cd..ea5a444aed3 100644 --- a/src/bundler/ServerComponentParseTask.rs +++ b/src/bundler/ServerComponentParseTask.rs @@ -365,7 +365,7 @@ fn generate_client_reference_proxy( value: StmtOrExpr::Expr(value), default_name: LocRef { loc: Loc::EMPTY, - ref_: Some(ref_), + ref_, }, })?; } else { diff --git a/src/bundler/defines.rs b/src/bundler/defines.rs index 5560bb3d7a3..2001d671d3d 100644 --- a/src/bundler/defines.rs +++ b/src/bundler/defines.rs @@ -35,10 +35,8 @@ pub(crate) use bun_ast::ExprData as DefineValue; pub struct Globals; impl Globals { pub const UNDEFINED: bun_ast::E::Undefined = bun_ast::E::Undefined; - pub const NAN: bun_ast::E::Number = bun_ast::E::Number { value: f64::NAN }; - pub const INFINITY: bun_ast::E::Number = bun_ast::E::Number { - value: f64::INFINITY, - }; + pub const NAN: bun_ast::E::Number = bun_ast::E::Number::new(f64::NAN); + pub const INFINITY: bun_ast::E::Number = bun_ast::E::Number::new(f64::INFINITY); #[inline] pub fn undefined_data() -> ExprData { diff --git a/src/bundler/linker_context/computeCrossChunkDependencies.rs b/src/bundler/linker_context/computeCrossChunkDependencies.rs index 08738701fa6..c446eced661 100644 --- a/src/bundler/linker_context/computeCrossChunkDependencies.rs +++ b/src/bundler/linker_context/computeCrossChunkDependencies.rs @@ -494,7 +494,7 @@ fn compute_cross_chunk_dependencies_with_chunk_metas( clause_items.push(bun_ast::ClauseItem { name: bun_ast::LocRef { - ref_: Some(ref_), + ref_, loc: bun_ast::Loc::EMPTY, }, alias, @@ -579,7 +579,7 @@ fn compute_cross_chunk_dependencies_with_chunk_metas( for item in cross_chunk_import.sorted_import_items.slice() { clauses.push(bun_ast::ClauseItem { name: bun_ast::LocRef { - ref_: Some(item.r#ref), + ref_: item.r#ref, loc: bun_ast::Loc::EMPTY, }, alias: bun_ast::StoreStr::new(item.export_alias.as_ref()), diff --git a/src/bundler/linker_context/convertStmtsForChunk.rs b/src/bundler/linker_context/convertStmtsForChunk.rs index 71b3c148d5b..604c95db2a8 100644 --- a/src/bundler/linker_context/convertStmtsForChunk.rs +++ b/src/bundler/linker_context/convertStmtsForChunk.rs @@ -128,7 +128,7 @@ pub fn convert_stmts_for_chunk( S::Import { namespace_ref: s.namespace_ref, import_record_index: s.import_record_index, - star_name_loc: Some(alias.loc), + star_name_loc: alias.loc, ..Default::default() }, stmt.loc, @@ -169,7 +169,7 @@ pub fn convert_stmts_for_chunk( S::Import { namespace_ref: s.namespace_ref, import_record_index: s.import_record_index, - star_name_loc: Some(stmt.loc), + star_name_loc: stmt.loc, ..Default::default() }, stmt.loc, @@ -497,10 +497,7 @@ pub fn convert_stmts_for_chunk( binding: Binding::alloc( bump, B::Identifier { - r#ref: s - .default_name - .ref_ - .expect("infallible: ref bound"), + r#ref: s.default_name.ref_, }, s2.value.loc, ), @@ -575,10 +572,7 @@ pub fn convert_stmts_for_chunk( binding: Binding::alloc( bump, B::Identifier { - r#ref: s - .default_name - .ref_ - .expect("infallible: ref bound"), + r#ref: s.default_name.ref_, }, e.loc, ), diff --git a/src/bundler/linker_context/convertStmtsForChunkForDevServer.rs b/src/bundler/linker_context/convertStmtsForChunkForDevServer.rs index c0e1898dfde..86633c66e22 100644 --- a/src/bundler/linker_context/convertStmtsForChunkForDevServer.rs +++ b/src/bundler/linker_context/convertStmtsForChunkForDevServer.rs @@ -88,7 +88,7 @@ pub fn convert_stmts_for_chunk_for_dev_server<'bump>( // empty object so body code referencing it doesn't throw. // SAFETY: `st.items` is an arena-owned fat ptr; len is always sound to read. let items_len = st.items.len(); - if st.star_name_loc.is_some() || items_len > 0 || st.default_name.is_some() { + if !st.star_name_loc.is_empty() || items_len > 0 || st.default_name.is_some() { stmts .inside_wrapper_prefix .append_non_dependency(Stmt::alloc( @@ -116,7 +116,7 @@ pub fn convert_stmts_for_chunk_for_dev_server<'bump>( || record.tag == ImportRecordTag::Bun || record.tag == ImportRecordTag::Runtime; let is_bare_import = - st.star_name_loc.is_none() && st.items.len() == 0 && st.default_name.is_none(); + st.star_name_loc.is_empty() && st.items.len() == 0 && st.default_name.is_none(); if is_builtin { if !is_bare_import { @@ -164,7 +164,7 @@ pub fn convert_stmts_for_chunk_for_dev_server<'bump>( b::Identifier { r#ref: st.namespace_ref, }, - st.star_name_loc.unwrap_or(stmt.loc), + st.star_name_loc.to_nullable().unwrap_or(stmt.loc), ), value: Some(call), }]), @@ -174,7 +174,7 @@ pub fn convert_stmts_for_chunk_for_dev_server<'bump>( ))?; } } else { - let loc = st.star_name_loc.unwrap_or(stmt.loc); + let loc = st.star_name_loc.to_nullable().unwrap_or(stmt.loc); if is_bare_import { esm_decls.push(ArrayBinding { binding: Binding { diff --git a/src/bundler/linker_context/doStep5.rs b/src/bundler/linker_context/doStep5.rs index f7fb2a3c802..dec1657e3e3 100644 --- a/src/bundler/linker_context/doStep5.rs +++ b/src/bundler/linker_context/doStep5.rs @@ -252,14 +252,18 @@ impl LinkerContext<'_> { // majority of parts (it only fills for `import * as ns`/enum // property accesses); skip the `to_vec()` alloc-round-trip in // that case. - let prop_use_refs: Vec = if part.import_symbol_property_uses.is_empty() { - Vec::new() - } else { - part.import_symbol_property_uses.keys().to_vec() + let prop_use_refs: Vec = match part.import_symbol_property_uses.as_ref() { + None => Vec::new(), + Some(m) => m.keys().to_vec(), }; for ref_ in &prop_use_refs { // Re-fetch each iteration to avoid overlapping &mut. - let properties: *const _ = part.import_symbol_property_uses.get(ref_).unwrap(); + let properties: *const _ = part + .import_symbol_property_uses + .as_ref() + .unwrap() + .get(ref_) + .unwrap(); let use_: &mut SymbolUse = part.symbol_uses.get_ptr_mut(ref_).unwrap(); // Rare path: this import is a TypeScript enum diff --git a/src/bundler/linker_context/generateCodeForFileInChunkJS.rs b/src/bundler/linker_context/generateCodeForFileInChunkJS.rs index 5970140bb64..5f525bea2fd 100644 --- a/src/bundler/linker_context/generateCodeForFileInChunkJS.rs +++ b/src/bundler/linker_context/generateCodeForFileInChunkJS.rs @@ -748,12 +748,7 @@ pub fn generate_code_for_file_in_chunk_js<'r, 'src>( } let class_name_loc = class.class.class_name.unwrap().loc; - let class_name_ref = class - .class - .class_name - .unwrap() - .ref_ - .expect("infallible: ref bound"); + let class_name_ref = class.class.class_name.unwrap().ref_; let lhs = hoist.wrap_identifier(class_name_loc, class_name_ref); let class_ref: StoreRef = StoreRef::from_bump(&mut class.class); @@ -989,14 +984,14 @@ impl DeclCollector { } StmtData::SFunction(s) => { if let Some(name_loc_ref) = s.func.name { - if let Some(name_ref) = name_loc_ref.ref_ { + if let Some(name_ref) = name_loc_ref.ref_.to_nullable() { self.add_ref(name_ref, DeclInfoKind::Lexical, r, c); } } } StmtData::SClass(s) => { if let Some(class_name) = s.class.class_name { - if let Some(name_ref) = class_name.ref_ { + if let Some(name_ref) = class_name.ref_.to_nullable() { self.add_ref(name_ref, DeclInfoKind::Lexical, r, c); } } diff --git a/src/bundler/linker_context/generateCodeForLazyExport.rs b/src/bundler/linker_context/generateCodeForLazyExport.rs index e1fbc29324c..81e82c5baef 100644 --- a/src/bundler/linker_context/generateCodeForLazyExport.rs +++ b/src/bundler/linker_context/generateCodeForLazyExport.rs @@ -523,7 +523,7 @@ pub fn generate_code_for_lazy_export( alloc.alloc_slice_fill_iter(core::iter::once(Stmt::alloc( S::ExportDefault { default_name: bun_ast::LocRef { - ref_: Some(generated.0), + ref_: generated.0, loc: stmt.loc, }, value: bun_ast::StmtOrExpr::Expr(expr), diff --git a/src/bundler/linker_context/postProcessJSChunk.rs b/src/bundler/linker_context/postProcessJSChunk.rs index 3413df73a69..03021aa1b25 100644 --- a/src/bundler/linker_context/postProcessJSChunk.rs +++ b/src/bundler/linker_context/postProcessJSChunk.rs @@ -149,7 +149,6 @@ pub fn post_process_js_chunk( tag: ImportRecordTag::None, loader: None, source_index: Index::INVALID, - module_id: 0, original_path: b"", flags: ImportRecordFlags::default(), }); @@ -333,7 +332,7 @@ pub fn post_process_js_chunk( ); if let Some(name) = &s.default_name { - if let Some(name_ref) = name.ref_ { + if let Some(name_ref) = name.ref_.to_nullable() { let local_name_id = { let local_name = chunk.renamer.name_for_symbol(name_ref); mi.str(local_name) @@ -354,7 +353,7 @@ pub fn post_process_js_chunk( // `S::Import.items: StoreSlice` — safe `Deref`. for item in s.items.iter() { - if let Some(name_ref) = item.name.ref_ { + if let Some(name_ref) = item.name.ref_.to_nullable() { let local_name_id = { let local_name = chunk.renamer.name_for_symbol(name_ref); mi.str(local_name) @@ -938,7 +937,7 @@ pub fn generate_entry_point_tail_js<'a>( S::ExportDefault { default_name: bun_ast::LocRef { loc: bun_ast::Loc::EMPTY, - ref_: Some(ast.wrapper_ref), + ref_: ast.wrapper_ref, }, value: StmtOrExpr::Expr(Expr::init( E::Call { @@ -1112,7 +1111,7 @@ pub fn generate_entry_point_tail_js<'a>( items.push(bun_ast::ClauseItem { name: bun_ast::LocRef { - ref_: Some(temp_ref), + ref_: temp_ref, loc: bun_ast::Loc::EMPTY, }, alias: bun_ast::StoreStr::new(alias), @@ -1145,7 +1144,7 @@ pub fn generate_entry_point_tail_js<'a>( // items.push(bun_ast::ClauseItem { name: bun_ast::LocRef { - ref_: Some(resolved_export_data.import_ref), + ref_: resolved_export_data.import_ref, loc: resolved_export_data.name_loc, }, alias: bun_ast::StoreStr::new(alias), @@ -1179,10 +1178,7 @@ pub fn generate_entry_point_tail_js<'a>( S::Return { value: Some(Expr::init( E::Identifier { - ref_: export_item - .name - .ref_ - .expect("infallible: ref bound"), + ref_: export_item.name.ref_, ..Default::default() }, export_item.name.loc, @@ -1225,7 +1221,7 @@ pub fn generate_entry_point_tail_js<'a>( stmts.push(Stmt::alloc( S::ExportDefault { default_name: bun_ast::LocRef { - ref_: Some(Ref::NONE), + ref_: Ref::NONE, loc: bun_ast::Loc::EMPTY, }, value: StmtOrExpr::Expr(Expr::init( diff --git a/src/bundler/linker_context/prepareCssAstsForChunk.rs b/src/bundler/linker_context/prepareCssAstsForChunk.rs index cbb77689781..2eb15f6844a 100644 --- a/src/bundler/linker_context/prepareCssAstsForChunk.rs +++ b/src/bundler/linker_context/prepareCssAstsForChunk.rs @@ -170,7 +170,6 @@ fn prepare_css_asts_for_chunk_impl(c: &LinkerContext, chunk: &mut Chunk, bump: & tag: ImportRecordTag::None, loader: None, source_index: AstIndex::default(), - module_id: 0, original_path: b"", flags: ImportRecordFlags::default(), }); @@ -301,7 +300,6 @@ fn prepare_css_asts_for_chunk_impl(c: &LinkerContext, chunk: &mut Chunk, bump: & tag: ImportRecordTag::None, loader: None, source_index: AstIndex::default(), - module_id: 0, original_path: b"", flags: ImportRecordFlags::default(), }); diff --git a/src/bundler/linker_context/renameSymbolsInChunk.rs b/src/bundler/linker_context/renameSymbolsInChunk.rs index 450e26c382d..59c30af3578 100644 --- a/src/bundler/linker_context/renameSymbolsInChunk.rs +++ b/src/bundler/linker_context/renameSymbolsInChunk.rs @@ -319,13 +319,13 @@ pub unsafe fn rename_symbols_in_chunk( { r.add_top_level_symbol(import.namespace_ref); if let Some(default_name) = &import.default_name { - if let Some(ref_) = default_name.ref_ { + if let Some(ref_) = default_name.ref_.to_nullable() { r.add_top_level_symbol(ref_); } } for item in import.items.slice() { - if let Some(ref_) = item.name.ref_ { + if let Some(ref_) = item.name.ref_.to_nullable() { r.add_top_level_symbol(ref_); } } @@ -347,7 +347,7 @@ pub unsafe fn rename_symbols_in_chunk( r.add_top_level_symbol(export_.namespace_ref); for item in export_.items.slice() { - if let Some(ref_) = item.name.ref_ { + if let Some(ref_) = item.name.ref_.to_nullable() { r.add_top_level_symbol(ref_); } } diff --git a/src/bundler/transpiler.rs b/src/bundler/transpiler.rs index eda6b46f3b2..0a07e29f49e 100644 --- a/src/bundler/transpiler.rs +++ b/src/bundler/transpiler.rs @@ -2017,10 +2017,7 @@ fn parse_data_loader<'a>( value: Some(prop.value.expect("infallible: prop has value")), }; export_clauses[count] = bun_ast::ClauseItem { - name: bun_ast::LocRef { - ref_: Some(ref_), - loc: key_loc, - }, + name: bun_ast::LocRef { ref_, loc: key_loc }, alias: bun_ast::StoreStr::new(name), alias_loc: key_loc, ..Default::default() @@ -2051,7 +2048,7 @@ fn parse_data_loader<'a>( value: bun_ast::StmtOrExpr::Expr(expr), default_name: bun_ast::LocRef { loc: bun_ast::Loc::default(), - ref_: Some(bun_ast::Ref::NONE), + ref_: bun_ast::Ref::NONE, }, }, bun_ast::Loc { start: 0 }, @@ -2072,7 +2069,7 @@ fn parse_data_loader<'a>( value: bun_ast::StmtOrExpr::Expr(expr), default_name: bun_ast::LocRef { loc: bun_ast::Loc::default(), - ref_: Some(bun_ast::Ref::NONE), + ref_: bun_ast::Ref::NONE, }, }, bun_ast::Loc { start: 0 }, @@ -2119,7 +2116,7 @@ fn parse_text_loader<'a>( value: bun_ast::StmtOrExpr::Expr(expr), default_name: bun_ast::LocRef { loc: bun_ast::Loc::default(), - ref_: Some(bun_ast::Ref::NONE), + ref_: bun_ast::Ref::NONE, }, }, bun_ast::Loc { start: 0 }, @@ -2177,7 +2174,7 @@ fn parse_md_loader<'a>( value: bun_ast::StmtOrExpr::Expr(expr), default_name: bun_ast::LocRef { loc: bun_ast::Loc::default(), - ref_: Some(bun_ast::Ref::NONE), + ref_: bun_ast::Ref::NONE, }, }, bun_ast::Loc { start: 0 }, diff --git a/src/bunfig/bunfig.rs b/src/bunfig/bunfig.rs index eca200865bc..ec5ebda3cb3 100644 --- a/src/bunfig/bunfig.rs +++ b/src/bunfig/bunfig.rs @@ -493,7 +493,7 @@ impl<'a> Parser<'a> { if let Some(expr) = test_.get(b"coverageThreshold") { 'outer: { if let ExprData::ENumber(n) = expr.data { - let v = n.value; + let v = n.value(); self.ctx.test_options.coverage.fractions.functions = v; self.ctx.test_options.coverage.fractions.lines = v; self.ctx.test_options.coverage.fractions.stmts = v; @@ -1484,7 +1484,7 @@ impl<'a> Parser<'a> { if let Some(min_age) = install_obj.get(b"minimumReleaseAge") { match &min_age.data { ExprData::ENumber(seconds) => { - if seconds.value < 0.0 { + if seconds.value() < 0.0 { self.add_error( min_age.loc, b"Expected positive number of seconds for minimumReleaseAge", @@ -1492,7 +1492,7 @@ impl<'a> Parser<'a> { return Ok(()); } const MS_PER_S: f64 = bun_core::time::MS_PER_S as f64; - install.minimum_release_age_ms = Some(seconds.value * MS_PER_S); + install.minimum_release_age_ms = Some(seconds.value() * MS_PER_S); } _ => { self.add_error( diff --git a/src/css/css_parser.rs b/src/css/css_parser.rs index 3bdf0af56f0..de3d91acc95 100644 --- a/src/css/css_parser.rs +++ b/src/css/css_parser.rs @@ -918,7 +918,6 @@ impl<'a> CustomAtRuleParser for BundlerAtRuleParser<'a> { tag: Default::default(), loader: None, source_index: Default::default(), - module_id: 0, original_path: b"", flags: Default::default(), }); @@ -2990,7 +2989,6 @@ mod stylesheet_impl { tag: Default::default(), loader: None, source_index: Default::default(), - module_id: 0, original_path: b"", flags: Default::default(), }); @@ -3507,7 +3505,6 @@ impl<'a> Parser<'a> { tag: Default::default(), loader: None, source_index: Default::default(), - module_id: 0, original_path: b"", flags: Default::default(), }); diff --git a/src/ini/lib.rs b/src/ini/lib.rs index 5627368ebc2..bcd705fedc5 100644 --- a/src/ini/lib.rs +++ b/src/ini/lib.rs @@ -1117,7 +1117,7 @@ mod draft { ExprData::EBoolean(b) => { write!(writer, "{}", if b.value { "true" } else { "false" }) } - ExprData::ENumber(n) => write!(writer, "{}", n.value), + ExprData::ENumber(n) => write!(writer, "{}", n.value()), ExprData::EString(s) => { write!(writer, "{}", bstr::BStr::new(&s.data)) } diff --git a/src/install/ConfigVersion.rs b/src/install/ConfigVersion.rs index 52d58e93ff6..797838da902 100644 --- a/src/install/ConfigVersion.rs +++ b/src/install/ConfigVersion.rs @@ -17,7 +17,7 @@ impl ConfigVersion { let ExprData::ENumber(e_number) = &expr.data else { return None; }; - let version: f64 = e_number.value; + let version: f64 = e_number.value(); if version == 0.0 { return Some(ConfigVersion::V0); diff --git a/src/install/lockfile/bun.lock.rs b/src/install/lockfile/bun.lock.rs index 4af75bb2428..224c3dbb4fa 100644 --- a/src/install/lockfile/bun.lock.rs +++ b/src/install/lockfile/bun.lock.rs @@ -1604,14 +1604,14 @@ pub fn parse_into_binary_lockfile( 'err: { match &lockfile_version_expr.data { ExprData::ENumber(num) => { - if num.value < 0.0 || num.value > u32::MAX as f64 { + if num.value() < 0.0 || num.value() > u32::MAX as f64 { break 'err; } - if num.value.fract() != 0.0 { + if num.value().fract() != 0.0 { break 'err; } - break 'lockfile_version num.value as u32; + break 'lockfile_version num.value() as u32; } _ => {} } diff --git a/src/install/migration.rs b/src/install/migration.rs index dd7a17191ce..75f7e4e2def 100644 --- a/src/install/migration.rs +++ b/src/install/migration.rs @@ -249,7 +249,7 @@ pub(crate) fn migrate_npm_lockfile<'a>( return Err(err!("InvalidNPMLockfile")); } if let Some(version) = json.get(b"lockfileVersion") { - if !(matches!(version.data, ExprData::ENumber(n) if n.value >= 2.0 && n.value <= 3.0)) { + if !(matches!(version.data, ExprData::ENumber(n) if n.value() >= 2.0 && n.value() <= 3.0)) { return Err(err!("NPMLockfileVersionMismatch")); } } else { diff --git a/src/install/npm.rs b/src/install/npm.rs index 3c605272205..6cc734a061d 100644 --- a/src/install/npm.rs +++ b/src/install/npm.rs @@ -2714,13 +2714,13 @@ impl PackageManifest { if let Some(file_count_) = dist.expr.as_property(b"fileCount") { if let JSON::ExprData::ENumber(n) = &file_count_.expr.data { - package_version.file_count = n.value as u32; + package_version.file_count = n.value() as u32; } } if let Some(file_count_) = dist.expr.as_property(b"unpackedSize") { if let JSON::ExprData::ENumber(n) = &file_count_.expr.data { - package_version.unpacked_size = n.value as u32; + package_version.unpacked_size = n.value() as u32; } } diff --git a/src/install/pnpm.rs b/src/install/pnpm.rs index bef2780a10f..3ffb55fde5e 100644 --- a/src/install/pnpm.rs +++ b/src/install/pnpm.rs @@ -278,10 +278,10 @@ pub(crate) fn migrate_pnpm_lockfile<'a>( 'err: { match &lockfile_version_expr.data { ExprData::ENumber(num) => { - if num.value < 0.0 { + if num.value() < 0.0 { break 'err; } - break 'lockfile_version num.value; + break 'lockfile_version num.value(); } ExprData::EString(version_str) => { let str = version_str.data.slice(); diff --git a/src/js_parser/defines_table.rs b/src/js_parser/defines_table.rs index 683eb5f0798..ee9c23167bc 100644 --- a/src/js_parser/defines_table.rs +++ b/src/js_parser/defines_table.rs @@ -225,10 +225,8 @@ fn pure_global_identifier_define() -> &'static defines::IdentifierDefine { mod identifiers { use super::{ExprData, OnceLock, SyncDefineData, defines, js_ast}; - const NAN_VAL: js_ast::E::Number = js_ast::E::Number { value: f64::NAN }; - const INF_VAL: js_ast::E::Number = js_ast::E::Number { - value: f64::INFINITY, - }; + const NAN_VAL: js_ast::E::Number = js_ast::E::Number::new(f64::NAN); + const INF_VAL: js_ast::E::Number = js_ast::E::Number::new(f64::INFINITY); // Step 2. Swap in certain literal values because those can be constant folded pub(super) fn undefined() -> &'static defines::IdentifierDefine { diff --git a/src/js_parser/fold.rs b/src/js_parser/fold.rs index efa0bf996a0..1009e161476 100644 --- a/src/js_parser/fold.rs +++ b/src/js_parser/fold.rs @@ -145,7 +145,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O .get(name) .copied(); let ref_ = match existing { - Some(loc_ref) => loc_ref.ref_.expect("infallible: ref bound"), + Some(loc_ref) => loc_ref.ref_, None => { // Generate a new import item symbol in the module scope let new_ref = p @@ -153,7 +153,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O .expect("unreachable"); let new_item = LocRef { loc: name_loc, - ref_: Some(new_ref), + ref_: new_ref, }; // SAFETY: module_scope is arena-owned and valid for the parser lifetime. VecExt::append(&mut p.module_scope_mut().generated, new_ref); @@ -387,7 +387,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let ref_ = if let Some(existing) = p.commonjs_named_exports.get(name) { - existing.loc_ref.ref_.expect("infallible: ref bound") + existing.loc_ref.ref_ } else { let sym_name: &'a [u8] = p.arena.alloc_slice_copy( format!("${}", bun_core::fmt::fmt_identifier(name)) @@ -404,7 +404,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O CommonJSNamedExport { loc_ref: LocRef { loc: name_loc, - ref_: Some(new_ref), + ref_: new_ref, }, needs_decl: true, }, @@ -450,7 +450,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // minify "long-string".length to 11 if name == b"length" { if let Some(len) = e_string_javascript_length(&str_) { - return Some(p.new_expr(E::Number { value: len as f64 }, loc)); + return Some(p.new_expr(E::Number::new(len as f64), loc)); } } } @@ -616,7 +616,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let ref_ = if let Some(existing) = p.commonjs_named_exports.get(name) { - existing.loc_ref.ref_.expect("infallible: ref bound") + existing.loc_ref.ref_ } else { let sym_name: &'a [u8] = p.arena.alloc_slice_copy( format!("${}", bun_core::fmt::fmt_identifier(name)) @@ -636,7 +636,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O CommonJSNamedExport { loc_ref: LocRef { loc: name_loc, - ref_: Some(new_ref), + ref_: new_ref, }, needs_decl: true, }, @@ -767,7 +767,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O return Some(p.wrap_inlined_enum( Expr { loc, - data: js_ast::ExprData::ENumber(E::Number { value: num }), + data: js_ast::ExprData::ENumber(E::Number::new(num)), }, name, )); @@ -853,12 +853,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O )) } - pub fn maybe_comma_spread_error(&mut self, comma_after_spread: Option) { + pub fn maybe_comma_spread_error(&mut self, comma_after_spread: bun_ast::Loc) { let p = self; - let Some(comma_after_spread) = comma_after_spread else { - return; - }; - if comma_after_spread.start == -1 { + if comma_after_spread.is_empty() { return; } diff --git a/src/js_parser/lib.rs b/src/js_parser/lib.rs index 390553b06b2..b4a9f7cb6fc 100644 --- a/src/js_parser/lib.rs +++ b/src/js_parser/lib.rs @@ -670,7 +670,7 @@ pub mod renamer { } // Labels are always declared in a nested scope, so we don't need to check. - if let Some(ref_) = scope.label_ref { + if let Some(ref_) = scope.label_ref.to_nullable() { let symbol = &mut symbols[ref_.inner_index() as usize]; let ns = SlotNamespace::Label; symbol.nested_scope_slot = slot.slots[ns]; diff --git a/src/js_parser/lower/lower_decorators.rs b/src/js_parser/lower/lower_decorators.rs index d6ae84a9413..4d07c516644 100644 --- a/src/js_parser/lower/lower_decorators.rs +++ b/src/js_parser/lower/lower_decorators.rs @@ -1127,7 +1127,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O value: None, }); if let Some(cn) = &class.class_name { - class_name_ref = cn.ref_.expect("infallible: ref bound"); + class_name_ref = cn.ref_; class_name_loc = cn.loc; } else { class_name_ref = ecr; @@ -1137,18 +1137,13 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O && can_be_class_binding_name(name) { class.class_name = Some(js_ast::LocRef { - ref_: Some(p.new_sym(js_ast::symbol::Kind::Other, name)), + ref_: p.new_sym(js_ast::symbol::Kind::Other, name), loc, }); } } } else { - class_name_ref = class - .class_name - .as_ref() - .unwrap() - .ref_ - .expect("infallible: ref bound"); + class_name_ref = class.class_name.as_ref().unwrap().ref_; class_name_loc = class.class_name.as_ref().unwrap().loc; } @@ -1814,7 +1809,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O }, loc, )); - dec_args.push(p.new_expr(E::Number { value: flags }, loc)); + dec_args.push(p.new_expr(E::Number::new(flags), loc)); dec_args.push(if is_private { let priv_ref = match &key_expr.data { js_ast::ExprData::EPrivateIdentifier(pi) => pi.ref_, @@ -2041,7 +2036,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O }, loc, )); - cls_dec_args.push(p.new_expr(E::Number { value: 0.0 }, loc)); + cls_dec_args.push(p.new_expr(E::Number::new(0.0), loc)); cls_dec_args.push(p.new_expr( E::EString { data: class_name_str, @@ -2084,7 +2079,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // 6: Static method extra initializers if !static_non_field_elements.is_empty() || has_static_private_methods { let i_e = p.use_ref(init_ref, loc); - let n_e = p.new_expr(E::Number { value: 3.0 }, loc); + let n_e = p.new_expr(E::Number::new(3.0), loc); let c_e = p.use_ref(class_name_ref, class_name_loc); suffix_exprs.push(p.call_rt(loc, b"__runInitializers", &[i_e, n_e, c_e])); } @@ -2156,12 +2151,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut run_args = BumpVec::with_capacity_in(4, bump); run_args.push(p.use_ref(init_ref, loc)); - run_args.push(p.new_expr( - E::Number { - value: Self::init_flag(field_idx), - }, - loc, - )); + run_args.push(p.new_expr(E::Number::new(Self::init_flag(field_idx)), loc)); run_args.push(p.use_ref(class_name_ref, class_name_loc)); if let Some(init_val) = entry.prop.initializer { run_args.push(init_val); @@ -2190,12 +2180,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Extra initializer let i_e = p.use_ref(init_ref, loc); - let n_e = p.new_expr( - E::Number { - value: Self::extra_init_flag(field_idx), - }, - loc, - ); + let n_e = p.new_expr(E::Number::new(Self::extra_init_flag(field_idx)), loc); let c_e = p.use_ref(class_name_ref, class_name_loc); suffix_exprs.push(p.call_rt(loc, b"__runInitializers", &[i_e, n_e, c_e])); } @@ -2206,7 +2191,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // 8: Class extra initializers if class_decorators_len > 0 { let i_e = p.use_ref(init_ref, loc); - let n_e = p.new_expr(E::Number { value: 1.0 }, loc); + let n_e = p.new_expr(E::Number::new(1.0), loc); let c_e = p.use_ref(class_name_ref, class_name_loc); suffix_exprs.push(p.call_rt(loc, b"__runInitializers", &[i_e, n_e, c_e])); } @@ -2221,7 +2206,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // ── Phase 7: Constructor injection ─────────────── if !instance_non_field_elements.is_empty() || has_instance_private_methods { let i_e = p.use_ref(init_ref, loc); - let n_e = p.new_expr(E::Number { value: 5.0 }, loc); + let n_e = p.new_expr(E::Number::new(5.0), loc); let t_e = p.new_expr(E::This {}, loc); let call = p.call_rt(loc, b"__runInitializers", &[i_e, n_e, t_e]); constructor_inject_stmts.push(p.s( @@ -2250,12 +2235,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut run_args = BumpVec::with_capacity_in(4, bump); run_args.push(p.use_ref(init_ref, loc)); - run_args.push(p.new_expr( - E::Number { - value: Self::init_flag(field_idx), - }, - loc, - )); + run_args.push(p.new_expr(E::Number::new(Self::init_flag(field_idx)), loc)); run_args.push(p.new_expr(E::This {}, loc)); if let Some(init_val) = entry.prop.initializer { run_args.push(init_val); @@ -2286,12 +2266,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Extra initializer let i_e = p.use_ref(init_ref, loc); - let n_e = p.new_expr( - E::Number { - value: Self::extra_init_flag(field_idx), - }, - loc, - ); + let n_e = p.new_expr(E::Number::new(Self::extra_init_flag(field_idx)), loc); let t_e = p.new_expr(E::This {}, loc); let call = p.call_rt(loc, b"__runInitializers", &[i_e, n_e, t_e]); constructor_inject_stmts.push(p.s( diff --git a/src/js_parser/lower/lower_esm_exports_hmr.rs b/src/js_parser/lower/lower_esm_exports_hmr.rs index fe298b6025a..f6d773f5742 100644 --- a/src/js_parser/lower/lower_esm_exports_hmr.rs +++ b/src/js_parser/lower/lower_esm_exports_hmr.rs @@ -159,17 +159,12 @@ impl<'a> ConvertESMExportsForHmr<'a> { let Some(symbol) = f.func.name else { break 'fast_refresh_edge_case; }; - let name = p.symbols - [symbol.ref_.expect("infallible: ref bound").inner_index() as usize] - .original_name; + let name = p.symbols[symbol.ref_.inner_index() as usize].original_name; if ReactRefresh::is_componentish_name(name.slice()) { // Lower to a function statement, and reference the function in the export list. self.export_props.push(G::Property { key: Some(Expr::init(E::EString::init(b"default"), stmt.loc)), - value: Some(Expr::init_identifier( - symbol.ref_.expect("infallible: ref bound"), - stmt.loc, - )), + value: Some(Expr::init_identifier(symbol.ref_, stmt.loc)), ..Default::default() }); break 'stmt *s; @@ -184,12 +179,7 @@ impl<'a> ConvertESMExportsForHmr<'a> { js_ast::StmtData::SClass(c) => { c.class.can_be_moved() && (if let Some(name) = c.class.class_name { - p.symbols[name - .ref_ - .expect("infallible: ref bound") - .inner_index() - as usize] - .use_count_estimate + p.symbols[name.ref_.inner_index() as usize].use_count_estimate == 0 } else { true @@ -197,10 +187,7 @@ impl<'a> ConvertESMExportsForHmr<'a> { } js_ast::StmtData::SFunction(f) => { if let Some(name) = f.func.name { - p.symbols[name.ref_.expect("infallible: ref bound").inner_index() - as usize] - .use_count_estimate - == 0 + p.symbols[name.ref_.inner_index() as usize].use_count_estimate == 0 } else { true } @@ -276,14 +263,11 @@ impl<'a> ConvertESMExportsForHmr<'a> { key: Some(Expr::init(E::EString::init(b"default"), stmt.loc)), value: Some(Expr::init_identifier( match s.data { - js_ast::StmtData::SClass(class) => class - .class - .class_name - .unwrap() - .ref_ - .expect("infallible: ref bound"), + js_ast::StmtData::SClass(class) => { + class.class.class_name.unwrap().ref_ + } js_ast::StmtData::SFunction(func) => { - func.func.name.unwrap().ref_.expect("infallible: ref bound") + func.func.name.unwrap().ref_ } _ => unreachable!(), }, @@ -301,12 +285,7 @@ impl<'a> ConvertESMExportsForHmr<'a> { break 'stmt stmt; } - let class_name_ref = st - .class - .class_name - .unwrap() - .ref_ - .expect("infallible: ref bound"); + let class_name_ref = st.class.class_name.unwrap().ref_; // Export as CommonJS self.export_props.push(G::Property { key: Some(Expr::init( @@ -334,19 +313,13 @@ impl<'a> ConvertESMExportsForHmr<'a> { st.func.flags.remove(bun_ast::flags::Function::IsExport); - self.visit_ref_to_export( - p, - st.func.name.unwrap().ref_.expect("infallible: ref bound"), - None, - stmt.loc, - false, - )?; + self.visit_ref_to_export(p, st.func.name.unwrap().ref_, None, stmt.loc, false)?; break 'stmt stmt; } js_ast::StmtData::SExportClause(st) => { for item in st.items.iter() { - let ref_ = item.name.ref_.expect("infallible: ref bound"); + let ref_ = item.name.ref_; self.visit_ref_to_export(p, ref_, Some(item.alias), item.name.loc, false)?; } @@ -358,12 +331,12 @@ impl<'a> ConvertESMExportsForHmr<'a> { st.import_record_index, st.namespace_ref, st.items, - Some(stmt.loc), + stmt.loc, None, stmt.loc, )?; for item in st.items.slice_mut().iter_mut() { - let ref_ = item.name.ref_.expect("infallible: ref bound"); + let ref_ = item.name.ref_; let symbol = &mut p.symbols[ref_.inner_index() as usize]; // Always set the namespace alias using the deduplicated import // record. When two `export { ... } from` statements reference @@ -371,12 +344,12 @@ impl<'a> ConvertESMExportsForHmr<'a> { // and its items are merged into the first. The symbols may // already have a namespace_alias from ImportScanner pointing at // the now-unused record, so we must update it. - symbol.namespace_alias = Some(G::NamespaceAlias { + symbol.namespace_alias = Some(bun_alloc::ast_box(G::NamespaceAlias { namespace_ref: deduped.namespace_ref, alias: item.original_name, import_record_index: deduped.import_record_index, ..Default::default() - }); + })); self.visit_ref_to_export( p, ref_, @@ -400,7 +373,7 @@ impl<'a> ConvertESMExportsForHmr<'a> { st.import_record_index, st.namespace_ref, bun_ast::StoreSlice::EMPTY, - Some(stmt.loc), + stmt.loc, None, stmt.loc, )?; @@ -456,7 +429,7 @@ impl<'a> ConvertESMExportsForHmr<'a> { import_record_index: u32, namespace_ref: Ref, items: js_ast::StoreSlice, - star_name_loc: Option, + star_name_loc: bun_ast::Loc, default_name: Option, loc: bun_ast::Loc, ) -> Result { @@ -531,9 +504,9 @@ impl<'a> ConvertESMExportsForHmr<'a> { p.symbol_uses.swap_remove(&namespace_ref); } } - if stmt.star_name_loc.is_none() { - if let Some(stl) = star_name_loc { - stmt.star_name_loc = Some(stl); + if stmt.star_name_loc.is_empty() { + if let Some(stl) = star_name_loc.to_nullable() { + stmt.star_name_loc = stl; } } if stmt.default_name.is_none() { @@ -605,7 +578,7 @@ impl<'a> ConvertESMExportsForHmr<'a> { let symbol = &p.symbols[ref_.inner_index() as usize]; ( symbol.kind, - symbol.has_been_assigned_to, + symbol.has_been_assigned_to(), symbol.original_name, ) }; diff --git a/src/js_parser/p.rs b/src/js_parser/p.rs index 214e4347cdb..fe5d8a41c71 100644 --- a/src/js_parser/p.rs +++ b/src/js_parser/p.rs @@ -1287,7 +1287,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O self.imports_to_convert_from_require .push(DeferredImportNamespace { namespace: LocRef { - ref_: Some(namespace_ref), + ref_: namespace_ref, loc: arg.loc, }, import_record_id: import_record_index, @@ -1484,7 +1484,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O break 'can_remove_part false; } if let Some(name) = &func.func.name { - let name_ref = name.ref_.expect("infallible: ref bound"); + let name_ref = name.ref_; let symbol: &Symbol = &self.symbols[name_ref.inner_index() as usize]; @@ -1511,7 +1511,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O break 'can_remove_part false; } if let Some(name) = &class.class.class_name { - let name_ref = name.ref_.expect("infallible: ref bound"); + let name_ref = name.ref_; let symbol: &Symbol = &self.symbols[name_ref.inner_index() as usize]; @@ -1641,7 +1641,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } } - if let Some(r#ref) = scope.label_ref { + if let Some(r#ref) = scope.label_ref.to_nullable() { let symbol = &symbols[r#ref.inner_index() as usize]; if symbol.slot_namespace() != js_ast::symbol::SlotNamespace::MustNotBeRenamed { // SAFETY: see above. @@ -1867,7 +1867,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O return self.wrap_inlined_enum( Expr { loc, - data: js_ast::ExprData::ENumber(E::Number { value: num }), + data: js_ast::ExprData::ENumber(E::Number::new(num)), }, name, ); @@ -1926,7 +1926,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O return self.wrap_inlined_enum( Expr { loc, - data: js_ast::ExprData::ENumber(E::Number { value: num }), + data: js_ast::ExprData::ENumber(E::Number::new(num)), }, name, ); @@ -2032,7 +2032,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O original_name: js_ast::StoreStr::new(b"Response"), alias_loc: bun_ast::Loc::default(), name: LocRef { - ref_: Some(response_ref), + ref_: response_ref, loc: bun_ast::Loc::default(), }, }); @@ -2054,8 +2054,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O self.response_ref, js_ast::NamedImport { alias: Some(js_ast::StoreStr::new(b"Response")), - alias_loc: Some(bun_ast::Loc::default()), - namespace_ref: Some(self.bun_app_namespace_ref), + alias_loc: bun_ast::Loc::default(), + namespace_ref: self.bun_app_namespace_ref, import_record_index: import_record_i, local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias_is_star: false, @@ -2070,7 +2070,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O import_record_index: import_record_i, is_single_line: true, default_name: None, - star_name_loc: None, + star_name_loc: bun_ast::Loc::EMPTY, phase_defer: false, }, bun_ast::Loc::default(), @@ -2162,7 +2162,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O original_name: js_ast::StoreStr::new(alias_name), alias_loc: bun_ast::Loc::default(), name: LocRef { - ref_: Some(ref_), + ref_, loc: bun_ast::Loc::default(), }, }; @@ -2175,12 +2175,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O if self.options.features.hot_module_reloading { let symbol = &mut self.symbols[ref_.inner_index() as usize]; if symbol.namespace_alias.is_none() { - symbol.namespace_alias = Some(js_ast::NamespaceAlias { + symbol.namespace_alias = Some(bun_alloc::ast_box(js_ast::NamespaceAlias { namespace_ref, alias: js_ast::StoreStr::new(alias_name), import_record_index: import_record_i, was_originally_property_access: false, - }); + })); } } @@ -2189,8 +2189,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O ref_, js_ast::NamedImport { alias: Some(js_ast::StoreStr::new(alias_name)), - alias_loc: Some(bun_ast::Loc::default()), - namespace_ref: Some(namespace_ref), + alias_loc: bun_ast::Loc::default(), + namespace_ref, import_record_index: import_record_i, local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias_is_star: false, @@ -2206,7 +2206,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O import_record_index: import_record_i, is_single_line: true, default_name: None, - star_name_loc: None, + star_name_loc: bun_ast::Loc::EMPTY, phase_defer: false, }, bun_ast::Loc::default(), @@ -2306,7 +2306,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O original_name: js_ast::StoreStr::new(entry.name), alias_loc: bun_ast::Loc::default(), name: LocRef { - ref_: Some(entry.r#ref), + ref_: entry.r#ref, loc: bun_ast::Loc::default(), }, }); @@ -2322,8 +2322,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O entry.r#ref, js_ast::NamedImport { alias: Some(js_ast::StoreStr::new(entry.name)), - alias_loc: Some(bun_ast::Loc::EMPTY), - namespace_ref: Some(namespace_ref), + alias_loc: bun_ast::Loc::EMPTY, + namespace_ref, import_record_index, local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias_is_star: false, @@ -2367,7 +2367,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O import_record_index, is_single_line: false, default_name: None, - star_name_loc: None, + star_name_loc: bun_ast::Loc::EMPTY, phase_defer: false, }, bun_ast::Loc::EMPTY, @@ -3229,12 +3229,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O self.bun_app_namespace_ref = self.new_symbol(js_ast::symbol::Kind::Other, b"import_bun_app")?; let symbol = &mut self.symbols[self.response_ref.inner_index() as usize]; - symbol.namespace_alias = Some(js_ast::NamespaceAlias { + symbol.namespace_alias = Some(bun_alloc::ast_box(js_ast::NamespaceAlias { namespace_ref: self.bun_app_namespace_ref, alias: js_ast::StoreStr::new(b"Response"), was_originally_property_access: false, import_record_index: u32::MAX, - }); + })); } } } @@ -3247,7 +3247,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } fn ensure_require_symbol(&mut self) { - if self.runtime_imports.__require.is_some() { + if !self.runtime_imports.__require.is_empty() { return; } // Call declare_symbol_maybe_generated with the hashed @@ -3273,7 +3273,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O hashed, ) .expect("oom"); - self.runtime_imports.__require = Some(ref_); + self.runtime_imports.__require = ref_; self.runtime_imports.put(b"__require", ref_); } @@ -3424,7 +3424,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // assert(obj.foo === 2) // if scope_kind == js_ast::scope::Kind::With { - self.symbols[symbol_idx].must_not_be_renamed = true; + self.symbols[symbol_idx].set_must_not_be_renamed(true); } if let Some(member_in_scope) = @@ -3714,7 +3714,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O return Some(self.b(B::Identifier { r#ref: ex.ref_ }, expr.loc)); } js_ast::ExprData::EArray(ex) => { - if let Some(spread) = ex.comma_after_spread { + if let Some(spread) = ex.comma_after_spread.to_nullable() { invalid_loc.push(InvalidLoc { loc: spread, kind: crate::parser::InvalidLocTag::Spread, @@ -3769,7 +3769,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O )); } js_ast::ExprData::EObject(mut ex) => { - if let Some(sp) = ex.comma_after_spread { + if let Some(sp) = ex.comma_after_spread.to_nullable() { invalid_loc.push(InvalidLoc { loc: sp, kind: crate::parser::InvalidLocTag::Spread, @@ -3970,7 +3970,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O .insert(bun_ast::ImportRecordFlags::IS_UNUSED); if let Some(name_loc) = stmt.default_name { - let name = self.load_name_from_ref(name_loc.ref_.expect("infallible: ref bound")); + let name = self.load_name_from_ref(name_loc.ref_); let r#ref = self.declare_symbol(js_ast::symbol::Kind::Other, name_loc.loc, name)?; self.is_import_item.insert(r#ref, ()); self.macro_.refs.put( @@ -3982,7 +3982,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O )?; } - if let Some(star) = stmt.star_name_loc { + if let Some(star) = stmt.star_name_loc.to_nullable() { let name = self.load_name_from_ref(stmt.namespace_ref); let r#ref = self.declare_symbol(js_ast::symbol::Kind::Other, star, name)?; stmt.namespace_ref = r#ref; @@ -3997,7 +3997,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // arena-owned `StoreSlice` valid for parser 'a. for item in stmt.items.iter() { - let name = self.load_name_from_ref(item.name.ref_.expect("infallible: ref bound")); + let name = self.load_name_from_ref(item.name.ref_); let r#ref = self.declare_symbol(js_ast::symbol::Kind::Other, item.name.loc, name)?; self.is_import_item.insert(r#ref, ()); @@ -4040,8 +4040,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O continue; } // Declare the symbol and store the ref - let name = - self.load_name_from_ref(item.name.ref_.expect("infallible: ref bound")); + let name = self.load_name_from_ref(item.name.ref_); let r#ref = self.declare_symbol(js_ast::symbol::Kind::Other, item.name.loc, name)?; self.bundler_feature_flag_ref = r#ref; @@ -4076,7 +4075,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // immediately rather than surfacing as odd printer output. debug_assert!( !stmt.phase_defer - || (stmt.star_name_loc.is_some() + || (!stmt.star_name_loc.is_empty() && stmt.default_name.is_none() && stmt.items.is_empty()) ); @@ -4092,7 +4091,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O .flags .set(bun_ast::ImportRecordFlags::PHASE_DEFER, stmt.phase_defer); - if let Some(star) = stmt.star_name_loc { + if let Some(star) = stmt.star_name_loc.to_nullable() { let name = self.load_name_from_ref(stmt.namespace_ref); stmt.namespace_ref = self.declare_symbol(js_ast::symbol::Kind::Import, star, name)?; @@ -4139,22 +4138,22 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Link the default item to the namespace if let Some(name_loc) = &mut stmt.default_name { 'outer: { - let name = self.load_name_from_ref(name_loc.ref_.expect("infallible: ref bound")); + let name = self.load_name_from_ref(name_loc.ref_); let r#ref = self.declare_symbol(js_ast::symbol::Kind::Import, name_loc.loc, name)?; - name_loc.ref_ = Some(r#ref); + name_loc.ref_ = r#ref; self.is_import_item.insert(r#ref, ()); // ensure every e_import_identifier holds the namespace if self.options.features.hot_module_reloading { let symbol = &mut self.symbols[r#ref.inner_index() as usize]; if symbol.namespace_alias.is_none() { - symbol.namespace_alias = Some(js_ast::NamespaceAlias { + symbol.namespace_alias = Some(bun_alloc::ast_box(js_ast::NamespaceAlias { namespace_ref: stmt.namespace_ref, alias: js_ast::StoreStr::new(b"default"), import_record_index: stmt.import_record_index, was_originally_property_access: false, - }); + })); } } @@ -4218,9 +4217,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // SAFETY: items_slice[i] is a live initialised `ClauseItem`; the // original slot is overwritten or compacted below before any drop. let mut item = unsafe { core::ptr::read(&raw const items_slice[i]) }; - let name = self.load_name_from_ref(item.name.ref_.expect("unreachable")); + let name = self.load_name_from_ref(item.name.ref_); let r#ref = self.declare_symbol(js_ast::symbol::Kind::Import, item.name.loc, name)?; - item.name.ref_ = Some(r#ref); + item.name.ref_ = r#ref; self.is_import_item.insert(r#ref, ()); // `ClauseItem.alias` is an arena-owned `StoreStr` valid for 'a. @@ -4231,12 +4230,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O if self.options.features.hot_module_reloading { let symbol = &mut self.symbols[r#ref.inner_index() as usize]; if symbol.namespace_alias.is_none() { - symbol.namespace_alias = Some(js_ast::NamespaceAlias { + symbol.namespace_alias = Some(bun_alloc::ast_box(js_ast::NamespaceAlias { namespace_ref: stmt.namespace_ref, alias: js_ast::StoreStr::new(alias), import_record_index: stmt.import_record_index, was_originally_property_access: false, - }); + })); } } @@ -4385,13 +4384,10 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let name = js_ast::LocRef { loc, - ref_: Some(self.new_symbol(js_ast::symbol::Kind::Other, identifier)?), + ref_: self.new_symbol(js_ast::symbol::Kind::Other, identifier)?, }; - VecExt::append( - &mut self.current_scope_mut().generated, - name.ref_.expect("infallible: ref bound"), - ); + VecExt::append(&mut self.current_scope_mut().generated, name.ref_); Ok(name) } @@ -4423,18 +4419,15 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O match &expr.data { js_ast::ExprData::EFunction(func_container) => { if let Some(_name) = &func_container.func.name { - if let Some(r#ref) = _name.ref_ { - return LocRef { - loc, - ref_: Some(r#ref), - }; + if let Some(r#ref) = _name.ref_.to_nullable() { + return LocRef { loc, ref_: r#ref }; } } } js_ast::ExprData::EIdentifier(ident) => { return LocRef { loc, - ref_: Some(ident.ref_), + ref_: ident.ref_, }; } js_ast::ExprData::EImportIdentifier(ident) => { @@ -4443,17 +4436,14 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O { return LocRef { loc, - ref_: Some(ident.ref_), + ref_: ident.ref_, }; } } js_ast::ExprData::EClass(class) => { if let Some(_name) = &class.class_name { - if let Some(r#ref) = _name.ref_ { - return LocRef { - loc, - ref_: Some(r#ref), - }; + if let Some(r#ref) = _name.ref_.to_nullable() { + return LocRef { loc, ref_: r#ref }; } } } @@ -4941,7 +4931,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // If these are both functions, remove the overwritten declaration if kind.is_function() && self.symbols[symbol_idx].kind.is_function() { - self.symbols[symbol_idx].remove_overwritten_function_declaration = true; + self.symbols[symbol_idx] + .set_remove_overwritten_function_declaration(true); } } MR::BecomePrivateGetSetPair => { @@ -4971,8 +4962,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O pub fn validate_function_name(&mut self, func: &G::Fn, kind: FunctionKind) { if let Some(name) = &func.name { // SAFETY: Symbol.original_name is an arena/source-contents slice valid for 'a. - let original_name: &[u8] = self.symbols - [name.ref_.expect("infallible: ref bound").inner_index() as usize] + let original_name: &[u8] = self.symbols[name.ref_.inner_index() as usize] .original_name .slice(); @@ -5108,7 +5098,6 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O tag: bun_ast::ImportRecordTag::None, loader: None, source_index: bun_ast::Index::INVALID, - module_id: 0, original_path: b"", flags: bun_ast::ImportRecordFlags::empty(), }); @@ -5169,7 +5158,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // continue; // } - self.symbols[member.1.ref_.inner_index() as usize].must_not_be_renamed = true; + self.symbols[member.1.ref_.inner_index() as usize].set_must_not_be_renamed(true); } } @@ -5323,15 +5312,17 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O for i in 0..self.relocated_top_level_vars.len() { // Follow links because "var" declarations may be merged due to hoisting let mut local = self.relocated_top_level_vars[i]; - while let Some(ref_) = local.ref_ { - let symbol = &self.symbols[ref_.inner_index() as usize]; + while !local.ref_.is_empty() { + let symbol = &self.symbols[local.ref_.inner_index() as usize]; if !symbol.has_link() { break; } - local.ref_ = Some(symbol.link.get()); + local.ref_ = symbol.link.get(); } self.relocated_top_level_vars[i] = local; - let Some(ref_) = local.ref_ else { continue }; + let Some(ref_) = local.ref_.to_nullable() else { + continue; + }; let declaration_entry = already_declared.get_or_put(ref_)?; if !declaration_entry.found_existing { let mut decls = bun_alloc::AstAlloc::vec(); @@ -5370,7 +5361,14 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O parts.push(js_ast::Part { stmts: final_stmts, symbol_uses: core::mem::take(&mut self.symbol_uses), - import_symbol_property_uses: core::mem::take(&mut self.import_symbol_property_uses), + import_symbol_property_uses: { + let m = core::mem::take(&mut self.import_symbol_property_uses); + if m.is_empty() { + None + } else { + Some(bun_alloc::ast_box(m)) + } + }, declared_symbols: self.declared_symbols.to_owned_slice(), import_record_indices: { let v = core::mem::replace( @@ -5670,7 +5668,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O pub fn ignore_usage_of_runtime_require(&mut self) { if self.options.features.auto_polyfill_require { - debug_assert!(self.runtime_imports.__require.is_some()); + debug_assert!(!self.runtime_imports.__require.is_empty()); let r = self.runtime_identifier_ref(bun_ast::Loc::EMPTY, b"__require"); self.ignore_usage(r); self.symbols[self.require_ref.inner_index() as usize].use_count_estimate = self.symbols @@ -6157,10 +6155,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let new_ref = self .declare_generated_symbol(js_ast::symbol::Kind::Other, symbol_name) .expect("unreachable"); - let loc_ref = LocRef { - loc, - ref_: Some(new_ref), - }; + let loc_ref = LocRef { loc, ref_: new_ref }; VecExt::append(&mut self.module_scope_mut().generated, new_ref); self.is_import_item.insert(new_ref, ()); self.jsx_imports.set(kind, loc_ref); @@ -6866,7 +6861,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O for (i, arg) in func.func.args.iter().enumerate() { for arg_decorator in arg.ts_decorators.slice() { let arg0 = self.new_expr( - E::Number { value: i as f64 }, + E::Number::new(i as f64), arg_decorator.loc, ); let args = self @@ -6911,7 +6906,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O }; let class_name = s_class.class.class_name.unwrap(); - let class_ref = class_name.ref_.expect("infallible: ref bound"); + let class_ref = class_name.ref_; let target: Expr = if prop.flags.contains(Flags::Property::IsStatic) { self.record_usage(class_ref); self.new_expr(E::Identifier::init(class_ref), class_name.loc) @@ -6993,7 +6988,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut target: Expr; if prop.flags.contains(Flags::Property::IsStatic) { let class_name = s_class.class.class_name.unwrap(); - let class_ref = class_name.ref_.expect("infallible: ref bound"); + let class_ref = class_name.ref_; self.record_usage(class_ref); target = self.new_expr(E::Identifier::init(class_ref), class_name.loc); } else { @@ -7217,7 +7212,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } let class_name = s_class.class.class_name.unwrap(); - let class_ref = class_name.ref_.expect("infallible: ref bound"); + let class_ref = class_name.ref_; let array_items = ExprNodeList::move_from_list(array); let array_expr = self.new_expr( E::Array { @@ -7606,10 +7601,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } pub fn wrap_identifier_hoisting(&mut self, loc: bun_ast::Loc, r#ref: Ref) -> Expr { - self.relocated_top_level_vars.push(LocRef { - loc, - ref_: Some(r#ref), - }); + self.relocated_top_level_vars + .push(LocRef { loc, ref_: r#ref }); self.record_usage(r#ref); Expr::init_identifier(r#ref, loc) } @@ -7657,7 +7650,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O if scope.kind_stops_hoisting() { break; } - if let Some(label_ref) = scope.label_ref { + if let Some(label_ref) = scope.label_ref.to_nullable() { if scope.kind == js_ast::scope::Kind::Label // `Symbol.original_name` is an arena-owned `StoreStr` valid for 'a. && strings::eql(name, self.symbols[label_ref.inner_index() as usize].original_name.slice()) @@ -8512,10 +8505,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O for stmt in part.stmts.iter() { if let js_ast::StmtData::SExportClause(clause) = &stmt.data { for item in clause.items.iter() { - if let Some(import) = self - .named_imports - .get_ptr_mut(&item.name.ref_.expect("infallible: ref bound")) - { + if let Some(import) = self.named_imports.get_ptr_mut(&item.name.ref_) { import.is_exported = true; } } @@ -8770,8 +8760,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let uses_exports_ref = self.symbols[self.exports_ref.inner_index() as usize].use_count_estimate > 0; let uses_require_ref = if self.options.bundle { - self.runtime_imports.__require.is_some() - && self.symbols[self.runtime_imports.__require.unwrap().inner_index() as usize] + !self.runtime_imports.__require.is_empty() + && self.symbols[self.runtime_imports.__require.inner_index() as usize] .use_count_estimate > 0 } else { @@ -8782,7 +8772,11 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // parser's accumulated runtime-helper refs into the Ast so the linker / // printer can emit `__require`, `__toESM`, etc. Precompute `require_ref` // first since it reads `__require` from the same struct we're taking. - let require_ref = self.runtime_imports.__require.unwrap_or(self.require_ref); + let require_ref = self + .runtime_imports + .__require + .to_nullable() + .unwrap_or(self.require_ref); let runtime_imports = core::mem::take(&mut self.runtime_imports); // Re-tag the arena-backed buffer @@ -9019,7 +9013,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O children: bun_alloc::AstAlloc::vec(), generated: bun_alloc::AstAlloc::vec(), kind: js_ast::scope::Kind::Entry, - label_ref: None, + label_ref: Ref::NONE, parent: None, ..Default::default() }); @@ -9324,13 +9318,11 @@ impl LowerUsingDeclarationsContext { // 1. always pass this param for hopefully better jit performance // 2. pass 1 or 0 to be shorter than `true` or `false` p.new_expr( - E::Number { - value: if local_kind == js_ast::s::Kind::KAwaitUsing { - 1.0 - } else { - 0.0 - }, - }, + E::Number::new(if local_kind == js_ast::s::Kind::KAwaitUsing { + 1.0 + } else { + 0.0 + }), stmt_loc, ), ]); @@ -9418,7 +9410,7 @@ impl LowerUsingDeclarationsContext { exports.push(js_ast::ClauseItem { name: LocRef { loc: decl.binding.loc, - ref_: Some(id_ref), + ref_: id_ref, }, alias: p.symbols[id_ref.inner_index() as usize].original_name, alias_loc: decl.binding.loc, @@ -9614,7 +9606,7 @@ impl LowerUsingDeclarationsContext { loc, ); let has_err_binding = p.b(B::Identifier { r#ref: has_err_ref }, loc); - let has_err_value = p.new_expr(E::Number { value: 1.0 }, loc); + let has_err_value = p.new_expr(E::Number::new(1.0), loc); let mut decls = bun_alloc::AstAlloc::vec(); VecExt::append( &mut decls, diff --git a/src/js_parser/parse/mod.rs b/src/js_parser/parse/mod.rs index f2203b55cf2..6714ca771d3 100644 --- a/src/js_parser/parse/mod.rs +++ b/src/js_parser/parse/mod.rs @@ -417,7 +417,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut arrow_arg_errors = DeferredArrowArgErrors::default(); let mut spread_range = bun_ast::Range::default(); let mut type_colon_range = bun_ast::Range::default(); - let mut comma_after_spread: Option = None; + let mut comma_after_spread = bun_ast::Loc::EMPTY; // Push a scope assuming this is an arrow function. It may not be, in which // case we'll need to roll this change back. This has to be done ahead of @@ -482,7 +482,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Spread arguments must come last. If there's a spread argument followed if is_spread { - comma_after_spread = Some(p.lexer.loc()); + comma_after_spread = p.lexer.loc(); } // Eat the comma token @@ -641,7 +641,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let name = LocRef { loc: p.lexer.loc(), - ref_: Some(p.store_name_in_ref(p.lexer.identifier)?), + ref_: p.store_name_in_ref(p.lexer.identifier)?, }; p.lexer.next()?; Ok(Some(name)) @@ -692,13 +692,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O name = Some(LocRef { loc: name_loc, - ref_: None, + ref_: js_ast::Ref::NONE, }); if !opts.is_typescript_declare { - name.as_mut().unwrap().ref_ = Some( - p.declare_symbol(js_ast::symbol::Kind::Class, name_loc, name_text) - .expect("unreachable"), - ); + name.as_mut().unwrap().ref_ = p + .declare_symbol(js_ast::symbol::Kind::Class, name_loc, name_text) + .expect("unreachable"); } } @@ -1171,12 +1170,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O }); } T::TNumericLiteral => { - key = p.new_expr( - E::Number { - value: p.lexer.number, - }, - p.lexer.loc(), - ); + key = p.new_expr(E::Number::new(p.lexer.number), p.lexer.loc()); // check for legacy octal literal p.lexer.next()?; } diff --git a/src/js_parser/parse/parse_entry.rs b/src/js_parser/parse/parse_entry.rs index f72795f5d20..1d76310d622 100644 --- a/src/js_parser/parse/parse_entry.rs +++ b/src/js_parser/parse/parse_entry.rs @@ -1198,10 +1198,7 @@ impl<'a> Parser<'a> { let (ns_ref, ns_loc, import_record_id) = { let deferred_import = &p.imports_to_convert_from_require[i]; ( - deferred_import - .namespace - .ref_ - .expect("infallible: ref bound"), + deferred_import.namespace.ref_, deferred_import.namespace.loc, deferred_import.import_record_id, ) @@ -1213,7 +1210,7 @@ impl<'a> Parser<'a> { import_part_stmts[0] = Stmt::alloc( S::Import { - star_name_loc: Some(ns_loc), + star_name_loc: ns_loc, import_record_index: import_record_id, namespace_ref: ns_ref, default_name: None, @@ -1374,7 +1371,6 @@ impl<'a> Parser<'a> { && p.imports_to_convert_from_require.as_slice()[0] .namespace .ref_ - .unwrap() .eql(id.ref_) { // We know it's 0 because there is only one import in the whole file @@ -1451,8 +1447,7 @@ impl<'a> Parser<'a> { p.imports_to_convert_from_require.as_slice() [req.unwrapped_id as usize] .namespace - .ref_ - .unwrap(); + .ref_; let stmt_loc = stmt.loc; part.stmts = { @@ -1990,7 +1985,7 @@ impl<'a> Parser<'a> { if p.symbols.as_slice()[r.inner_index() as usize].use_count_estimate > 0 { clauses.push(js_ast::ClauseItem { name: js_ast::LocRef { - ref_: Some(r), + ref_: r, loc: bun_ast::Loc::EMPTY, }, alias: js_ast::StoreStr::new(symbol_name.as_bytes()), @@ -2018,7 +2013,7 @@ impl<'a> Parser<'a> { items: clauses, import_record_index: import_record_id, default_name: None, - star_name_loc: None, + star_name_loc: bun_ast::Loc::EMPTY, is_single_line: false, phase_defer: false, }, diff --git a/src/js_parser/parse/parse_fn.rs b/src/js_parser/parse/parse_fn.rs index 8f6a0d3bc27..d2526661bb3 100644 --- a/src/js_parser/parse/parse_fn.rs +++ b/src/js_parser/parse/parse_fn.rs @@ -59,7 +59,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let ref_ = p.new_symbol(js_ast::symbol::Kind::Other, name_text)?; name = Some(js_ast::LocRef { loc: name_loc, - ref_: Some(ref_), + ref_, }); } @@ -142,7 +142,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O js_ast::symbol::Kind::HoistedFunction }; - n.ref_ = Some(p.declare_symbol(kind, n.loc, name_text)?); + n.ref_ = p.declare_symbol(kind, n.loc, name_text)?; } func.name = name; @@ -183,7 +183,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut func = G::Fn { name, flags: initial_flags, - arguments_ref: None, + arguments_ref: js_ast::Ref::NONE, open_parens_loc: p.lexer.loc(), ..Default::default() }; @@ -357,16 +357,14 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // this if it wasn't already declared above because arguments are allowed to // be called "arguments", in which case the real "arguments" is inaccessible. if !p.current_scope().members.contains_key(arguments_str) { - func.arguments_ref = Some( - p.declare_symbol_maybe_generated::( + func.arguments_ref = p + .declare_symbol_maybe_generated::( js_ast::symbol::Kind::Arguments, func.open_parens_loc, arguments_str, ) - .expect("unreachable"), - ); - p.symbols[func.arguments_ref.unwrap().inner_index() as usize].must_not_be_renamed = - true; + .expect("unreachable"); + p.symbols[func.arguments_ref.inner_index() as usize].set_must_not_be_renamed(true); } p.lexer.expect(T::TCloseParen)?; @@ -446,7 +444,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O }; name = Some(js_ast::LocRef { loc: name_loc, - ref_: Some(ref_), + ref_, }); p.lexer.next()?; diff --git a/src/js_parser/parse/parse_import_export.rs b/src/js_parser/parse/parse_import_export.rs index 13626ffe5c4..393dafc5502 100644 --- a/src/js_parser/parse/parse_import_export.rs +++ b/src/js_parser/parse/parse_import_export.rs @@ -123,7 +123,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let alias = p.parse_clause_alias(b"import")?; let mut name = LocRef { loc: alias_loc, - ref_: Some(p.store_name_in_ref(alias)?), + ref_: p.store_name_in_ref(alias)?, }; let mut original_name = alias; p.lexer.next()?; @@ -147,7 +147,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O original_name = p.lexer.identifier; name = LocRef { loc: p.lexer.loc(), - ref_: Some(p.store_name_in_ref(original_name)?), + ref_: p.store_name_in_ref(original_name)?, }; p.lexer.next()?; @@ -173,7 +173,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O original_name = p.lexer.identifier; name = LocRef { loc: p.lexer.loc(), - ref_: Some(p.store_name_in_ref(original_name)?), + ref_: p.store_name_in_ref(original_name)?, }; p.lexer.expect(T::TIdentifier)?; @@ -222,7 +222,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O original_name = p.lexer.identifier; name = LocRef { loc: alias_loc, - ref_: Some(p.store_name_in_ref(original_name)?), + ref_: p.store_name_in_ref(original_name)?, }; p.lexer.expect(T::TIdentifier)?; } else if !is_identifier { @@ -296,7 +296,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let name = LocRef { loc: alias_loc, - ref_: Some(p.store_name_in_ref(alias).expect("unreachable")), + ref_: p.store_name_in_ref(alias).expect("unreachable"), }; let original_name = alias; diff --git a/src/js_parser/parse/parse_prefix.rs b/src/js_parser/parse/parse_prefix.rs index 0a0a155b012..1db995433cd 100644 --- a/src/js_parser/parse/parse_prefix.rs +++ b/src/js_parser/parse/parse_prefix.rs @@ -301,12 +301,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O #[inline] fn pfx_t_numeric_literal(p: &mut Self) -> PResult { let loc = p.lexer.loc(); - let value = p.new_expr( - E::Number { - value: p.lexer.number, - }, - loc, - ); + let value = p.new_expr(E::Number::new(p.lexer.number), loc); // p.checkForLegacyOctalLiteral() p.lexer.next()?; Ok(value) @@ -565,10 +560,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O name = Some(js_ast::LocRef { loc: p.lexer.loc(), - ref_: Some( - p.new_symbol(symbol::Kind::Other, name_text) - .expect("unreachable"), - ), + ref_: p + .new_symbol(symbol::Kind::Other, name_text) + .expect("unreachable"), }); p.lexer.next()?; } @@ -631,10 +625,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O name = Some(js_ast::LocRef { loc: p.lexer.loc(), - ref_: Some( - p.new_symbol(symbol::Kind::Other, name_text) - .expect("unreachable"), - ), + ref_: p + .new_symbol(symbol::Kind::Other, name_text) + .expect("unreachable"), }); p.lexer.next()?; } @@ -802,7 +795,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O Ok(p.new_expr( E::Array { items: items_list, - comma_after_spread: comma_after_spread.to_nullable(), + comma_after_spread, is_single_line, close_bracket_loc, ..Default::default() @@ -892,11 +885,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O Ok(p.new_expr( E::Object { properties: properties_list, - comma_after_spread: if comma_after_spread.start > 0 { - Some(comma_after_spread) - } else { - None - }, + comma_after_spread, is_single_line, close_brace_loc, ..Default::default() diff --git a/src/js_parser/parse/parse_property.rs b/src/js_parser/parse/parse_property.rs index 20e84693571..2df1a2d3332 100644 --- a/src/js_parser/parse/parse_property.rs +++ b/src/js_parser/parse/parse_property.rs @@ -262,12 +262,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O match p.lexer.token { T::TNumericLiteral => { - key = p.new_expr( - E::Number { - value: p.lexer.number, - }, - p.lexer.loc(), - ); + key = p.new_expr(E::Number::new(p.lexer.number), p.lexer.loc()); // p.checkForLegacyOctalLiteral() p.lexer.next()?; } diff --git a/src/js_parser/parse/parse_stmt.rs b/src/js_parser/parse/parse_stmt.rs index 205fdce7557..0102d1de983 100644 --- a/src/js_parser/parse/parse_stmt.rs +++ b/src/js_parser/parse/parse_stmt.rs @@ -1416,7 +1416,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O p.lexer.expect_contextual_keyword(b"as")?; stmt = S::Import { namespace_ref: p.store_name_in_ref(p.lexer.identifier)?, - star_name_loc: Some(p.lexer.loc()), + star_name_loc: p.lexer.loc(), import_record_index: u32::MAX, ..Default::default() }; @@ -1467,7 +1467,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O import_record_index: u32::MAX, default_name: Some(LocRef { loc: p.lexer.loc(), - ref_: Some(p.store_name_in_ref(default_name)?), + ref_: p.store_name_in_ref(default_name)?, }), ..Default::default() }; @@ -1502,7 +1502,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O p.lexer.expect_contextual_keyword(b"as")?; stmt = S::Import { namespace_ref: p.store_name_in_ref(p.lexer.identifier)?, - star_name_loc: Some(p.lexer.loc()), + star_name_loc: p.lexer.loc(), import_record_index: u32::MAX, phase_defer: true, ..Default::default() @@ -1591,7 +1591,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O p.lexer.next()?; p.lexer.expect_contextual_keyword(b"as")?; stmt.namespace_ref = p.store_name_in_ref(p.lexer.identifier)?; - stmt.star_name_loc = Some(p.lexer.loc()); + stmt.star_name_loc = p.lexer.loc(); p.lexer.expect(T::TIdentifier)?; } // "import defaultItem, {item1, item2} from 'path'" @@ -1645,7 +1645,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let _name = LocRef { loc: label_loc, - ref_: Some(label_ref), + ref_: label_ref, }; let mut nested_opts = ParseStatementOptions::default(); diff --git a/src/js_parser/parse/parse_typescript.rs b/src/js_parser/parse/parse_typescript.rs index 35a9c4290b6..0ed358bd521 100644 --- a/src/js_parser/parse/parse_typescript.rs +++ b/src/js_parser/parse/parse_typescript.rs @@ -188,7 +188,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Declare the namespace and create the scope let mut name = LocRef { loc: name_loc, - ref_: None, + ref_: Ref::NONE, }; let scope_index = p.push_scope_for_parse_pass(ScopeKind::Entry, loc)?; p.current_scope_mut().ts_namespace = Some(ts_namespace); @@ -237,7 +237,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O StmtData::SFunction(func) => { if func.func.flags.contains(flags::Function::IsExport) { let locref = func.func.name.unwrap(); - let ref_ = locref.ref_.expect("infallible: ref bound"); + let ref_ = locref.ref_; // SAFETY: original_name is an arena-owned slice valid for 'a. let fn_name: &[u8] = p.symbols[ref_.inner_index() as usize].original_name.slice(); @@ -255,7 +255,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O StmtData::SClass(class) => { if class.is_export { let locref = class.class.class_name.unwrap(); - let ref_ = locref.ref_.expect("infallible: ref bound"); + let ref_ = locref.ref_; // SAFETY: original_name is an arena-owned slice valid for 'a. let class_name: &[u8] = p.symbols[ref_.inner_index() as usize].original_name.slice(); @@ -272,7 +272,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } StmtData::SNamespace(ns) => { if ns.is_export { - let ref_ = ns.name.ref_.expect("infallible: ref bound"); + let ref_ = ns.name.ref_; if let Some(member_data) = p.ref_to_ts_namespace_member.get(&ref_) { let member_data = clone_ts_member_data(member_data); // SAFETY: original_name is arena-owned, valid for 'a. @@ -291,7 +291,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } StmtData::SEnum(ns) => { if ns.is_export { - let ref_ = ns.name.ref_.expect("infallible: ref bound"); + let ref_ = ns.name.ref_; if let Some(member_data) = p.ref_to_ts_namespace_member.get(&ref_) { let member_data = clone_ts_member_data(member_data); // SAFETY: original_name is arena-owned, valid for 'a. @@ -416,9 +416,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O p.pop_scope(); if !opts.is_typescript_declare { - name.ref_ = Some(p.declare_symbol(SymbolKind::TsNamespace, name_loc, name_text)?); + name.ref_ = p.declare_symbol(SymbolKind::TsNamespace, name_loc, name_text)?; p.ref_to_ts_namespace_member - .insert(name.ref_.expect("infallible: ref bound"), ns_member_data); + .insert(name.ref_, ns_member_data); } // S::Namespace.stmts is `StoreSlice` (arena slice). BumpVec → bump slice. @@ -541,7 +541,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O p.lexer.expect(T::TIdentifier)?; let mut name = LocRef { loc: name_loc, - ref_: Some(Ref::NONE), + ref_: Ref::NONE, }; // Generate the namespace object @@ -554,12 +554,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Declare the enum and create the scope let scope_index = p.scopes_in_order.len(); if !opts.is_typescript_declare { - name.ref_ = Some(p.declare_symbol(SymbolKind::TsEnum, name_loc, name_text)?); + name.ref_ = p.declare_symbol(SymbolKind::TsEnum, name_loc, name_text)?; let _ = p.push_scope_for_parse_pass(ScopeKind::Entry, loc)?; p.current_scope_mut().ts_namespace = Some(ts_namespace); // debug-assert no prior entry. let prev = p.ref_to_ts_namespace_member.insert( - name.ref_.expect("infallible: ref bound"), + name.ref_, TSNamespaceMemberData::Namespace(exported_members), ); debug_assert!(prev.is_none()); diff --git a/src/js_parser/parser.rs b/src/js_parser/parser.rs index 5e5d2ecd9ce..2b9cb776620 100644 --- a/src/js_parser/parser.rs +++ b/src/js_parser/parser.rs @@ -668,46 +668,30 @@ pub struct JSXImportSymbols { impl JSXImportSymbols { pub(crate) fn get(&self, name: &[u8]) -> Option { if name == b"jsx" { - return self.jsx.map(|jsx| jsx.ref_.expect("infallible: ref bound")); + return self.jsx.map(|jsx| jsx.ref_); } if name == b"jsxDEV" { - return self - .jsx_dev - .map(|jsx| jsx.ref_.expect("infallible: ref bound")); + return self.jsx_dev.map(|jsx| jsx.ref_); } if name == b"jsxs" { - return self - .jsxs - .map(|jsxs| jsxs.ref_.expect("infallible: ref bound")); + return self.jsxs.map(|jsxs| jsxs.ref_); } if name == b"Fragment" { - return self - .fragment - .map(|f| f.ref_.expect("infallible: ref bound")); + return self.fragment.map(|f| f.ref_); } if name == b"createElement" { - return self - .create_element - .map(|c| c.ref_.expect("infallible: ref bound")); + return self.create_element.map(|c| c.ref_); } None } pub(crate) fn get_with_tag(&self, tag: JSXImport) -> Option { match tag { - JSXImport::Jsx => self.jsx.map(|jsx| jsx.ref_.expect("infallible: ref bound")), - JSXImport::JsxDEV => self - .jsx_dev - .map(|jsx| jsx.ref_.expect("infallible: ref bound")), - JSXImport::Jsxs => self - .jsxs - .map(|jsxs| jsxs.ref_.expect("infallible: ref bound")), - JSXImport::Fragment => self - .fragment - .map(|f| f.ref_.expect("infallible: ref bound")), - JSXImport::CreateElement => self - .create_element - .map(|c| c.ref_.expect("infallible: ref bound")), + JSXImport::Jsx => self.jsx.map(|jsx| jsx.ref_), + JSXImport::JsxDEV => self.jsx_dev.map(|jsx| jsx.ref_), + JSXImport::Jsxs => self.jsxs.map(|jsxs| jsxs.ref_), + JSXImport::Fragment => self.fragment.map(|f| f.ref_), + JSXImport::CreateElement => self.create_element.map(|c| c.ref_), } } @@ -1873,19 +1857,15 @@ impl<'a> ParseStatementOptions<'a> { pub mod prefill { use super::*; - pub mod string_literal { - pub(crate) const CHILDREN: [u8; 8] = *b"children"; - } - pub mod value { use super::*; pub const E_THIS: E::This = E::This {}; - pub(crate) const ZERO: E::Number = E::Number { value: 0.0 }; + pub(crate) const ZERO: E::Number = E::Number::new(0.0); } pub mod string { use super::*; - pub(crate) const CHILDREN: E::String = E::String::from_static(&string_literal::CHILDREN); + pub(crate) const CHILDREN: E::String = E::String::from_static(b"children"); } pub mod data { diff --git a/src/js_parser/repl_transforms.rs b/src/js_parser/repl_transforms.rs index d338c2d1b0b..ab028540070 100644 --- a/src/js_parser/repl_transforms.rs +++ b/src/js_parser/repl_transforms.rs @@ -133,7 +133,7 @@ impl<'a, const TS: bool, const SCAN: bool> P<'a, TS, SCAN> { // Hoist as: var funcName; // Inner: this.funcName = funcName; function funcName() {} if let Some(name_loc) = func.func.name { - let name_ref = name_loc.ref_.expect("infallible: ref bound"); + let name_ref = name_loc.ref_; hoisted_stmts.push(self.s( S::Local { kind: S::Kind::KVar, @@ -198,7 +198,7 @@ impl<'a, const TS: bool, const SCAN: bool> P<'a, TS, SCAN> { // Hoist as: var ClassName; (use var so it persists to vm context) // Inner: ClassName = class ClassName {} if let Some(name_loc) = class.class.class_name { - let name_ref = name_loc.ref_.expect("infallible: ref bound"); + let name_ref = name_loc.ref_; hoisted_stmts.push(self.s( S::Local { kind: S::Kind::KVar, @@ -276,7 +276,7 @@ impl<'a, const TS: bool, const SCAN: bool> P<'a, TS, SCAN> { // `items` is an arena-owned `StoreSlice` valid for 'a. let import_items: &[bun_ast::ClauseItem] = import_data.items.slice(); - if import_data.star_name_loc.is_some() { + if !import_data.star_name_loc.is_empty() { // import * as X from 'mod' -> var X = await import('mod') hoisted_stmts.push(self.s( S::Local { @@ -320,7 +320,7 @@ impl<'a, const TS: bool, const SCAN: bool> P<'a, TS, SCAN> { } else if let Some(default_name) = import_data.default_name { // import X from 'mod' -> var X = (await import('mod')).default // import X, { a } from 'mod' -> var __ns = await import('mod'); var X = __ns.default; var a = __ns.a; - let default_ref = default_name.ref_.expect("infallible: ref bound"); + let default_ref = default_name.ref_; hoisted_stmts.push(self.s( S::Local { kind: S::Kind::KVar, @@ -574,7 +574,7 @@ impl<'a, const TS: bool, const SCAN: bool> P<'a, TS, SCAN> { // For each named import: var name; name = __ns.originalName; for item in import_items.iter() { - let item_ref = item.name.ref_.expect("infallible: ref bound"); + let item_ref = item.name.ref_; hoisted_stmts.push(self.s( S::Local { kind: S::Kind::KVar, diff --git a/src/js_parser/scan/scan_imports.rs b/src/js_parser/scan/scan_imports.rs index 98141a4b43b..a57b83f6abf 100644 --- a/src/js_parser/scan/scan_imports.rs +++ b/src/js_parser/scan/scan_imports.rs @@ -148,20 +148,11 @@ impl<'a> ImportScanner<'a> { if let Some(default_name) = st.default_name { found_imports = true; - let symbol = &p.symbols[default_name - .ref_ - .expect("infallible: ref bound") - .inner_index() - as usize]; + let symbol = &p.symbols[default_name.ref_.inner_index() as usize]; // TypeScript has a separate definition of unused if is_typescript_enabled - && p.ts_use_counts[default_name - .ref_ - .expect("infallible: ref bound") - .inner_index() - as usize] - != 0 + && p.ts_use_counts[default_name.ref_.inner_index() as usize] != 0 { is_unused_in_typescript = false; } @@ -173,7 +164,7 @@ impl<'a> ImportScanner<'a> { } // Remove the star import if it's unused - if st.star_name_loc.is_some() { + if !st.star_name_loc.is_empty() { found_imports = true; let symbol = &p.symbols[st.namespace_ref.inner_index() as usize]; @@ -207,7 +198,7 @@ impl<'a> ImportScanner<'a> { } if !has_any { - st.star_name_loc = None; + st.star_name_loc = bun_ast::Loc::EMPTY; did_remove_star_loc = true; } } @@ -220,7 +211,7 @@ impl<'a> ImportScanner<'a> { let mut items_end: usize = 0; let len = items.len(); for idx in 0..len { - let ref_ = items[idx].name.ref_.expect("infallible: ref bound"); + let ref_ = items[idx].name.ref_; let symbol = &p.symbols[ref_.inner_index() as usize]; // TypeScript has a separate definition of unused @@ -281,7 +272,7 @@ impl<'a> ImportScanner<'a> { || (!is_typescript_enabled && p.options.features.trim_unused_imports && found_imports - && st.star_name_loc.is_none() + && st.star_name_loc.is_empty() // SAFETY: arena-owned slice; see above. && st.items.slice().is_empty() && st.default_name.is_none()) @@ -311,20 +302,20 @@ impl<'a> ImportScanner<'a> { == 0); if convert_star_to_clause && !keep_unused_imports { - st.star_name_loc = None; + st.star_name_loc = bun_ast::Loc::EMPTY; } if is_typescript_enabled { - let default_binding = st - .default_name - .map(|name| (name.ref_.expect("infallible: ref bound"), name.loc)); - let star_binding = st.star_name_loc.map(|loc| (st.namespace_ref, loc)); - let item_bindings = st.items.slice().iter().map(|item| { - ( - item.name.ref_.expect("infallible: ref bound"), - item.name.loc, - ) - }); + let default_binding = st.default_name.map(|name| (name.ref_, name.loc)); + let star_binding = st + .star_name_loc + .to_nullable() + .map(|loc| (st.namespace_ref, loc)); + let item_bindings = st + .items + .slice() + .iter() + .map(|item| (item.name.ref_, item.name.loc)); for (name_ref, import_loc) in default_binding .into_iter() @@ -380,7 +371,7 @@ impl<'a> ImportScanner<'a> { let st_items: &[js_ast::ClauseItem] = st.items.slice(); if p.options.bundle { - if st.star_name_loc.is_some() && existing_count > 0 { + if !st.star_name_loc.is_empty() && existing_count > 0 { let existing = existing_items.unwrap(); // Map keys are Box<[u8]> that drop with the parser; copy into the // AST arena so the `StoreStr` stored on NamedImport / NamespaceAlias @@ -402,11 +393,11 @@ impl<'a> ImportScanner<'a> { for alias in &sorted { let item: LocRef = *existing.get(alias).unwrap(); handle_oom(p.named_imports.put( - item.ref_.expect("infallible: ref bound"), + item.ref_, js_ast::NamedImport { alias: Some(js_ast::StoreStr::new(*alias)), - alias_loc: Some(item.loc), - namespace_ref: Some(namespace_ref), + alias_loc: item.loc, + namespace_ref, import_record_index: st.import_record_index, local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias_is_star: false, @@ -415,7 +406,7 @@ impl<'a> ImportScanner<'a> { )); let name: LocRef = item; - let name_ref = name.ref_.expect("infallible: ref bound"); + let name_ref = name.ref_; // Make sure the printer prints this as a property access let symbol: &mut Symbol = @@ -423,13 +414,16 @@ impl<'a> ImportScanner<'a> { // SAFETY: `original_name` is an arena-owned slice valid for 'p. let original_name = symbol.original_name.slice(); - symbol.namespace_alias = Some(G::NamespaceAlias { - namespace_ref, - alias: js_ast::StoreStr::new(*alias), - import_record_index: st.import_record_index, - was_originally_property_access: st.star_name_loc.is_some() - && existing.contains(original_name), - }); + symbol.namespace_alias = + Some(bun_alloc::ast_box(G::NamespaceAlias { + namespace_ref, + alias: js_ast::StoreStr::new(*alias), + import_record_index: st.import_record_index, + was_originally_property_access: !st + .star_name_loc + .is_empty() + && existing.contains(original_name), + })); // Also record these automatically-generated top-level namespace alias symbols p.declared_symbols @@ -444,10 +438,10 @@ impl<'a> ImportScanner<'a> { handle_oom(p.named_imports.ensure_unused_capacity( st_items.len() + usize::from(st.default_name.is_some()) - + usize::from(st.star_name_loc.is_some()), + + usize::from(!st.star_name_loc.is_empty()), )); - if let Some(loc) = st.star_name_loc { + if let Some(loc) = st.star_name_loc.to_nullable() { record!() .flags .insert(import_record::Flags::CONTAINS_IMPORT_STAR); @@ -456,8 +450,8 @@ impl<'a> ImportScanner<'a> { js_ast::NamedImport { alias_is_star: true, alias: Some(raw_str(b"")), - alias_loc: Some(loc), - namespace_ref: Some(Ref::NONE), + alias_loc: loc, + namespace_ref: Ref::NONE, import_record_index: st.import_record_index, local_parts_with_uses: bun_alloc::AstAlloc::vec(), is_exported: false, @@ -470,11 +464,11 @@ impl<'a> ImportScanner<'a> { .flags .insert(import_record::Flags::CONTAINS_DEFAULT_ALIAS); p.named_imports.put_assume_capacity( - default.ref_.expect("infallible: ref bound"), + default.ref_, js_ast::NamedImport { alias: Some(raw_str(b"default")), - alias_loc: Some(default.loc), - namespace_ref: Some(namespace_ref), + alias_loc: default.loc, + namespace_ref, import_record_index: st.import_record_index, local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias_is_star: false, @@ -485,14 +479,14 @@ impl<'a> ImportScanner<'a> { for item in st_items.iter() { let name: LocRef = item.name; - let name_ref = name.ref_.expect("infallible: ref bound"); + let name_ref = name.ref_; p.named_imports.put_assume_capacity( name_ref, js_ast::NamedImport { alias: Some(item.alias), - alias_loc: Some(name.loc), - namespace_ref: Some(namespace_ref), + alias_loc: name.loc, + namespace_ref, import_record_index: st.import_record_index, local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias_is_star: false, @@ -516,14 +510,14 @@ impl<'a> ImportScanner<'a> { } let name: LocRef = item.name; - let name_ref = name.ref_.expect("infallible: ref bound"); + let name_ref = name.ref_; p.named_imports.put( name_ref, js_ast::NamedImport { alias: Some(item.alias), - alias_loc: Some(name.loc), - namespace_ref: Some(namespace_ref), + alias_loc: name.loc, + namespace_ref, import_record_index: st.import_record_index, local_parts_with_uses: bun_alloc::AstAlloc::vec(), alias_is_star: false, @@ -537,19 +531,22 @@ impl<'a> ImportScanner<'a> { if record!() .flags .contains(import_record::Flags::CONTAINS_IMPORT_STAR) - || st.star_name_loc.is_some() + || !st.star_name_loc.is_empty() { // SAFETY: arena-owned slice valid for 'p. let original_name = symbol.original_name.slice(); - symbol.namespace_alias = Some(G::NamespaceAlias { - namespace_ref, - alias: item.alias, - import_record_index: st.import_record_index, - was_originally_property_access: st.star_name_loc.is_some() - && existing_items - .map(|m| m.contains(original_name)) - .unwrap_or(false), - }); + symbol.namespace_alias = + Some(bun_alloc::ast_box(G::NamespaceAlias { + namespace_ref, + alias: item.alias, + import_record_index: st.import_record_index, + was_originally_property_access: !st + .star_name_loc + .is_empty() + && existing_items + .map(|m| m.contains(original_name)) + .unwrap_or(false), + })); } } @@ -558,19 +555,19 @@ impl<'a> ImportScanner<'a> { .contains(import_record::Flags::WAS_ORIGINALLY_REQUIRE) { let symbol = &mut p.symbols[namespace_ref.inner_index() as usize]; - symbol.namespace_alias = Some(G::NamespaceAlias { + symbol.namespace_alias = Some(bun_alloc::ast_box(G::NamespaceAlias { namespace_ref, alias: js_ast::StoreStr::EMPTY, import_record_index: st.import_record_index, was_originally_property_access: false, - }); + })); } } p.import_records_for_current_part .push(st.import_record_index); - if st.star_name_loc.is_some() { + if !st.star_name_loc.is_empty() { record!() .flags .insert(import_record::Flags::CONTAINS_IMPORT_STAR); @@ -602,14 +599,10 @@ impl<'a> ImportScanner<'a> { if let Some(name) = st.func.name { // SAFETY: arena-owned slice valid for 'p. let original_name: &'p [u8] = p.symbols - [name.ref_.expect("infallible: ref bound").inner_index() as usize] + [name.ref_.inner_index() as usize] .original_name .slice(); - p.record_export( - name.loc, - original_name, - name.ref_.expect("infallible: ref bound"), - )?; + p.record_export(name.loc, original_name, name.ref_)?; } else { p.log().add_range_error( Some(p.source), @@ -627,14 +620,10 @@ impl<'a> ImportScanner<'a> { if let Some(name) = st.class.class_name { // SAFETY: arena-owned slice valid for 'p. let original_name: &'p [u8] = p.symbols - [name.ref_.expect("infallible: ref bound").inner_index() as usize] + [name.ref_.inner_index() as usize] .original_name .slice(); - p.record_export( - name.loc, - original_name, - name.ref_.expect("infallible: ref bound"), - )?; + p.record_export(name.loc, original_name, name.ref_)?; } else { p.log().add_range_error( Some(p.source), @@ -718,7 +707,7 @@ impl<'a> ImportScanner<'a> { let _ = &mut st; // This is defer'd so that we still record export default for identifiers - if let Some(ref_) = deferred_default_name.ref_ { + if let Some(ref_) = deferred_default_name.ref_.to_nullable() { let _ = p.record_export(deferred_default_name.loc, b"default", ref_); } } @@ -727,11 +716,7 @@ impl<'a> ImportScanner<'a> { for item in st.items.slice().iter() { // SAFETY: arena-owned alias slice valid for 'p. let alias: &'p [u8] = item.alias.slice(); - p.record_export( - item.alias_loc, - alias, - item.name.ref_.expect("infallible: ref bound"), - )?; + p.record_export(item.alias_loc, alias, item.name.ref_)?; } } js_ast::StmtData::SExportStar(st) => { @@ -745,8 +730,8 @@ impl<'a> ImportScanner<'a> { js_ast::NamedImport { alias: None, alias_is_star: true, - alias_loc: Some(alias.loc), - namespace_ref: Some(Ref::NONE), + alias_loc: alias.loc, + namespace_ref: Ref::NONE, import_record_index: st.import_record_index, is_exported: true, local_parts_with_uses: bun_alloc::AstAlloc::vec(), @@ -771,9 +756,7 @@ impl<'a> ImportScanner<'a> { .ensure_unused_capacity(items.len()) .expect("unreachable"); for item in items.iter() { - let ref_ = item.name.ref_.unwrap_or_else(|| { - p.panic("Expected export from item to have a name", format_args!("")) - }); + let ref_ = item.name.ref_; // Note that the imported alias is not item.Alias, which is the // exported alias. This is somewhat confusing because each // SExportFrom statement is basically SImport + SExportClause in one. @@ -782,8 +765,8 @@ impl<'a> ImportScanner<'a> { js_ast::NamedImport { alias_is_star: false, alias: Some(item.original_name), - alias_loc: Some(item.name.loc), - namespace_ref: Some(st.namespace_ref), + alias_loc: item.name.loc, + namespace_ref: st.namespace_ref, import_record_index: st.import_record_index, is_exported: true, local_parts_with_uses: bun_alloc::AstAlloc::vec(), diff --git a/src/js_parser/scan/scan_side_effects.rs b/src/js_parser/scan/scan_side_effects.rs index 98dc85f1b56..f48ef8c2240 100644 --- a/src/js_parser/scan/scan_side_effects.rs +++ b/src/js_parser/scan/scan_side_effects.rs @@ -333,9 +333,9 @@ impl SideEffects { // We only do this optimization if the other side is a known primitive with side effects // to avoid corrupting shared nodes when the other side is an undefined identifier if matches!(bin.left.data, ExprData::ENumber(_)) { - bin.left.data = ExprData::ENumber(E::Number { value: 0.0 }); + bin.left.data = ExprData::ENumber(E::Number::new(0.0)); } else if matches!(bin.right.data, ExprData::ENumber(_)) { - bin.right.data = ExprData::ENumber(E::Number { value: 0.0 }); + bin.right.data = ExprData::ENumber(E::Number::new(0.0)); } } _ => {} @@ -391,7 +391,7 @@ impl SideEffects { } else if !is_computed { continue; } else { - let zero = p.new_expr(E::Number { value: 0.0 }, prev_value.loc); + let zero = p.new_expr(E::Number::new(0.0), prev_value.loc); e_object.properties.mut_(j).value = Some(zero); } } @@ -907,7 +907,7 @@ impl SideEffects { ok: true, }, ExprData::ENumber(e) => Result { - value: e.value != 0.0 && !e.value.is_nan(), + value: e.value() != 0.0 && !e.value().is_nan(), side_effects: SideEffects::NoSideEffects, ok: true, }, diff --git a/src/js_parser/scan/scan_symbols.rs b/src/js_parser/scan/scan_symbols.rs index 76db1e2f4e1..0d1f947078c 100644 --- a/src/js_parser/scan/scan_symbols.rs +++ b/src/js_parser/scan/scan_symbols.rs @@ -82,11 +82,11 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let ts_mut = &mut *ts_namespace; ts_mut.property_accesses.insert(name, new_ref); self.symbols[new_ref.inner_index() as usize].namespace_alias = - Some(js_ast::NamespaceAlias { + Some(bun_alloc::ast_box(js_ast::NamespaceAlias { namespace_ref: arg_ref, alias: js_ast::StoreStr::new(name), ..Default::default() - }); + })); break 'brk new_ref; } } @@ -138,7 +138,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // property on the target object of the "with" statement. We must not rename // it or we risk changing the behavior of the code. if is_inside_with_scope { - self.symbols[ref_.inner_index() as usize].must_not_be_renamed = true; + self.symbols[ref_.inner_index() as usize].set_must_not_be_renamed(true); } // Track how many times we've referenced this symbol diff --git a/src/js_parser/visit/mod.rs b/src/js_parser/visit/mod.rs index ef873c88926..d1a954f2f89 100644 --- a/src/js_parser/visit/mod.rs +++ b/src/js_parser/visit/mod.rs @@ -99,12 +99,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O }; self.fn_only_data_visit = FnOnlyDataVisit { is_this_nested: true, - arguments_ref: func.arguments_ref, + arguments_ref: func.arguments_ref.to_nullable(), ..Default::default() }; if let Some(name) = func.name { - if let Some(name_ref) = name.ref_ { + if let Some(name_ref) = name.ref_.to_nullable() { self.record_declared_symbol(name_ref); let symbol_name = self.load_name_from_ref(name_ref); if is_eval_or_arguments(symbol_name) { @@ -344,7 +344,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O self.imports_to_convert_from_require [req.unwrapped_id as usize] .namespace - .ref_ = Some(ref_); + .ref_ = ref_; self.import_items_for_namespace .insert(ref_, ImportItemForNamespaceMap::default()); continue 'outer; @@ -802,7 +802,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O self.visit_ts_decorators(&mut class.ts_decorators); if let Some(name) = class.class_name { - self.record_declared_symbol(name.ref_.expect("infallible: ref bound")); + self.record_declared_symbol(name.ref_); } self.push_scope_for_visit_pass(ScopeKind::ClassName, name_scope_loc) @@ -826,7 +826,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Use "const" for this symbol to match JavaScript run-time semantics. You // are not allowed to assign to this symbol (it throws a TypeError). if let Some(name) = class.class_name { - let name_ref = name.ref_.expect("infallible: ref bound"); + let name_ref = name.ref_; shadow_ref.set(name_ref); let original_name: &'a [u8] = self.symbols[name_ref.inner_index() as usize] .original_name @@ -836,7 +836,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O .put( original_name, ScopeMember { - ref_: name.ref_.unwrap_or(Ref::NONE), + ref_: name.ref_, loc: name.loc, }, ) @@ -1145,7 +1145,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O .declare_symbol(SymbolKind::Other, bind_loc, name) .unwrap_or(id_ref); self.symbols[field_symbol_ref.inner_index() as usize] - .must_not_be_renamed = true; + .set_must_not_be_renamed(true); let field_ident = self.new_expr( E::Identifier { ref_: field_symbol_ref, @@ -1182,7 +1182,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } else if class.class_name.is_none() { let sr = shadow_ref.get(); class.class_name = Some(LocRef { - ref_: Some(sr), + ref_: sr, loc: name_scope_loc, }); self.record_declared_symbol(sr); @@ -1281,14 +1281,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Annex B of the JavaScript standard. // SAFETY: current_scope is a valid arena ptr for the parse. if !p.current_scope().kind_stops_hoisting() - && p.symbols[data - .func - .name - .unwrap() - .ref_ - .expect("infallible: ref bound") - .inner_index() - as usize] + && p.symbols[data.func.name.unwrap().ref_.inner_index() as usize] .kind == SymbolKind::HoistedFunction { @@ -1332,7 +1325,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // means neither identifier can be renamed to something else. So in that // case we give up and do not preserve the semantics of the original code. let name = data.func.name.unwrap(); - let name_ref = name.ref_.expect("infallible: ref bound"); + let name_ref = name.ref_; // SAFETY: current_scope is a valid arena ptr for the parse. if p.current_scope().contains_direct_eval { if let Some(hoisted_ref) = diff --git a/src/js_parser/visit/visit_binary.rs b/src/js_parser/visit/visit_binary.rs index c433537dda0..c0259a3e0c8 100644 --- a/src/js_parser/visit/visit_binary.rs +++ b/src/js_parser/visit/visit_binary.rs @@ -362,7 +362,7 @@ impl BinaryExpressionVisitor { if is_call_target && e_.right.has_value_for_this_in_call() { return Expr::join_with_comma( Expr { - data: ExprData::ENumber(E::Number { value: 0.0 }), + data: ExprData::ENumber(E::Number::new(0.0)), loc: e_.left.loc, }, e_.right, @@ -422,12 +422,7 @@ impl BinaryExpressionVisitor { if p.should_fold_typescript_constant_expressions { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { - return p.new_expr( - E::Number { - value: vals[0] + vals[1], - }, - v.loc, - ); + return p.new_expr(E::Number::new(vals[0] + vals[1]), v.loc); } // "'abc' + 'xyz'" => "'abcxyz'" @@ -466,12 +461,7 @@ impl BinaryExpressionVisitor { if p.should_fold_typescript_constant_expressions { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { - return p.new_expr( - E::Number { - value: vals[0] - vals[1], - }, - v.loc, - ); + return p.new_expr(E::Number::new(vals[0] - vals[1]), v.loc); } } } @@ -479,12 +469,7 @@ impl BinaryExpressionVisitor { if p.should_fold_typescript_constant_expressions { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { - return p.new_expr( - E::Number { - value: vals[0] * vals[1], - }, - v.loc, - ); + return p.new_expr(E::Number::new(vals[0] * vals[1]), v.loc); } } } @@ -492,12 +477,7 @@ impl BinaryExpressionVisitor { if p.should_fold_typescript_constant_expressions { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { - return p.new_expr( - E::Number { - value: vals[0] / vals[1], - }, - v.loc, - ); + return p.new_expr(E::Number::new(vals[0] / vals[1]), v.loc); } } } @@ -509,9 +489,7 @@ impl BinaryExpressionVisitor { // Rust `%` on f64 has libc fmod semantics (LLVM frem), // which matches what JavaScriptCore does: // https://github.com/oven-sh/WebKit/blob/7a0b13626e5db69aa5a32d037431d381df5dfb61/Source/JavaScriptCore/runtime/MathCommon.cpp#L574-L597 - E::Number { - value: vals[0] % vals[1], - }, + E::Number::new(vals[0] % vals[1]), v.loc, ); } @@ -521,12 +499,8 @@ impl BinaryExpressionVisitor { if p.should_fold_typescript_constant_expressions { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { - return p.new_expr( - E::Number { - value: bun_ast::math::pow(vals[0], vals[1]), - }, - v.loc, - ); + return p + .new_expr(E::Number::new(bun_ast::math::pow(vals[0], vals[1])), v.loc); } } } @@ -537,12 +511,7 @@ impl BinaryExpressionVisitor { let left = float_to_int32(vals[0]); let right: u32 = (float_to_int32(vals[1]) as u32) % 32; let result: i32 = left.wrapping_shl(right); - return p.new_expr( - E::Number { - value: result as f64, - }, - v.loc, - ); + return p.new_expr(E::Number::new(result as f64), v.loc); } } } @@ -554,12 +523,7 @@ impl BinaryExpressionVisitor { let right: u32 = (float_to_int32(vals[1]) as u32) % 32; // wrapping_shr on i32 is an arithmetic shift right let result: i32 = left.wrapping_shr(right); - return p.new_expr( - E::Number { - value: result as f64, - }, - v.loc, - ); + return p.new_expr(E::Number::new(result as f64), v.loc); } } } @@ -570,12 +534,7 @@ impl BinaryExpressionVisitor { let left: u32 = float_to_int32(vals[0]) as u32; let right: u32 = (float_to_int32(vals[1]) as u32) % 32; let result: u32 = left.wrapping_shr(right); - return p.new_expr( - E::Number { - value: result as f64, - }, - v.loc, - ); + return p.new_expr(E::Number::new(result as f64), v.loc); } } } @@ -584,9 +543,9 @@ impl BinaryExpressionVisitor { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { return p.new_expr( - E::Number { - value: (float_to_int32(vals[0]) & float_to_int32(vals[1])) as f64, - }, + E::Number::new( + (float_to_int32(vals[0]) & float_to_int32(vals[1])) as f64, + ), v.loc, ); } @@ -597,9 +556,9 @@ impl BinaryExpressionVisitor { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { return p.new_expr( - E::Number { - value: (float_to_int32(vals[0]) | float_to_int32(vals[1])) as f64, - }, + E::Number::new( + (float_to_int32(vals[0]) | float_to_int32(vals[1])) as f64, + ), v.loc, ); } @@ -610,9 +569,9 @@ impl BinaryExpressionVisitor { if let Some(vals) = Expr::extract_numeric_values(&e_.left.data, &e_.right.data) { return p.new_expr( - E::Number { - value: (float_to_int32(vals[0]) ^ float_to_int32(vals[1])) as f64, - }, + E::Number::new( + (float_to_int32(vals[0]) ^ float_to_int32(vals[1])) as f64, + ), v.loc, ); } diff --git a/src/js_parser/visit/visit_expr.rs b/src/js_parser/visit/visit_expr.rs index 986bba02a14..f1f6adc7729 100644 --- a/src/js_parser/visit/visit_expr.rs +++ b/src/js_parser/visit/visit_expr.rs @@ -244,7 +244,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O p.commonjs_module_exports_assigned_deoptimized = true; } - p.symbols[result.r#ref.inner_index() as usize].has_been_assigned_to = true; + p.symbols[result.r#ref.inner_index() as usize].set_has_been_assigned_to(true); } let mut original_name: Option<&[u8]> = None; @@ -1059,9 +1059,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O if p.options.features.minify_syntax { if let Some(number) = index.data.as_e_number() { - if number.value >= 0.0 - && number.value < (usize::MAX as f64) - && number.value % 1.0 == 0.0 + if number.value() >= 0.0 + && number.value() < (usize::MAX as f64) + && number.value() % 1.0 == 0.0 { // "foo"[2] -> "o" if let Some(str_) = target.data.as_e_string() { @@ -1088,7 +1088,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } } else if let Some(array) = target.data.as_e_array() { // [x][0] -> x - if array.items.len_u32() == 1 && number.value == 0.0 { + if array.items.len_u32() == 1 && number.value() == 0.0 { let inlined = *array.items.at(0); if inlined.can_be_inlined_from_property_access() { *e = inlined; @@ -1097,7 +1097,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } // ['a', 'b', 'c'][1] -> 'b' - let int: usize = number.value as usize; + let int: usize = number.value() as usize; if int < array.items.len_u32() as usize && p.expr_can_be_removed_if_unused(&target) { @@ -1273,9 +1273,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O if p.should_fold_typescript_constant_expressions { if let Some(value) = SideEffects::to_number(&e_.value.data) { *e = p.new_expr( - E::Number { - value: f64::from(!float_to_int32(value)), - }, + E::Number::new(f64::from(!float_to_int32(value))), expr.loc, ); return; @@ -1290,13 +1288,13 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } Op::UnPos => { if let Some(num) = SideEffects::to_number(&e_.value.data) { - *e = p.new_expr(E::Number { value: num }, expr.loc); + *e = p.new_expr(E::Number::new(num), expr.loc); return; } } Op::UnNeg => { if let Some(num) = SideEffects::to_number(&e_.value.data) { - *e = p.new_expr(E::Number { value: -num }, expr.loc); + *e = p.new_expr(E::Number::new(-num), expr.loc); return; } } @@ -1503,7 +1501,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // "(1 ? this.fn : 2)()" => "(0, this.fn)()" if is_call_target && e_.yes.has_value_for_this_in_call() { *e = p - .new_expr(E::Number { value: 0.0 }, e_.test_.loc) + .new_expr(E::Number::new(0.0), e_.test_.loc) .join_with_comma(e_.yes); return; } @@ -1531,7 +1529,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // "(1 ? this.fn : 2)()" => "(0, this.fn)()" if is_call_target && e_.no.has_value_for_this_in_call() { *e = p - .new_expr(E::Number { value: 0.0 }, e_.test_.loc) + .new_expr(E::Number::new(0.0), e_.test_.loc) .join_with_comma(e_.no); return; } @@ -2315,16 +2313,11 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let str_ = target_str.data; let arg1 = e_.args.at(0).unwrap_inlined(); if let Data::ENumber(n) = &arg1.data { - let float = n.value; + let float = n.value(); if float % 1.0 == 0.0 && float < (str_.len() as f64) && float >= 0.0 { let char_ = str_[float as usize]; if char_ < 0x80 { - *e = p.new_expr( - E::Number { - value: f64::from(char_), - }, - expr.loc, - ); + *e = p.new_expr(E::Number::new(f64::from(char_)), expr.loc); return; } } @@ -2574,8 +2567,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // SAFETY: current_scope is a live arena ptr while the parser exists. && !p.current_scope().contains_direct_eval && e_.func.name.is_some() - && e_.func.name.unwrap().ref_.is_some() - && p.symbols[e_.func.name.unwrap().ref_.expect("infallible: ref bound").inner_index() as usize] + && !e_.func.name.unwrap().ref_.is_empty() + && p.symbols[e_.func.name.unwrap().ref_.inner_index() as usize] .use_count_estimate == 0 { @@ -2601,7 +2594,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O final_expr = p.keep_expr_symbol_name( final_expr, // SAFETY: original_name is arena-owned, valid for 'a. - p.symbols[name.ref_.expect("infallible: ref bound").inner_index() as usize] + p.symbols[name.ref_.inner_index() as usize] .original_name .slice(), ); @@ -2643,8 +2636,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // SAFETY: current_scope is a live arena ptr while the parser exists. && !p.current_scope().contains_direct_eval && e_.class_name.is_some() - && e_.class_name.unwrap().ref_.is_some() - && p.symbols[e_.class_name.unwrap().ref_.expect("infallible: ref bound").inner_index() as usize] + && !e_.class_name.unwrap().ref_.is_empty() + && p.symbols[e_.class_name.unwrap().ref_.inner_index() as usize] .use_count_estimate == 0 { diff --git a/src/js_parser/visit/visit_stmt.rs b/src/js_parser/visit/visit_stmt.rs index ff3f0588c7a..6b1606baada 100644 --- a/src/js_parser/visit/visit_stmt.rs +++ b/src/js_parser/visit/visit_stmt.rs @@ -136,13 +136,13 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O p.record_declared_symbol(data.namespace_ref); if let Some(default_name) = data.default_name { - p.record_declared_symbol(default_name.ref_.expect("infallible: ref bound")); + p.record_declared_symbol(default_name.ref_); } let items = data.items.slice(); if !items.is_empty() { for item in items.iter() { - p.record_declared_symbol(item.name.ref_.expect("infallible: ref bound")); + p.record_declared_symbol(item.name.ref_); } } @@ -179,7 +179,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut any_replaced = false; if p.options.features.replace_exports.count() > 0 { for i in 0..items_len { - let name = p.load_name_from_ref(items[i].name.ref_.expect("infallible: ref bound")); + let name = p.load_name_from_ref(items[i].name.ref_); let symbol = p.find_symbol(items[i].alias_loc, name)?; let ref_ = symbol.r#ref; @@ -212,7 +212,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O continue; } - items[i].name.ref_ = Some(ref_); + items[i].name.ref_ = ref_; // Compaction: items[..end] is the kept prefix; items[i] is dead // after this iteration and the slice is truncated to `end` below. items.swap(end, i); @@ -220,7 +220,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } } else { for i in 0..items_len { - let name = p.load_name_from_ref(items[i].name.ref_.expect("infallible: ref bound")); + let name = p.load_name_from_ref(items[i].name.ref_); let symbol = p.find_symbol(items[i].alias_loc, name)?; let ref_ = symbol.r#ref; @@ -243,7 +243,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O continue; } - items[i].name.ref_ = Some(ref_); + items[i].name.ref_ = ref_; // Compaction: items[..end] is the kept prefix; items[i] is dead // after this iteration and the slice is truncated to `end` below. items.swap(end, i); @@ -283,7 +283,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut j: usize = 0; // This is a re-export and the symbols created here are used to reference for i in 0..items.len() { - let old_ref = items[i].name.ref_.expect("infallible: ref bound"); + let old_ref = items[i].name.ref_; // alias is arena-owned (`ArenaStr`), valid for 'a. let alias = items[i].alias.slice(); @@ -300,7 +300,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Compaction: items[..j] is the kept prefix; items[i] is dead // after this iteration and the slice is truncated to `j` below. items.swap(j, i); - items[j].name.ref_ = Some(ref_); + items[j].name.ref_ = ref_; j += 1; } @@ -309,11 +309,11 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } else { // This is a re-export and the symbols created here are used to reference for item in items.iter_mut() { - let _name = p.load_name_from_ref(item.name.ref_.expect("infallible: ref bound")); + let _name = p.load_name_from_ref(item.name.ref_); let ref_ = p.new_symbol(js_ast::symbol::Kind::Import, _name)?; VecExt::append(&mut p.cur_scope().generated, ref_); p.record_declared_symbol(ref_); - item.name.ref_ = Some(ref_); + item.name.ref_ = ref_; } } @@ -372,7 +372,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // closure invoked at every return site below. macro_rules! record_on_exit { () => { - if let Some(ref_) = data.default_name.ref_ { + if let Some(ref_) = data.default_name.ref_.to_nullable() { p.record_declared_symbol(ref_); } }; @@ -437,7 +437,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O if p.local_type_names.get(original_name).copied() == Some(true) { // the name points to a type — don't try to declare // this symbol, drop the statement. - data.default_name.ref_ = None; + data.default_name.ref_ = Ref::NONE; restore_dead!(); record_on_exit!(); return Ok(()); @@ -447,12 +447,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } } - if data - .default_name - .ref_ - .expect("infallible: ref bound") - .is_source_contents_slice() - { + if data.default_name.ref_.is_source_contents_slice() { data.default_name = p.create_default_name(expr.loc).expect("unreachable"); } @@ -513,7 +508,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O G::Decl { binding: p.b( B::Identifier { - r#ref: data.default_name.ref_.expect("infallible: ref bound"), + r#ref: data.default_name.ref_, }, data.default_name.loc, ), @@ -577,7 +572,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O StmtData::SFunction(mut func_ref) => { let func: &mut S::Function = &mut *func_ref; let name: &'a [u8] = if let Some(func_loc) = func.func.name { - p.load_name_from_ref(func_loc.ref_.expect("infallible: ref bound")) + p.load_name_from_ref(func_loc.ref_) } else { func.func.name = Some(data.default_name); js_ast::ClauseItem::DEFAULT_ALIAS @@ -598,12 +593,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O return Ok(()); } - if data - .default_name - .ref_ - .expect("infallible: ref bound") - .is_source_contents_slice() - { + if data.default_name.ref_.is_source_contents_slice() { data.default_name = p.create_default_name(stmt.loc).expect("unreachable"); } @@ -680,7 +670,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // // const Foo = _s(function Foo() {}) // export default Foo; - if let Some(r) = loc_ref.ref_ { + if let Some(r) = loc_ref.ref_.to_nullable() { break 'brk r; } } @@ -713,7 +703,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O break 'emit_temp_var ref_to_use; } } else { - data.default_name.ref_.expect("infallible: ref bound") + data.default_name.ref_ }; if p.options.features.server_components.wraps_exports() { @@ -764,11 +754,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } StmtData::SClass(mut class_ref) => { let class: &mut S::Class = &mut *class_ref; - let _ = p.visit_class( - s2_loc, - &mut class.class, - data.default_name.ref_.expect("infallible: ref bound"), - ); + let _ = p.visit_class(s2_loc, &mut class.class, data.default_name.ref_); if p.is_control_flow_dead { restore_dead!(); @@ -802,12 +788,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } } - if data - .default_name - .ref_ - .expect("infallible: ref bound") - .is_source_contents_slice() - { + if data.default_name.ref_.is_source_contents_slice() { data.default_name = p.create_default_name(stmt.loc).expect("unreachable"); } @@ -820,7 +801,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O || class.class.should_lower_standard_decorators { if class.class.class_name.is_none() - || class.class.class_name.unwrap().ref_.is_none() + || class.class.class_name.unwrap().ref_.is_empty() { class.class.class_name = Some(data.default_name); } @@ -888,13 +869,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mark_as_dead = p.options.features.dead_code_elimination && data.func.flags.contains(flags::Function::IsExport) && p.options.features.replace_exports.count() > 0 - && p.is_export_to_eliminate( - data.func - .name - .expect("infallible: name checked") - .ref_ - .expect("infallible: ref bound"), - ); + && p.is_export_to_eliminate(data.func.name.expect("infallible: name checked").ref_); let original_is_dead = p.is_control_flow_dead; if mark_as_dead { @@ -911,16 +886,11 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let open_parens_loc = data.func.open_parens_loc; data.func = p.visit_func(core::mem::take(&mut data.func), open_parens_loc); - let name_ref = data - .func - .name - .expect("infallible: name checked") - .ref_ - .expect("infallible: ref bound"); + let name_ref = data.func.name.expect("infallible: name checked").ref_; debug_assert!(name_ref.is_symbol()); let name_symbol = &p.symbols[name_ref.inner_index() as usize]; let original_name: &'a [u8] = name_symbol.original_name.slice(); - let remove_overwritten = name_symbol.remove_overwritten_function_declaration; + let remove_overwritten = name_symbol.remove_overwritten_function_declaration(); // Handle exporting this function from a namespace if data.func.flags.contains(flags::Function::IsExport) @@ -944,10 +914,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O }, stmt.loc, ), - Expr::init_identifier( - func_name.ref_.expect("infallible: ref bound"), - func_name.loc, - ), + Expr::init_identifier(func_name.ref_, func_name.loc), )); } else if !mark_as_dead { if remove_overwritten { @@ -1057,8 +1024,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O data.class .class_name .expect("infallible: name checked") - .ref_ - .expect("infallible: ref bound"), + .ref_, ); let original_is_dead = p.is_control_flow_dead; @@ -1085,8 +1051,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O .class .class_name .expect("infallible: name checked") - .ref_ - .expect("infallible: ref bound"); + .ref_; let name = p.load_name_from_ref(ref_); if let Some(replacement) = p.options.features.replace_exports.get_ptr(name).cloned() { if p.inject_replacement_export( @@ -1103,7 +1068,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // Handle exporting this class from a namespace if was_export_inside_namespace { let class_name = data.class.class_name.expect("infallible: name checked"); - let class_name_ref = class_name.ref_.expect("infallible: ref bound"); + let class_name_ref = class_name.ref_; let original_name = p.symbols[class_name_ref.inner_index() as usize] .original_name .slice(); @@ -1287,17 +1252,10 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O data: &mut S::Break, ) -> Result<(), Error> { if let Some(label) = &mut data.label { - let r = label.ref_.unwrap_or_else(|| { - p.panic_loc( - "Expected label to have a ref", - format_args!(""), - Some(label.loc), - ) - }); - let name = p.load_name_from_ref(r); + let name = p.load_name_from_ref(label.ref_); let res = p.find_label_symbol(label.loc, name); if res.found { - label.ref_ = Some(res.r#ref); + label.ref_ = res.r#ref; } else { data.label = None; } @@ -1320,16 +1278,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O data: &mut S::Continue, ) -> Result<(), Error> { if let Some(label) = &mut data.label { - let r = label.ref_.unwrap_or_else(|| { - p.panic_loc( - "Expected continue label to have a ref", - format_args!(""), - Some(label.loc), - ) - }); - let name = p.load_name_from_ref(r); + let name = p.load_name_from_ref(label.ref_); let res = p.find_label_symbol(label.loc, name); - label.ref_ = Some(res.r#ref); + label.ref_ = res.r#ref; if res.found && !res.is_loop { let r = js_lexer::range_of_identifier(p.source, stmt.loc); p.log().add_range_error_fmt( @@ -1356,12 +1307,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O ) -> Result<(), Error> { p.push_scope_for_visit_pass(js_ast::scope::Kind::Label, stmt.loc) .expect("unreachable"); - let name = p.load_name_from_ref(data.name.ref_.expect("infallible: ref bound")); + let name = p.load_name_from_ref(data.name.ref_); let ref_ = p .new_symbol(js_ast::symbol::Kind::Label, name) .expect("unreachable"); - data.name.ref_ = Some(ref_); - p.cur_scope().label_ref = Some(ref_); + data.name.ref_ = ref_; + p.cur_scope().label_ref = ref_; match data.stmt.data { StmtData::SFor(_) | StmtData::SForIn(_) @@ -1482,7 +1433,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O alias: js_ast::StoreStr::new(key), alias_loc: bin.left.loc, name: js_ast::LocRef { - ref_: Some(ref_), + ref_, loc: last_loc, }, ..Default::default() @@ -2168,11 +2119,10 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // maps. We are avoiding that to reduce memory usage, since // enum inlining already uses alot of hash maps. if p.current_scope == p.module_scope && p.options.bundle { - p.top_level_enums - .push(data.name.ref_.expect("infallible: ref bound")); + p.top_level_enums.push(data.name.ref_); } - p.record_declared_symbol(data.name.ref_.expect("infallible: ref bound")); + p.record_declared_symbol(data.name.ref_); p.push_scope_for_visit_pass(js_ast::scope::Kind::Entry, stmt.loc)?; p.record_declared_symbol(data.arg); @@ -2230,12 +2180,12 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O match underlying_value.data { js_ast::ExprData::ENumber(num) => { exported_members.get_ptr_mut(name).unwrap().data = - js_ast::ts::Data::EnumNumber(num.value); + js_ast::ts::Data::EnumNumber(num.value()); p.ref_to_ts_namespace_member - .insert(value.ref_, js_ast::ts::Data::EnumNumber(num.value)); + .insert(value.ref_, js_ast::ts::Data::EnumNumber(num.value())); - next_numeric_value = Some(num.value + 1.0); + next_numeric_value = Some(num.value() + 1.0); } js_ast::ExprData::EString(str_) => { has_string_value = true; @@ -2257,7 +2207,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } } } else if let Some(num) = next_numeric_value { - value.value = Some(p.new_expr(E::Number { value: num }, value.loc)); + value.value = Some(p.new_expr(E::Number::new(num), value.loc)); next_numeric_value = Some(num + 1.0); @@ -2350,7 +2300,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O stmt.loc, data.is_export, data.name.loc, - data.name.ref_.expect("infallible: ref bound"), + data.name.ref_, data.arg, value_stmts.into_bump_slice_mut(), all_values_are_pure, @@ -2365,7 +2315,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O stmt: &mut Stmt, data: &mut S::Namespace, ) -> Result<(), Error> { - p.record_declared_symbol(data.name.ref_.expect("infallible: ref bound")); + p.record_declared_symbol(data.name.ref_); // Scan ahead for any variables inside this namespace. This must be done // ahead of time before visiting any statements inside the namespace @@ -2400,7 +2350,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O stmt.loc, data.is_export, data.name.loc, - data.name.ref_.expect("infallible: ref bound"), + data.name.ref_, data.arg, prepend_list.into_bump_slice_mut(), false, diff --git a/src/js_parser_jsc/Macro.rs b/src/js_parser_jsc/Macro.rs index 7daa679604e..21487816ceb 100644 --- a/src/js_parser_jsc/Macro.rs +++ b/src/js_parser_jsc/Macro.rs @@ -809,17 +809,13 @@ impl<'a> Run<'a> { T::Integer => { return Ok(Expr::init( - E::Number { - value: value.to_int32() as f64, - }, + E::Number::new(value.to_int32() as f64), self.caller.loc, )); } T::Double => { return Ok(Expr::init( - E::Number { - value: value.as_number(), - }, + E::Number::new(value.as_number()), self.caller.loc, )); } diff --git a/src/js_parser_jsc/expr_jsc.rs b/src/js_parser_jsc/expr_jsc.rs index 12e6fb8b3a2..d681377c37e 100644 --- a/src/js_parser_jsc/expr_jsc.rs +++ b/src/js_parser_jsc/expr_jsc.rs @@ -104,7 +104,7 @@ pub(crate) fn array_to_js( } pub(crate) fn number_to_js(this: E::Number) -> JSValue { - JSValue::js_number(this.value) + JSValue::js_number(this.value()) } pub(crate) fn object_to_js( diff --git a/src/js_printer/lib.rs b/src/js_printer/lib.rs index 425286b4850..b1d2293c50f 100644 --- a/src/js_printer/lib.rs +++ b/src/js_printer/lib.rs @@ -1464,7 +1464,7 @@ fn is_identifier_or_numeric_constant_or_property_access(expr: &js_ast::Expr) -> use js_ast::ExprData; match &expr.data { ExprData::EIdentifier(_) | ExprData::EDot(_) | ExprData::EIndex(_) => true, - ExprData::ENumber(e) => e.value.is_infinite() || e.value.is_nan(), + ExprData::ENumber(e) => e.value().is_infinite() || e.value().is_nan(), _ => false, } } @@ -2004,7 +2004,7 @@ pub mod __gated_printer { unreachable!(); } - if import.star_name_loc.is_some() { + if !import.star_name_loc.is_empty() { self.print(b"var "); self.print_symbol(import.namespace_ref); self.print_space(); @@ -2028,7 +2028,7 @@ pub mod __gated_printer { if let Some(default) = &import.default_name { self.print_semicolon_if_needed(); self.print(b"var "); - self.print_symbol(default.ref_.expect("infallible: ref bound")); + self.print_symbol(default.ref_); match statement { None => { self.print_equals(); @@ -2080,7 +2080,7 @@ pub mod __gated_printer { self.print_whitespacer(ws!(b"} = ")); - if import.star_name_loc.is_none() && import.default_name.is_none() { + if import.star_name_loc.is_empty() && import.default_name.is_none() { match statement { None => self.print_require_or_import_expr( import.import_record_index, @@ -2093,7 +2093,7 @@ pub mod __gated_printer { Some(s) => self.print(s), } } else if let Some(name) = &import.default_name { - self.print_symbol(name.ref_.expect("infallible: ref bound")); + self.print_symbol(name.ref_); } else { self.print_symbol(import.namespace_ref); } @@ -2105,20 +2105,20 @@ pub mod __gated_printer { // bypasses printDeclStmt/printBinding, so we must record vars explicitly. // reshaped for borrowck — compute names before borrowing module_info. if Self::MAY_HAVE_MODULE_INFO && self.module_info.is_some() { - if import.star_name_loc.is_some() { + if !import.star_name_loc.is_empty() { let name = self.name_for_symbol(import.namespace_ref); let mi = self.module_info().expect("infallible: module_info enabled"); let id = mi.str(name); mi.add_var(id, analyze_transpiled_module::VarKind::Declared); } if let Some(default) = &import.default_name { - let name = self.name_for_symbol(default.ref_.expect("infallible: ref bound")); + let name = self.name_for_symbol(default.ref_); let mi = self.module_info().expect("infallible: module_info enabled"); let id = mi.str(name); mi.add_var(id, analyze_transpiled_module::VarKind::Declared); } for item in slice_of(import.items).iter() { - let name = self.name_for_symbol(item.name.ref_.expect("infallible: ref bound")); + let name = self.name_for_symbol(item.name.ref_); let mi = self.module_info().expect("infallible: module_info enabled"); let id = mi.str(name); mi.add_var(id, analyze_transpiled_module::VarKind::Declared); @@ -3077,7 +3077,7 @@ pub mod __gated_printer { } fn print_clause_item_as(&mut self, item: &js_ast::ClauseItem, as_: ClauseItemAs) { - let name = self.name_for_symbol(item.name.ref_.expect("infallible: ref bound")); + let name = self.name_for_symbol(item.name.ref_); match as_ { ClauseItemAs::Import => { @@ -3387,12 +3387,7 @@ pub mod __gated_printer { let mut found: Option = None; if let Some(exports) = self.options.commonjs_named_exports { for (idx, value) in exports.values().iter().enumerate() { - if value - .loc_ref - .ref_ - .expect("infallible: ref bound") - .eql(id.ref_) - { + if value.loc_ref.ref_.eql(id.ref_) { found = Some(idx); break; } @@ -3435,7 +3430,7 @@ pub mod __gated_printer { self.print(b"]"); } } else { - self.print_symbol(value.loc_ref.ref_.expect("infallible: ref bound")); + self.print_symbol(value.loc_ref.ref_); } } } @@ -3861,11 +3856,7 @@ pub mod __gated_printer { if let Some(sym) = &e.func.name { self.print_space_before_identifier(); self.add_source_mapping(sym.loc); - self.print_symbol(sym.ref_.unwrap_or_else(|| { - Output::panic(format_args!( - "internal error: expected E.Function's name symbol to have a ref" - )) - })); + self.print_symbol(sym.ref_); } self.print_func(&e.func); @@ -3886,11 +3877,7 @@ pub mod __gated_printer { if let Some(name) = &e.class_name { self.print(b" "); self.add_source_mapping(name.loc); - self.print_symbol(name.ref_.unwrap_or_else(|| { - Output::panic(format_args!( - "internal error: expected E.Class's name symbol to have a ref" - )) - })); + self.print_symbol(name.ref_); } self.print_class(e); if wrap { @@ -4219,7 +4206,7 @@ pub mod __gated_printer { } ExprData::ENumber(e) => { self.add_source_mapping(expr.loc); - self.print_number(e.value, level); + self.print_number(e.value(), level); } ExprData::EIdentifier(e) => { let name = self.name_for_symbol(e.ref_); @@ -4703,7 +4690,7 @@ pub mod __gated_printer { } js_ast::InlinedEnumValueDecoded::Number(num) => { item.key.as_mut().unwrap().data = - ExprData::ENumber(E::Number { value: num }); + ExprData::ENumber(E::Number::new(num)); set_flag( &mut item.flags, js_ast::flags::Property::IsComputed, @@ -4770,7 +4757,7 @@ pub mod __gated_printer { // Automatically print numbers that would cause a syntax error as computed properties if !IS_JSON && !item.flags.contains(js_ast::flags::Property::IsComputed) - && matches!(&key.data, ExprData::ENumber(e) if self.number_property_key_must_be_computed(e.value)) + && matches!(&key.data, ExprData::ENumber(e) if self.number_property_key_must_be_computed(e.value())) { // "{ -1: 0 }" must be printed as "{ [-1]: 0 }" // "{ 1/0: 0 }" must be printed as "{ [1/0]: 0 }" @@ -5052,7 +5039,7 @@ pub mod __gated_printer { // Automatically print numbers that would cause a syntax error as computed properties let key_must_be_computed = matches!( &property.key.data, - ExprData::ENumber(e) if self.number_property_key_must_be_computed(e.value) + ExprData::ENumber(e) if self.number_property_key_must_be_computed(e.value()) ); if property.flags.contains(js_ast::flags::Property::IsComputed) @@ -5218,9 +5205,7 @@ pub mod __gated_printer { "Internal error: expected func to have a name ref" )) }); - let name_ref = name.ref_.unwrap_or_else(|| { - Output::panic(format_args!("Internal error: expected func to have a name")) - }); + let name_ref = name.ref_; if s.func.flags.contains(G::FnFlags::IsExport) { if !REWRITE_ESM_TO_CJS { @@ -5274,13 +5259,7 @@ pub mod __gated_printer { self.print_indent(); self.print_space_before_identifier(); self.add_source_mapping(stmt.loc); - let name_ref = s - .class - .class_name - .as_ref() - .unwrap() - .ref_ - .expect("infallible: ref bound"); + let name_ref = s.class.class_name.as_ref().unwrap().ref_; if s.is_export { if !REWRITE_ESM_TO_CJS { self.print(b"export "); @@ -5376,12 +5355,11 @@ pub mod __gated_printer { self.maybe_print_space(); } - let func_name: Option<&[u8]> = - func.func.name.as_ref().map(|name| { - self.name_for_symbol( - name.ref_.expect("infallible: ref bound"), - ) - }); + let func_name: Option<&[u8]> = func + .func + .name + .as_ref() + .map(|name| self.name_for_symbol(name.ref_)); if let Some(fn_name) = func_name { self.print_identifier(fn_name); } @@ -5408,14 +5386,14 @@ pub mod __gated_printer { StmtData::SClass(class) => { self.print_space_before_identifier(); - let class_name: Option<&[u8]> = class.class.class_name.as_ref().map(|name| - self.name_for_symbol(name.ref_.unwrap_or_else(|| Output::panic(format_args!("Internal error: Expected class to have a name ref")))) - ); + let class_name: Option<&[u8]> = class + .class + .class_name + .as_ref() + .map(|name| self.name_for_symbol(name.ref_)); if let Some(name) = &class.class.class_name { self.print(b"class "); - let n = self.name_for_symbol( - name.ref_.expect("infallible: ref bound"), - ); + let n = self.name_for_symbol(name.ref_); self.print_identifier(n); } else { self.print(b"class"); @@ -5516,11 +5494,7 @@ pub mod __gated_printer { // reshaped for borrowck — detach symbol from // `&self` via `BackRef` (arena-backed table outlives print). let symbol = BackRef::::new( - self.symbols() - .get_with_link_const( - item.name.ref_.expect("infallible: ref bound"), - ) - .unwrap(), + self.symbols().get_with_link_const(item.name.ref_).unwrap(), ); let name = symbol.original_name.slice(); let mut did_print = false; @@ -5592,7 +5566,7 @@ pub mod __gated_printer { // `&self` via `BackRef` (arena-backed; outlives the print pass). let symbol = self .symbols() - .get_const(item.name.ref_.expect("infallible: ref bound")) + .get_const(item.name.ref_) .map(BackRef::::new); if let Some(symbol) = symbol { if let Some(namespace) = &symbol.namespace_alias { @@ -5601,9 +5575,7 @@ pub mod __gated_printer { namespace.import_record_index as usize, ); self.print(b"var "); - self.print_symbol( - item.name.ref_.expect("infallible: ref bound"), - ); + self.print_symbol(item.name.ref_); self.print_equals(); self.print_namespace_alias(import_record, namespace); self.print_semicolon_after_statement(); @@ -5653,8 +5625,7 @@ pub mod __gated_printer { self.print_indent(); } - let name = - self.name_for_symbol(item.name.ref_.expect("infallible: ref bound")); + let name = self.name_for_symbol(item.name.ref_); self.print_export_clause_item(item); if Self::MAY_HAVE_MODULE_INFO { @@ -5729,8 +5700,7 @@ pub mod __gated_printer { id }; for item in slice_of(s.items).iter() { - let name = self - .name_for_symbol(item.name.ref_.expect("infallible: ref bound")); + let name = self.name_for_symbol(item.name.ref_); let mi = self.module_info().expect("infallible: module_info enabled"); let alias_id = mi.str(item.alias.slice()); let name_id = mi.str(name); @@ -5865,11 +5835,7 @@ pub mod __gated_printer { } self.print_space_before_identifier(); self.add_source_mapping(stmt.loc); - self.print_symbol(s.name.ref_.unwrap_or_else(|| { - Output::panic(format_args!( - "Internal error: expected label to have a name" - )) - })); + self.print_symbol(s.name.ref_); self.print(b":"); self.print_body(s.stmt, tlmtlo.sub_var()); } @@ -6030,9 +5996,7 @@ pub mod __gated_printer { self.print_space(); self.print(b"default:"); self.print_space(); - self.print_symbol( - default_name.ref_.expect("infallible: ref bound"), - ); + self.print_symbol(default_name.ref_); if !slice_of(s.items).is_empty() { self.print_space(); @@ -6105,7 +6069,7 @@ pub mod __gated_printer { if let Some(name) = &s.default_name { self.print(b" "); - self.print_symbol(name.ref_.expect("infallible: ref bound")); + self.print_symbol(name.ref_); item_count += 1; } @@ -6297,8 +6261,7 @@ pub mod __gated_printer { }; if let Some(name) = &s.default_name { - let local_name = - self.name_for_symbol(name.ref_.expect("infallible: ref bound")); + let local_name = self.name_for_symbol(name.ref_); let mi = self.module_info().expect("infallible: module_info enabled"); let local_name_id = mi.str(local_name); mi.add_var(local_name_id, analyze_transpiled_module::VarKind::Lexical); @@ -6307,8 +6270,7 @@ pub mod __gated_printer { } for item in slice_of(s.items).iter() { - let local_name = self - .name_for_symbol(item.name.ref_.expect("infallible: ref bound")); + let local_name = self.name_for_symbol(item.name.ref_); let mi = self.module_info().expect("infallible: module_info enabled"); let local_name_id = mi.str(local_name); mi.add_var(local_name_id, analyze_transpiled_module::VarKind::Lexical); @@ -6366,7 +6328,7 @@ pub mod __gated_printer { self.print(b"break"); if let Some(label) = &s.label { self.print(b" "); - self.print_symbol(label.ref_.expect("infallible: ref bound")); + self.print_symbol(label.ref_); } self.print_semicolon_after_statement(); } @@ -6377,7 +6339,7 @@ pub mod __gated_printer { self.print(b"continue"); if let Some(label) = &s.label { self.print(b" "); - self.print_symbol(label.ref_.expect("infallible: ref bound")); + self.print_symbol(label.ref_); } self.print_semicolon_after_statement(); } @@ -6711,8 +6673,7 @@ pub mod __gated_printer { self.print_semicolon_after_statement(); if REWRITE_ESM_TO_CJS && is_export && !decls.is_empty() { - // `runtime::Imports` flattens this to `Option`, so no `.ref_` projection. - let export_ref = self.options.runtime_imports.__export.unwrap(); + let export_ref = self.options.runtime_imports.__export; for decl in decls { self.print_indent(); self.print_symbol(export_ref); @@ -7061,7 +7022,7 @@ pub mod __gated_printer { let _ = self.fmt(format_args!(", {},", item_count)); if item_count == 0 { // Add a comment explaining why the number could be zero - self.print(if import.star_name_loc.is_some() { + self.print(if !import.star_name_loc.is_empty() { b" // namespace import".as_slice() } else { b" // bare import".as_slice() @@ -7889,13 +7850,13 @@ pub fn print_ast<'a, W: WriterTrait, const ASCII_ONLY: bool, const GENERATE_SOUR let dont_break_the_code = [tree.module_ref, tree.exports_ref, tree.require_ref]; for ref_ in dont_break_the_code { if let Some(symbol) = minify_renamer.symbols.get_mut(ref_) { - symbol.must_not_be_renamed = true; + symbol.set_must_not_be_renamed(true); } } for named_export in tree.named_exports.values() { if let Some(symbol) = minify_renamer.symbols.get_mut(named_export.ref_) { - symbol.must_not_be_renamed = true; + symbol.set_must_not_be_renamed(true); } } diff --git a/src/js_printer/renamer.rs b/src/js_printer/renamer.rs index 203ce5dce5a..bda80bbf559 100644 --- a/src/js_printer/renamer.rs +++ b/src/js_printer/renamer.rs @@ -386,7 +386,7 @@ impl MinifyRenamer { if let Some(i) = symbol.nested_scope_slot() { let slot = &mut self.slots[ns][i as usize]; slot.count += count; - if symbol.must_start_with_capital_letter_for_jsx { + if symbol.must_start_with_capital_letter_for_jsx() { slot.needs_capital_for_jsx = true; } return Ok(()); @@ -408,7 +408,7 @@ impl MinifyRenamer { let symbol: &Symbol = self.symbols.get_const(stable.ref_).unwrap(); // Reshaped for borrowck — capture symbol fields before mut-borrowing slots let ns = symbol.slot_namespace(); - let must_start_with_capital = symbol.must_start_with_capital_letter_for_jsx; + let must_start_with_capital = symbol.must_start_with_capital_letter_for_jsx(); let slots = &mut self.slots[ns]; let gpe = self.top_level_symbol_to_slot.get_or_put(stable.ref_)?; @@ -1165,7 +1165,7 @@ pub fn compute_reserved_names_for_scope( ) { for member in scope.members.values() { let symbol: &Symbol = symbols.get_const(member.ref_).unwrap(); - if symbol.kind == symbol::Kind::Unbound || symbol.must_not_be_renamed { + if symbol.kind == symbol::Kind::Unbound || symbol.must_not_be_renamed() { // SAFETY: `original_name` is an AST-arena slice. names .put(symbol.original_name.slice(), 1) @@ -1175,7 +1175,7 @@ pub fn compute_reserved_names_for_scope( for ref_ in scope.generated.slice() { let symbol: &Symbol = symbols.get_const(*ref_).unwrap(); - if symbol.kind == symbol::Kind::Unbound || symbol.must_not_be_renamed { + if symbol.kind == symbol::Kind::Unbound || symbol.must_not_be_renamed() { // SAFETY: `original_name` is an AST-arena slice. names .put(symbol.original_name.slice(), 1) diff --git a/src/parsers/json.rs b/src/parsers/json.rs index 7771dd9126a..136ef070508 100644 --- a/src/parsers/json.rs +++ b/src/parsers/json.rs @@ -192,13 +192,13 @@ where T::TNumericLiteral => { let value = self.lexer.number; self.lexer.next()?; - Ok(new_expr(E::Number { value }, loc)) + Ok(new_expr(E::Number::new(value), loc)) } T::TMinus => { self.lexer.next()?; let value = self.lexer.number; self.lexer.expect(T::TNumericLiteral)?; - Ok(new_expr(E::Number { value: -value }, loc)) + Ok(new_expr(E::Number::new(-value), loc)) } T::TOpenBracket => { self.lexer.next()?; @@ -498,13 +498,13 @@ where T::TNumericLiteral => { let value = self.lexer.number; self.lexer.next()?; - Ok(new_expr(E::Number { value }, loc)) + Ok(new_expr(E::Number::new(value), loc)) } T::TMinus => { self.lexer.next()?; let value = self.lexer.number; self.lexer.expect(T::TNumericLiteral)?; - Ok(new_expr(E::Number { value: -value }, loc)) + Ok(new_expr(E::Number::new(-value), loc)) } T::TOpenBracket => { self.lexer.next()?; @@ -641,7 +641,7 @@ macro_rules! impl_to_ast_int { impl ToAst for $t { fn to_ast(&self, _bump: &Bump) -> Result { Ok(Expr { - data: js_ast::expr::Data::ENumber(E::Number { value: *self as f64 }), + data: js_ast::expr::Data::ENumber(E::Number::new(*self as f64)), loc: bun_ast::Loc::default(), }) } @@ -658,7 +658,7 @@ macro_rules! impl_to_ast_float { impl ToAst for $t { fn to_ast(&self, _bump: &Bump) -> Result { Ok(Expr { - data: js_ast::expr::Data::ENumber(E::Number { value: *self as f64 }), + data: js_ast::expr::Data::ENumber(E::Number::new(*self as f64)), loc: bun_ast::Loc::default(), }) } diff --git a/src/parsers/json5.rs b/src/parsers/json5.rs index 23904c448f1..87800a95fab 100644 --- a/src/parsers/json5.rs +++ b/src/parsers/json5.rs @@ -531,7 +531,7 @@ impl<'a> JSON5Parser<'a> { } TokenData::Number(n) => { self.scan()?; - Ok(Expr::init(E::Number { value: n }, loc)) + Ok(Expr::init(E::Number::new(n), loc)) } TokenData::Boolean(b) => { self.scan()?; @@ -544,15 +544,10 @@ impl<'a> JSON5Parser<'a> { TokenData::Identifier(s) => { if s == b"NaN" { self.scan()?; - return Ok(Expr::init(E::Number { value: f64::NAN }, loc)); + return Ok(Expr::init(E::Number::new(f64::NAN), loc)); } else if s == b"Infinity" { self.scan()?; - return Ok(Expr::init( - E::Number { - value: f64::INFINITY, - }, - loc, - )); + return Ok(Expr::init(E::Number::new(f64::INFINITY), loc)); } Err(ParseError::UnexpectedToken) } diff --git a/src/parsers/toml.rs b/src/parsers/toml.rs index d6b3a07148d..dc1731fac67 100644 --- a/src/parsers/toml.rs +++ b/src/parsers/toml.rs @@ -348,21 +348,21 @@ impl<'a> TOML<'a> { T::t_numeric_literal => { let value = self.lexer.number; self.lexer.next()?; - Ok(self.e(E::Number { value }, loc)) + Ok(self.e(E::Number::new(value), loc)) } T::t_minus => { self.lexer.next()?; let value = self.lexer.number; self.lexer.expect(T::t_numeric_literal)?; - Ok(self.e(E::Number { value: -value }, loc)) + Ok(self.e(E::Number::new(-value), loc)) } T::t_plus => { self.lexer.next()?; let value = self.lexer.number; self.lexer.expect(T::t_numeric_literal)?; - Ok(self.e(E::Number { value }, loc)) + Ok(self.e(E::Number::new(value), loc)) } T::t_open_brace => { self.lexer.next()?; diff --git a/src/parsers/yaml.rs b/src/parsers/yaml.rs index 2a1245dfbf9..8ce4c2ade17 100644 --- a/src/parsers/yaml.rs +++ b/src/parsers/yaml.rs @@ -1787,7 +1787,7 @@ impl NodeScalar { match self { NodeScalar::Null => Expr::init(E::Null {}, pos.loc()), NodeScalar::Boolean(value) => Expr::init(E::Boolean { value: *value }, pos.loc()), - NodeScalar::Number(value) => Expr::init(E::Number { value: *value }, pos.loc()), + NodeScalar::Number(value) => Expr::init(E::Number::new(*value), pos.loc()), NodeScalar::String(value) => { // For `Utf16` we route through `E::String::init_utf16`. // @@ -1871,7 +1871,7 @@ fn yaml_merge_key_expr_eql(l: &Expr, r: &Expr) -> bool { match (&l.data, &r.data) { (ast::ExprData::ENull(_), _) => true, (ast::ExprData::EBoolean(lb), ast::ExprData::EBoolean(rb)) => lb.value == rb.value, - (ast::ExprData::ENumber(ln), ast::ExprData::ENumber(rn)) => ln.value == rn.value, + (ast::ExprData::ENumber(ln), ast::ExprData::ENumber(rn)) => ln.value() == rn.value(), (ast::ExprData::EString(ls), ast::ExprData::EString(rs)) => { // UTF-8/UTF-16-aware string equality. if ls.is_utf16 != rs.is_utf16 { @@ -1899,7 +1899,7 @@ fn yaml_merge_key_expr_hash(key: &Expr) -> u64 { ast::ExprData::ENull(_) => 0, ast::ExprData::EBoolean(b) => 1 + b.value as u64, ast::ExprData::ENumber(n) => { - let value = if n.value == 0.0 { 0.0 } else { n.value }; + let value = if n.value() == 0.0 { 0.0 } else { n.value() }; value.to_bits() } ast::ExprData::EString(s) => s.hash(), diff --git a/src/runtime/api/JSON5Object.rs b/src/runtime/api/JSON5Object.rs index 9e3d5d8ffc5..1b5da97def4 100644 --- a/src/runtime/api/JSON5Object.rs +++ b/src/runtime/api/JSON5Object.rs @@ -454,7 +454,7 @@ fn expr_to_js_with_check( match expr.data { ExprData::ENull(_) => Ok(JSValue::NULL), ExprData::EBoolean(boolean) => Ok(JSValue::from(boolean.value)), - ExprData::ENumber(number) => Ok(JSValue::js_number(number.value)), + ExprData::ENumber(number) => Ok(JSValue::js_number(number.value())), ExprData::EString(str) => estring_to_js(str.get(), global), ExprData::EArray(arr) => { JSValue::create_array_from_iter(global, arr.slice().iter(), |item| { diff --git a/src/runtime/api/JSTranspiler.rs b/src/runtime/api/JSTranspiler.rs index f1de7db502a..462676d4ac2 100644 --- a/src/runtime/api/JSTranspiler.rs +++ b/src/runtime/api/JSTranspiler.rs @@ -924,9 +924,7 @@ fn export_replacement_value( if value.is_number() { return Ok(Some(Expr { - data: bun_ast::ExprData::ENumber(bun_ast::E::Number { - value: value.as_number(), - }), + data: bun_ast::ExprData::ENumber(bun_ast::E::Number::new(value.as_number())), loc: bun_ast::Loc::EMPTY, })); } diff --git a/src/runtime/api/YAMLObject.rs b/src/runtime/api/YAMLObject.rs index ffb4193dd46..f1b0afcb712 100644 --- a/src/runtime/api/YAMLObject.rs +++ b/src/runtime/api/YAMLObject.rs @@ -1156,7 +1156,7 @@ impl<'a> ParserCtx<'a> { match expr.data { ExprData::ENull(_) => Ok(JSValue::NULL), ExprData::EBoolean(boolean) => Ok(JSValue::from(boolean.value)), - ExprData::ENumber(number) => Ok(JSValue::js_number(number.value)), + ExprData::ENumber(number) => Ok(JSValue::js_number(number.value())), ExprData::EString(str) => Ok(bun_js_parser_jsc::value_string_to_js( str.get(), self.global, diff --git a/src/runtime/cli/audit_command.rs b/src/runtime/cli/audit_command.rs index 6a2c6be484c..3401d0fe187 100644 --- a/src/runtime/cli/audit_command.rs +++ b/src/runtime/cli/audit_command.rs @@ -552,7 +552,7 @@ fn parse_vulnerability( } else if let ExprData::ENumber(num) = &value.data { if field_name == b"id" { let mut s: Vec = Vec::new(); - write!(&mut s, "{}", num.value as u64).expect("unreachable"); + write!(&mut s, "{}", num.value() as u64).expect("unreachable"); vulnerability.id = s.into_boxed_slice(); } } diff --git a/src/runtime/cli/pm_pkg_command.rs b/src/runtime/cli/pm_pkg_command.rs index c7097e928da..448bad48790 100644 --- a/src/runtime/cli/pm_pkg_command.rs +++ b/src/runtime/cli/pm_pkg_command.rs @@ -441,10 +441,10 @@ impl PmPkgCommand { })), ExprData::ENumber(n) => { let mut v = Vec::new(); - if n.value.floor() == n.value { - write!(&mut v, "{:.0}", n.value).or_write_failed()?; + if n.value().floor() == n.value() { + write!(&mut v, "{:.0}", n.value()).or_write_failed()?; } else { - write!(&mut v, "{}", n.value).or_write_failed()?; + write!(&mut v, "{}", n.value()).or_write_failed()?; } Ok(v.into_boxed_slice()) } @@ -764,16 +764,11 @@ impl PmPkgCommand { } if let Some(int_val) = bun_core::fmt::parse_decimal::(value) { - return Ok(Expr::init( - E::Number { - value: int_val as f64, - }, - Loc::EMPTY, - )); + return Ok(Expr::init(E::Number::new(int_val as f64), Loc::EMPTY)); } if let Some(float_val) = parse_f64(value) { - return Ok(Expr::init(E::Number { value: float_val }, Loc::EMPTY)); + return Ok(Expr::init(E::Number::new(float_val), Loc::EMPTY)); } let temp_source = Source::init_path_string(b"package.json", value); diff --git a/src/runtime/cli/upgrade_command.rs b/src/runtime/cli/upgrade_command.rs index 5c399eda80c..8021e7a06a2 100644 --- a/src/runtime/cli/upgrade_command.rs +++ b/src/runtime/cli/upgrade_command.rs @@ -442,7 +442,7 @@ impl UpgradeCommand { if let Some(size_) = asset.as_property(b"size") { if let bun_ast::ExprData::ENumber(n) = &size_.expr.data { version.size = - u32::try_from(((n.value.ceil()) as i32).max(0)).unwrap(); + u32::try_from(((n.value().ceil()) as i32).max(0)).unwrap(); } } return Ok(Some(version)); diff --git a/src/sourcemap/lib.rs b/src/sourcemap/lib.rs index 034c97e7024..0fcfc1676f7 100644 --- a/src/sourcemap/lib.rs +++ b/src/sourcemap/lib.rs @@ -953,7 +953,7 @@ pub fn parse_json( if let Some(version) = json.get(b"version") { match version.data.as_e_number() { - Some(n) if n.value == 3.0 => {} + Some(n) if n.value() == 3.0 => {} _ => return Err(bun_core::err!("UnsupportedVersion")), } }