diff --git a/Cargo.lock b/Cargo.lock index 3fe628aa5b7..7e500abef5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -355,6 +355,7 @@ dependencies = [ "bstr", "bumpalo", "bun_alloc", + "bun_analytics", "bun_ast", "bun_base64", "bun_collections", diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 73555ea53b7..ecc11a7121d 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -282,11 +282,9 @@ impl Expr { } } -// Expr — property/object/string accessor methods. -// TODO(port): these call into `E::Object::as_property` / `EString` -// methods that need `bun_core::utf16_eql_string`/`to_utf8_alloc` (track-A -// blocked_on) and `Vec::deep_clone`. Types are real; bodies un-gate with -// the parser round once those land. +// Expr — property/object/string accessor methods. These call into +// `E::Object::as_property` / `EString` methods backed by +// `bun_core::utf16_eql_string` / `to_utf8_alloc` and `Vec::deep_clone`. impl Expr { pub fn has_any_property_named(&self, names: &'static [&'static [u8]]) -> bool { diff --git a/src/ast/fold_string_addition.rs b/src/ast/fold_string_addition.rs index 49d44be3c68..a297acbde51 100644 --- a/src/ast/fold_string_addition.rs +++ b/src/ast/fold_string_addition.rs @@ -3,9 +3,9 @@ use crate::{self as js_ast, E, Expr, StoreRef, e}; use bun_alloc::Arena; // bumpalo::Bump re-export // ── local rope helpers ───────────────────────────────────────────────────── -// `EString::push` / `EString::clone_rope_nodes` are still gated in E.rs -// (round-C draft); inline the minimal surface here so this file can un-gate -// without touching E.rs. These mirror the Zig bodies 1:1. +// Mirrors the Zig `E.String.push` / `E.String.cloneRopeNodes` bodies 1:1. +// `estring_push` takes the rope tail as a `StoreRef` (callers here +// already hold one) instead of `&mut EString` like `EString::push` does. #[inline] fn store_append_string(s: E::EString) -> StoreRef { diff --git a/src/bun_bin/Cargo.toml b/src/bun_bin/Cargo.toml index dded78f6dd5..b9cb62bbde5 100644 --- a/src/bun_bin/Cargo.toml +++ b/src/bun_bin/Cargo.toml @@ -30,7 +30,5 @@ bun_crash_handler.workspace = true bun_mimalloc_sys.workspace = true bun_platform.workspace = true -# Phase-C: bun_runtime now compiles green; pulled in for `Cli::start()`. -# bun_jsc remains gated until the JSC bridge links. +# bun_runtime is pulled in for `Cli::start()`; bun_jsc comes in transitively. bun_runtime.workspace = true -# bun_jsc.workspace = true diff --git a/src/bun_bin/lib.rs b/src/bun_bin/lib.rs index e5e1caae85e..5e4bc1352a6 100644 --- a/src/bun_bin/lib.rs +++ b/src/bun_bin/lib.rs @@ -36,7 +36,7 @@ use core::ffi::{c_char, c_int}; -mod phase_c_exports; +mod link_exports; // Force-link `bun_platform` so its `#[no_mangle]` C exports // (`sys_epoll_pwait2`, `ioctl_ficlone`, …) reach the linker. diff --git a/src/bun_bin/phase_c_exports.rs b/src/bun_bin/link_exports.rs similarity index 98% rename from src/bun_bin/phase_c_exports.rs rename to src/bun_bin/link_exports.rs index 6a9a63426f6..d2b9beabe9d 100644 --- a/src/bun_bin/phase_c_exports.rs +++ b/src/bun_bin/link_exports.rs @@ -1,4 +1,5 @@ -//! PHASE-C link bridge — **transient**, not a permanent grab-bag. +//! Link-time `#[no_mangle]` export bridge — **transient**, not a permanent +//! grab-bag. //! //! Every symbol that used to be stubbed here now has a real home (the `.rs` //! sibling of the Zig `export fn`) inside `bun_jsc` / `bun_runtime` / @@ -18,7 +19,7 @@ //! //! Calling convention: `jsc.conv` is plain `"C"` on every non-Windows-x64 //! target, so `extern "C"` is correct on Linux/macOS. The Windows path is not -//! exercised in Phase C. +//! currently exercised here. #![allow( non_snake_case, @@ -62,7 +63,7 @@ type VirtualMachine = c_void; // Real-body exports (no gated-crate dependency) // ════════════════════════════════════════════════════════════════════════════ -// PHASE-C: C++ callback — Zig: `pub export fn Bun__panic(msg, len) noreturn` +// C++ callback — Zig: `pub export fn Bun__panic(msg, len) noreturn` // REAL: src/main.rs (binary-level export; defined here directly) #[unsafe(no_mangle)] pub extern "C" fn Bun__panic(msg: *const u8, len: usize) -> ! { @@ -85,7 +86,7 @@ pub extern "C" fn Bun__panic(msg: *const u8, len: usize) -> ! { // Bun__NODE_NO_WARNINGS // REAL: `Bun__getTLSRejectUnauthorizedValue` / `Bun__isNoProxy` now exported -// directly from `bun_jsc::virtual_machine_exports` (un-gated in phase-d). +// directly from `bun_jsc::virtual_machine_exports`. // REAL: now provided by bun_runtime (src/runtime/napi/napi_body.rs). // napi_internal_suppress_crash_on_abort_if_desired diff --git a/src/bun_core/Progress.rs b/src/bun_core/Progress.rs index b5c6e780226..ec5455a4441 100644 --- a/src/bun_core/Progress.rs +++ b/src/bun_core/Progress.rs @@ -63,8 +63,8 @@ unsafe extern "system" { // Progress's terminal handle is the canonical `output::File` (vtable-backed // stderr/File from `OutputSinkVTable`). The duplicate `ProgressTerminalVTable` -// from B-0 round 1 is removed; tty/ansi/winsize route through the new -// `OutputSinkVTable` slots so `bun_core` stays T0 (no `bun_sys` dep). +// was removed; tty/ansi/winsize route through the `OutputSinkVTable` slots so +// `bun_core` stays T0 (no `bun_sys` dep). use crate::Fd; pub use crate::output::File; use crate::output::output_sink; diff --git a/src/bun_core/string/mod.rs b/src/bun_core/string/mod.rs index c72bb459e38..a909b618b4c 100644 --- a/src/bun_core/string/mod.rs +++ b/src/bun_core/string/mod.rs @@ -2734,7 +2734,7 @@ pub use wtf::parse_double; /// /// Unlike `Cell`, [`set`] derefs the previous value and [`replace`] /// returns an [`OwnedString`] — so the only way to leak a refcount is to -/// `mem::forget` the cell or its `replace` result. The R-2 `&self` migrations +/// `mem::forget` the cell or its `replace` result. The `&self` migrations /// introduced `Cell::set(..)` calls that silently leaked the old +1. /// /// [`get`] returns a bitwise `String` copy with **borrow** semantics (no ref diff --git a/src/bundler/Cargo.toml b/src/bundler/Cargo.toml index 3b48c09466b..82508c9b722 100644 --- a/src/bundler/Cargo.toml +++ b/src/bundler/Cargo.toml @@ -27,10 +27,7 @@ bumpalo.workspace = true typed-arena.workspace = true bun_base64.workspace = true bun_alloc.workspace = true -# TODO(b2-blocked): bun_analytics — adding the dep triggers a fresh build of -# upstream crates (css/logger/js_parser) with in-progress breakage. Re-add once -# the tree is green; usages in options.rs are gated or stubbed locally. -# bun_analytics.workspace = true +bun_analytics.workspace = true bun_resolver.workspace = true # `bun_resolve_builtins` only depends on `bun_options_types` + `bun_string` # (both already in this graph), so no cycle. diff --git a/src/bundler/LinkerContext.rs b/src/bundler/LinkerContext.rs index 6604e63b54e..340ff6e8c95 100644 --- a/src/bundler/LinkerContext.rs +++ b/src/bundler/LinkerContext.rs @@ -60,10 +60,10 @@ bun_core::declare_scope!(LinkerCtx, visible); bun_core::declare_scope!(TreeShake, hidden); // ══════════════════════════════════════════════════════════════════════════ -// CYCLEBREAK(b0): vtable instance for `bun_crash_handler::BundleGenerateChunkVTable` -// (cold-path §Dispatch — crash trace only). crash_handler (T1) holds erased -// `(*const LinkerContext, *const Chunk, *const PartRange)`; bundler supplies -// the formatter that knows their layout. Mirrors src/crash_handler/crash_handler.zig:135. +// Vtable instance for `bun_crash_handler::BundleGenerateChunkVTable` (cold +// path — crash trace only). `crash_handler` holds erased `(*const +// LinkerContext, *const Chunk, *const PartRange)`; the bundler supplies the +// formatter that knows their layout. Mirrors src/crash_handler/crash_handler.zig:135. // ══════════════════════════════════════════════════════════════════════════ #[cfg(feature = "show_crash_trace")] bun_crash_handler::link_impl_BundleGenerateChunkCtx! { diff --git a/src/bundler/ParseTask.rs b/src/bundler/ParseTask.rs index 060c5cb62ea..2d075849372 100644 --- a/src/bundler/ParseTask.rs +++ b/src/bundler/ParseTask.rs @@ -488,11 +488,6 @@ export var __callDispose = (stack, error, hasError) => { // ══════════════════════════════════════════════════════════════════════════ // Per-file parse worker — `getAST`/`getCodeForParseTask`/`runFromThreadPool`. -// The struct/FFI surface and `get_runtime_source` are real. Bodies -// that touch the still-gated `crate::ThreadPool` Worker module or the opaque -// `JSBundlerPlugin`/`FileMap` forward-decls remain ``-gated -// per-function below with explicit `// blocked_on:` notes; they un-gate by -// deletion once those modules land. // ══════════════════════════════════════════════════════════════════════════ pub mod parse_worker { use super::*; diff --git a/src/bundler/ThreadPool.rs b/src/bundler/ThreadPool.rs index 070c01f30b4..62e025dfa3d 100644 --- a/src/bundler/ThreadPool.rs +++ b/src/bundler/ThreadPool.rs @@ -639,8 +639,7 @@ impl Worker { // PORT NOTE: `MimallocArena::help_catch_memory_issues` collected // mimalloc's deferred frees + zero-filled freed pages. The Rust // arena is `bumpalo::Bump`, which has no equivalent — calls - // dropped, gated on the real `MimallocArena` un-gate - // (`bun_alloc/MimallocArena.rs` is ``). + // dropped, gated on the real `MimallocArena` un-gate. } worker diff --git a/src/bundler/bundle_v2.rs b/src/bundler/bundle_v2.rs index 84434316aff..29b4d1946c4 100644 --- a/src/bundler/bundle_v2.rs +++ b/src/bundler/bundle_v2.rs @@ -367,10 +367,10 @@ pub mod bv2_impl { use bun_resolver::fs::PathResolverExt as _; use bun_resolver::{self as _resolver, Resolver, is_package_path}; use bun_threading::ThreadPool as ThreadPoolLib; - // TODO(b0): bake_types arrives from move-in (TYPE_ONLY Side/Graph/BuiltInModule/Framework → bundler) + // TODO(port): bake_types arrives from move-in (TYPE_ONLY Side/Graph/BuiltInModule/Framework → bundler) use self::bake_types as bake; - /// CYCLEBREAK(b0) TYPE_ONLY: pure value types from bake that bundler needs without + /// CYCLEBREAK TYPE_ONLY: pure value types from bake that bundler needs without /// depending on the full DevServer. Move-in pass keeps these as the canonical defs; /// bun_bake (post tier-6 collapse: bun_runtime::bake) re-exports from here. pub mod bake_types { @@ -492,7 +492,7 @@ pub mod bv2_impl { /// In Zig this lives on the legacy package_json `Framework`; the duck-typed /// `comptime TranspilerType` callers reach it through `options.framework.?`. pub client_css_in_js: crate::options::ClientCssInJs, - // TODO(b0-genuine): remaining Framework field `file_system_router_types` + // TODO(port): remaining Framework field `file_system_router_types` // stays in T6; only bake::FrameworkRouter reads it. _opaque_tail: (), } @@ -739,10 +739,10 @@ pub mod bv2_impl { } } } - // TODO(b0): jsc::api arrives from move-in (TYPE_ONLY → bundler) + // TODO(port): jsc::api arrives from move-in (TYPE_ONLY → bundler) use self::api as jsc_api; - /// CYCLEBREAK(b0) TYPE_ONLY: data-only halves of `jsc::api::JSBundler` and + /// CYCLEBREAK TYPE_ONLY: data-only halves of `jsc::api::JSBundler` and /// `jsc::api::BuildArtifact` that the bundler reads/constructs without touching /// JSC. The JS-thread halves (dispatch onto the JS event loop, `toJS`, plugin /// FFI bodies) stay in tier-6 (`bun_runtime::api`) and re-export these. @@ -5229,7 +5229,7 @@ pub mod bv2_impl { Ok(ctx) } - // TODO(b0-genuine): body has deep DevServer field access (current_bundle.start_data, + // TODO(port): body has deep DevServer field access (current_bundle.start_data, // css_entry_points, etc.). After tier-6 collapse this fn should be HOISTED into // bun_runtime::bake (which can name DevServer concretely) and call back into BundleV2 // helpers. Until then the entry-point fields are reached through the vtable. diff --git a/src/bundler/cache.rs b/src/bundler/cache.rs index 72f90118c3c..58c47c20fea 100644 --- a/src/bundler/cache.rs +++ b/src/bundler/cache.rs @@ -9,19 +9,19 @@ use bun_parsers::json_parser; use bun_resolver::fs as fs_mod; use bun_sys::{self, Fd}; -// B-3 UNIFIED: `Define` is now the single canonical `bun_js_parser::defines::Define` -// (re-exported via `crate::defines`); `JavaScript::parse`/`scan` and the bundler's +// `Define` is the single canonical `bun_js_parser::defines::Define` (re-exported +// via `crate::defines`); `JavaScript::parse`/`scan` and the bundler's // `BundleOptions.define` share the same nominal type. use js_parser::defines::Define; // ══════════════════════════════════════════════════════════════════════════ -// B-3 UNIFIED: `RuntimeTranspilerCache` is canonical in `bun_js_parser` -// (lower tier) so `Features.runtime_transpiler_cache: Option<*mut RTC>` and +// `RuntimeTranspilerCache` is canonical in `bun_ast` (a lower-tier crate) +// so `Features.runtime_transpiler_cache: Option<*mut RTC>` and // `ParseOptions.runtime_transpiler_cache: Option<&mut RTC>` are the same // nominal type. This crate adds the env-var-gated `disabled`/`set_disabled` via -// the `RuntimeTranspilerCacheExt` trait below — those need `bun_core::env_var` -// which sits a tier above js_parser. `Entry` / `Metadata` stay concrete here; -// the canonical +// the `RuntimeTranspilerCacheExt` trait below; the disk-I/O / `js_printer` +// dispatch also lives here because it needs `bun_js_printer`, which sits a +// tier above `bun_ast`. `Entry` / `Metadata` stay concrete here; the canonical // struct stores them type-erased as `*mut ()`. // ══════════════════════════════════════════════════════════════════════════ use bun_ast::RuntimeTranspilerCache; @@ -37,7 +37,7 @@ pub const RUNTIME_TRANSPILER_CACHE_VERSION: u32 = 20; pub static DISABLED: AtomicBool = AtomicBool::new(false); /// Extension surface for the canonical `RuntimeTranspilerCache` (defined in -/// `bun_js_parser`). Separate trait so the env-var-dependent bodies stay in +/// `bun_ast`). Separate trait so the env-var-dependent bodies stay in /// this crate without an orphan-rule violation. pub trait RuntimeTranspilerCacheExt { /// Mirrors the Zig `pub var is_disabled` namespaced const — kept as an diff --git a/src/bundler/defines.rs b/src/bundler/defines.rs index fda8465fe62..406911f18b2 100644 --- a/src/bundler/defines.rs +++ b/src/bundler/defines.rs @@ -12,7 +12,7 @@ use crate::defines_table::{ }; // ══════════════════════════════════════════════════════════════════════════ -// B-3 UNIFIED: `Define` / `DefineData` / `DotDefine` / `Flags` / `Options` / +// `Define` / `DefineData` / `DotDefine` / `Flags` / `Options` / // `RawDefines` / `UserDefines` / `UserDefinesArray` are canonical in // `bun_js_parser::defines` (lower tier) so the parser's `P.define: &'a Define` // and `BundleOptions.define: Box` are the *same* nominal type. This diff --git a/src/bundler/linker.rs b/src/bundler/linker.rs index dc3bb9005e6..740cd0a35e5 100644 --- a/src/bundler/linker.rs +++ b/src/bundler/linker.rs @@ -12,7 +12,7 @@ use bun_paths::{self, SEP}; // PORT NOTE: two `fs` shapes are in play here. `bun_resolver::fs` (`Fs`) holds // the singleton `FileSystem` / `DirnameStore`; `bun_paths::fs` (`PFs`) defines // the `Path`/`PathName` value types that `ImportRecord.path` is typed against. -// Both port `src/resolver/fs.zig`; B-3 collapses them. Until then, construct +// Both port `src/resolver/fs.zig`; until they are unified, construct // `import_record.path` via `PFs::Path` so the field assignment unifies. use bun_core::strings; use bun_paths::fs as PFs; diff --git a/src/bundler/linker_context/scanImportsAndExports.rs b/src/bundler/linker_context/scanImportsAndExports.rs index 54d373d125a..aae48087730 100644 --- a/src/bundler/linker_context/scanImportsAndExports.rs +++ b/src/bundler/linker_context/scanImportsAndExports.rs @@ -799,8 +799,8 @@ pub fn scan_imports_and_exports( dependencies.push(Dependency { // PORT NOTE: `crate::Index` ↔ `bun_ast::Index` are both // `#[repr(transparent)] u32` newtypes ported from the - // same Zig `ast.Index`; bridge by `.value` until B-3 - // collapses them to a single re-export. + // same Zig `ast.Index`; bridge through the inner u32 + // until they are collapsed to a single re-export. source_index: bun_ast::Index(target_source_index.get()), part_index: *part_index, }); diff --git a/src/bundler/options.rs b/src/bundler/options.rs index c026c4dd991..befdab79842 100644 --- a/src/bundler/options.rs +++ b/src/bundler/options.rs @@ -17,40 +17,25 @@ use bun_resolver::package_json::{MacroMap as MacroRemap, PackageJSON}; #[allow(unused_imports)] use bun_url::URL; use std::borrow::Cow; -// TODO(b2-blocked): bun_analytics — Cargo.toml does not yet list the dep -// (adding it triggers upstream rebuilds with in-progress breakage). The -// `analytics::features::*` counters are pure telemetry side effects; the -// increment call-sites below are ``-gated until the dep is wired -// so the no-op is explicit (PORTING.md §Forbidden patterns: silent no-ops). - -mod analytics { - #[allow(non_upper_case_globals)] - pub mod features { - use core::sync::atomic::AtomicUsize; - // Zig: `analytics.Features.{define,loaders,macros,external} += n`. - // Real statics live in `bun_analytics::features::*` (AtomicUsize). - pub static define: AtomicUsize = AtomicUsize::new(0); - pub static loaders: AtomicUsize = AtomicUsize::new(0); - pub static macros: AtomicUsize = AtomicUsize::new(0); - pub static external: AtomicUsize = AtomicUsize::new(0); - } -} +// Zig: `analytics.Features.{define,loaders,macros,external} += n` — the real +// `bun_analytics::features::*` `AtomicUsize` counters. +use bun_analytics as analytics; use enum_map::{Enum, EnumMap}; pub use crate::defines; pub use defines::Define; -// B-3: `Define::init` / `DefineData::{from_input,parse}` are extension-trait +// `Define::init` / `DefineData::{from_input,parse}` are extension-trait // methods (the canonical types live in `bun_js_parser::defines`); bring the // traits into scope so the associated-fn call syntax below resolves. #[allow(unused_imports)] use crate::defines::{DefineDataExt as _, DefineExt as _}; pub use bun_options_types::global_cache::GlobalCache; -// ── B-2 type aliases for incomplete lower-tier surfaces ── -// TODO(b2-blocked): bun_resolver::package_json::ESModule::ConditionsMap — module +// ── Type aliases for incomplete lower-tier surfaces ── +// TODO(port): bun_resolver::package_json::ESModule::ConditionsMap — module // path doesn't expose this yet; local alias matches Zig `StringArrayHashMap(void)`. pub type ConditionsMap = StringArrayHashMap<()>; -// TODO(b2-blocked): bun_sys::Dir — directory handle. Mapped to Fd for now +// TODO(port): bun_sys::Dir — directory handle. Mapped to Fd for now // (matches `bun.FD.fromStdDir` pattern). pub type Dir = bun_sys::Fd; /// `Loader.HashTable` (Zig nested type alias). Unified with the canonical @@ -353,7 +338,7 @@ pub trait TargetExt: Copy { impl TargetExt for Target { fn bake_graph(self) -> crate::bake_types::Graph { - // TODO(b0): bake::Graph arrives from move-in (TYPE_ONLY → bundler) + // TODO(port): bake::Graph arrives from move-in (TYPE_ONLY → bundler) match self { Target::Browser => crate::bake_types::Graph::Client, Target::BakeServerComponentsSsr => crate::bake_types::Graph::Ssr, @@ -572,7 +557,7 @@ pub struct LoaderResult<'a> { pub package_json: Option<&'a PackageJSON>, } -// TODO(b2-blocked): bun_paths::path_literal! + Fs::Path::loader + strings::eql_long +// TODO(port): bun_paths::path_literal! + Fs::Path::loader + strings::eql_long // arity — body touches VmLoaderCtx vtable which is real but the helper APIs are not. pub fn get_loader_and_virtual_source<'a>( specifier_str: &'a [u8], @@ -1437,7 +1422,7 @@ pub struct BundleOptions<'a> { // directly — all access goes through crate::dispatch::DevServerVTable. pub dev_server: *const (), /// Set when Bake is bundling. Affects module resolution. - // TODO(b0): bake::Framework arrives from move-in (TYPE_ONLY → bundler) + // TODO(port): bake::Framework arrives from move-in (TYPE_ONLY → bundler) pub framework: Option<&'a crate::bake_types::Framework>, pub serve_plugins: Option]>>, @@ -1468,7 +1453,7 @@ pub struct BundleOptions<'a> { pub optimize_imports: Option<&'a StringSet>, } -// B-3 UNIFIED: was a local dup of `bun_options_types::bundle_enums::ForceNodeEnv` +// PORT NOTE: was a local dup of `bun_options_types::bundle_enums::ForceNodeEnv` // (resolver carried a second FORWARD_DECL copy). Canonical type now lives in // bun_options_types; re-exported here so `options::ForceNodeEnv` call sites in // bundle_v2.rs / transpiler.rs are unchanged. @@ -1699,7 +1684,7 @@ impl<'a> BundleOptions<'a> { !self.defines_loaded } - // TODO(b2-blocked): defines_from_transform_options (see above) + + // TODO(port): defines_from_transform_options (see above) + // api::TransformOptions.define field (peechy `TransformOptions` body still // opaque). pub fn load_defines( @@ -1900,13 +1885,10 @@ impl<'a> BundleOptions<'a> { optimize_imports: None, }; - // TODO(b2-blocked): bun_analytics dep not yet wired in bundler/Cargo.toml - { - analytics::features::define - .fetch_add(usize::from(transform.define.is_some()), Ordering::Relaxed); - analytics::features::loaders - .fetch_add(usize::from(transform.loaders.is_some()), Ordering::Relaxed); - } + analytics::features::define + .fetch_add(usize::from(transform.define.is_some()), Ordering::Relaxed); + analytics::features::loaders + .fetch_add(usize::from(transform.loaders.is_some()), Ordering::Relaxed); opts.serve_plugins = transform .serve_plugins @@ -2047,17 +2029,14 @@ impl<'a> BundleOptions<'a> { opts.tsconfig_override = Some(tsconfig.clone()); } - // TODO(b2-blocked): bun_analytics dep not yet wired in bundler/Cargo.toml - { - analytics::features::macros.fetch_add( - usize::from(opts.target == Target::BunMacro), - Ordering::Relaxed, - ); - analytics::features::external.fetch_add( - usize::from(!transform.external.is_empty()), - Ordering::Relaxed, - ); - } + analytics::features::macros.fetch_add( + usize::from(opts.target == Target::BunMacro), + Ordering::Relaxed, + ); + analytics::features::external.fetch_add( + usize::from(!transform.external.is_empty()), + Ordering::Relaxed, + ); Ok(opts) } } @@ -2148,7 +2127,7 @@ pub fn open_output_dir(output_dir: &[u8]) -> Result { } /// Port of `fs.zig` `Fs.File` (path + contents pair). `bun_resolver::fs` -/// does not surface this type yet (TODO(b2-blocked)); local mirror keeps +/// does not surface this type yet (TODO(port)); local mirror keeps /// `TransformOptions.entry_point` self-contained. pub struct EntryPointFile { pub path: bun_paths::fs::Path<'static>, diff --git a/src/bundler/transpiler.rs b/src/bundler/transpiler.rs index 2b979bfe9fd..e7c6484a752 100644 --- a/src/bundler/transpiler.rs +++ b/src/bundler/transpiler.rs @@ -1,6 +1,6 @@ // ══════════════════════════════════════════════════════════════════════════ // `Transpiler` — the legacy single-file transpile path (pre-`bundle_v2`). -// resolver↔bundler cycle broken in O; `bun_resolver` is now a direct dep so +// resolver↔bundler cycle is broken; `bun_resolver` is now a direct dep so // the struct and all method bodies are un-gated and live at this tier. // ══════════════════════════════════════════════════════════════════════════ @@ -862,7 +862,7 @@ pub struct ParseResult { // SoA `len()`/column accessors aren't reachable. Use AoS `Vec` for now; // `is_pending_import` only scans `import_record_id`, so the layout // difference is observable only as a SoA→AoS perf delta. - // TODO(b3): switch back to `MultiArrayList` once the + // TODO(port): switch back to `MultiArrayList` once the // derive lands upstream in `bun_resolver`. pub pending_imports: Vec, @@ -1050,7 +1050,7 @@ fn init_file_system( /// `Box<[Box<[u8]>]>`/`StringSet`/`StringArrayHashMap` so this is a faithful /// value copy rather than a `Default` stub. /// -/// TODO(b3): drop this once `bun_options_types::BundleOptions` exists and both +/// TODO(port): drop this once `bun_options_types::BundleOptions` exists and both /// crates re-export it — `Resolver::init1` will then take the canonical type /// directly and Zig's `bundle_options` value can flow through unchanged /// (transpiler.zig:209 passes the same `options` to both struct fields). @@ -2352,10 +2352,10 @@ impl<'a> Transpiler<'a> { // PERF(port): one extra alloc vs Zig's borrowed-slice — profile if hot. let symbols = bun_ast::symbol::Map::init_with_one_list(core::mem::take(&mut ast.symbols)); - // `runtime_imports` is now forwarded — after Round-G `Ast.runtime_imports` - // is the real `parser::Runtime::Imports`, the same type + // `runtime_imports` is forwarded as-is: `Ast.runtime_imports` is the + // real `parser::Runtime::Imports`, the same type // `js_printer::Options.runtime_imports` takes (via `js_ast::runtime`), - // so the seam is gone. Spec: zig:593/619/645. + // so there is no conversion seam. Spec: zig:593/619/645. // `target` is now forwarded via `to_bundle_enums_target` below — it // *does* affect the EsmAscii/bun-runtime path (js_printer/lib.rs:6872 // gates the `var {require}=import.meta;` hoist on `target == Bun`; diff --git a/src/bunfig/Cargo.toml b/src/bunfig/Cargo.toml index b0eb238d7ba..6b025fb276f 100644 --- a/src/bunfig/Cargo.toml +++ b/src/bunfig/Cargo.toml @@ -9,10 +9,10 @@ path = "lib.rs" [lints] workspace = true -# MOVE_DOWN(b0): bunfig parser + `Arguments::loadConfig` lifted out of -# `bun_runtime::cli` so mid-tier crates (notably `bun_install`) can load -# bunfig.toml without depending on tier-6. All deps below are already -# transitive deps of `bun_install`; no new cycles introduced. +# bunfig parser + `Arguments::loadConfig` lifted out of `bun_runtime::cli` so +# mid-tier crates (notably `bun_install`) can load bunfig.toml without +# depending on the runtime. All deps below are already transitive deps of +# `bun_install`; no new cycles introduced. [dependencies] bun_io.workspace = true strum.workspace = true diff --git a/src/cares_sys/c_ares.rs b/src/cares_sys/c_ares.rs index 3fe1ee60a66..4cd5e3e8fa7 100644 --- a/src/cares_sys/c_ares.rs +++ b/src/cares_sys/c_ares.rs @@ -742,7 +742,7 @@ const _: () = assert!(core::mem::size_of::() == 0); /// Implemented by the type that owns a `*mut Channel` and receives socket- /// state callbacks. Zig: `Container.onDNSSocketState` + `this.channel = ch`. /// -/// R-2: methods take `&self`. The c-ares `sock_state_cb` re-enters the +/// Methods take `&self`. The c-ares `sock_state_cb` re-enters the /// container while a `&self` borrow may already be live in `on_dns_poll`; /// the implementor routes mutation through interior mutability. pub trait ChannelContainer: Sized { @@ -795,7 +795,7 @@ impl Channel { writable: c_int, ) { // SAFETY: `ctx` is the `&C` registered below; `on_dns_socket_state` - // takes `&self` (R-2) so the shared borrow is sufficient. + // takes `&self` so the shared borrow is sufficient. let container = unsafe { &*ctx.cast_const().cast::() }; container.on_dns_socket_state(socket, readable != 0, writable != 0); } @@ -810,7 +810,7 @@ impl Channel { // default stand means setServers() works as the documented workaround. opts.flags = ARES_FLAG_NOCHECKRESP; opts.sock_state_cb = Some(on_sock_state::); - // R-2: `*mut` spelling is signature-only (c-ares stores a `void*`); the + // `*mut` spelling is signature-only (c-ares stores a `void*`); the // callback derefs as shared (`&*const`) and the implementor mutates via // interior mutability. opts.sock_state_cb_data = (this as *const C).cast_mut().cast::(); diff --git a/src/css/css_parser.rs b/src/css/css_parser.rs index a354dcca478..b9aef24e3ec 100644 --- a/src/css/css_parser.rs +++ b/src/css/css_parser.rs @@ -1278,8 +1278,8 @@ where // at-rule arms now call the leaf-module parse fns directly (`LayerName`, // `SupportsCondition`, `KeyframesName`, `PageSelector`, `ContainerName`, // `ContainerCondition`, `FontPaletteValuesRule`, `PageRule`, `PropertyRule` -// have un-gated). Only `@font-face`/`@keyframes` block bodies remain -// inline-``-gated on their `RuleBodyItemParser` trait impls. +// have un-gated). Only `@font-face`/`@keyframes` block bodies route through +// dedicated `RuleBodyItemParser` impls in their leaf modules. mod rule_parsers { use super::*; use crate::selectors::parser as selector_parser; @@ -3907,7 +3907,7 @@ impl<'a> Parser<'a> { } // ────────────────────────────────────────────────────────────────────── - // `*_cloned` helpers — C-7 in PORT_NOTES_PLAN. + // `*_cloned` helpers. // // These wrap `expect_*` / `slice_from` and return the slice with its // lifetime detached from `&mut self` (to `'static`, matching `Token`'s @@ -3915,7 +3915,7 @@ impl<'a> Parser<'a> { // sites in the CSS parser route through here instead of laundering the // lifetime locally. // - // Once C-9 threads `'i` through `Token<'i>`, these become safe + // Once `'i` is threaded through `Token<'i>`, these become safe // `-> CssResult<&'i [u8]>` and the body drops the `unsafe` — no caller // changes needed. // ────────────────────────────────────────────────────────────────────── diff --git a/src/css/media_query.rs b/src/css/media_query.rs index bdb4a8c39bc..2a6eb3e8322 100644 --- a/src/css/media_query.rs +++ b/src/css/media_query.rs @@ -1237,8 +1237,8 @@ fn write_min_max( // ───────────────────────── deep_clone ───────────────────────── // Arena-aware `deep_clone` — port of Zig's per-type `deepClone(arena)` -// bodies. Un-gated this round so `rules::dc::{media_list,query_feature}` can -// route through real impls instead of `#[derive(Clone)]` passthroughs. +// bodies, so `rules::dc::{media_list,query_feature}` can route through real +// impls instead of `#[derive(Clone)]` passthroughs. // // PORT NOTE: written as **inherent** methods (not `#[derive(DeepClone)]`) to // match the Zig hand-written bodies exactly: Zig copies `name`/`qualifier`/ diff --git a/src/css/properties/custom.rs b/src/css/properties/custom.rs index 19ef4ef4ead..e266a5897b2 100644 --- a/src/css/properties/custom.rs +++ b/src/css/properties/custom.rs @@ -9,14 +9,10 @@ use bun_collections::VecExt; // `EnvironmentVariableName::{parse, to_css}`, `Function::to_css`, // `CustomProperty::parse`, `UnparsedProperty::parse` are now real. // -// A few leaf calls (Url::parse/to_css, CustomIdent::to_css) are still -// ``-gated in *other* files; those bodies are inlined verbatim -// under `mod ext` below so the hub compiles without touching +// A few leaf calls (Url::parse/to_css, CustomIdent::to_css) have their bodies +// inlined verbatim under `mod ext` below so the hub compiles without touching // `values/{url,ident}.rs`. `DashedIdentReference::{parse_with_options,to_css}` -// are now real and forwarded directly. Remaining internal -// `` gates carry `blocked_on:` notes for the next round -// (ComponentParser un-gate from `values::color::gated_full_impl`; -// `properties::animation` un-gate; `get_fallback` chain). +// are now real and forwarded directly. use crate as css; use crate::PrintResult; @@ -48,13 +44,11 @@ use crate::generics::{CssEql, CssHash, DeepClone}; use bun_alloc::Arena; // ─── External-gate shims ─────────────────────────────────────────────────── -// `TokenList::{parse,to_css}` bottom out on a handful of leaf fns that still -// carry `` in *other* files (`values/{url,ident}.rs`, -// `css_modules.rs`). Those gates are stale — every dependency they cite now -// exists — but this round's edit scope is `custom.rs` + `css_parser.rs` only. -// To un-gate the TokenList hub without touching those files, the leaf bodies -// are inlined here verbatim. Once `url.rs`/`ident.rs` un-gate, callers below -// can swap back to the canonical methods and this module drops. +// `TokenList::{parse,to_css}` bottom out on a handful of leaf fns whose +// canonical homes live in *other* files (`values/{url,ident}.rs`, +// `css_modules.rs`). To un-gate the TokenList hub without touching those +// files, the leaf bodies were inlined here verbatim. Once callers swap back +// to the canonical methods in `url.rs`/`ident.rs`, this module drops. mod ext { use super::*; use crate::dependencies; @@ -77,7 +71,7 @@ mod ext { } /// Inline of `Url::to_css` (gated in `values/url.rs` on `WriteAll for - /// Vec`, which this round adds in css_parser.rs). + /// Vec`, defined in css_parser.rs). pub(super) fn url_to_css(this: &Url, dest: &mut Printer) -> PrintResult<()> { let dep: Option = if dest.dependencies.is_some() { // PORT NOTE: reshaped for borrowck — `get_import_records` borrows diff --git a/src/css/properties/font.rs b/src/css/properties/font.rs index f4dd6a0f720..63eade155b7 100644 --- a/src/css/properties/font.rs +++ b/src/css/properties/font.rs @@ -10,12 +10,11 @@ // by `properties_generated.rs`, `declaration.rs`, and // `rules/{font_face,font_palette_values}.rs`. // -// Most `parse` / `to_css` *bodies* remain ``-gated below -// because they bottom out on still-unported leaf surface (DeriveParse / -// DeriveToCss proc-macros, EnumProperty derive over strum, Vec::parse, -// parse_utility::parse_string, generics::is_compatible blanket). Each gate -// carries a `blocked_on:` note so the next round can lift bodies as their -// deps land. +// Most `parse` / `to_css` *bodies* remain gated below because they bottom out +// on still-unported leaf surface (DeriveParse / DeriveToCss proc-macros, +// EnumProperty derive over strum, Vec::parse, parse_utility::parse_string, +// generics::is_compatible blanket). Each gate carries a `blocked_on:` note so +// the bodies can be lifted as their deps land. #![allow(unused_imports, dead_code)] #![warn(unused_must_use)] diff --git a/src/css/properties/mod.rs b/src/css/properties/mod.rs index 6afb1464cb5..1466f0a8f39 100644 --- a/src/css/properties/mod.rs +++ b/src/css/properties/mod.rs @@ -193,11 +193,11 @@ pub mod contain; pub mod display; pub mod effects; pub mod flex; -// `font`: un-gated — real data types (FontWeight / FontSize / FontStretch / -// FontFamily / FontStyle / FontVariantCaps / LineHeight / Font / FontHandler) -// live in `font.rs`. parse/to_css/handle_property bodies remain internally -// ``-gated there until DeriveParse/DeriveToCss proc-macros + -// EnumProperty derive land. +// `font`: real data types (FontWeight / FontSize / FontStretch / FontFamily / +// FontStyle / FontVariantCaps / LineHeight / Font / FontHandler) and hand-rolled +// parse/to_css/handle_property bodies live in `font.rs`. Some sites carry +// `blocked_on:` notes pointing at the eventual DeriveParse/DeriveToCss +// proc-macros and EnumProperty derive that would replace the hand-rolled bodies. pub mod font; pub mod grid; // `list`: un-gated — real ListStyleType / CounterStyle / Symbols / Symbol @@ -220,18 +220,17 @@ pub mod transform; pub mod transition; pub mod ui; -// `css_modules`: un-gated — real `Composes` payload (names/from/loc/ -// cssparser_loc) + `Specifier` enum (Global/ImportRecordIndex) live in -// `css_modules.rs`. `Composes::to_css` stays internally ``-gated -// on `CustomIdent::to_css` (Printer::write_ident). +// `css_modules`: real `Composes` payload (names/from/loc/cssparser_loc) + +// `Specifier` enum (Global/ImportRecordIndex) and parse/to_css/deep_clone/eql/ +// hash bodies live in `css_modules.rs`. pub mod css_modules; -// `custom`: un-gated — real data types (TokenList / TokenOrValue / -// CustomProperty / CustomPropertyName / UnparsedProperty / EnvironmentVariable -// / Variable / Function / UnresolvedColor / UAEnvironmentVariable) live in -// `custom.rs`. parse/to_css/deep_clone/eql/hash bodies remain internally -// ``-gated there until their leaf deps (ident/url/color/ -// generics) un-gate. +// `custom`: real data types (TokenList / TokenOrValue / CustomProperty / +// CustomPropertyName / UnparsedProperty / EnvironmentVariable / Variable / +// Function / UnresolvedColor / UAEnvironmentVariable) and parse/to_css/ +// deep_clone/eql/hash bodies live in `custom.rs`. A few leaf calls +// (Url::parse/to_css, CustomIdent::to_css) are inlined under `mod ext` there +// so the hub compiles without touching `values/{url,ident}.rs`. pub mod custom; pub mod properties_generated; diff --git a/src/css/rules/keyframes.rs b/src/css/rules/keyframes.rs index 17bdb409c1c..c2a8021dde0 100644 --- a/src/css/rules/keyframes.rs +++ b/src/css/rules/keyframes.rs @@ -353,11 +353,6 @@ pub struct KeyframesListParser; // PORT NOTE: in Zig these are nested `pub const DeclarationParser = struct { ... }` // namespaces that the css parser duck-types via `@hasDecl`. In Rust they become // trait impls on `KeyframesListParser`. -// -// blocked_on: css::{DeclarationParser, AtRuleParser, QualifiedRuleParser, -// RuleBodyItemParser} trait signatures (css_parser.rs round-5 surface), -// Parser::parse_comma_separated, DeclarationBlock::parse, ParserOptions::default -// arena threading. const _: () = { use css::css_parser::{ diff --git a/src/css/rules/media.rs b/src/css/rules/media.rs index 29ec17f97ae..b2a6a38ed14 100644 --- a/src/css/rules/media.rs +++ b/src/css/rules/media.rs @@ -15,8 +15,7 @@ pub struct MediaRule { // ─── behavior bodies ────────────────────────────────────────────────────── // PORT NOTE: `minify` lives in `rules/mod.rs` (hoisted next to `CssRuleList:: // minify` so the dispatch can call it without re-exporting `MinifyContext` -// here). `to_css` un-gated this round — `MediaList::{always_matches,to_css}` -// and `CssRuleList::to_css` are both real now. +// here). impl MediaRule { pub fn to_css(&self, dest: &mut Printer) -> Result<(), PrintErr> { if dest.minify && self.query.always_matches() { diff --git a/src/css/rules/mod.rs b/src/css/rules/mod.rs index e2721400317..72a6d6bf261 100644 --- a/src/css/rules/mod.rs +++ b/src/css/rules/mod.rs @@ -344,16 +344,14 @@ pub(super) mod dc { // (The Zig `implementDeepClone` returns `this.*` for simple-copy types.) // ─── shared serialization helpers for leaf rules ────────────────────────── -// Several leaf-rule `to_css` bodies bottom out on helpers whose canonical -// homes are still ``-gated outside `rules/` (DeclarationBlock:: -// to_css_block, VendorPrefix::toCss, CustomIdent/DashedIdent ::toCss). The -// bodies are tiny and have no further blockers, so they're inlined here so the -// 12 leaf rules can serialize for real. Once the upstream gates drop, callers -// switch back and these are deleted. - -/// Port of `DeclarationBlock.toCssBlock` (declaration.zig). The real impl is -/// gated in `declaration.rs`; `Property::to_css` is un-gated so the body is -/// trivially inlinable here. +// Local copies of `DeclarationBlock::to_css_block`, `VendorPrefix::to_css`, and +// `CustomIdent::to_css` shared by the leaf-rule `to_css` bodies in `rules/`. +// The canonical impls live outside `rules/` (`declaration.rs`, `css_parser.rs`, +// `values/ident.rs`); these duplicates can be deleted once callers route +// through them directly. + +/// Port of `DeclarationBlock.toCssBlock` (declaration.zig); duplicates +/// `DeclarationBlock::to_css_block`. pub(super) fn decl_block_to_css( decls: &css::DeclarationBlock<'_>, dest: &mut Printer, @@ -387,9 +385,8 @@ pub(super) fn decl_block_to_css( dest.write_char(b'}') } -/// Port of `VendorPrefix.toCss` (css_parser.zig:182). Lives here because the -/// canonical `impl VendorPrefix` block in lib.rs hasn't grown a `to_css` yet -/// and `rules/` is the only un-gated caller. +/// Port of `VendorPrefix.toCss` (css_parser.zig); duplicates +/// `VendorPrefix::to_css` (css_parser.rs). #[inline] pub(super) fn vendor_prefix_to_css( prefix: css::VendorPrefix, @@ -534,11 +531,6 @@ impl CssRuleList { where R: for<'b> css::generics::DeepClone<'b>, { - // blocked_on (style arm only): StyleRule::{minify,is_compatible, - // update_prefix,hash_key,is_duplicate}, selector::{is_compatible, - // is_equivalent,Selector::from_component}, SelectorList::deep_clone, - // DeclarationBlock::deep_clone — all `` in their leaves. - let mut style_rules = StyleRuleKeyMap::default(); let mut rules: Vec> = Vec::new(); diff --git a/src/css/rules/property.rs b/src/css/rules/property.rs index 9ad9bec6ae5..76608cc4f8f 100644 --- a/src/css/rules/property.rs +++ b/src/css/rules/property.rs @@ -61,12 +61,9 @@ impl PropertyRule { impl PropertyRule { pub fn deep_clone(&self, bump: &bun_alloc::Arena) -> Self { - // PORT NOTE: `css.implementDeepClone` field-walk. `SyntaxString` has an - // inherent `deep_clone(&self, &Arena)`. While `ParsedComponent` is - // ``-gated to `()`, `Option<()>` is `Copy` → identity; - // once it un-gates, swap to `self.initial_value.as_ref().map(|v| - // v.deep_clone(bump))` (values/syntax.rs already provides the - // inherent impl). + // PORT NOTE: `css.implementDeepClone` field-walk. `SyntaxString` and + // `ParsedComponent` (values/syntax.rs) each provide an inherent + // `deep_clone(&self, &Arena)`. Self { name: self.name.deep_clone(bump), syntax: self.syntax.deep_clone(bump), diff --git a/src/css/rules/style.rs b/src/css/rules/style.rs index dea7f1cf83c..c5abf0aca36 100644 --- a/src/css/rules/style.rs +++ b/src/css/rules/style.rs @@ -39,9 +39,8 @@ impl StyleRule { // std.hash.Wyhash.init(0) — same algorithm as bun.hash let mut hasher = bun_wyhash::Wyhash::init(0); self.selectors.hash(&mut hasher); - // PORT NOTE: `DeclarationBlock::hash_property_ids` is still - // ``-gated in declaration.rs; inline its body here. The - // Zig `PropertyId.hash` is `hasher.update(asBytes(&@intFromEnum(self)))` + // PORT NOTE: inlined `DeclarationBlock::hash_property_ids`. The Zig + // `PropertyId.hash` is `hasher.update(asBytes(&@intFromEnum(self)))` // — i.e. just the u16 tag bytes. for decl in self.declarations.declarations.iter() { let tag = decl.property_id().tag() as u16; diff --git a/src/css/selectors/parser.rs b/src/css/selectors/parser.rs index a0e85d4245f..fb3c1e7b252 100644 --- a/src/css/selectors/parser.rs +++ b/src/css/selectors/parser.rs @@ -4309,11 +4309,11 @@ pub enum ViewTransitionPartName { impl ViewTransitionPartName { pub fn to_css(&self, dest: &mut Printer) -> Result<(), PrintErr> { - // PORT NOTE: `CustomIdentFns::to_css` is ``-gated on - // `Printer::{css_module,write_ident}`; inline the - // `write_ident(v, false)` body (CSS-modules custom-ident scoping is a - // serializer concern, not a grammar concern — the gated impl just - // toggles the second arg). + // PORT NOTE: Zig calls `CustomIdentFns.toCss` here, which routes + // through `Printer.writeIdent` and applies CSS-module custom-ident + // scoping when enabled. This inline writes the unscoped form + // (`Printer::write_ident(v, false)` ≡ `serialize_identifier`); switch + // to `CustomIdent::to_css` if view-transition part names need scoping. let write_ci = |name: &CustomIdent, dest: &mut Printer| -> Result<(), PrintErr> { dest.serialize_identifier(name.v()) }; diff --git a/src/css/selectors/selector.rs b/src/css/selectors/selector.rs index ee59eb71c99..fa3d972d0d1 100644 --- a/src/css/selectors/selector.rs +++ b/src/css/selectors/selector.rs @@ -569,12 +569,10 @@ fn is_selector_unused( for component in selector.components.iter() { match component { Component::Class(ident) | Component::Id(ident) => { - // PORT NOTE: `IdentOrRef::as_original_string` is - // ``-gated (blocked_on bun_ast::symbol::List::at - // + Symbol.original_name). Inline the ident arm; the ref arm - // (CSS-modules symbol-table lookup) is unreachable until - // `Parser::add_symbol_for_name` un-gates (see - // `SelectorParser::new_local_identifier`). + // PORT NOTE: inline of `IdentOrRef::as_original_string`'s + // ident arm. The ref arm (CSS-modules symbol-table lookup via + // `bun_ast::symbol::List::at` + `Symbol.original_name`) is + // still skipped — see the `blocked_on` note below. let actual_ident: &[u8] = match (*ident).as_ident() { // SAFETY: arena-owned slice (`'static` placeholder for the arena lifetime). Some(i) => unsafe { crate::arena_str(i.v) }, diff --git a/src/css_jsc/lib.rs b/src/css_jsc/lib.rs index fdd334f7f84..fe366494550 100644 --- a/src/css_jsc/lib.rs +++ b/src/css_jsc/lib.rs @@ -8,10 +8,7 @@ )] #![warn(unused_must_use)] //! `bun_css_jsc` — JSC bridge for `bun_css`. All fn bodies -//! compile against the `bun_jsc` / `bun_css` surface. The two -//! `OutputColorFormat::{Hsl,Lab}` match-arm bodies in `color_js` remain -//! ``-gated on `bun_css::values::color::*::{into_hsl,into_lab}` -//! (the colorspace matrix tables in `values/color.rs` are still gated). +//! compile against the `bun_jsc` / `bun_css` surface. pub mod color_js; pub mod css_internals; diff --git a/src/event_loop/AutoFlusher.rs b/src/event_loop/AutoFlusher.rs index f3456d41542..c4d7127109b 100644 --- a/src/event_loop/AutoFlusher.rs +++ b/src/event_loop/AutoFlusher.rs @@ -38,7 +38,7 @@ pub fn erase_flush_callback() -> DeferredRepeatingTask { trampoline:: } -// PORT NOTE (b0): Zig passed `*jsc.VirtualMachine` and reached +// PORT NOTE: Zig passed `*jsc.VirtualMachine` and reached // `vm.event_loop().deferred_tasks`. To break the event_loop→jsc upward edge, // callers now pass the `DeferredTaskQueue` directly (it lives in this crate). // Higher-tier call sites do `&mut vm.event_loop().deferred_tasks` themselves. diff --git a/src/event_loop/EventLoopTimer.rs b/src/event_loop/EventLoopTimer.rs index f93875b4194..813c3e8d272 100644 --- a/src/event_loop/EventLoopTimer.rs +++ b/src/event_loop/EventLoopTimer.rs @@ -135,7 +135,7 @@ impl EventLoopTimer { /// If self was created by set{Immediate,Timeout,Interval}, return its /// JS-timer epoch (used for stable ordering of equal-deadline timers). /// - /// PORT NOTE (b0): Zig `jsTimerInternalsFlags` did `@fieldParentPtr` into + /// PORT NOTE: Zig `jsTimerInternalsFlags` did `@fieldParentPtr` into /// `TimeoutObject`/`ImmediateObject`/`AbortSignalTimeout` (all tier-6 /// runtime types). The container_of dispatch lives in /// `bun_runtime::dispatch::__bun_js_timer_epoch` (link-time extern). @@ -153,7 +153,7 @@ impl EventLoopTimer { /// Fire the timer's callback. /// - /// PORT NOTE (b0): the `match self.tag { … container_of … }` body was + /// PORT NOTE: the `match self.tag { … container_of … }` body was /// hot-dispatch over ~20 tier-6 variant types (Subprocess, DevServer, /// PostgresSQLConnection, …). That match lives in /// `bun_runtime::dispatch::__bun_fire_timer` (link-time extern). `vm` is diff --git a/src/event_loop/MiniEventLoop.rs b/src/event_loop/MiniEventLoop.rs index e8dd5c97a93..5a30860dbfb 100644 --- a/src/event_loop/MiniEventLoop.rs +++ b/src/event_loop/MiniEventLoop.rs @@ -664,7 +664,7 @@ pub trait AbstractVM<'a> { fn abstract_vm(self) -> Self::Wrapped; } -// PORT NOTE (b0): `impl AbstractVM for &VirtualMachine` cannot live here +// PORT NOTE: `impl AbstractVM for &VirtualMachine` cannot live here // without naming the tier-6 `VirtualMachine` type. The impl moves to // `bun_runtime` (move-in pass), which constructs `JsVM { vm, vtable }`. diff --git a/src/http/ssl_config.rs b/src/http/ssl_config.rs index 5013aa57407..8cc8b58193d 100644 --- a/src/http/ssl_config.rs +++ b/src/http/ssl_config.rs @@ -1,7 +1,7 @@ //! MOVE-IN: ssl_config (MOVE_DOWN bun_runtime::socket::SSLConfig → bun_http) //! Ground truth: src/runtime/socket/SSLConfig.zig //! JSC-dependent constructors (from_js / from_generated / read_from_blob / -//! handle_path / handle_file*) stay in bun_runtime (tier-6, Pass C). +//! handle_path / handle_file*) stay in bun_runtime (tier-6). use core::ffi::{CStr, c_char}; use std::sync::atomic::{AtomicU64, Ordering}; diff --git a/src/install/Cargo.toml b/src/install/Cargo.toml index ac7b104ac76..0048165e688 100644 --- a/src/install/Cargo.toml +++ b/src/install/Cargo.toml @@ -34,8 +34,6 @@ bun_alloc.workspace = true bun_bunfig.workspace = true bun_clap.workspace = true bun_core.workspace = true -# TODO(b1): bun_bundler dep gated — crate not green yet -# bun_bundler.workspace = true bun_collections.workspace = true bun_crash_handler.workspace = true bun_dns.workspace = true diff --git a/src/install/lockfile.rs b/src/install/lockfile.rs index 75cd8598da1..d516414128d 100644 --- a/src/install/lockfile.rs +++ b/src/install/lockfile.rs @@ -635,7 +635,7 @@ impl Lockfile { // to `manager` (already moved into the call above for `Option<&mut PackageManager>`) // and the `&mut Lockfile` inside `result`. Restoring it requires the // `manager.as_deref_mut()` reborrow which today's `Option<&mut PackageManager>` - // surface forbids. Until reconciler-6, the debug round-trip is omitted. + // surface forbids. The debug round-trip is omitted until that reshape lands. // TODO(port): re-enable BUN_DEBUG_TEST_TEXT_LOCKFILE round-trip once borrowck reshape lands. self.load_from_bytes(manager, buf, log) } diff --git a/src/install/lockfile/Tree.rs b/src/install/lockfile/Tree.rs index db36172c6a7..e8ecafef962 100644 --- a/src/install/lockfile/Tree.rs +++ b/src/install/lockfile/Tree.rs @@ -191,7 +191,7 @@ pub enum IteratorPathStyle { // PORT NOTE: reshaped — Zig stores `lockfile: *const Lockfile`; here we store // the four buffer slices the iterator actually reads so callers from both // `crate::lockfile` (stub) and `crate::lockfile_real` can drive the same -// iterator without a unified `Lockfile` type (reconciler-6). +// iterator without a unified `Lockfile` type. pub struct Iterator<'a, const PATH_STYLE: IteratorPathStyle> { pub tree_id: Id, pub path_buf: PathBuffer, diff --git a/src/install_types/NodeLinker.rs b/src/install_types/NodeLinker.rs index c6e87c92b9d..f1d01b30b3e 100644 --- a/src/install_types/NodeLinker.rs +++ b/src/install_types/NodeLinker.rs @@ -95,7 +95,7 @@ unsafe extern "Rust" { } /// Owned, type-erased JSC regex; drops through the vtable. -// FORWARD_DECL(b0): bun_jsc::RegularExpression — stored as raw NonNull<()> +// `bun_jsc::RegularExpression` forward-declared as a raw `NonNull<()>` // (NOT Box: a zero-sized opaque Box is a dangling sentinel that would // leak the real JSC allocation and skip its destructor). pub struct RegularExpression(NonNull<()>); diff --git a/src/io/PipeReader.rs b/src/io/PipeReader.rs index 00517310e99..cba90170c83 100644 --- a/src/io/PipeReader.rs +++ b/src/io/PipeReader.rs @@ -619,7 +619,7 @@ impl PosixBufferedReader { _size_hint: isize, received_hup_initially: bool, ) { - // PORT_NOTES_PLAN R-2: `&mut parent` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut parent` carries LLVM `noalias`, but // `vtable.on_read_chunk` below re-enters JS (e.g. // `FileReader::on_read_chunk` resolves a promise → drains microtasks) // and user code can reach this reader via a fresh @@ -811,7 +811,7 @@ impl PosixBufferedReader { received_hup: bool, sys_fn: impl Fn(Fd, &mut [u8], usize) -> sys::Result, ) { - // PORT_NOTES_PLAN R-2: `&mut parent` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut parent` carries LLVM `noalias`, but // `vtable.on_read_chunk` below re-enters JS (resolves the pending // read, drains microtasks, fires `'data'`) and user code can reach // this reader via a fresh `&mut PosixBufferedReader` from the parent's @@ -1273,7 +1273,7 @@ impl WindowsBufferedReader { self.flags.remove(WindowsFlags::HAS_INFLIGHT_READ); return true; } - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `vtable.on_read_chunk` re-enters JS and user code can reach this // reader via a fresh `&mut WindowsBufferedReader` from the parent's // intrusive `reader` field, writing `self.flags` (e.g. via `pause` / diff --git a/src/io/PipeWriter.rs b/src/io/PipeWriter.rs index d8e7838e0ed..6ce45953d92 100644 --- a/src/io/PipeWriter.rs +++ b/src/io/PipeWriter.rs @@ -377,7 +377,7 @@ impl PosixBufferedWriter { /// See [`parent_event_loop`](Self::parent_event_loop) for the encapsulated /// type invariant. `on_error` may re-enter via the parent's intrusive /// `writer` field; callers that read `self` afterwards must launder - /// (R-2 noalias) — this accessor does not. + /// (noalias re-entry) — this accessor does not. #[inline] fn parent_on_error(&self, err: sys::Error) { // SAFETY: type invariant — set-once parent backref outlives writer. @@ -424,7 +424,7 @@ impl PosixBufferedWriter { } fn _on_write(&mut self, written: usize, status: WriteStatus) { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `Parent::on_write` (e.g. `IOWriter::on_write`) re-enters via a fresh // `&mut Self` from the parent's intrusive `writer` field and may write // `self.handle` / `self.is_done`. ASM-verified PROVEN_CACHED in the @@ -716,7 +716,7 @@ impl PosixStreamingWriter { /// `unsafe { Parent::on_write(self.parent(), ..) }` blocks (one per /// `WriteResult` arm) into one. `on_write` may re-enter via the parent's /// intrusive `writer` field; callers that read `self` afterwards must - /// launder (R-2 noalias) — the existing laundered sites in `_on_write` / + /// launder (noalias re-entry) — the existing laundered sites in `_on_write` / /// `register_poll` keep their raw-pointer dispatch and do **not** route /// through this accessor. #[inline] @@ -825,7 +825,7 @@ impl PosixStreamingWriter { let loop_ = unsafe { Parent::loop_(self.parent()) }.cast(); match poll.register_with_fd(loop_, FilePollKind::Writable, poll.fd()) { sys::Result::Err(err) => { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `Parent::on_error` (e.g. `FileSink::on_error`) re-enters via // a fresh `&mut Self` from the parent's intrusive `writer` // field and may write `self.is_done` / `self.handle`. @@ -1552,7 +1552,7 @@ impl WindowsBufferedWriter { /// Type invariant (encapsulated `unsafe`): `self.parent` is populated by /// [`set_parent`](BaseWindowsPipeWriter::set_parent) before any write path /// is reached, and the writer is an intrusive field of `*parent` so the - /// pointee strictly outlives `self`. Takes the R-2 `*mut Self` so the field + /// pointee strictly outlives `self`. Takes the `*mut Self` so the field /// read completes before dispatch and no Rust borrow of `*this` is live /// across the (re-entrant) `Parent::on_error` call. Collapses the two /// identical dispatch blocks in `on_write_complete` / @@ -1570,7 +1570,7 @@ impl WindowsBufferedWriter { } fn on_write_complete(&mut self, status: uv::ReturnCode) { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `Parent::on_write` (e.g. `FileSink::on_write`) re-enters JS via // promise resolution and may call back into this writer through a fresh // `&mut Self` derived from the parent's intrusive `writer` field @@ -1646,10 +1646,10 @@ impl WindowsBufferedWriter { return; } - // PORT_NOTES_PLAN R-2: launder `*this` for the same reason as the + // Launder `*this` (see bun_ptr::LaunderedSelf) for the same reason as the // Streaming sibling above — `close()` → `Parent::on_close` → JS may // re-enter via `with_mut(|w| ..)`; the post-call `(*this).parent()` - // must reload. NOALIAS_HUNT cluster E. + // must reload. // SAFETY: data was set to `self as *mut Self` in write(); libuv invokes // this callback on the single-threaded event loop with no other Rust // borrow of `*this` live, so this is the sole access path. @@ -2052,7 +2052,7 @@ impl WindowsStreamingWriter { /// pointee strictly outlives `self`. Unlike a `&self` accessor (which would /// place a `readonly`/SB-protector on `*self` for the duration of the /// re-entrant `Parent::on_error` call — see the `parent_on_error` note on - /// [`WindowsBufferedWriter`]), this takes the R-2 `*mut Self`: the field + /// [`WindowsBufferedWriter`]), this takes the `*mut Self`: the field /// read completes before dispatch, so no Rust borrow of `*this` is live /// across the (re-entrant) call. Collapses the five identical /// `Parent::on_error(Self::r(this).parent(), err)` dispatch blocks in @@ -2103,7 +2103,7 @@ impl WindowsStreamingWriter { } fn on_write_complete(&mut self, status: uv::ReturnCode) { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `Parent::on_write` (e.g. `FileSink::on_write`) re-enters JS via // promise resolution and may call back into this writer through a fresh // `&mut Self` derived from the parent's intrusive `writer` field @@ -2212,7 +2212,7 @@ impl WindowsStreamingWriter { return; } - // PORT_NOTES_PLAN R-2: launder `*this`. `this.on_write_complete()` / + // Launder `*this` (see bun_ptr::LaunderedSelf). `this.on_write_complete()` / // `this.close()` below both reach `Parent::on_write`/`on_close` → // FileSink → JS, which can `self.writer.with_mut(|w| w.end()/close())` // forming a fresh aliased `&mut WindowsStreamingWriter`. The @@ -2223,7 +2223,7 @@ impl WindowsStreamingWriter { // error path (`close()` → `on_error(this.parent())` → guard deref) // reads `this.parent` after re-entry; route those through a // black-boxed raw ptr so any inlined call chain cannot - // store-forward across the JS re-entry. NOALIAS_HUNT cluster E. + // store-forward across the JS re-entry. // SAFETY: data was set to `self as *mut Self` in process_send(); libuv // invokes this callback on the single-threaded event loop with no other // Rust borrow of `*this` live, so this is the sole access path. @@ -2256,7 +2256,7 @@ impl WindowsStreamingWriter { /// this tries to send more data returning if we are writable or not after this fn process_send(&mut self) { log!("processSend"); - // PORT_NOTES_PLAN R-2: same noalias re-entry hazard as + // Same noalias re-entry hazard (see bun_ptr::LaunderedSelf) as // `on_write_complete` above. The three synchronous-error arms call // `Parent::on_error` (re-enters JS via FileSink::on_error → promise // reject; user callback may `writer.with_mut(|w| w.end())`/`.close()` diff --git a/src/io/lib.rs b/src/io/lib.rs index 8d4d74800d8..7bc997cb0e5 100644 --- a/src/io/lib.rs +++ b/src/io/lib.rs @@ -6,9 +6,7 @@ // ════════════════════════════════════════════════════════════════════════════ // Loop / Poll / Waker / Closer / FilePoll-vtable / heap / pipes / MaxBuf / // openForWriting / PipeReader / PipeWriter compile on POSIX. `source` and the -// Windows*Reader/Writer impls are `#[cfg(windows)]`-gated (libuv-only). See -// TODO(port) notes for remaining shims (`bun_sys::syslog`, `bun_sys::Error::oom`, -// `bun_core::debug_warn`). +// Windows*Reader/Writer impls are `#[cfg(windows)]`-gated (libuv-only). // ════════════════════════════════════════════════════════════════════════════ #![allow(dead_code, unused_variables, unused_imports, unused_mut, clippy::all)] diff --git a/src/js_parser/fold.rs b/src/js_parser/fold.rs index e9a62a26595..a4f2acd4e23 100644 --- a/src/js_parser/fold.rs +++ b/src/js_parser/fold.rs @@ -20,10 +20,10 @@ use bun_ast::ast_result::CommonJSNamedExport; use bun_ast::{self as js_ast, B, Binding, E, Expr, Flags, G, LocRef, S, Stmt, Symbol}; // ── local EString shims ──────────────────────────────────────────────────── -// E.rs currently carries two `impl EString` blocks (live + round-C draft) with -// overlapping inherent methods, so calls like `EString::init`/`javascript_length` -// /`eql_bytes` are E0034-ambiguous from here. These thin wrappers go through -// public fields directly and are removed once E.rs is deduped. +// Thin wrappers around `E::EString` field access. Added when `e.rs` carried +// duplicate `impl EString` blocks and `EString::init` / `javascript_length` / +// `eql_bytes` were E0034-ambiguous from here. The duplicates have since been +// merged, so these can be replaced with the inherent methods. #[inline] fn e_string_init(data: &[u8]) -> E::EString { E::EString { @@ -59,7 +59,7 @@ fn e_string_eql_bytes(s: &E::EString, other: &[u8]) -> bool { } // Zig: `pub fn AstMaybe(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { diff --git a/src/js_parser/lib.rs b/src/js_parser/lib.rs index ec1c599f733..d5a15da40b5 100644 --- a/src/js_parser/lib.rs +++ b/src/js_parser/lib.rs @@ -259,8 +259,8 @@ impl<'a, const IS_TS: bool, const SCAN: bool> bun_ast::expr::EqlParser pub mod defines_table; // ─── from bun_bundler::defines (src/bundler/defines.zig) ──────────────────── -// B-3 UNIFIED: canonical `Define` / `DefineData` / `DotDefine` live here so the -// parser (`P.define: &'a Define`) and the bundler (`BundleOptions.define: +// Canonical `Define` / `DefineData` / `DotDefine` live here so the parser +// (`P.define: &'a Define`) and the bundler (`BundleOptions.define: // Box`) share one nominal type. `bun_bundler::defines` re-exports these // and layers the json-parse / dotenv `init` on top via an extension trait. The // pure-global fallback table also lives at this tier (`defines_table`) so @@ -963,7 +963,7 @@ pub mod renamer { use bun_ast::symbol::{self, INVALID_NESTED_SCOPE_SLOT, SlotNamespace, Symbol}; use bun_collections::VecExt; - // Round-C alias kept for P.rs/Parser.rs callers. + // Alias kept for P.rs/Parser.rs callers. pub type SymbolMap = bun_ast::symbol::Map; pub fn assign_nested_scope_slots( diff --git a/src/js_parser/lower/lower_decorators.rs b/src/js_parser/lower/lower_decorators.rs index a7ba015cf8f..a080e09be0f 100644 --- a/src/js_parser/lower/lower_decorators.rs +++ b/src/js_parser/lower/lower_decorators.rs @@ -22,7 +22,7 @@ use bun_ast::{self as js_ast, B, E, Expr, ExprNodeList, Flags, G, S, Stmt, StmtN type BumpVec<'a, T> = bun_alloc::ArenaVec<'a, T>; // Zig: `pub fn LowerDecorators(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. // ── Local helper types ─────────────────────────────────────────────────────── diff --git a/src/js_parser/lower/lower_esm_exports_hmr.rs b/src/js_parser/lower/lower_esm_exports_hmr.rs index 59df59f0ca6..9829a81aa3e 100644 --- a/src/js_parser/lower/lower_esm_exports_hmr.rs +++ b/src/js_parser/lower/lower_esm_exports_hmr.rs @@ -9,9 +9,8 @@ use crate::p::P; use crate::parser::{ReactRefresh, Ref, TempRef}; use bun_ast::{self as js_ast, B, Binding, E, Expr, G, S, Stmt}; -// PORT NOTE: `P::generate_temp_ref` is ``-gated in P.rs (round-6 -// re-gate); replicate it here so this file can un-gate independently. Body is -// a 1:1 port of P.zig `generateTempRefWithScope` with `scope = current_scope`. +// PORT NOTE: local copy of `P::generate_temp_ref`. Body is a 1:1 port of +// P.zig `generateTempRefWithScope` with `scope = current_scope`. // `P::will_use_renamer` is private — its body is inlined. fn generate_temp_ref<'p, const TS: bool, const SCAN: bool>( p: &mut P<'p, TS, SCAN>, diff --git a/src/js_parser/p.rs b/src/js_parser/p.rs index aed559be598..3aefb842118 100644 --- a/src/js_parser/p.rs +++ b/src/js_parser/p.rs @@ -21,6 +21,7 @@ use bun_wyhash::Wyhash; use crate::defines::{Define, DefineData}; use crate::lexer as js_lexer; use crate::parse::parse_entry::Options as ParserOptions; +use crate::renamer; use crate::{ ARGUMENTS_STR as arguments_str, DeferredArrowArgErrors, DeferredErrors, DeferredImportNamespace, EXPORTS_STRING_NAME as exports_string_name, ExprBindingTuple, @@ -40,9 +41,6 @@ use bun_ast::{ B, Binding, BindingNodeIndex, E, Expr, ExprNodeIndex, ExprNodeList, Flags, G, LocRef, S, Scope, Stmt, StmtNodeList, Symbol, }; -// Round-D/E modules: stub re-exports so type signatures referencing them compile. -// Real bodies un-gate per-file later. -use crate::renamer; // Type aliases matching the Zig `const List = std.ArrayListUnmanaged;` etc. // In this AST crate, lists are arena-backed. @@ -151,11 +149,11 @@ impl<'a> ImportRecordList<'a> { /// (so the parser can be dropped without aliasing the records the linker / /// printer now own). /// - /// Round-G fix: previously `to_ast` reached through `items_mut()` and - /// wrapped the *live* BumpVec slice, leaving `self` non-empty; the BumpVec's - /// Drop then ran element destructors on records the returned `Ast` still - /// pointed at. This adapter restores Zig's move-and-zero semantics for both - /// the bump-backed and externally-borrowed variants. + /// Previously `to_ast` reached through `items_mut()` and wrapped the + /// *live* BumpVec slice, leaving `self` non-empty; the BumpVec's Drop + /// then ran element destructors on records the returned `Ast` still + /// pointed at. This adapter restores Zig's move-and-zero semantics for + /// both the bump-backed and externally-borrowed variants. pub fn move_to_baby_list(&mut self, arena: &'a Bump) -> Vec { match core::mem::replace(self, Self::Owned(BumpVec::new_in(arena))) { Self::Owned(v) => Vec::from_bump_vec(v), @@ -195,8 +193,7 @@ pub type MacroCallCountType = u32; // ─── Re-exports of sibling-module impls (Zig: `pub const X = mod.X;`) ─── // In Rust these are inherent methods on `P` defined in sibling files via separate -// `impl<...> P<...>` blocks. Round-D/E: those files un-gate per-module; until -// then their re-exports are gated so the *struct* + core helpers compile. +// `impl<...> P<...>` blocks. pub use crate::parse::parse_skip_typescript::*; pub use crate::parse::*; pub use crate::visit::*; @@ -888,9 +885,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } // ═══════════════════════════════════════════════════════════════════════════ -// Round-D: core helper methods on P. Un-gated in groups; heavy bodies that -// touch unfinished E/S/ts surface or call into parse_*/visit_* sibling files -// stay individually ` // blocked_on:` below. +// Core helper methods on P. Heavy bodies that touch unfinished E/S/ts surface +// or call into parse_*/visit_* sibling files stay individually +// `// blocked_on:` below. // ═══════════════════════════════════════════════════════════════════════════ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { pub const ALLOW_MACROS: bool = true /* TODO(port): feature_flag::IS_MACRO_ENABLED */; @@ -1668,7 +1665,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // IntoExprData::as_e_call() lands. /// Zig: `p.b(t, loc)` — bump-allocate a binding payload and wrap it in `Binding`. - /// `BindingAlloc` (Binding.rs round-G2) replaces the Zig `@TypeOf(t)` switch. + /// `BindingAlloc` (Binding.rs) replaces the Zig `@TypeOf(t)` switch. /// /// PORT NOTE: Zig's `p.b(t: anytype)` had a `@typeInfo == .pointer` arm that /// dispatched to `Binding.init(t, loc)` (wrap-existing-allocation) instead of @@ -6833,9 +6830,9 @@ fn path_package_name<'a>(path: &fs::Path<'a>) -> Option<&'a [u8]> { } // ═══════════════════════════════════════════════════════════════════════════ -// Round-D/E heavy method bodies (lower_class / to_ast / react_refresh / etc.). -// lower_class + emit_decorator_metadata_for_prop + serialize_metadata are -// un-gated and compile against the full bun_ast::ts::Metadata variant set. +// Heavy method bodies (lower_class / to_ast / react_refresh / etc.). +// lower_class + emit_decorator_metadata_for_prop + serialize_metadata +// compile against the full bun_ast::ts::Metadata variant set. // Remaining individually-gated methods carry their own `blocked_on:` tags. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { pub fn lower_class(&mut self, stmtorexpr: js_ast::StmtOrExpr) -> &'a mut [Stmt] { @@ -7647,9 +7644,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O Expr::init_identifier(r#ref, loc) } - // wrap_inlined_enum: moved to ungated impl (round-G). - - // value_for_define / is_dot_define_match: moved to ungated impl (round-G). + // wrap_inlined_enum / value_for_define / is_dot_define_match: see the + // earlier impl block above. // One statement could potentially expand to several statements pub fn stmts_to_single_stmt(&mut self, loc: bun_ast::Loc, stmts: &'a mut [Stmt]) -> Stmt { @@ -7739,7 +7735,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O unreachable!("not implemented") } - // runtime_identifier_ref / runtime_identifier / call_runtime: moved to ungated impl (round-G). + // runtime_identifier_ref / runtime_identifier / call_runtime: see the + // earlier impl block above. pub fn extract_decls_for_binding( binding: Binding, @@ -7863,8 +7860,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O r#ref } - // compute_ts_enums_map() lives in the round-G `to_ast` impl block below - // (deduped — earlier draft body removed once both un-gated). + // compute_ts_enums_map() lives in the `to_ast` impl block below. pub fn should_lower_using_declarations(&self, stmts: &[Stmt]) -> bool { // TODO: We do not support lowering await, but when we do this needs to point to that var @@ -8368,10 +8364,10 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let mut hmr_transform_ctx = ConvertESMExportsForHmr { last_part, // Spec P.zig:6390: `p.source.path.isNodeModule()`. - // Round-G fix: `bun_paths::fs::Path::is_node_module` is now real - // (checks `name.dir` for `node_modules` with the - // platform separator); the former inline copy mis-handled the - // Windows separator via a cross-crate `const_format` const. + // `bun_paths::fs::Path::is_node_module` checks `name.dir` for + // `node_modules` with the platform separator; a former + // inline copy mis-handled the Windows separator via a + // cross-crate `const_format` const. is_in_node_modules: self.source.path.is_node_module(), imports_seen: Default::default(), export_star_props: Vec::new(), @@ -8835,10 +8831,10 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O let parts_list = Vec::::from_bump_vec(core::mem::replace(parts, BumpVec::new_in(arena))); // Spec P.zig:6697: `ImportRecord.List.moveFromList(&p.import_records)`. - // Round-G fix: use the dedicated adapter so the parser-side list is - // left empty (Zig move-and-zero) and the BumpVec is leaked into the - // arena rather than dropped — downstream (printer, linker) resolves - // every `S.Import`/`E.RequireString`/`E.Import` by index against this. + // Use the dedicated adapter so the parser-side list is left empty (Zig + // move-and-zero) and the BumpVec is leaked into the arena rather than + // dropped — downstream (printer, linker) resolves every + // `S.Import`/`E.RequireString`/`E.Import` by index against this. let import_records: Vec = self.import_records.move_to_baby_list(arena); // PERF: box at the construction site so the ~1 KB `Ast` is written @@ -8847,9 +8843,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // `js_parser::Result` PERF NOTE). Ok(Box::new(js_ast::Ast { // Spec P.zig:6644: `.runtime_imports = p.runtime_imports`. - // Round-G: `Ast.runtime_imports` is now the real - // `parser::Runtime::Imports`; moved out above (P is terminal after - // `to_ast`). + // `Ast.runtime_imports` is `parser::Runtime::Imports`; moved out + // above (P is terminal after `to_ast`). runtime_imports, module_scope, exports_ref: self.exports_ref, @@ -9317,15 +9312,13 @@ pub struct LowerUsingDeclarationsContext { pub has_await_using: bool, } -// Round-H un-gate: `generate_temp_ref` / `call_runtime` are now real (5516/6407), -// so the only blockers were API-shape divergences. Reshaped: +// Reshaped API surface relative to the Zig source: // • `call_runtime` takes `ExprNodeList` → wrap bump slices via `from_bump_slice` // • `DeclaredSymbol.ref_` / `LocRef.ref_` (not `r#ref`) // • `DeclaredSymbolList`/`Vec` API has no arena param in this port // • `G::Decl::List` → `G::DeclList` (free alias; inherent assoc type not used) -// reconciler-6 re-gate removed: those API divergences are fixed inline below; -// `generate_temp_ref` is real (round-G, see ~6407). DO NOT re-gate — `visit.rs` -// calls these via `should_lower_using_declarations` path. +// DO NOT gate this impl — `visit.rs` calls these via the +// `should_lower_using_declarations` path. impl LowerUsingDeclarationsContext { pub fn init<'a, const T: bool, const S_: bool>( p: &mut P<'a, T, S_>, diff --git a/src/js_parser/parse/mod.rs b/src/js_parser/parse/mod.rs index 7904872aba4..aa95018f4ed 100644 --- a/src/js_parser/parse/mod.rs +++ b/src/js_parser/parse/mod.rs @@ -45,7 +45,7 @@ use bun_ast::{ }; // Zig: `pub fn Parse(comptime ts, comptime jsx, comptime scan) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { diff --git a/src/js_parser/parse/parse_fn.rs b/src/js_parser/parse/parse_fn.rs index 09c34713417..0a92e2ab647 100644 --- a/src/js_parser/parse/parse_fn.rs +++ b/src/js_parser/parse/parse_fn.rs @@ -16,7 +16,7 @@ use bun_ast::{E, Expr, ExprNodeList, Flags, G, S, Stmt}; type Error = bun_core::Error; // Zig: `pub fn ParseFn(comptime typescript, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { // Zig: `const is_typescript_enabled = P.is_typescript_enabled;` diff --git a/src/js_parser/parse/parse_import_export.rs b/src/js_parser/parse/parse_import_export.rs index 757b4f510f4..53b1646e61e 100644 --- a/src/js_parser/parse/parse_import_export.rs +++ b/src/js_parser/parse/parse_import_export.rs @@ -9,7 +9,7 @@ use bun_ast::{ClauseItem, E, Expr, LocRef}; use bun_core::Error; // Zig: `fn ParseImportExport(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { diff --git a/src/js_parser/parse/parse_jsx.rs b/src/js_parser/parse/parse_jsx.rs index 0d989077ee3..080b1b4ec2f 100644 --- a/src/js_parser/parse/parse_jsx.rs +++ b/src/js_parser/parse/parse_jsx.rs @@ -12,7 +12,7 @@ use bun_core::err; use bun_core::strings; // Zig: `pub fn ParseJSXElement(comptime ...) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT` +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT` // (sealed trait + ZST), so this becomes a direct `impl` on `P` instead of a wrapper struct. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { diff --git a/src/js_parser/parse/parse_prefix.rs b/src/js_parser/parse/parse_prefix.rs index e8eef5e4195..2ef770ea545 100644 --- a/src/js_parser/parse/parse_prefix.rs +++ b/src/js_parser/parse/parse_prefix.rs @@ -26,10 +26,10 @@ use bun_ast::{self as js_ast, B, E, Expr, ExprData, ExprNodeList, G, OpCode, sco type PResult = core::result::Result; // Zig: `fn ParsePrefix(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. The 30+ per-token `t_*` helpers are private; only `parse_prefix` is -// surfaced. Round-G un-gates the per-token bodies (same JsxT pattern as parseStmt.rs); helper -// names pfx_-prefixed to avoid colliding with parseStmt.rs / parseSuffix.rs mixins on the same `P`. +// surfaced. Helper names are pfx_-prefixed to avoid colliding with parseStmt.rs / parseSuffix.rs +// mixins on the same `P`. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { fn pfx_t_super(p: &mut Self, level: Level) -> PResult { diff --git a/src/js_parser/parse/parse_property.rs b/src/js_parser/parse/parse_property.rs index 619b91092ac..596f4f00921 100644 --- a/src/js_parser/parse/parse_property.rs +++ b/src/js_parser/parse/parse_property.rs @@ -26,7 +26,7 @@ use js_ast::{ use js_lexer::T; // Zig: `fn ParseProperty(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { diff --git a/src/js_parser/parse/parse_skip_typescript.rs b/src/js_parser/parse/parse_skip_typescript.rs index d9cc1170176..278510ad6c1 100644 --- a/src/js_parser/parse/parse_skip_typescript.rs +++ b/src/js_parser/parse/parse_skip_typescript.rs @@ -12,7 +12,7 @@ use bun_ast::{self as js_ast, Op}; use bun_core::{self, Error, err}; // Zig: `fn SkipTypescript(comptime ts, comptime jsx, comptime scan_only) type { return struct {...} }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. // PORT NOTE: Zig nested `Bitset` inside `SkipTypeOptions`; Rust hoists it to a module-level diff --git a/src/js_parser/parse/parse_stmt.rs b/src/js_parser/parse/parse_stmt.rs index 3990fa9b8f2..53cc777d582 100644 --- a/src/js_parser/parse/parse_stmt.rs +++ b/src/js_parser/parse/parse_stmt.rs @@ -32,10 +32,9 @@ use js_ast::expr::EFlags; type Result = core::result::Result; // Zig: `pub fn ParseStmt(comptime ts, comptime jsx, comptime scan_only) type { return struct {...} }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. The 25+ per-token `t_*` helpers are private; only `parse_stmt` is -// surfaced. Round-G un-gated the simpler `t_*` bodies; phase-d ported the remaining -// `t_export`/`t_import`/fallthrough bodies inline (the `_draft_heavy` staging mod is gone). +// surfaced. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { // PORT NOTE on `#[inline]` / `#[inline(never)]` / `#[cold]` annotations across the `t_*` arms: diff --git a/src/js_parser/parse/parse_suffix.rs b/src/js_parser/parse/parse_suffix.rs index 74eb23e3eee..ff633a25296 100644 --- a/src/js_parser/parse/parse_suffix.rs +++ b/src/js_parser/parse/parse_suffix.rs @@ -17,9 +17,9 @@ use bun_ast::op::Level; use bun_ast::{self as js_ast, E, Expr, ExprData, Op, OpCode, OptionalChain}; // Zig: `fn ParseSuffix(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. The 50+ per-token `t_*` helpers are private; only `parse_suffix` is -// surfaced. Round-G un-gates the per-token bodies (same JsxT pattern as parseStmt.rs). +// surfaced. #[derive(Clone, Copy, PartialEq, Eq)] enum Continuation { diff --git a/src/js_parser/parse/parse_typescript.rs b/src/js_parser/parse/parse_typescript.rs index 0bb744766b4..11aa49a894d 100644 --- a/src/js_parser/parse/parse_typescript.rs +++ b/src/js_parser/parse/parse_typescript.rs @@ -34,7 +34,7 @@ fn clone_ts_member_data(d: &TSNamespaceMemberData) -> TSNamespaceMemberData { } // Zig: `pub fn ParseTypescript(comptime ...) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { diff --git a/src/js_parser/parser.rs b/src/js_parser/parser.rs index 9a0a814a35a..1a2d25ecf4e 100644 --- a/src/js_parser/parser.rs +++ b/src/js_parser/parser.rs @@ -12,16 +12,6 @@ use bun_core::Output; use bun_wyhash::Wyhash; // Re-exports (mirrors the Zig `pub const X = @import(...)` block at the bottom). -// Round-C: stub the still-gated submodules so the helper *types* in this file -// compile; the real bodies arrive in rounds D/E. -#[allow(non_snake_case)] -pub mod ConvertESMExportsForHmr { - pub type Ctx = (); -} -#[allow(non_snake_case)] -pub mod ImportScanner { - pub type State = (); -} pub use bun_paths::fs; /// `bun_options_types` is missing several items P.rs/Parser.rs reference @@ -620,7 +610,7 @@ pub type RuntimeNames = Runtime::Names; pub use crate::p::{NewParser, P}; pub use bun_collections::StringHashMap as StringHashMapRe; // TODO(port): name collision with `StringHashMap` re-export -// NOTE(b0): `pub use bun_js_printer as js_printer;` removed — js_printer is same-tier mutual +// NOTE: `pub use bun_js_printer as js_printer;` removed — js_printer is same-tier mutual // (js_printer depends on js_parser). Downstream callers import bun_js_printer directly. pub use bun_ast as js_ast; diff --git a/src/js_parser/repl_transforms.rs b/src/js_parser/repl_transforms.rs index 267f028e932..8d0d9bc8ee3 100644 --- a/src/js_parser/repl_transforms.rs +++ b/src/js_parser/repl_transforms.rs @@ -15,7 +15,7 @@ use bun_ast::stmt::Data as StmtData; use bun_ast::{B, Binding, E, Expr, ExprNodeList, G, S, Stmt}; // Zig: `pub fn ReplTransforms(comptime P: type) type { return struct { ... } }` -// — file-split mixin pattern. Round-D lowered to direct `impl P` block. +// — file-split mixin pattern, lowered to a direct `impl P` block. use crate::p::P; diff --git a/src/js_parser/scan/scan_imports.rs b/src/js_parser/scan/scan_imports.rs index 0f392785aa8..d13c94eaee0 100644 --- a/src/js_parser/scan/scan_imports.rs +++ b/src/js_parser/scan/scan_imports.rs @@ -656,7 +656,6 @@ impl<'a> ImportScanner<'a> { // But only if it's anonymous // PORT NOTE: comptime `P != bun.bundle_v2.AstBuilder` check elided — // this monomorphization is the parser `P` only (see fn-level TODO). - // blocked_on: P::module_exports gated (reconciler-6 re-gate in P.rs) if !HOT_MODULE_RELOADING_TRANSFORMATIONS && will_transform_to_common_js { let expr = core::mem::take(&mut st.value).to_expr(); // Arena allocation that persists in the AST. diff --git a/src/js_parser/scan/scan_side_effects.rs b/src/js_parser/scan/scan_side_effects.rs index f7b61bbaf66..0224d707c68 100644 --- a/src/js_parser/scan/scan_side_effects.rs +++ b/src/js_parser/scan/scan_side_effects.rs @@ -7,9 +7,9 @@ use bun_ast::symbol; use bun_ast::{self, Binding, E, Expr, ExprData, G, Op, Stmt, StmtData, StoreRef}; use bun_collections::VecExt; -// PORT NOTE: round-E un-gate. SideEffects in Zig is an enum with associated fns that -// take `p: anytype`. Round-E converts the unbounded `

` generic to concrete -// `P<'a, TS, SCAN>`. Method bodies gated; the `Result` type and enum surface are real. +// PORT NOTE: SideEffects in Zig is an enum with associated fns that take +// `p: anytype`. The Rust port replaces the unbounded `

` generic with the +// concrete `P<'a, TS, SCAN>`. #[repr(u8)] // Zig: enum(u1) — Rust has no u1 repr; u8 is the smallest #[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] diff --git a/src/js_parser/visit/mod.rs b/src/js_parser/visit/mod.rs index 0e3e0ff6ce8..0e732dc419c 100644 --- a/src/js_parser/visit/mod.rs +++ b/src/js_parser/visit/mod.rs @@ -39,7 +39,7 @@ use core::ptr::NonNull; type ListManaged<'bump, T> = BumpVec<'bump, T>; // Zig: `pub fn Visit(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { @@ -706,8 +706,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O } } - // PORT NOTE: P::stmts_to_single_stmt is ``-gated (P.rs:6267, blocked on - // S::Block Default). Inline a local copy until that un-gates. + // Local duplicate of `P::stmts_to_single_stmt` (p.rs). fn stmts_to_single_stmt_(&mut self, loc: bun_ast::Loc, stmts: &'a mut [Stmt]) -> Stmt { if stmts.is_empty() { return Stmt { diff --git a/src/js_parser/visit/visit_binary.rs b/src/js_parser/visit/visit_binary.rs index dece2316d35..4761b370276 100644 --- a/src/js_parser/visit/visit_binary.rs +++ b/src/js_parser/visit/visit_binary.rs @@ -14,7 +14,7 @@ use bun_ast::{ // PORT NOTE: The Zig `CreateBinaryExpressionVisitor(comptime ts, comptime jsx, comptime scan_only) type` // returned an anonymous namespace struct whose only public item was `BinaryExpressionVisitor`. -// Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so `BinaryExpressionVisitor` carries +// `const JSX: JSXTransformType` was lowered to `J: JsxT`, so `BinaryExpressionVisitor` carries // the parser generics directly. // Diff readers should map: // Zig: CreateBinaryExpressionVisitor(TS, JSX, SCAN).BinaryExpressionVisitor diff --git a/src/js_parser/visit/visit_expr.rs b/src/js_parser/visit/visit_expr.rs index 1d8d0a2a2c9..a03d0fbd499 100644 --- a/src/js_parser/visit/visit_expr.rs +++ b/src/js_parser/visit/visit_expr.rs @@ -38,7 +38,7 @@ use js_ast::ExprTag as Tag; use js_ast::OpCode as Op; // Zig: `pub fn VisitExpr(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. The 25+ per-variant `e_*` helpers are private; only `visit_expr` / // `visit_expr_in_out` are surfaced. @@ -550,8 +550,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O // TODO(port): jsxChildrenKeyData in Zig is a mutable `var` of `Expr.Data` // pointing at `Prefill.String.Children`. ExprData::EString wants a - // `StoreRef` (arena-backed) so a process-static won't compile (see - // P.rs `` ~7552). Allocate via `p.new_expr` from the const + // `StoreRef` (arena-backed) so a process-static won't compile. + // Allocate via `p.new_expr` from the const // `prefill::string::CHILDREN` instead — small extra alloc. // PERF(port): was process-static — profile if it shows up on a hot path let children_key = p.new_expr(prefill::string::CHILDREN, expr.loc); diff --git a/src/js_parser/visit/visit_stmt.rs b/src/js_parser/visit/visit_stmt.rs index 0c900fa2fda..d85d6b51676 100644 --- a/src/js_parser/visit/visit_stmt.rs +++ b/src/js_parser/visit/visit_stmt.rs @@ -67,9 +67,9 @@ fn list_to_stmts<'a>(list: StmtList<'a>) -> StmtNodeList { } // Zig: `pub fn VisitStmt(comptime ts, comptime jsx, comptime scan_only) type { return struct { ... } }` -// — file-split mixin pattern. Round-C lowered `const JSX: JSXTransformType` → `J: JsxT`, so this is +// — file-split mixin pattern. `const JSX: JSXTransformType` was lowered to `J: JsxT`, so this is // a direct `impl P` block. The 30+ per-variant `s_*` helpers are private; only -// `visit_and_append_stmt` is surfaced. Full draft body preserved under mod _draft below. +// `visit_and_append_stmt` is surfaced. impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_ONLY> { // Thin alias of `current_scope_mut()` kept for local readability. diff --git a/src/js_printer/lib.rs b/src/js_printer/lib.rs index 5bbfc8e4317..b67ed05be6f 100644 --- a/src/js_printer/lib.rs +++ b/src/js_printer/lib.rs @@ -6743,9 +6743,6 @@ pub mod __gated_printer { }; self.print_decls(keyword, decls, ExprFlag::none(), tlm); self.print_semicolon_after_statement(); - // TODO(port): bun_ast::runtime::Imports::__export — the - // full `runtime.rs` is ``-gated upstream; the active - // `parser.rs::Runtime::Imports` stub is a fieldless unit struct. if REWRITE_ESM_TO_CJS && is_export && !decls.is_empty() { // PORT NOTE: Zig stored `?GeneratedSymbol`; the Rust `runtime::Imports` diff --git a/src/jsc/AbortSignal.rs b/src/jsc/AbortSignal.rs index c99577f6515..4651caa4807 100644 --- a/src/jsc/AbortSignal.rs +++ b/src/jsc/AbortSignal.rs @@ -260,10 +260,10 @@ impl AbortReason { } } - // PORT NOTE (phase-d): `to_body_value_error` reaches into - // `bun_runtime::webcore::body::value::ValueError` (forward dep on - // `bun_runtime`). The conversion is trivial and is reconstructed at the - // call-site in `bun_runtime` once that tier un-gates. + // PORT NOTE: Zig `AbortReason.toBodyValueError` returned + // `webcore::Body::ValueError`, which lives in `bun_runtime` (a crate that + // depends on `bun_jsc`). The conversion is trivial and is reconstructed at + // the call sites in `bun_runtime` rather than inverting the crate DAG here. } // ────────────────────────────────────────────────────────────────────────── diff --git a/src/jsc/BuildMessage.rs b/src/jsc/BuildMessage.rs index 168d2a776ff..fb41acdbc69 100644 --- a/src/jsc/BuildMessage.rs +++ b/src/jsc/BuildMessage.rs @@ -7,7 +7,7 @@ use crate::{ }; #[crate::JsClass] // codegen: JSBuildMessage (toJS / fromJS / fromJSDirect wired by derive) -// R-2 (`sharedThis`): every JS-facing host-fn takes `&self`; the only field +// `sharedThis`: every JS-facing host-fn takes `&self`; the only field // mutated post-construction (`logged`, flipped by `VirtualMachine::print_error_*`) // is `Cell` so re-entrant JS cannot stack two `&mut` to the same `m_ctx`. pub struct BuildMessage { diff --git a/src/jsc/Cargo.toml b/src/jsc/Cargo.toml index 6b4013a535b..051c2f353a4 100644 --- a/src/jsc/Cargo.toml +++ b/src/jsc/Cargo.toml @@ -38,7 +38,7 @@ bun_event_loop.workspace = true bun_hash.workspace = true bun_http.workspace = true bun_http_types.workspace = true -# TODO(b1): bun_http_jsc has a forward-dep on bun_jsc; cannot depend on it here (cycle). Gate usages. +# bun_http_jsc has a forward-dep on bun_jsc; cannot depend on it here (cycle). Gate usages. bun_install.workspace = true bun_io.workspace = true bun_js_parser.workspace = true diff --git a/src/jsc/HTTPServerAgent.rs b/src/jsc/HTTPServerAgent.rs index f5a3d751191..1ee15ccbe35 100644 --- a/src/jsc/HTTPServerAgent.rs +++ b/src/jsc/HTTPServerAgent.rs @@ -42,14 +42,13 @@ impl HTTPServerAgent { // #region Events // - // PORT NOTE (phase-d): `notify_server_started` / `notify_server_stopped` / - // `notify_server_routes_updated` reach into `bun_jsc::api::AnyServer` and - // `ServerConfig::RouteDeclaration`, which live in `bun_runtime` (forward - // dep). The C++ side only needs `Bun__HTTPServerAgent__setEnabled` for - // linkage; the per-event notifiers are called from Rust → C++ (FFI decls - // below) and are wired from `bun_runtime` once that tier un-gates. The - // event-body Zig ports are preserved in HTTPServerAgent.zig and will land - // when `AnyServer` is reachable. + // PORT NOTE: `notify_server_started` / `notify_server_stopped` / + // `notify_server_routes_updated` build their payloads from `AnyServer` and + // `ServerConfig::RouteDeclaration`, which live in `bun_runtime` (a crate + // that depends on `bun_jsc`). The C++ side only needs + // `Bun__HTTPServerAgent__setEnabled` for linkage; the per-event notifiers + // call through the FFI decls below from `src/runtime/server/mod.rs:: + // http_server_agent` rather than inverting the crate DAG here. // #endregion } diff --git a/src/jsc/ResolveMessage.rs b/src/jsc/ResolveMessage.rs index bd994a3bb38..e4f557c6150 100644 --- a/src/jsc/ResolveMessage.rs +++ b/src/jsc/ResolveMessage.rs @@ -9,7 +9,7 @@ use crate::{ CallFrame, JSGlobalObject, JSValue, JsClass, JsResult, StringJsc as _, ZigStringJsc as _, }; -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`. `msg` and +// Host-fn re-entrancy: every JS-exposed method takes `&self`. `msg` and // `referrer` are read-only after construction; only `logged` is mutated // post-wrap (by `VirtualMachine::print_error_like_object` via the JSCell ptr), // so it gets `Cell`. diff --git a/src/jsc/SystemError.rs b/src/jsc/SystemError.rs index 2787aed62cc..a5fa495aedc 100644 --- a/src/jsc/SystemError.rs +++ b/src/jsc/SystemError.rs @@ -58,7 +58,7 @@ impl From for SystemError { } /// `union(enum) { err: SystemError, result: Result }` — collapsed to a -/// `core::result::Result` alias in Phase F so callers get `?` for free. +/// `core::result::Result` alias so callers get `?` for free. pub type Maybe = core::result::Result; // TODO(port): move to jsc_sys diff --git a/src/jsc/VirtualMachine.rs b/src/jsc/VirtualMachine.rs index 0ee5e0b90a1..0522e86ca9a 100644 --- a/src/jsc/VirtualMachine.rs +++ b/src/jsc/VirtualMachine.rs @@ -148,7 +148,8 @@ pub struct VirtualMachine { // self-referential and cannot carry `<'a>`, so we erase to `'static` and the // owner guarantees the borrowed `log` outlives the VM (see `init`). pub transpiler: Transpiler<'static>, - // TODO(b2-cycle): `bun_watcher` is `ImportWatcher` from hot_reloader.rs (gated sibling). + // TODO(port): widen to `*mut crate::hot_reloader::ImportWatcher` (sibling + // module, no crate cycle); see `bun_watcher_ptr` for the cast. pub bun_watcher: *mut c_void, pub console: *mut crate::console_object::ConsoleObject, // TODO(port): lifetime — LIFETIMES.tsv says BORROW_PARAM (`&'a mut bun_ast::Log`); @@ -168,7 +169,7 @@ pub struct VirtualMachine { pub overridden_main: crate::strong::Optional, pub entry_point: bun_bundler::entry_points::ServerEntryPoint, pub origin: bun_url::URL<'static>, - // TODO(b2-cycle): `node_fs` is `Option>`. + // TODO(port): `node_fs` is `Option>`. pub node_fs: Option<*mut c_void>, /// Opaque per-VM `bun_runtime` state (boxed `timer::All` + /// `Body::Value::HiveAllocator` + …). Set by @@ -193,13 +194,13 @@ pub struct VirtualMachine { // `transpiler.resolver.standalone_module_graph` without a downcast. pub standalone_module_graph: Option<&'static dyn bun_resolver::StandaloneModuleGraph>, pub smol: bool, - // TODO(b2-cycle): `dns_result_order` is `bun_runtime::api::dns::Resolver::Order`. + // TODO(port): `dns_result_order` is `bun_runtime::api::dns::Resolver::Order`. pub dns_result_order: u8, pub cpu_profiler_config: Option, pub heap_profiler_config: Option, pub counters: Counters, - // TODO(b2-cycle): `hot_reload` is `bun_runtime::cli::Command::HotReload`. + // TODO(port): `hot_reload` is `bun_runtime::cli::Command::HotReload`. pub hot_reload: u8, pub jsc_vm: *mut VM, @@ -213,7 +214,13 @@ pub struct VirtualMachine { pub exit_handler: ExitHandler, pub default_tls_reject_unauthorized: Option, - // TODO(b2-cycle): `default_verbose_fetch` is `Option`. + // Spec field is `Option`. Kept as `Option` + // (storing the enum's `repr(u8)` ordinal) so the zero-fill in `init` reads + // as `None`: `HTTPVerboseLevel` is a 3-variant `#[repr(u8)]` enum, so + // `Option` uses a niche and all-zero bytes decode as + // `Some(HTTPVerboseLevel::None)`, silently skipping the env-var lookup. + // Converting to the enum type would need an explicit `write(None)` in the + // `addr_of_mut!` init block, like `default_tls_reject_unauthorized` above. pub default_verbose_fetch: Option, /// Do not access this field directly! It exists in the VirtualMachine struct so @@ -231,7 +238,8 @@ pub struct VirtualMachine { pub had_errors: bool, pub macros: MacroMap, - // TODO(b2-cycle): `MacroEntryPoint` from `bun_bundler::entry_points` (gated). + // TODO(port): widen value type to `*mut bun_bundler::entry_points::MacroEntryPoint` + // (already a direct dep). pub macro_entry_points: bun_collections::ArrayHashMap, pub macro_mode: bool, pub no_macros: bool, @@ -285,7 +293,6 @@ pub struct VirtualMachine { pub is_handling_uncaught_exception: bool, pub exit_on_uncaught_exception: bool, - // TODO(b2): `modules` is `ModuleLoader::AsyncModule::Queue` (AsyncModule.rs gated). pub modules: crate::async_module::Queue, pub aggressive_garbage_collection: GCLevel, @@ -361,7 +368,7 @@ unsafe extern "C" { safe fn Zig__GlobalObject__destructOnExit(global: &JSGlobalObject); } -/// `hot_reload` is stored as `u8` (TODO(b2-cycle): widen to +/// `hot_reload` is stored as `u8` (TODO(port): widen to /// `bun_options_types::context::HotReload`). Mirror the Zig enum ordinals so /// the un-gated accessors below can compare without naming the type. pub const HOT_RELOAD_NONE: u8 = 0; @@ -1433,10 +1440,10 @@ impl VirtualMachine { if self.hot_reload != HOT_RELOAD_HOT { return None; } - // TODO(b2-cycle): spec lazy-inits via `RareData::hotMap(allocator)`; - // that accessor is gated in `rare_data.rs::_accessor_body`. Until it - // un-gates, return whatever the field already holds (callers that need - // the lazy-init path are themselves gated on `bun_runtime`). + // TODO(port): spec lazy-inits via `RareData::hotMap(allocator)` + // (now `crate::rare_data::RareData::hot_map`); wire that in. For now + // return whatever the field already holds — the callers that need the + // lazy-init path live in `bun_runtime`. self.rare_data.as_deref_mut()?.hot_map.as_mut() } @@ -1629,7 +1636,7 @@ pub struct RuntimeHooks { pub print_exception: fn(vm: &mut VirtualMachine, value: JSValue, exception_list: Option<&mut ExceptionList>), /// `vm.timer.insert(&mut event_loop_timer)` — `Timer::All` lives in - /// `bun_runtime::RuntimeState` (b2-cycle); low-tier callers + /// `bun_runtime::RuntimeState` (forward-dep on `bun_jsc`); low-tier callers /// (`AbortSignal::Timeout`) reach it through this slot. pub timer_insert: unsafe fn( vm: *mut VirtualMachine, @@ -1644,12 +1651,12 @@ pub struct RuntimeHooks { /// `SSL_CTX*`, shared by every `tls: true` outbound connection that didn't /// supply explicit options. The storage slot lives in `RareData` /// (low-tier) but population reaches `RuntimeState.ssl_ctx_cache` - /// (`bun_runtime`, b2-cycle); spec rare_data.zig:741. + /// (`bun_runtime`); spec rare_data.zig:741. pub default_client_ssl_ctx: unsafe fn(vm: *mut VirtualMachine) -> *mut uws::SslCtx, /// `RareData.sslCtxCache().getOrCreateOpts(opts, &err)` — per-VM /// digest-keyed weak `SSL_CTX*` cache. Returns a +1 ref or `None` on /// BoringSSL rejection (`err` populated). `SSLContextCache` lives in - /// `bun_runtime::RuntimeState` (b2-cycle). + /// `bun_runtime::RuntimeState` (forward-dep on `bun_jsc`). pub ssl_ctx_cache_get_or_create: unsafe fn( vm: *mut VirtualMachine, opts: uws::SocketContext::BunSocketContextOptions, @@ -1842,7 +1849,7 @@ impl VirtualMachine { impl VirtualMachine { /// `vm.timer.insert(timer)` — dispatches through `RuntimeHooks` because - /// `Timer::All` lives in `bun_runtime` (b2-cycle). + /// `Timer::All` lives in `bun_runtime` (forward-dep on `bun_jsc`). /// /// # Safety /// `timer` must point at a live `EventLoopTimer` not currently linked into @@ -2230,9 +2237,9 @@ impl VirtualMachine { /// `eventLoop().autoTickActive()` — like [`auto_tick`](Self::auto_tick) /// but only sleeps in the uSockets loop while it has active handles - /// (spec event_loop.zig:456). The real body lives in `event_loop.rs` - /// behind `` until the b2-cycle (`Timer::All`) breaks; until - /// then route through the same `auto_tick` hook so drain loops in + /// (spec event_loop.zig:456). The real body lives in `event_loop.rs`; + /// `Timer::All` lives in `bun_runtime` so route through the same + /// `auto_tick` hook so drain loops in /// `on_before_exit` / `bun_main` still make forward progress. #[inline] pub fn auto_tick_active(&mut self) { @@ -2722,7 +2729,7 @@ pub struct Options { pub env_loader: Option>>, pub store_fd: bool, pub smol: bool, - // TODO(b2-cycle): real type is `bun_runtime::api::dns::Resolver::Order`. + // TODO(port): real type is `bun_runtime::api::dns::Resolver::Order`. pub dns_result_order: u8, /// `--print` needs the result from evaluating the main module. pub eval: bool, @@ -3059,8 +3066,8 @@ impl VirtualMachine { pub fn get_verbose_fetch(&mut self) -> bun_http::HTTPVerboseLevel { use bun_http::HTTPVerboseLevel as L; if let Some(v) = self.default_verbose_fetch { - // PORT NOTE: field is `Option` until the b2-cycle widens it; - // map ordinals back. + // Field stores the `repr(u8)` ordinal (see field decl for why); + // map it back to the enum. return match v { 1 => L::Headers, 2 => L::Curl, @@ -3479,7 +3486,7 @@ impl VirtualMachine { /// attributes and forces a real reload on every `.get()` — no raw-pointer /// laundering needed for the condition. pub fn wait_for(&mut self, cond: &core::cell::Cell) { - // R-2 noalias mitigation (PORT_NOTES_PLAN R-2; precedent + // noalias mitigation (see bun_ptr::LaunderedSelf; precedent // `b818e70e1c57` NodeHTTPResponse::cork): `&mut self` is // LLVM-`noalias`, but `tick()/auto_tick()` re-enter JS which reaches // `self` again via `VirtualMachine::get()`. Launder `self` so each @@ -4204,8 +4211,9 @@ impl VirtualMachine { let mut log = bun_ast::Log::default(); jsc_vm.log = NonNull::new(&raw mut log); jsc_vm.transpiler.resolver.log = NonNull::from(&mut log); - // TODO(b2-cycle): `transpiler.linker.log` / `resolver.package_manager.log` - // — gated bundler fields. + // TODO(port): Zig also re-points `transpiler.linker.log` and + // `resolver.package_manager.log`; the latter sits behind the + // `AutoInstaller` trait object so it needs a vtable hook. // PORT NOTE: Zig `defer { restore old_log }` — fires on every exit // (including `?` from `ResolveMessage::create` below), so the VM's // `log` cannot be left pointing at the dropped stack `log`. Hand-roll @@ -4771,7 +4779,7 @@ impl VirtualMachine { if value.js_type() == jsc::JSType::DOMWrapper { // `as_class_ref` is the audited `as_::() → &T` backref-deref; - // R-2: shared borrow — `logged` is `Cell`. + // Shared borrow — `logged` is `Cell`. if let Some(build_error) = value.as_class_ref::() { if !build_error.logged.get() { if self.had_errors { diff --git a/src/jsc/array_buffer.rs b/src/jsc/array_buffer.rs index bbda76af8a7..644739a512f 100644 --- a/src/jsc/array_buffer.rs +++ b/src/jsc/array_buffer.rs @@ -1009,7 +1009,7 @@ impl MarkedArrayBuffer { // Deallocators // ────────────────────────────────────────────────────────────────────────── -// `no_mangle` dropped: 0 C++ refs (phase_c_exports.rs mention is a comment). +// `no_mangle` dropped: 0 C++ refs (link_exports.rs mention is a comment). #[allow(non_upper_case_globals)] pub use bun_alloc::c_thunks::mi_free_bytes as MarkedArrayBuffer_deallocator; diff --git a/src/jsc/event_loop.rs b/src/jsc/event_loop.rs index 8a9f5e1eea6..009584bb354 100644 --- a/src/jsc/event_loop.rs +++ b/src/jsc/event_loop.rs @@ -457,7 +457,7 @@ impl EventLoop { this_value: JSValue, arguments: &[JSValue], ) { - // R-2 noalias mitigation (see PORT_NOTES_PLAN R-2; precedent + // noalias mitigation (see bun_ptr::LaunderedSelf; precedent // `b818e70e1c57` NodeHTTPResponse::cork): `&mut self` carries LLVM // `noalias`, and `callback.call()` receives nothing derived from // `self`, so LLVM is licensed to forward `self.entered_event_loop_count` @@ -489,7 +489,7 @@ impl EventLoop { this_value: JSValue, arguments: &[JSValue], ) -> JSValue { - // R-2 noalias mitigation — see `run_callback` above. + // noalias re-entry mitigation — see `run_callback` above. let this: *mut Self = core::hint::black_box(core::ptr::from_mut(self)); // SAFETY: `this` is the unique live `EventLoop`; short-lived `&mut`. unsafe { (*this).enter() }; @@ -769,7 +769,7 @@ impl EventLoop { /// observe the post-swap `immediate_tasks` (next-tick immediates), not the /// un-drained current batch (busy-spin hazard, spec Timer.zig:251-256). pub fn tick_immediate_tasks(&mut self, virtual_machine: *mut VirtualMachine) { - // R-2 noalias mitigation (PORT_NOTES_PLAN R-2; precedent + // noalias mitigation (see bun_ptr::LaunderedSelf; precedent // `b818e70e1c57` NodeHTTPResponse::cork): `&mut self` is `noalias`, and // the only thing reaching the `__bun_run_immediate_task` extern call is // `virtual_machine` — a *separate* pointer parameter that LLVM is told diff --git a/src/jsc/host_fn.rs b/src/jsc/host_fn.rs index 2eee649f112..f4784311bdc 100644 --- a/src/jsc/host_fn.rs +++ b/src/jsc/host_fn.rs @@ -507,15 +507,14 @@ pub fn host_fn_internal_props( // `_shared` siblings — `&T` receiver instead of `&mut T`. // // Emitted by `generate-classes.ts` when a `.classes.ts` definition sets -// `sharedThis: true` (R-2 noalias re-entrancy). `&mut T` carries LLVM -// `noalias`, so a host-fn that re-enters JS while holding `&mut self` lets -// the optimiser cache `*self` fields across the FFI call — proven miscompile -// in `NodeHTTPResponse::cork` (b818e70e1c57). `&T` is `readonly`, not -// `noalias`; aliased shared borrows are sound, and the user impl uses -// `Cell`/`JsCell` for any field it mutates. +// `sharedThis: true`. `&mut T` carries LLVM `noalias`, so a host-fn that +// re-enters JS while holding `&mut self` lets the optimiser cache `*self` +// fields across the FFI call — a proven miscompile in `NodeHTTPResponse::cork`. +// `&T` is `readonly`, not `noalias`; aliased shared borrows are sound, and the +// user impl uses `Cell`/`JsCell` for any field it mutates. // -// The `&mut` originals above are kept until every type has migrated -// (Phase 3 of `R-2-design.md` deletes them and drops the `_shared` suffix). +// The `&mut` originals above are kept until every type has migrated; once +// they're all on `sharedThis`, delete them and drop the `_shared` suffix. // ────────────────────────────────────────────────────────────────────────── /// Prototype method (`sharedThis`): `fn(&self, &JSGlobalObject, &CallFrame) -> R`. diff --git a/src/jsc/hot_reloader.rs b/src/jsc/hot_reloader.rs index de3bce70a7c..85d5b19ffa7 100644 --- a/src/jsc/hot_reloader.rs +++ b/src/jsc/hot_reloader.rs @@ -154,7 +154,7 @@ impl HotReloaderCtx for VirtualMachine { fn bun_watcher_mut(&mut self) -> &mut Watcher { // PORT NOTE: Zig's three-way `@TypeOf(this.ctx.bun_watcher)` reflection // collapses here — `VirtualMachine.bun_watcher` is the type-erased - // `*mut ImportWatcher` (TODO(b2-cycle) field comment in + // `*mut ImportWatcher` (TODO(port) field comment in // VirtualMachine.rs), and `getContext` only runs after // `enable_hot_module_reloading` has populated it, so the `.None` arm // is unreachable. @@ -226,7 +226,9 @@ impl HotReloaderCtx for VirtualMachine { ImportWatcher::Hot(w) | ImportWatcher::Watch(w) => &raw mut **w, ImportWatcher::None => unreachable!(), }; - // The VM holds `bun_watcher` type-erased as `*mut c_void` (b2-cycle). + // The VM holds `bun_watcher` type-erased as `*mut c_void`; see the + // `TODO(port)` on the field decl in VirtualMachine.rs to widen it to + // `*mut ImportWatcher` (same crate, no cycle). self.bun_watcher = bun_core::heap::into_raw(iw).cast::(); // Wire the resolver's directory-watch callback at the same time. diff --git a/src/jsc/ipc.rs b/src/jsc/ipc.rs index fdbb22b896f..d4fb36c3796 100644 --- a/src/jsc/ipc.rs +++ b/src/jsc/ipc.rs @@ -139,7 +139,7 @@ impl InternalMsgHolder { pub fn flush(&mut self, global: &JSGlobalObject) -> JsResult<()> { debug_assert!(self.is_ready()); - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `dispatch_unsafe` → `event_loop.run_callback` runs the JS IPC // listener which can re-enter via a fresh `&mut Self` from the // owner's `m_ctx` and write `self.cb` / `self.worker` / diff --git a/src/jsc/rare_data.rs b/src/jsc/rare_data.rs index 6f505d65669..5ca41559b94 100644 --- a/src/jsc/rare_data.rs +++ b/src/jsc/rare_data.rs @@ -862,7 +862,7 @@ impl RareData { } } pub fn close_all_watchers_for_isolation(&mut self) { - // R-2 noalias mitigation (PORT_NOTES_PLAN R-2; precedent + // noalias mitigation (see bun_ptr::LaunderedSelf; precedent // `b818e70e1c57` NodeHTTPResponse::cork): `(w.close)(w.ptr)` is an // opaque fn-pointer call that receives nothing derived from `self`. It // re-enters JS (FSWatcher.close → "close" event), which can call diff --git a/src/jsc/webcore_types.rs b/src/jsc/webcore_types.rs index 624da3d2efa..eaf94126cd7 100644 --- a/src/jsc/webcore_types.rs +++ b/src/jsc/webcore_types.rs @@ -51,7 +51,7 @@ pub enum ClosingState { /// `webcore.Blob` (src/runtime/webcore/Blob.zig:7-52). The `m_ctx` payload of /// the codegen'd `JSBlob` wrapper. /// -/// R-2 (`sharedThis`): every JS-facing host-fn takes `&Blob` (not `&mut Blob`) +/// `sharedThis`: every JS-facing host-fn takes `&Blob` (not `&mut Blob`) /// so re-entrant JS calls cannot stack two `&mut` to the same instance. Fields /// mutated by host-fns are therefore wrapped in `Cell` (Copy scalars) or /// `JsCell` (the non-Copy `store`). `Cell` and `JsCell` are both @@ -202,7 +202,7 @@ impl Blob { unsafe { &*self.content_type.get() } } - /// Borrowed accessor for the `JsCell`-wrapped store. R-2: the field is + /// Borrowed accessor for the `JsCell`-wrapped store. The field is /// interior-mutable so host-fns can take `&self`; this projects back to the /// `Option<&StoreRef>` shape every caller used pre-migration. #[inline] diff --git a/src/jsc_macros/lib.rs b/src/jsc_macros/lib.rs index b599f71d754..410141eeced 100644 --- a/src/jsc_macros/lib.rs +++ b/src/jsc_macros/lib.rs @@ -124,7 +124,7 @@ fn expand_host_fn(args: HostFnArgs, func: ItemFn) -> syn::Result { .first() .is_some_and(|a| matches!(a, FnArg::Receiver(_))); - // R-2 (PORT_NOTES_PLAN): for `&self` receivers, materialise `&*__this` + // noalias re-entry (see bun_ptr::LaunderedSelf): for `&self` receivers, materialise `&*__this` // (NOT `&mut *__this`). A method that calls back into JS can be re-entered // on the same `m_ctx`; holding a `noalias` `&mut Self` across that re-entry // is Stacked-Borrows UB. Such methods take `&self` and route mutation @@ -215,7 +215,7 @@ fn expand_host_fn(args: HostFnArgs, func: ItemFn) -> syn::Result { }, quote! { ::bun_jsc::JSValue }, quote! { - // SAFETY: see `Method`. `&self` getters get `&*` (R-2); `&mut + // SAFETY: see `Method`. `&self` getters get `&*`; `&mut // self` getters that lazily mutate keep `&mut *`. #this_reborrow let __g = unsafe { &*__global }; diff --git a/src/options_types/context.rs b/src/options_types/context.rs index 6f8eb3c3649..bd2095da4cd 100644 --- a/src/options_types/context.rs +++ b/src/options_types/context.rs @@ -424,9 +424,9 @@ pub struct TestOptions { pub test_filter_pattern: Option>, /// `?*bun.jsc.RegularExpression` — typed as opaque to keep this file free /// of `jsc/` references. Read via `test_filter_regex()`. - // FORWARD_DECL(b0): erased bun_jsc::RegularExpression to break the T3→T6 - // back-edge. High tier owns construction/destruction; this field only - // stores the pointer. LIFETIMES.tsv says OWNED, so the high-tier setter is + // Erased `bun_jsc::RegularExpression` to avoid a `bun_options_types` → + // `bun_jsc` dependency edge. The higher-tier crate owns construction and + // destruction; this field only stores the pointer, and the setter is // responsible for freeing any previous value. pub test_filter_regex: Option>, // SAFETY: erased *mut bun_jsc::RegularExpression pub max_concurrency: u32, diff --git a/src/options_types/schema.rs b/src/options_types/schema.rs index 50b63de0630..16803ef0cbf 100644 --- a/src/options_types/schema.rs +++ b/src/options_types/schema.rs @@ -442,7 +442,7 @@ pub mod api { internal = 8, } - // ─── peechy batch 2: hand-expanded for downstream wfs ──────────────── + // ─── hand-expanded peechy schema types ─────────────────────────────── // Jsx / JsxRuntime / StringMap / EnvConfig / LoadedEnvConfig / // LoadedRouteConfig / RouteConfig / FrameworkEntryPoint{,Type,Map,Message} / // PackagesMode / CssInJsBehavior / LoaderMap / LoadedFramework. diff --git a/src/ptr/lib.rs b/src/ptr/lib.rs index 908a819acb5..65ca95030f0 100644 --- a/src/ptr/lib.rs +++ b/src/ptr/lib.rs @@ -276,8 +276,8 @@ pub unsafe fn detach_lifetime_mut<'a, T: ?Sized>(r: &mut T) -> &'a mut T { } /// Marker trait for types whose `&mut self` methods launder `self` through -/// `core::hint::black_box` (PORT_NOTES_PLAN **R-2**) before dispatching a -/// re-entrant parent/user callback, then reborrow via [`LaunderedSelf::r`]. +/// `core::hint::black_box` before dispatching a re-entrant parent/user +/// callback, then reborrow via [`LaunderedSelf::r`]. /// /// Zig has no `noalias` on `*Self`, so the original `.zig` just writes /// `this.*` directly; this trait is the Rust-port-only artifact that makes the @@ -294,7 +294,7 @@ pub unsafe fn detach_lifetime_mut<'a, T: ?Sized>(r: &mut T) -> &'a mut T { /// sole live borrow at the point of use — never held across the next /// parent/user dispatch. pub unsafe trait LaunderedSelf: Sized { - /// Reborrow a PORT_NOTES_PLAN R-2 laundered self-pointer. + /// Reborrow a `black_box`-laundered self-pointer. /// /// `this` is the `black_box`-laundered address of an outer `&mut self`; /// the laundered raw pointer carries no `noalias`, so the compiler may not @@ -653,7 +653,7 @@ unsafe impl Sync for BackRef {} pub trait AsCtxPtr { /// `self`'s address as `*mut Self` for deferred-task / scopeguard / /// `ref_guard` ctx slots. The closures/trampolines deref it as shared - /// (`&*p`) — every method they reach is `&self` post-R-2, so no write + /// (`&*p`) — every method they reach is `&self`, so no write /// provenance is required; the `*mut` spelling is purely to match the /// existing `DerefOnDrop` / `HasAutoFlush` / `RefCount` ABI. #[inline(always)] diff --git a/src/ptr/ref_count.rs b/src/ptr/ref_count.rs index 7c99f64846d..04731e5617f 100644 --- a/src/ptr/ref_count.rs +++ b/src/ptr/ref_count.rs @@ -16,7 +16,7 @@ use core::sync::atomic::{AtomicU32, Ordering}; use bun_core::StoredTrace; use bun_core::ThreadLock; -// PORT NOTE(b0): was `bun_collections::{ArrayHashMap, HashMap}` (T1 → upward). +// PORT NOTE: was `bun_collections::{ArrayHashMap, HashMap}` (T1 → upward). // Debug-only diagnostic storage; std HashMap drops insertion order for `frees` // which is acceptable for leak reports. use std::collections::HashMap; @@ -1099,7 +1099,7 @@ pub struct DebugData { #[cfg(debug_assertions)] impl DebugData { - // PORT NOTE(b0): was `pub const EMPTY` — std HashMap::new() is non-const. + // PORT NOTE: was `pub const EMPTY` — std HashMap::new() is non-const. pub fn empty() -> Self { Self { magic: MAGIC_VALID, diff --git a/src/resolve_builtins/Cargo.toml b/src/resolve_builtins/Cargo.toml index e5a297cefa5..65ccfe75c7f 100644 --- a/src/resolve_builtins/Cargo.toml +++ b/src/resolve_builtins/Cargo.toml @@ -19,7 +19,8 @@ enum-map.workspace = true enumset.workspace = true libc.workspace = true bitflags.workspace = true -# TODO(b1): bun_bundler dep removed — crate does not compile yet; re-add when options::Target lands. +# bun_bundler intentionally not depended on — bun_bundler already depends on +# this crate, so adding it here would create a cycle. # bun_bundler.workspace = true bun_options_types.workspace = true bun_ast.workspace = true diff --git a/src/resolver/options.rs b/src/resolver/options.rs index dab1bd9fd3c..026b4bd430c 100644 --- a/src/resolver/options.rs +++ b/src/resolver/options.rs @@ -192,10 +192,9 @@ pub mod bundle_options { } } -// B-3 UNIFIED: FORWARD_DECL dropped — canonical type moved down to -// `bun_options_types::bundle_enums::ForceNodeEnv`. Re-exported so the -// `options::ForceNodeEnv` / `bundle_options::ForceNodeEnv` paths and the -// field on the local `BundleOptions` subset stay source-compatible. +// Canonical type lives in `bun_options_types::bundle_enums::ForceNodeEnv`. +// Re-exported so the `options::ForceNodeEnv` / `bundle_options::ForceNodeEnv` +// paths and the field on the local `BundleOptions` subset stay source-compatible. pub use ::bun_options_types::ForceNodeEnv; /// Port of `bundler/options.zig` `Framework` (Bake) — only the diff --git a/src/resolver/resolver.rs b/src/resolver/resolver.rs index d8d2b3a7069..4e92edfa732 100644 --- a/src/resolver/resolver.rs +++ b/src/resolver/resolver.rs @@ -1576,7 +1576,7 @@ impl<'a> Resolver<'a> { if let Some(f) = self.opts.framework.as_ref() { if let Some(mod_) = f.built_in_modules.get(import_path) { match mod_ { - // TYPE_ONLY(b0): BuiltInModule relocated bun_runtime::bake::framework → bun_options_types (T3) + // `BuiltInModule` lives in `bun_options_types` (relocated from `bun_runtime::bake::framework`). bun_options_types::BuiltInModule::Code(_) => { return Ok(Result { import_kind: kind, diff --git a/src/router/lib.rs b/src/router/lib.rs index 2cbd5bd3062..994ccce2598 100644 --- a/src/router/lib.rs +++ b/src/router/lib.rs @@ -365,7 +365,7 @@ struct RouteIndex { hash: u32, } -// TODO(b2-blocked): bun_collections::MultiArrayElement derive — proc-macro not +// TODO(port): bun_collections::MultiArrayElement derive — proc-macro not // yet landed, so MultiArrayList can't expose per-field column // accessors. Hand-rolled SoA struct (semantically identical to Zig's // MultiArrayList(RouteIndex)) until the derive exists. @@ -1024,7 +1024,7 @@ pub struct Route { pub has_uppercase: bool, } -// TODO(b1): inherent assoc types unstable; module-level alias instead. +// TODO(port): inherent assoc types unstable; module-level alias instead. pub type RoutePtr = TinyPtr; impl Route { @@ -1582,7 +1582,7 @@ pub mod pattern { let segment = &path_[0..path_.iter().position(|&b| b == b'/').unwrap_or(path_.len())]; if !str_.eql_bytes(segment) { - params.truncate(0); // TODO(b1): was shrink_retaining_capacity (MultiArrayList API) + params.truncate(0); // TODO(port): was shrink_retaining_capacity (MultiArrayList API) return false; } @@ -1605,7 +1605,7 @@ pub mod pattern { path_ = &path_[i + 1..]; if pattern.is_end(name) { - params.truncate(0); // TODO(b1): was shrink_retaining_capacity (MultiArrayList API) + params.truncate(0); // TODO(port): was shrink_retaining_capacity (MultiArrayList API) return false; } @@ -1931,7 +1931,7 @@ pub mod pattern { pub kind: Tag, } - // TODO(b1): thiserror not in deps; manual Display/Error impl. + // TODO(port): thiserror not in deps; manual Display/Error impl. #[derive(strum::IntoStaticStr, Debug, Clone, Copy)] pub enum PatternParseError { CatchAllMustBeAtTheEnd, diff --git a/src/runtime/api/HashObject.rs b/src/runtime/api/HashObject.rs index 86241ecaac2..1b0c7bf0a86 100644 --- a/src/runtime/api/HashObject.rs +++ b/src/runtime/api/HashObject.rs @@ -190,10 +190,10 @@ pub fn adler32(global: &JSGlobalObject, frame: &CallFrame) -> JsResult hash_wrap::(global, frame) } -// phase-d: explicit export name — bare `#[host_fn]` defaults the C symbol to -// the Rust ident (`crc32`), which collides with `node_zlib_binding::crc32`'s -// shim. The shim ident (`__jsc_host_crc32`) is unchanged, so `create()` below -// keeps resolving. +// Explicit export name — bare `#[host_fn]` defaults the C symbol to the Rust +// ident (`crc32`), which collides with `node_zlib_binding::crc32`'s shim. The +// shim ident (`__jsc_host_crc32`) is unchanged, so `create()` below keeps +// resolving. #[bun_jsc::host_fn(export = "Bun__HashObject__crc32")] pub fn crc32(global: &JSGlobalObject, frame: &CallFrame) -> JsResult { hash_wrap::(global, frame) diff --git a/src/runtime/api/JSBundler.rs b/src/runtime/api/JSBundler.rs index d637c4c5bd0..53c62b051bb 100644 --- a/src/runtime/api/JSBundler.rs +++ b/src/runtime/api/JSBundler.rs @@ -1942,7 +1942,7 @@ impl BuildArtifact { #[bun_jsc::host_fn(getter)] pub fn get_size(this: &Self, global_object: &JSGlobalObject) -> JSValue { - // `Blob::get_size` is `&self` post-R-2 (lazy size caches are + // `Blob::get_size` is `&self` (lazy size caches are // Cell-backed inside `Blob`), so a shared borrow is sound here. this.blob.get_size(global_object) } diff --git a/src/runtime/api/JSTranspiler.rs b/src/runtime/api/JSTranspiler.rs index dde52dce2d2..86784fdf5f0 100644 --- a/src/runtime/api/JSTranspiler.rs +++ b/src/runtime/api/JSTranspiler.rs @@ -1179,7 +1179,7 @@ impl Drop for TranspilerStateGuard { } impl JSTranspiler { - // ─── R-2 interior-mutability helpers ───────────────────────────────────── + // ─── Interior-mutability helpers ───────────────────────────────────────── /// `self`'s address as `*mut Self` for `IntrusiveRc::init_ref` and similar /// FFI ctx slots that spell the parameter `*mut`. The only mutation through @@ -1207,8 +1207,8 @@ impl JSTranspiler { /// borrow's lifetime. `Transpiler::parse` may re-enter JS via macros; if /// that JS calls back into a `JSTranspiler` host-fn on *this same instance* /// the inner `Transpiler` is re-borrowed — a pre-existing spec-level hazard - /// (Zig holds a raw `*Transpiler` across the same call) that R-2's - /// outer-struct fix does not address. The R-2 invariant this upholds is + /// (Zig holds a raw `*Transpiler` across the same call) that the noalias-re-entry migration's + /// outer-struct fix does not address. The noalias re-entry invariant this upholds is /// that no `noalias &mut JSTranspiler` is live across that re-entry. #[inline] unsafe fn transpiler_mut(&self) -> &mut Transpiler::Transpiler<'static> { diff --git a/src/runtime/api/bun/Terminal.rs b/src/runtime/api/bun/Terminal.rs index 5e5ccfc0a39..07d8f75e419 100644 --- a/src/runtime/api/bun/Terminal.rs +++ b/src/runtime/api/bun/Terminal.rs @@ -92,7 +92,7 @@ pub mod js { // constructor) and intrusive refcounting (finalize → deref, not heap::take), // neither of which the macro's default hooks support. The C-ABI shims live in // `mod js` above and `extern "C" fn finalize` below. -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim still emits `this: &mut Terminal` — `&mut T` auto-derefs to `&T` // so the impls below compile against either. The @@ -353,7 +353,7 @@ impl Terminal { self.global_this.get() } - // ─── R-2 interior-mutability helpers ───────────────────────────────────── + // ─── Interior-mutability helpers ───────────────────────────────────────── /// Read-modify-write the packed `Cell` through `&self`. #[inline] @@ -390,7 +390,7 @@ impl Terminal { // `writer.parent = …` in `init_terminal`. The Terminal is heap-stable // (`heap::into_raw`) and outlives every reader/writer callback (the // intrusive +1 ref held by the I/O machinery is dropped only after the - // last callback fires). R-2: shared borrow only — bodies take `&self`; + // last callback fires). Shared borrow only — bodies take `&self`; // field writes go through `Cell`/`JsCell`, so re-entrant JS forming a // fresh `&Self` from `m_ctx` aliases soundly. unsafe { &*this } @@ -470,7 +470,7 @@ impl Terminal { this_value: JsCell::new(JsRef::empty()), flags: Cell::new(Flags::empty()), })); - // SAFETY: just allocated, non-null, exclusively owned here. R-2: `&` + // SAFETY: just allocated, non-null, exclusively owned here. `&` // (not `&mut`) — every method below takes `&self`; field writes go // through `Cell`/`JsCell`. let terminal = unsafe { &*terminal }; @@ -1644,7 +1644,7 @@ impl Terminal { } self.update_flags(|f| f.insert(Flags::CLOSED)); - // Close writer (closes write_fd). R-2: `with_mut` borrow is held across + // Close writer (closes write_fd). `with_mut` borrow is held across // the synchronous `on_writer_close` parent callback, but that callback // touches only `flags`/`ref_count` (separate `Cell`s), never `writer`. self.writer.with_mut(|w| w.close()); @@ -1733,7 +1733,7 @@ impl Terminal { // IOReader callbacks pub fn on_reader_done(&self) { bun_output::scoped_log!(Terminal, "onReaderDone"); - // R-2: `&self` (no `noalias`) + `Cell` makes the prior + // `&self` (no `noalias`) + `Cell` makes the prior // `black_box`-launder unnecessary — the post-`call_exit_callback` // `flags` load is a fresh `Cell::get()` that LLVM cannot fold across // the re-entrant JS call (UnsafeCell suppresses the alias assumption). @@ -1754,7 +1754,7 @@ impl Terminal { pub fn on_reader_error(&self, err: sys::Error) { bun_output::scoped_log!(Terminal, "onReaderError: {:?}", err); - // R-2: see `on_reader_done` — `&self` + `Cell` replaces the + // See `on_reader_done` — `&self` + `Cell` replaces the // prior `black_box` launder. // Error - downgrade to weak ref to allow GC // Skip JS interactions if already finalized @@ -1895,7 +1895,7 @@ impl Terminal { fn deinit_and_destroy(this: *mut Terminal) { bun_output::scoped_log!(Terminal, "deinit"); // SAFETY: caller is `deref_()` with ref_count == 0; `this` was heap-allocated. - // R-2: deref as shared — `close_internal` takes `&self` and all field + // Deref as shared — `close_internal` takes `&self` and all field // mutation routes through `Cell`/`JsCell`. let t = unsafe { &*this }; // Set reader/writer done flags to prevent extra deref calls in closeInternal diff --git a/src/runtime/api/bun/subprocess.rs b/src/runtime/api/bun/subprocess.rs index 1469676e56f..da1990fba91 100644 --- a/src/runtime/api/bun/subprocess.rs +++ b/src/runtime/api/bun/subprocess.rs @@ -108,7 +108,7 @@ pub use bun_spawn::process::StdioKind; // bare ident in extern signatures). The `JsClass` impl + finalize/construct C-ABI // hooks are hand-expanded below for `Subprocess<'_>`. // -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). Host-fn bodies re-enter // JS (`run_callback`, promise resolve, getters that materialise streams) and a // live `&mut Self` across those calls would alias the fresh `&mut Self` the @@ -240,7 +240,7 @@ impl<'a> Subprocess<'a> { #[inline] #[allow(clippy::mut_from_ref)] pub(super) fn process_mut(&self) -> &mut Process { - // SAFETY: see `process()` — Zig `*Process` semantics. R-2: `&self` + // SAFETY: see `process()` — Zig `*Process` semantics. `&self` // (interior-mutability) so callers don't need `&mut Subprocess`; // `Process` lives in a separate allocation (BackRef) so the returned // `&mut` never aliases `*self`. Single JS-mutator thread. @@ -283,7 +283,7 @@ impl<'a> Subprocess<'a> { #[inline] pub fn deref(&self) { // SAFETY: `&self` → live `*const Self`; destructor handles the Box. - // R-2: `&self` so callers can `defer self.deref()` without holding a + // `&self` so callers can `defer self.deref()` without holding a // unique borrow across re-entrant JS. unsafe { RefCount::::deref(self.as_ctx_ptr()) } } @@ -905,7 +905,7 @@ impl Subprocess<'_> { // defer this.deref(); // defer this.disconnectIPC(true); - // R-2: now that both take `&self`, scopeguard would no longer alias — + // Now that both take `&self`, scopeguard would no longer alias — // kept explicit at the tail for now (no early returns in this body). if self.event_loop_timer.get().state == EventLoopTimerState::ACTIVE { @@ -1479,7 +1479,7 @@ pub mod testing_apis { return Err(global_this.throw(format_args!("first argument must be a Subprocess"))); }; // SAFETY: `from_js` returned a live `*mut Subprocess` owned by the JS wrapper. - // R-2: deref as shared (`&*const`) — fields are interior-mutable. + // Deref as shared (`&*const`) — fields are interior-mutable. let subprocess = unsafe { &*subprocess_ptr }; let kind_str = kind_value.to_bun_string(global_this)?; // defer kind_str.deref() — bun_core::String Drop handles deref. diff --git a/src/runtime/api/cron.rs b/src/runtime/api/cron.rs index 48f3969d580..c064cc687b2 100644 --- a/src/runtime/api/cron.rs +++ b/src/runtime/api/cron.rs @@ -1311,7 +1311,7 @@ impl Drop for CronRemoveJob { // CronJob — in-process callback-style cron (Bun.cron(expr, cb)) // ============================================================================ -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). `on_timer_fire` // calls `cb.call()` which re-enters JS; that JS may call `stop()`/`ref()`/ // `unref()` on this same wrapper, so a `noalias` `&mut Self` held across the @@ -1408,7 +1408,7 @@ impl CronJob { /// callers. /// /// Only valid while the caller holds at least one intrusive ref (timer - /// heap, list entry, `pending_ref`, or a `ref_guard`). R-2: shared borrow + /// heap, list entry, `pending_ref`, or a `ref_guard`). Shared borrow /// only — every field is `Cell`/`JsCell`/read-only-after-construction, so /// re-entrant JS forming a fresh `&Self` aliases soundly. #[inline] @@ -1589,7 +1589,7 @@ impl CronJob { // Timer heap holds the entry; `this` is live until the guard drops. let _guard = Self::ref_guard(this); // Bracket-ref above keeps `this` alive across scheduleNext → - // finishDeferredStop. R-2: shared (`&*`) — `cb.call()` re-enters JS, + // finishDeferredStop. Shared (`&*`) — `cb.call()` re-enters JS, // which may call `stop()`/`ref()`/`unref()` on this same wrapper; a // `noalias` `&mut Self` here would be Stacked-Borrows UB. All mutation // is interior (`Cell`/`JsCell`). @@ -1718,7 +1718,7 @@ impl CronJob { #[bun_jsc::host_fn(method)] pub fn stop(&self, _global: &JSGlobalObject, frame: &CallFrame) -> JsResult { // SAFETY: `bun_vm()` returns the per-thread singleton. - // R-2: `self_stop` may `deref()` and free `self`; route through the + // `self_stop` may `deref()` and free `self`; route through the // `*mut Self` ctx pointer (interior mutation only — see `as_ctx_ptr`). Self::self_stop(self.as_ctx_ptr(), self.global.bun_vm()); Ok(frame.this()) @@ -1782,7 +1782,7 @@ impl CronJob { pending_ref: Cell::new(false), in_fire: Cell::new(false), })); - // SAFETY: just allocated; unique. R-2: shared deref — all mutation is + // SAFETY: just allocated; unique. Shared deref — all mutation is // interior. let job_ref = unsafe { &*job }; diff --git a/src/runtime/api/filesystem_router.rs b/src/runtime/api/filesystem_router.rs index a8185d3bd78..94b5c2c9873 100644 --- a/src/runtime/api/filesystem_router.rs +++ b/src/runtime/api/filesystem_router.rs @@ -94,7 +94,7 @@ impl<'a, 'r> Router::ResolverLike for RouterResolver<'a, 'r> { // `codegen_cached_accessors!` proc-macro wires the extern. bun_jsc::codegen_cached_accessors!("FileSystemRouter"; routes); -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `JsCell` for the two fields that `reload`/`match` // mutate. The codegen shim may still emit `this: &mut FileSystemRouter` — // `&mut T` reborrows to `&T` so the impls compile against either. @@ -470,7 +470,7 @@ impl FileSystemRouter { // our `vm` borrow is fresh under Stacked Borrows. let vm = global_this.bun_vm().as_mut(); - // R-2: snapshot the config fields up front so the `JsCell::get()` borrow is + // Snapshot the config fields up front so the `JsCell::get()` borrow is // released before `JsCell::set()` below installs the new router. let (cfg_dir, cfg_extensions, cfg_asset_prefix_path) = { let cfg = &this.router.get().config; @@ -607,7 +607,7 @@ impl FileSystemRouter { }; let mut params = route_param::List::default(); // `defer params.deinit(allocator)` → Drop - // SAFETY (R-2): short-lived `&mut Router` for the route lookup; + // SAFETY (noalias re-entry): short-lived `&mut Router` for the route lookup; // `match_page_with_allocator` is pure (no JS re-entry), and the returned // `Match<'p>` borrows `params`/`path_bytes`, not `*router`, so the // exclusive borrow ends at the `;`. @@ -714,7 +714,7 @@ pub struct MatchedRoute { // do) would assert unique access to these fields under Stacked Borrows and invalidate // the stored pointers — UB on next deref. pub route_holder: UnsafeCell>, - // R-2: lazily populated by `get_query`/`get_params` (now `&self`). + // Lazily populated by `get_query`/`get_params` (now `&self`). pub query_string_map: JsCell>, pub param_map: JsCell>, pub params_list_holder: UnsafeCell>, @@ -1007,7 +1007,7 @@ impl MatchedRoute { .set(QueryStringMap::init_with_scanner(scanner)?); } - // R-2: `create_query_object` writes only into a fresh plain JSObject (no + // `create_query_object` writes only into a fresh plain JSObject (no // user setters), so this `with_mut` borrow cannot be re-entered. this.param_map .with_mut(|m| Self::create_query_object(global_this, m.as_mut().unwrap())) @@ -1040,7 +1040,7 @@ impl MatchedRoute { } // If it's still null, the query string has no names. - // R-2: see `get_params` re `with_mut` re-entry. + // See `get_params` re `with_mut` re-entry. this.query_string_map.with_mut(|m| match m { Some(map) => Self::create_query_object(global_this, map), None => Ok(JSValue::create_empty_object(global_this, 0)), diff --git a/src/runtime/api/glob.rs b/src/runtime/api/glob.rs index 97e83f938de..26c1d97177b 100644 --- a/src/runtime/api/glob.rs +++ b/src/runtime/api/glob.rs @@ -410,7 +410,7 @@ fn decr_pending_activity_flag(has_pending_activity: &AtomicUsize) { } impl Glob { - // R-2 (host-fn re-entrancy): all JS-exposed methods take `&self`. `Glob`'s + // Host-fn re-entrancy: all JS-exposed methods take `&self`. `Glob`'s // fields are read-only after construction (`pattern`) or already atomic // (`has_pending_activity`), so no `Cell`/`JsCell` wrapping is needed — the // `&mut self` receivers were vestigial. The codegen shim still emits diff --git a/src/runtime/api/html_rewriter.rs b/src/runtime/api/html_rewriter.rs index 9b874f7b0ed..fe54305937a 100644 --- a/src/runtime/api/html_rewriter.rs +++ b/src/runtime/api/html_rewriter.rs @@ -1393,8 +1393,8 @@ where // SAFETY: `this` is the Box/Box userdata // pointer we registered with lol-html; it lives in LOLHTMLContext for the // duration of the rewriter. `&` (not `&mut`) — `cb.call()` below re-enters - // JS, which may re-enter another `handler_callback` on the same handler - // (R-2); aliased `&H` is sound, aliased `&mut H` is not. + // JS, which may re-enter another `handler_callback` on the same handler; + // aliased `&H` is sound, aliased `&mut H` is not. let this = unsafe { &*this }; let global = this.global(); // PORT NOTE: spec (html_rewriter.zig:938,954,969,972) re-derives @@ -1641,7 +1641,7 @@ fn html_string_value( pub struct TextChunk { // Intrusive RefCount; *Self is the JS wrapper m_ctx. ref_count: Cell, - // R-2: `Cell` so host-fns take `&self` (re-entry-safe). + // `Cell` so host-fns take `&self` (re-entry-safe). pub text_chunk: Cell<*mut lolhtml_sys::TextChunk>, } @@ -1708,7 +1708,7 @@ impl_wrapper_like!(TextChunk, lolhtml::TextChunk); pub struct DocType { // Intrusive RefCount; *Self is the JS wrapper m_ctx. ref_count: Cell, - // R-2: `Cell` so host-fns take `&self` (re-entry-safe). + // `Cell` so host-fns take `&self` (re-entry-safe). pub doctype: Cell<*mut lolhtml_sys::DocType>, } @@ -1793,7 +1793,7 @@ impl_wrapper_like!(DocType, lolhtml::DocType); pub struct DocEnd { // Intrusive RefCount; *Self is the JS wrapper m_ctx. ref_count: Cell, - // R-2: `Cell` so host-fns take `&self` (re-entry-safe). + // `Cell` so host-fns take `&self` (re-entry-safe). pub doc_end: Cell<*mut lolhtml_sys::DocEnd>, } @@ -1825,7 +1825,7 @@ impl_wrapper_like!(DocEnd, lolhtml::DocEnd); pub struct Comment { // Intrusive RefCount; *Self is the JS wrapper m_ctx. ref_count: Cell, - // R-2: `Cell` so host-fns take `&self` (re-entry-safe). + // `Cell` so host-fns take `&self` (re-entry-safe). pub comment: Cell<*mut lolhtml_sys::Comment>, } @@ -1899,7 +1899,7 @@ impl_wrapper_like!(Comment, lolhtml::Comment); pub struct EndTag { // Intrusive RefCount; *Self is the JS wrapper m_ctx. ref_count: Cell, - // R-2: `Cell` so host-fns take `&self` (re-entry-safe). + // `Cell` so host-fns take `&self` (re-entry-safe). pub end_tag: Cell<*mut lolhtml_sys::EndTag>, } @@ -1994,7 +1994,7 @@ impl_wrapper_like!(EndTag, lolhtml::EndTag); pub struct AttributeIterator { // Intrusive RefCount; *Self is the JS wrapper m_ctx. ref_count: Cell, - // R-2: `Cell` so host-fns take `&self` (re-entry-safe). + // `Cell` so host-fns take `&self` (re-entry-safe). pub iterator: Cell<*mut lolhtml_sys::AttributeIterator>, } @@ -2096,13 +2096,13 @@ impl AttributeIterator { pub struct Element { // Intrusive RefCount; *Self is the JS wrapper m_ctx. ref_count: Cell, - // R-2: `Cell` so host-fns take `&self` (re-entry-safe). + // `Cell` so host-fns take `&self` (re-entry-safe). pub element: Cell<*mut lolhtml_sys::Element>, /// AttributeIterator instances created by `getAttributes()` that borrow /// from `element`. They must be detached in `invalidate()` when the /// handler returns so that JS cannot dereference the freed lol-html /// attribute buffer. - /// R-2: `JsCell` (non-Copy `Vec`) — pushed/drained from `&self` host-fns + /// `JsCell` (non-Copy `Vec`) — pushed/drained from `&self` host-fns /// (`get_attributes`, `set_attribute`, `remove_attribute`). The `with_mut` /// closures do not call into JS, so the short `&mut Vec` borrow cannot /// overlap a re-entrant access. @@ -2140,7 +2140,7 @@ impl Element { /// the handler is returning, or because `setAttribute` / `removeAttribute` /// is about to mutate the `Vec` the iterators borrow from. fn detach_attribute_iterators(&self) { - // R-2: take the Vec out of the cell, drain on the stack — no `&mut` + // Take the Vec out of the cell, drain on the stack — no `&mut` // projection of `self` is held across `detach()`/`deref()` (which do // not re-enter JS, but defence-in-depth keeps the JsCell borrow zero-len). let iters = self.attribute_iterators.replace(Vec::new()); @@ -2446,7 +2446,7 @@ impl Element { // without detaching it would be a use-after-free. // SAFETY: attr_iter is a fresh heap::alloc allocation (refcount==1). unsafe { (*attr_iter).ref_() }; - // R-2: `with_mut` — closure does not call into JS (push only). + // `with_mut` — closure does not call into JS (push only). self.attribute_iterators.with_mut(|v| v.push(attr_iter)); // SAFETY: attr_iter is live (refcount==2 now); ownership is shared with // the GC wrapper via the intrusive refcount (`finalize` → `deref`). diff --git a/src/runtime/api/js_bundle_completion_task.rs b/src/runtime/api/js_bundle_completion_task.rs index 2f64c71fcb1..2b27850837e 100644 --- a/src/runtime/api/js_bundle_completion_task.rs +++ b/src/runtime/api/js_bundle_completion_task.rs @@ -571,7 +571,7 @@ impl JSBundleCompletionTask { this.plugins = None; // SAFETY: `html_build_task` is a backref set by `HTMLBundle::Route` which // bumped its own refcount before scheduling and stays alive until this returns. - // R-2: deref as shared — `on_complete` takes `&self`. + // Deref as shared — `on_complete` takes `&self`. unsafe { html_bundle::Route::on_complete(&*html_build_task, this) }; return Ok(()); } diff --git a/src/runtime/bake/bake_body.rs b/src/runtime/bake/bake_body.rs index ce2d56f4607..0bbe28615a6 100644 --- a/src/runtime/bake/bake_body.rs +++ b/src/runtime/bake/bake_body.rs @@ -11,9 +11,9 @@ use bun_alloc::Arena; // = bumpalo::Bump use bun_collections::ArrayHashMap; use bun_core::Output; use bun_jsc::{CallFrame, JSGlobalObject, JSValue, JsError, JsResult, ZigStringSlice}; -// peechy batch 2 landed: `bun_options_types::schema::api` now provides -// {StringMap, LoaderMap, DotEnvBehavior, SourceMapMode, TransformOptions}. -// Alias as `bun_schema` so existing field paths resolve unchanged. +// `bun_options_types::schema::api` provides {StringMap, LoaderMap, +// DotEnvBehavior, SourceMapMode, TransformOptions}. Alias as `bun_schema` so +// existing field paths resolve unchanged. use bun_core::{ZStr, strings}; use bun_options_types::schema as bun_schema; use bun_paths::{self as paths, PathBuffer}; diff --git a/src/runtime/crypto/CryptoHasher.rs b/src/runtime/crypto/CryptoHasher.rs index 14ca95931fa..48613c36de5 100644 --- a/src/runtime/crypto/CryptoHasher.rs +++ b/src/runtime/crypto/CryptoHasher.rs @@ -58,7 +58,7 @@ fn is_bun_file_blob(input: &BlobOrStringOrBuffer) -> bool { /// `extern "C" fn(..., *mut CryptoHasher)` shims — C++ never reads this layout /// (it round-trips `m_ctx` as `void*`). /// -/// R-2 (`sharedThis`): every JS-facing host-fn takes `&CryptoHasher` (not +/// `sharedThis`: every JS-facing host-fn takes `&CryptoHasher` (not /// `&mut`). The discriminant is fixed at construction; only the payload mutates, /// so each variant payload is wrapped in [`JsCell`] (UnsafeCell projector, /// single-JS-thread). The codegen shim still emits `this: &mut CryptoHasher` — @@ -599,7 +599,7 @@ impl CryptoHasher { } } CryptoHasher::Hmac(inner) => { - // R-2: check None first via shared `.get()`, then mutate via + // Check None first via shared `.get()`, then mutate via // `with_mut`. No JS re-entry between the check and the write // (HMAC_Update is a pure FFI call), so the `unwrap` is sound. if inner.get().is_none() { @@ -633,7 +633,7 @@ impl CryptoHasher { .expect("OOM"), )), CryptoHasher::Hmac(inner) => 'brk: { - // R-2: `HMAC::copy` takes `&mut self` (writes nothing — Zig + // `HMAC::copy` takes `&mut self` (writes nothing — Zig // legacy signature). Project a short `&mut` via `with_mut`; // no JS re-entry inside (HMAC_CTX_copy is a pure FFI call). let copy_result = inner.with_mut(|opt| opt.as_mut().map(|h| h.copy())); @@ -758,7 +758,7 @@ impl CryptoHasher { break 'brk Ok(hmac.r#final(output_digest_slice)); } CryptoHasher::Evp(inner) => { - // R-2: `with_mut` scopes the `&mut EVP` to the FFI call; the + // `with_mut` scopes the `&mut EVP` to the FFI call; the // returned `&'a mut [u8]` borrows `output_digest_slice` (not // `self`), so it escapes the closure cleanly. let engine = boring_engine(global); @@ -1185,7 +1185,7 @@ impl_static_hasher!(hashers::SHA512_256, "SHA512_256", JSSHA512_256, 32); // The per-monomorphization `JsClass` impl + extern shims live in // `build/*/codegen/generated_classes.rs` (one block per `pub type` alias below); // `#[repr(C)]` here only silences the `improper_ctypes` lint on those externs. -// R-2 (`sharedThis`): every JS-facing host-fn takes `&StaticCryptoHasher`. +// `sharedThis`: every JS-facing host-fn takes `&StaticCryptoHasher`. // `hashing` is mutated by `update`/`final_` → `JsCell`; `digested` is a // Copy flag → `Cell`. #[repr(C)] diff --git a/src/runtime/dispatch.rs b/src/runtime/dispatch.rs index 8bbaa9da701..aa0aa5610b6 100644 --- a/src/runtime/dispatch.rs +++ b/src/runtime/dispatch.rs @@ -213,7 +213,7 @@ pub fn run_task( }; } /// `CompressionStream::::run_from_js_thread` takes `*mut T` (full - /// allocation provenance — R-2) so its trailing `T::deref()` may free the box. + /// allocation provenance) so its trailing `T::deref()` may free the box. macro_rules! compression_arm { ($T:ty) => {{ // SAFETY: §Dispatch — tag identifies pointee; live m_ctx payload. @@ -727,7 +727,7 @@ pub unsafe fn __bun_run_file_poll(poll: *mut FilePoll, size_or_offset: i64) { crate::shell::io_writer::on_poll(&mut *h, size_or_offset as isize, hup) }), poll_tag::DNS_RESOLVER => { - // R-2: deref as shared (`&*const`) — `on_dns_poll` takes `&self` and + // Deref as shared (`&*const`) — `on_dns_poll` takes `&self` and // `Channel::process` re-enters the resolver via c-ares callbacks. // SAFETY: tag set with this pointee type at `FilePoll::init`. let resolver = unsafe { &*owner.ptr.cast_const().cast::() }; @@ -987,7 +987,7 @@ pub unsafe fn __bun_fire_timer(t: *mut EventLoopTimer, now: *const ElTimespec, v timer_arm!(UpgradedDuplex, event_loop_timer, |c, _now, _vm| (*c) .on_timeout()) } - // R-2: shared deref — `check_timeouts` re-enters via `ares_process_fd`. + // Shared deref — `check_timeouts` re-enters via `ares_process_fd`. EventLoopTimerTag::DNSResolver => { timer_arm!(DNSResolver, event_loop_timer, |c, now, vm| { (&*c.cast_const()).check_timeouts(&*now, &*vm) diff --git a/src/runtime/dns_jsc/dns.rs b/src/runtime/dns_jsc/dns.rs index f2aed8b144d..0d81672dbb8 100644 --- a/src/runtime/dns_jsc/dns.rs +++ b/src/runtime/dns_jsc/dns.rs @@ -71,7 +71,7 @@ type Sockaddr = netc::sockaddr; /// `bun_jsc → bun_runtime` dependency cycle; this function owns the lazy init /// and the cast back to `*mut GlobalData`. /// -/// R-2: returns `&Resolver` (shared). All Resolver mutation routes through +/// Returns `&Resolver` (shared). All Resolver mutation routes through /// `Cell` / `JsCell` fields, so a shared borrow is sufficient and avoids the /// `noalias` hazard when c-ares callbacks re-enter on the same global resolver. #[inline] @@ -3608,7 +3608,7 @@ type PollType = FilePoll; type PollsMap = ArrayHashMap; -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). c-ares // completion callbacks re-enter this Resolver (e.g. `request_completed`, // `drain_pending_*`) while a `&self` borrow is live in `on_dns_poll` / @@ -3725,7 +3725,7 @@ pub trait HasPendingCacheKey { /// `field` is the runtime tag of the comptime field name (some request types are reachable /// via more than one field, e.g. `pending_host_cache_{cares,native}`). /// - /// R-2: takes `&Resolver` and projects `&mut` via the field's `JsCell`. + /// Takes `&Resolver` and projects `&mut` via the field's `JsCell`. /// Callers hold the borrow only for a short, non-reentrant window /// (slot read/claim/unset). #[allow(clippy::mut_from_ref)] @@ -4006,7 +4006,7 @@ impl Resolver { } } - // ─── R-2 interior-mutability helpers ──────────────────────────────────── + // ─── Interior-mutability helpers ──────────────────────────────────────── /// `self`'s address as `*mut Self` for c-ares / `FilePoll` / `IntrusiveRc` /// ctx slots and `Self::deref`. Callbacks deref it as `&*const` (shared) — @@ -4029,7 +4029,7 @@ impl Resolver { nsec: now.nsec, }; let uws_loop = vm.uws_loop(); - // R-2: `&self` carries no `noalias`, and every field touched below is + // `&self` carries no `noalias`, and every field touched below is // UnsafeCell-backed, so the re-entrant `ares_process_fd` callbacks // (`request_completed`, `drain_pending_*`) may freely re-derive // `&Resolver` from their stored ctx without aliasing UB. @@ -4159,7 +4159,7 @@ impl Resolver { /// Dispatch to the GetAddrInfo PendingCache by field enum. /// - /// R-2: returns `&mut` from `&self` via `JsCell::get_mut`. Callers hold + /// Returns `&mut` from `&self` via `JsCell::get_mut`. Callers hold /// the borrow only for the duration of a slot read/claim/unset and never /// across a re-entrant call (the c-ares callback path that re-enters the /// resolver runs *after* the borrow is dropped). @@ -4195,7 +4195,7 @@ impl Resolver { // SAFETY: the matched arm guarantees `self.$f` *is* // `JsCell, 32>>` for this `T::CACHE_FIELD`; // the cast is an identity transmute (same layout, same lifetime). - // R-2: `JsCell::as_ptr` projects `&mut` from `&self`; caller + // `JsCell::as_ptr` projects `&mut` from `&self`; caller // holds the borrow only for a short, non-reentrant window // (see `pending_host_cache` doc). unsafe { @@ -4734,7 +4734,7 @@ impl Resolver { /// libuv (`on_dns_poll_uv`) instead, and the only caller /// (`dispatch::__bun_run_file_poll`) is itself `#[cfg(not(windows))]`. /// - /// R-2: `&self` (no `noalias`). `Channel::process` (== `ares_process_fd`) + /// `&self` (no `noalias`). `Channel::process` (== `ares_process_fd`) /// synchronously fires c-ares completion callbacks which re-enter this /// Resolver via a fresh `&Resolver` (e.g. `request_completed`, /// `drain_pending_*`, `ref_`/`deref`). With every mutable field diff --git a/src/runtime/ffi/ffi_body.rs b/src/runtime/ffi/ffi_body.rs index 610045bc5cf..182d460df80 100644 --- a/src/runtime/ffi/ffi_body.rs +++ b/src/runtime/ffi/ffi_body.rs @@ -1,5 +1,3 @@ -#![allow(unexpected_cfgs)] // `feature = "tinycc"` is a Phase-C placeholder; `bun_codegen_embed` is set via RUSTFLAGS in scripts/build/rust.ts. - use core::cell::Cell; use core::ffi::{c_char, c_int, c_long, c_void}; use core::fmt::{self, Write as _}; @@ -21,7 +19,7 @@ use bun_paths::{self as path, MAX_PATH_BYTES, PathBuffer}; use bun_resolver::fs as Fs; use bun_sys::{self, Fd}; -// ─── Local shims for upstream surfaces not yet wired (Phase D) ─────────────── +// ─── Local shims for upstream surfaces not yet wired ───────────────────────── /// `bun.sys.directoryExistsAt(FD.cwd(), path).isTrue()` — local helper while /// `bun_core::Fd` lacks an inherent forwarder. @@ -222,11 +220,11 @@ impl Offsets { } } -// R-2 (host-fn re-entrancy): the JS-exposed `close()` method takes `&self`; +// Host-fn re-entrancy: the JS-exposed `close()` method takes `&self`; // per-field interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). // `close()` does not itself re-enter JS, but routing mutation through // `UnsafeCell`-backed fields suppresses `noalias` on the `&Self` the codegen -// shim materialises from `m_ctx`, which is the systemic R-2 guarantee. +// shim materialises from `m_ctx`, which is the systemic guarantee. #[bun_jsc::JsClass(no_constructor)] pub struct FFI { pub dylib: JsCell>, // TODO(port): std.DynLib equivalent diff --git a/src/runtime/ffi/host_fns.rs b/src/runtime/ffi/host_fns.rs index f72bffbac2e..0f417e0a3d1 100644 --- a/src/runtime/ffi/host_fns.rs +++ b/src/runtime/ffi/host_fns.rs @@ -9,7 +9,7 @@ //! gated; `Function::compile` therefore short-circuits with a `Step::Failed` //! when the `tinycc` feature is off (which it always is until //! `bun_tcc_sys::tcc` un-gates). The full TCC body is preserved in -//! `ffi_body.rs` (``) for reference. +//! `ffi_body.rs` for reference. use std::ffi::c_void; use std::io::Write as _; diff --git a/src/runtime/ffi_imports.rs b/src/runtime/ffi_imports.rs index 19716076b73..4b51a6ed178 100644 --- a/src/runtime/ffi_imports.rs +++ b/src/runtime/ffi_imports.rs @@ -1,6 +1,6 @@ //! Consolidated `unsafe extern "C" { … }` import surface for `bun_runtime`. //! -//! Phase-f goal: one `extern "C"` block per crate instead of the ~308 +//! Goal: one `extern "C"` block per crate instead of the ~308 //! scattered across `src/runtime/**/*.rs` (each with its own //! `#[allow(improper_ctypes)]` and a slightly different spelling of the same //! C++ symbol). The generator at `src/codegen/generate-host-exports.ts` emits diff --git a/src/runtime/hw_exports.rs b/src/runtime/hw_exports.rs index fd037a1873d..6089f25b9d9 100644 --- a/src/runtime/hw_exports.rs +++ b/src/runtime/hw_exports.rs @@ -1,4 +1,4 @@ -//! phase-d: handwritten Zig `@export` / `export fn` C-ABI symbols whose bodies +//! Handwritten Zig `@export` / `export fn` C-ABI symbols whose bodies //! live in `bun_jsc::VirtualMachine` but whose link names must be emitted from //! a crate that *depends on* `bun_jsc` (so the bodies can call back into the //! real `VirtualMachine` struct without inverting the crate DAG). Each fn here diff --git a/src/runtime/image/Image.rs b/src/runtime/image/Image.rs index 76e00ca410d..94a4accf0b6 100644 --- a/src/runtime/image/Image.rs +++ b/src/runtime/image/Image.rs @@ -56,7 +56,7 @@ fn format_name(f: codecs::Format) -> &'static str { // did via `js.sourceJSSetCached`. pub use crate::generated_classes::js_Image as js; -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). `max_pixels` // / `auto_orient` are read-only after construction so stay bare. #[bun_jsc::JsClass] @@ -433,7 +433,7 @@ fn source_from_js( // ───────────────────────────── chainable ops ──────────────────────────────── impl Image { - /// R-2 helper: read-modify-write the `Cell` in one shot so each + /// Helper: read-modify-write the `Cell` in one shot so each /// chainable setter stays a single field-write under `&self`. #[inline] fn update_pipeline(&self, f: impl FnOnce(&mut Pipeline)) { @@ -1298,7 +1298,7 @@ impl<'a> BlobReadChain<'a> { fn on_read_bytes_impl(self: Box, r: ReadBytesResult) { let global = self.global; // SAFETY: `image` is a BACKREF kept alive by the Strong `this_ref` - // bump in `start()`; we are on the JS thread. R-2: shared deref — + // bump in `start()`; we are on the JS thread. Shared deref — // mutation goes through `Cell`/`JsCell`. let image = unsafe { &*self.image }; let mut outer = self.outer; @@ -1718,7 +1718,7 @@ impl<'a> PipelineTask<'a> { mem::take(&mut self.input).release(); let global = self.global; // SAFETY: BACKREF; JS thread; wrapper kept alive by `this_ref` Strong. - // R-2: shared deref — mutation goes through `Cell`. + // Shared deref — mutation goes through `Cell`. let image = unsafe { &*self.image }; // Stash final dims here (JS thread) — `run()` is on a WorkPool thread // so writing `self.image.*` there would race the synchronous getters. @@ -2032,7 +2032,7 @@ impl<'a> Drop for PipelineTask<'a> { // `self.deliver.deinit()` — `Strong` Drop on the `WriteDest` arm. // SAFETY: `image` is a BACKREF kept alive by the wrapper's Strong // `this_ref` while pending_tasks > 0; we are on the JS thread. - // R-2: shared deref — mutation goes through `Cell`/`JsCell`. + // Shared deref — mutation goes through `Cell`/`JsCell`. let image = unsafe { &*self.image }; image.pending_tasks.set(image.pending_tasks.get() - 1); if image.pending_tasks.get() == 0 { diff --git a/src/runtime/jsc_hooks.rs b/src/runtime/jsc_hooks.rs index 6ff3c4c76c1..a3b2e393bc6 100644 --- a/src/runtime/jsc_hooks.rs +++ b/src/runtime/jsc_hooks.rs @@ -68,7 +68,7 @@ use crate::webcore::blob::BlobExt as _; /// PORT NOTE: in Zig these are value fields of `VirtualMachine` /// (`vm.timer: api.Timer.All`, `vm.entry_point: ServerEntryPoint`, /// `vm.body_value_pool`). The low-tier `VirtualMachine` carries `()` -/// placeholders for them (see `// TODO(b2-cycle)` markers in +/// placeholders for them (see `// TODO(port)` markers in /// `VirtualMachine.rs`); until those slots widen to `*mut c_void`, the /// thread-local is the recovery path. pub struct RuntimeState { @@ -122,7 +122,7 @@ pub fn runtime_state() -> *mut RuntimeState { /// Recover this thread's `timer::All` heap as a raw pointer. /// -/// PORT NOTE (b2-cycle): `bun_jsc::VirtualMachine.timer` is a `()` placeholder; +/// PORT NOTE: `bun_jsc::VirtualMachine.timer` is a `()` placeholder; /// the real `All` lives in [`RuntimeState::timer`] until that slot widens. /// Null only before [`init_runtime_state`] has run (e.g. `bun_jsc` unit tests /// with no high tier, or `Bun__Timer__getNextID` racing init). @@ -304,7 +304,7 @@ unsafe fn init_runtime_state( // zeroed bytes are not a valid `Transpiler` to drop). // // PORT NOTE: `configure_transform_options_for_bun_vm` lives in the - // ``-gated `bun_jsc::config` module; its body (3 field overwrites) is + // `bun_jsc::config` module; its body (3 field overwrites) is // inlined below over the caller-supplied `opts.transform_options`. // SAFETY: `vm.log` was set to a fresh leaked `Box` by // `VirtualMachine::init` immediately before this hook fires. @@ -397,7 +397,7 @@ unsafe fn init_runtime_state( // `VirtualMachine.init`. The hook signature has no error // channel, so log + leave the field zeroed (validity-UB on // first read — same failure mode as before this hook existed). - // TODO(b2): widen `init_runtime_state` return to `Result<_, Error>`. + // TODO(port): widen `init_runtime_state` return to `Result<_, Error>`. bun_core::Output::err("Transpiler", "{}", format_args!("init failed: {e:?}")); } } @@ -590,7 +590,7 @@ unsafe fn load_preloads( let global: *mut JSGlobalObject = unsafe { &*vm }.global; // ── guard: zeroed transpiler ──────────────────────────────────────── // `init_runtime_state` swallows `Transpiler::init`'s `Err` (logs + leaves - // `vm.transpiler` as zeroed bytes — see its `TODO(b2): widen return`). + // `vm.transpiler` as zeroed bytes — see its `TODO(port): widen return`). // Spec VirtualMachine.zig:1240 uses `try Transpiler.init(...)`, so // `loadPreloads` is unreachable with an invalid transpiler; in Rust we // must check `fs.is_null()` to avoid null-deref UB on `--preload` until @@ -709,43 +709,32 @@ unsafe fn load_preloads( let _protected = JSValue::from_cell(promise).protected(); // ── wait ──────────────────────────────────────────────────────── - // TODO(b2-cycle): HMR `pending_internal_promise` swap loop (spec VirtualMachine.zig:2248-2261) — un-gate with `hot_reloader.rs` / ImportWatcher. Until then, fall through to the non-watcher `wait_for_promise` path below. - { - // SAFETY: per fn contract. - if unsafe { &*vm }.is_watcher_enabled() { - // pending_internal_promise can change if hot module reloading is - // enabled (spec VirtualMachine.zig:2248-2261). - // SAFETY: `el` is the live per-thread event loop. - let el = unsafe { &*vm }.event_loop(); - unsafe { (*el).perform_gc() }; - loop { - // SAFETY: `pending_internal_promise` was set just above (or - // swapped by HMR to another live cell); `status()` is a - // read-only FFI call on a live JSC heap cell. - let pip = unsafe { &*vm }.pending_internal_promise.unwrap_or(promise); - if unsafe { &*pip }.status() != PromiseStatus::Pending { - break; - } - // SAFETY: `el` is the live per-thread event loop. - unsafe { (*el).tick() }; - let pip = unsafe { &*vm }.pending_internal_promise.unwrap_or(promise); - if unsafe { &*pip }.status() == PromiseStatus::Pending { - // SAFETY: per fn contract — short-lived `&mut *vm` for the - // dispatched `auto_tick` hook (same shape as - // `wait_for_promise` below). - unsafe { (*vm).auto_tick() }; - } + // SAFETY: per fn contract. + if unsafe { &*vm }.is_watcher_enabled() { + // pending_internal_promise can change if hot module reloading is + // enabled (spec VirtualMachine.zig:2248-2261). + // SAFETY: `el` is the live per-thread event loop. + let el = unsafe { &*vm }.event_loop(); + unsafe { (*el).perform_gc() }; + loop { + // SAFETY: `pending_internal_promise` was set just above (or + // swapped by HMR to another live cell); `status()` is a + // read-only FFI call on a live JSC heap cell. + let pip = unsafe { &*vm }.pending_internal_promise.unwrap_or(promise); + if unsafe { &*pip }.status() != PromiseStatus::Pending { + break; } - } else { // SAFETY: `el` is the live per-thread event loop. - unsafe { (*(*vm).event_loop()).perform_gc() }; - // SAFETY: per fn contract — short-lived `&mut *vm`; `promise` is a - // live protected JSC heap cell. - unsafe { (*vm).wait_for_promise(AnyPromise::Internal(promise)) }; + unsafe { (*el).tick() }; + let pip = unsafe { &*vm }.pending_internal_promise.unwrap_or(promise); + if unsafe { &*pip }.status() == PromiseStatus::Pending { + // SAFETY: per fn contract — short-lived `&mut *vm` for the + // dispatched `auto_tick` hook (same shape as + // `wait_for_promise` below). + unsafe { (*vm).auto_tick() }; + } } - } // end - // PORT NOTE: non-watcher fallback while the HMR loop above is gated. - { + } else { // SAFETY: `el` is the live per-thread event loop. unsafe { (*(*vm).event_loop()).perform_gc() }; // SAFETY: per fn contract — short-lived `&mut *vm`; `promise` is a @@ -858,9 +847,8 @@ unsafe fn auto_tick(vm: *mut VirtualMachine) { } // ── DateHeaderTimer / imminent-GC ─────────────────────────────────── - // TODO(b2-cycle): `timer::All::update_date_header_timer_if_necessary` — - // not yet on the B-2 `All` surface (only insert/remove/update/get_timeout/ - // drain_timers are real). No-op until the DateHeaderTimer body un-gates. + // TODO(port): call `timer::All::update_date_header_timer_if_necessary` + // here (the impl exists on `All`; this call site never wired it up). // SAFETY: `el` is the live per-thread event loop. unsafe { (*el).run_imminent_gc_timer() }; @@ -989,8 +977,8 @@ unsafe fn auto_tick_active(vm: *mut VirtualMachine) { } } - // TODO(b2-cycle): `timer::All::update_date_header_timer_if_necessary` — - // not yet on the B-2 `All` surface (see `auto_tick` above). + // TODO(port): call `timer::All::update_date_header_timer_if_necessary` + // here (see `auto_tick` above). let state = runtime_state(); if state.is_null() { @@ -1961,9 +1949,7 @@ fn transpile_source_code_inner( | L::Json5 | L::Text | L::Md => { - // TODO(b2-blocked): `bun_ast::ASTMemoryAllocator::Scope` — gated in - // `bun_js_parser`. Spec :117-119. - + // Spec :117-119. let mut _ast_scope = bun_ast::ast_memory_allocator::Scope::default(); _ast_scope.enter(); @@ -2033,10 +2019,6 @@ fn transpile_source_code_inner( // `_reset_arena` guard (`ModuleLoader::reset_arena`, // spec :1083) runs after `process_fetch_log` and // resets/reclaims it then — matching the spec lifetime. - // TODO(b2-cycle): once AsyncModule un-gates, the - // enqueue site must `ScopeGuard::into_inner` and hand - // the `Box` to the queue instead of reaching - // here. *slot = Some(arena); return; } @@ -2157,31 +2139,21 @@ fn transpile_source_code_inner( let args_log_nn = core::ptr::NonNull::new(args.log).expect("args.log is non-null"); unsafe { (*jsc_vm).transpiler.log = args.log; - { - (*jsc_vm).transpiler.resolver.log = args_log_nn; - } - // TODO(b2-blocked): `Linker` is a unit stub in `bun_bundler` - // — `.log` field un-gates with `linker.rs`. - - { - (*jsc_vm).transpiler.linker.log = args.log; - if let Some(pm) = (*jsc_vm).transpiler.resolver.package_manager { - // TODO(blocked_on): bun_resolver::package_json::PackageManager::log - // — the resolver-side stub only exposes `lockfile`/`on_wake`. - let _ = pm; - } + (*jsc_vm).transpiler.resolver.log = args_log_nn; + (*jsc_vm).transpiler.linker.log = args.log; + if let Some(pm) = (*jsc_vm).transpiler.resolver.package_manager { + // TODO(blocked_on): bun_resolver::package_json::PackageManager::log + // — the resolver-side stub only exposes `lockfile`/`on_wake`. + let _ = pm; } } let _log_guard = scopeguard::guard(jsc_vm, move |jsc_vm| unsafe { (*jsc_vm).transpiler.log = old_log; - - { - (*jsc_vm).transpiler.resolver.log = old_log_nn; - (*jsc_vm).transpiler.linker.log = old_log; - if let Some(pm) = (*jsc_vm).transpiler.resolver.package_manager { - // TODO(blocked_on): bun_resolver::package_json::PackageManager::log - let _ = pm; - } + (*jsc_vm).transpiler.resolver.log = old_log_nn; + (*jsc_vm).transpiler.linker.log = old_log; + if let Some(pm) = (*jsc_vm).transpiler.resolver.package_manager { + // TODO(blocked_on): bun_resolver::package_json::PackageManager::log + let _ = pm; } }); @@ -2313,9 +2285,11 @@ fn transpile_source_code_inner( use bun_bundler::transpiler::{AlreadyBundled, ParseOptions, ParseResult}; use bun_jsc::resolved_source::Tag as ResolvedSourceTag; - // TODO(b2-cycle): `Debugger::set_breakpoint_on_first_line` + - // `runtime_transpiler_store::set_break_point_on_first_line` — - // gated; spec gates on `vm.debugger != null && debugger.set_...`. + // TODO(port): wire up the spec gate `is_main && + // vm.debugger != null && debugger.set_breakpoint_on_first_line` + // (both `Debugger::set_breakpoint_on_first_line` and + // `runtime_transpiler_store::set_break_point_on_first_line()` + // exist; this call site never plumbed them). let set_breakpoint_on_first_line = false; let _ = is_main; @@ -2672,7 +2646,7 @@ fn transpile_source_code_inner( list: core::mem::take(&mut entry.sourcemap).into_vec(), }, ); - // TODO(b2-blocked): `ModuleInfoDeserialized::create_from_cached_record`. + // TODO(port): `ModuleInfoDeserialized::create_from_cached_record`. let source_code = match &mut entry.output_code { OutputCode::String(s) => *s, OutputCode::Utf8(utf8) => { @@ -2738,7 +2712,7 @@ fn transpile_source_code_inner( specifier: input_specifier.dupe_ref(), source_url: create_if_different(input_specifier, path.text), is_commonjs_module, - // TODO(b2-blocked): `module_info` (:423-428). + // TODO(port): `module_info` (:423-428). tag, ..Default::default() })); @@ -2818,7 +2792,7 @@ fn transpile_source_code_inner( // Spec :516-523. let is_commonjs_module = parse_result.ast.has_commonjs_export_names || parse_result.ast.exports_kind == bun_ast::ExportsKind::Cjs; - // TODO(b2-blocked): `analyze_transpiled_module::ModuleInfo::create`. + // TODO(port): `analyze_transpiled_module::ModuleInfo::create`. // ── js_printer::print ─────────────────────────────────────── // Spec :525-539. @@ -2867,7 +2841,7 @@ fn transpile_source_code_inner( &mut *(*extra).source_code_printer, bun_js_printer::Format::EsmAscii, mapper.get(), - // TODO(b2-blocked): `analyze_transpiled_module:: + // TODO(port): `analyze_transpiled_module:: // ModuleInfo::create` (spec :516-523) — pass it // through once the create-side above is un-gated. None, @@ -2880,11 +2854,6 @@ fn transpile_source_code_inner( } // Spec :553-558 — watcher path uses ref-counted source. - // TODO(b2-blocked): `VirtualMachine::ref_counted_resolved_source`. - // Spec RETURNS the ref-counted `ResolvedSource` here (with - // `is_commonjs_module`/`module_info` patched on). Gated so the - // fall-through to the non-watcher tail below is an explicit, - // intentional degradation rather than a silent live divergence. if unsafe { &*jsc_vm }.is_watcher_enabled() { // SAFETY: `extra.source_code_printer` is non-null per // `TranspileExtra` contract; rederive after the print block @@ -2900,7 +2869,7 @@ fn transpile_source_code_inner( ) }; resolved_source.is_commonjs_module = is_commonjs_module; - // TODO(b2-blocked): `analyze_transpiled_module::ModuleInfo::create`. + // TODO(port): `analyze_transpiled_module::ModuleInfo::create`. resolved_source.module_info = core::ptr::null_mut(); return Ok(OwnedResolvedSource::new(resolved_source)); } @@ -2986,7 +2955,7 @@ fn transpile_source_code_inner( specifier: input_specifier.dupe_ref(), source_url: create_if_different(input_specifier, path.text), is_commonjs_module, - // TODO(b2-blocked): `analyze_transpiled_module::ModuleInfo::create`. + // TODO(port): `analyze_transpiled_module::ModuleInfo::create`. module_info: core::ptr::null_mut(), tag, ..Default::default() @@ -3009,7 +2978,7 @@ fn transpile_source_code_inner( // SAFETY: per fn contract. let main = unsafe { &*jsc_vm }.main(); if referrer == b"undefined" && main == path.text { - // TODO(b2-blocked): `globalThis.wasmSourceBytes` put + + // TODO(port): `globalThis.wasmSourceBytes` put + // `@embedFile("../js/wasi-runner.js")` — needs `ArrayBuffer::create` // and a Rust `include_bytes!` of the wasi runner. Spec :638-658. @@ -3049,7 +3018,7 @@ fn transpile_source_code_inner( // Spec :680 — `jsc_vm.hot_reload == .hot`. `HotReload` is // `{ none=0, hot=1, watch=2 }` (src/options_types/Context.zig:118); // `!= 0` would also match `.watch`, which is wrong. - // TODO(b2-cycle): `hot_reload` is `cli::Command::HotReload` enum + // TODO(port): `hot_reload` is `cli::Command::HotReload` enum // (gated as `u8`); compare to the `.hot` discriminant explicitly. const HOT_RELOAD_HOT: u8 = 1; let hot = unsafe { &*jsc_vm }.hot_reload == HOT_RELOAD_HOT; @@ -3325,9 +3294,9 @@ fn get_hardcoded_module( specifier: &bun_core::String, hardcoded: HardcodedModule, ) -> Option { - // TODO(b2-cycle): `bun_analytics::Features::builtin_modules.insert(hardcoded)` - // — the `EnumSet` static lives in T5 (`bun_resolve_builtins`) - // and is not yet wired into `bun_analytics`. + // TODO(port): `analytics.Features.builtin_modules.insert(hardcoded)` — + // the static is `bun_analytics::features::BUILTIN_MODULES` (a + // `Mutex>`); insert `<&'static str>::from(hardcoded)`. match hardcoded { HardcodedModule::BunMain => { @@ -3370,23 +3339,13 @@ fn get_hardcoded_module( HardcodedModule::BunWrap => { // `Runtime.Runtime.sourceCode()` — the bundler's CJS-interop // shim, embedded as a static string in `bun_ast::runtime`. - - // TODO(b2-cycle): `Runtime::source_code()` — `bun_ast::runtime` - // is a stub re-export until `runtime.rs` un-gates there. - { - return Some(OwnedResolvedSource::new(ResolvedSource { - source_code: bun_core::String::init(bun_ast::runtime::Runtime::source_code()), - // +1 each: ~SourceProvider() derefs both. - specifier: specifier.dupe_ref(), - source_url: specifier.dupe_ref(), - ..ResolvedSource::default() - })); - } - // Fail closed: until `Runtime::source_code()` un-gates, returning - // a default-zeroed `ResolvedSource` here would hand C++ a garbage - // `.tag`. Spec returns a populated source; `None` falls through to - // `FetchBuiltinResult::NotFound` → coherent error instead. - None + Some(OwnedResolvedSource::new(ResolvedSource { + source_code: bun_core::String::init(bun_ast::runtime::Runtime::source_code()), + // +1 each: ~SourceProvider() derefs both. + specifier: specifier.dupe_ref(), + source_url: specifier.dupe_ref(), + ..ResolvedSource::default() + })) } // Zig: `inline else => |tag| jsSyntheticModule(@field(ResolvedSource.Tag, @tagName(tag)), specifier)` // — every other `HardcodedModule` is served straight out of the @@ -3556,9 +3515,8 @@ export default db; // `options.getLoaderAndVirtualSource` (spec bundler/options.zig:909-1040). // // The canonical Rust port (`bun_bundler::options::get_loader_and_virtual_source`) -// is ``-gated behind a `VmLoaderCtx` vtable that nothing -// constructs yet, and `Fs::Path::loader` returns the lower-tier -// `bun_ast::Loader` (a *distinct* nominal type from the +// goes through a `VmLoaderCtx` vtable, and `Fs::Path::loader` returns the +// lower-tier `bun_ast::Loader` (a *distinct* nominal type from the // `bun_ast::Loader` we need for `TranspileExtra`). Porting the // body inline here lets us name `VirtualMachine` directly (no vtable) and look // the loader up in `transpiler.options.loaders` (which is already @@ -4943,7 +4901,7 @@ unsafe fn resolve_hook( (*vm).log = Some(log_nn); (*vm).transpiler.resolver.log = log_nn; (*vm).transpiler.linker.log = log_nn.as_ptr(); - // TODO(b2-cycle): `transpiler.resolver.package_manager` log swap — + // TODO(port): `transpiler.resolver.package_manager` log swap — // gated alongside the PM field (see transpile_source_code §log-swap). } scopeguard::defer! { diff --git a/src/runtime/node.rs b/src/runtime/node.rs index b01722f6a03..dc80db51da4 100644 --- a/src/runtime/node.rs +++ b/src/runtime/node.rs @@ -93,9 +93,8 @@ pub mod dirent { } // node_fs.rs (~4.7kL): async task machinery (AsyncFSTask/UVFSRequest/cp/ -// readdir-recursive) is JSC-dense and re-gated *inside* the file with -// ``. Sync `impl NodeFS` (read_file/write_file/stat/mkdir et al.), -// `args::*`, `ret::*` are live. +// readdir-recursive) plus sync `impl NodeFS` +// (read_file/write_file/stat/mkdir et al.), `args::*`, `ret::*`. #[path = "node/node_fs.rs"] pub mod fs; @@ -197,7 +196,7 @@ pub type gid_t = bun_sys::windows::libuv::uv_gid_t; /// We can't really use Zig's error handling for syscalls because Node.js expects the "real" errno to be returned /// and various issues with std.posix that make it too unstable for arbitrary user input (e.g. how .BADF is marked as unreachable) /// -/// Phase F: collapsed from a bespoke `enum Maybe { Err, Result }` into a plain +/// Collapsed from a bespoke `enum Maybe { Err, Result }` into a plain /// `core::result::Result` alias. The Zig-parity helper methods (`todo`, /// `success`, `errno_sys*`, `to_js`, …) move to the [`MaybeExt`] / /// [`MaybeSysExt`] / [`MaybeToJsExt`] extension traits below so call sites can diff --git a/src/runtime/node/net/BlockList.rs b/src/runtime/node/net/BlockList.rs index 412da4c6632..4597266fb6f 100644 --- a/src/runtime/node/net/BlockList.rs +++ b/src/runtime/node/net/BlockList.rs @@ -64,7 +64,7 @@ pub struct BlockList { // TODO(port): lifetime — field is write-only (assigned in constructor, // never read; `deinit` ignores it). global_this: *const JSGlobalObject, - // R-2: interior mutability so every host_fn takes `&self`. All access is + // Interior mutability so every host_fn takes `&self`. All access is // serialized by `mutex` (held across every read and every `with_mut`), so // the `JsCell` single-thread invariant is upheld even though `BlockList` // can be touched from multiple JS realms via structured clone. diff --git a/src/runtime/node/node_fs.rs b/src/runtime/node/node_fs.rs index 08f208080ce..532d6344338 100644 --- a/src/runtime/node/node_fs.rs +++ b/src/runtime/node/node_fs.rs @@ -775,7 +775,7 @@ mod _async_tasks { let path = if strings::eql_comptime(args.path.slice(), b"/dev/null") { ZStr::from_static(b"\\\\.\\NUL\0") } else { - // SAFETY (R-2): single-JS-thread `JsCell` projection of the + // SAFETY (noalias re-entry): single-JS-thread `JsCell` projection of the // scratch path buffer; the borrow is held only across the // libuv enqueue below (which copies `path` internally) and // never across a JS re-entry point. @@ -955,7 +955,7 @@ mod _async_tasks { } NodeFSFunctionEnum::Statfs => { let args: &args::StatFS = args_as!(args::StatFS); - // SAFETY (R-2): single-JS-thread `JsCell` projection; held only + // SAFETY (noalias re-entry): single-JS-thread `JsCell` projection; held only // across the libuv enqueue (copies `path` internally). let path = args .path @@ -4980,11 +4980,11 @@ impl NodeFS { // buf_to_free dropped at scope exit let mut remain = stat_size.max(0) as u64; - // VERIFY-FIX(round1): Zig `while (cond) {} else {}` runs the else only when - // the loop exits because `cond` became false — never on `break`. The - // `if remain == 0` check below was wrong: `break 'toplevel` after - // `remain` had already saturated to 0 would still enter the else. Track - // an explicit `broke` flag instead. + // Zig `while (cond) {} else {}` runs the else only when the loop exits + // because `cond` became false — never on `break`. An `if remain == 0` + // check would be wrong: `break 'toplevel` after `remain` had already + // saturated to 0 would still enter the else. Track an explicit `broke` + // flag instead. let mut broke = false; 'toplevel: while remain > 0 { let read_len = (buf.len() as u64).min(remain) as usize; @@ -5170,12 +5170,14 @@ impl NodeFS { let _close_src = scopeguard::guard(src_fd, |fd| fd.close()); let mut flags: i32 = sys::O::CREAT | sys::O::WRONLY; - // VERIFY-FIX(round1): was `usize` then passed as `&mut (wrote as u64)` — - // that wrote into a discarded temporary so the deferred ftruncate - // always saw 0. The scopeguard variant also double-borrowed `wrote`. - // The Zig `defer` runs after `copy_file_using_read_write_loop` returns - // into this scope; there are no early returns between open(dest) and - // that call, so inlining the cleanup after is equivalent. + // `wrote` must be `u64` (not `usize` reborrowed via + // `&mut (wrote as u64)`) — that would write into a discarded + // temporary so the deferred ftruncate would always see 0. A + // scopeguard variant also double-borrowed `wrote`. The Zig + // `defer` runs after `copy_file_using_read_write_loop` + // returns into this scope; there are no early returns + // between open(dest) and that call, so inlining the cleanup + // after is equivalent. let mut wrote: u64 = 0; if args.mode.shouldnt_overwrite() { flags |= sys::O::EXCL; @@ -5356,12 +5358,12 @@ impl NodeFS { } let mut flags: i32 = sys::O::CREAT | sys::O::WRONLY; - // VERIFY-FIX(round1): `wrote` is read by the deferred-close scopeguard - // *after* the copy loops below mutate it. As a `usize` captured by-copy - // the guard always saw 0, and the `&mut (wrote as u64)` call sites - // wrote into discarded temporaries. `Cell` lets the guard borrow - // by reference while the loops `get`/`set`, matching Zig's `var wrote: u64` - // observed by `defer` at scope-exit time. + // `wrote` is read by the deferred-close scopeguard *after* the copy + // loops below mutate it. As a `usize` captured by-copy the guard + // would always see 0, and `&mut (wrote as u64)` call sites would + // write into discarded temporaries. `Cell` lets the guard + // borrow by reference while the loops `get`/`set`, matching Zig's + // `var wrote: u64` observed by `defer` at scope-exit time. let wrote: core::cell::Cell = core::cell::Cell::new(0); if args.mode.shouldnt_overwrite() { flags |= sys::O::EXCL; diff --git a/src/runtime/node/node_fs_binding.rs b/src/runtime/node/node_fs_binding.rs index 10d4220107e..f96308be32b 100644 --- a/src/runtime/node/node_fs_binding.rs +++ b/src/runtime/node/node_fs_binding.rs @@ -54,7 +54,7 @@ where return Ok(JSValue::ZERO); } - // R-2: `JsCell::with_mut` scopes the `&mut NodeFS` to the blocking + // `JsCell::with_mut` scopes the `&mut NodeFS` to the blocking // syscall; `dispatch` never re-enters JS, and `Maybe` is fully owned // (`sys::Error.path` is `Box<[u8]>`, not a borrow into `sync_error_buf`). let mut result = this @@ -139,7 +139,7 @@ where run_sync:: } -// R-2 (host-fn re-entrancy): every JS-exposed binding takes `&self`; the +// Host-fn re-entrancy: every JS-exposed binding takes `&self`; the // single mutable field `node_fs` is wrapped in `JsCell` so the // `sync_error_buf` scratch buffer and `&mut NodeFS` syscall dispatches are // projected through interior mutability instead of `&mut Binding`. The @@ -231,7 +231,7 @@ impl Binding { return Ok(JSValue::ZERO); } - // R-2: blocking syscall — `&mut NodeFS` scoped to the call, no JS re-entry. + // Blocking syscall — `&mut NodeFS` scoped to the call, no JS re-entry. match this.node_fs.with_mut(|nfs| nfs.cp(&cp_args, Flavor::Sync)) { Err(ref err) => Err(global.throw_value(err.to_js(global))), Ok(()) => Ok(JSValue::UNDEFINED), @@ -283,7 +283,7 @@ impl Binding { return Ok(JSValue::ZERO); } - // R-2: `NodeFS::watch` only reads `self.vm` (no scratch-buffer write); + // `NodeFS::watch` only reads `self.vm` (no scratch-buffer write); // scoped via `with_mut` so the borrow cannot outlive the call. match this .node_fs @@ -421,7 +421,7 @@ pub fn create_binding(global: &JSGlobalObject) -> JSValue { let module = Binding::new(Binding::default()); let vm = global.bun_vm_ptr(); - // R-2: init-time write before the JS wrapper exists; `with_mut` here is + // Init-time write before the JS wrapper exists; `with_mut` here is // trivially un-aliased (sole owner of the fresh `Box`). module.node_fs.with_mut(|nfs| nfs.vm = NonNull::new(vm)); diff --git a/src/runtime/node/node_fs_stat_watcher.rs b/src/runtime/node/node_fs_stat_watcher.rs index 98e1cbb4e01..703e4d0e600 100644 --- a/src/runtime/node/node_fs_stat_watcher.rs +++ b/src/runtime/node/node_fs_stat_watcher.rs @@ -190,7 +190,7 @@ impl StatWatcherScheduler { pub fn append(this: *mut Self, watcher: *mut StatWatcher) { // BACKREF — `watcher` is a live ref-counted StatWatcher (we ref() it - // below). R-2: shared `&` only — all field access goes through + // below). Shared `&` only — all field access goes through // Cell/Atomic. `ParentRef` Deref collapses the per-site raw deref. let w = ParentRef::from(NonNull::new(watcher).expect("append: watcher")); log!("append new watcher {}", bstr::BStr::new(w.path.as_bytes())); @@ -355,7 +355,7 @@ impl StatWatcherScheduler { } // BACKREF — `watcher` is a live `*mut StatWatcher` from the intrusive // queue; alive because we hold a ref on it (taken in `append`). - // R-2: shared `&` only — `restat()` may enqueue a main-thread task + // Shared `&` only — `restat()` may enqueue a main-thread task // that derefs the same `StatWatcher` concurrently; aliased `&` is // sound where `&mut` would not be. `ParentRef` Deref gives that `&`. let w = ParentRef::from(NonNull::new(watcher).expect("work_pool_callback: watcher")); @@ -396,7 +396,7 @@ impl StatWatcherScheduler { // TODO: make this a top-level struct // -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). `closed` is // `AtomicBool` because it is genuinely cross-thread (written by `close()` on // the JS thread, read by the work-pool callback). `last_check` is `Cell` @@ -590,7 +590,7 @@ impl StatWatcher { fn deinit(this: *mut StatWatcher) { log!("deinit {:x}", this as usize); - // BACKREF — last ref; exclusive access. R-2: all field mutation goes + // BACKREF — last ref; exclusive access. All field mutation goes // through Cell/JsCell/Atomic so shared `&` suffices; `ParentRef` Deref // collapses the per-site raw deref. let this_ref = ParentRef::from(NonNull::new(this).expect("deinit: watcher")); @@ -674,7 +674,7 @@ impl StatWatcher { log!("Finalize\n"); // Refcounted: hand ownership back to the raw refcount FIRST so a panic // in the work below leaks instead of UAF-ing the scheduler's alias. - // R-2: do NOT form `&mut Self` — the work-pool thread may concurrently + // Do NOT form `&mut Self` — the work-pool thread may concurrently // hold `&*watcher` (see `work_pool_callback`); `Box::into_raw` then // `&*ptr` keeps the access shared. let this_ptr: *mut Self = bun_core::heap::into_raw(self); @@ -694,7 +694,7 @@ impl StatWatcher { // SAFETY: balance the ref from createAndSchedule(); raw ptr captured (not `&self`). let _ref_guard = unsafe { WatcherRefGuard::adopt(this) }; // BACKREF — `this` is alive (ref'd in - // InitialStatTask::create_and_schedule). R-2: all field access via + // InitialStatTask::create_and_schedule). All field access via // Cell/JsCell/Atomic; `ParentRef` Deref gives safe `&Self`. let this_ref = ParentRef::from(NonNull::new(this).expect("initial_stat_success: watcher")); if this_ref.closed.load(Ordering::Relaxed) { @@ -726,7 +726,7 @@ impl StatWatcher { // SAFETY: balance the ref from createAndSchedule(); raw ptr captured (not `&self`). let _ref_guard = unsafe { WatcherRefGuard::adopt(this) }; // BACKREF — `this` is alive (ref'd in - // InitialStatTask::create_and_schedule). R-2: `cb.call()` below + // InitialStatTask::create_and_schedule). `cb.call()` below // re-enters JS, which may call `do_close()` → fresh `&Self` from // m_ctx; aliased `&` is sound, aliased `&mut` is not. `ParentRef` // Deref gives that shared `&`. @@ -800,7 +800,7 @@ impl StatWatcher { } self.set_last_stat(&res); - // R-2: derive the ctx pointer from `&self` — the callback derefs it as + // Derive the ctx pointer from `&self` — the callback derefs it as // shared (`&*const`), so no write provenance is required. let this_ptr: *mut StatWatcher = self.as_ctx_ptr(); Self::ref_(this_ptr); // Ensure it stays alive long enough to receive the callback. @@ -816,7 +816,7 @@ impl StatWatcher { ) -> bun_event_loop::JsResult<()> { // SAFETY: balance the ref from restat(); raw ptr captured (not `&self`). let _ref_guard = unsafe { WatcherRefGuard::adopt(this) }; - // BACKREF — `this` is alive (ref'd in restat()). R-2: `cb.call()` + // BACKREF — `this` is alive (ref'd in restat()). `cb.call()` // below re-enters JS, which may call `do_close()` → fresh `&Self` from // m_ctx; aliased `&` is sound, aliased `&mut` is not (and the // work-pool thread may still hold `&*watcher`). `ParentRef` Deref @@ -894,7 +894,7 @@ impl StatWatcher { // path we own the only reference (sole-owner contract for `deinit`). let guard = scopeguard::guard(this_ptr, |p| Self::deinit(p)); // BACKREF — `this_ptr` just leaked from Box; alive until deref drops - // it. R-2: all field mutation goes through Cell/JsCell so shared `&` + // it. All field mutation goes through Cell/JsCell so shared `&` // suffices (and `to_js_ptr` below creates the JS wrapper, after which // the codegen shim may form its own `&Self`). `ParentRef` Deref gives // that shared `&`. @@ -1066,7 +1066,7 @@ impl InitialStatTask { // `enqueue_task_concurrent` take `&self` (mutation goes through // `Guarded`/atomics). The main thread may concurrently run // `close()`/`finalize()` after `init()` returns the watcher to JS; - // both also deref as shared (R-2), so aliased `&` is sound. + // both also deref as shared, so aliased `&` is sound. // `ParentRef` Deref gives that shared `&`. let this_ref = ParentRef::from(NonNull::new(this).expect("run_owned: watcher")); diff --git a/src/runtime/node/node_fs_watcher.rs b/src/runtime/node/node_fs_watcher.rs index ca35b100346..573de97f89b 100644 --- a/src/runtime/node/node_fs_watcher.rs +++ b/src/runtime/node/node_fs_watcher.rs @@ -33,7 +33,7 @@ use super::path_watcher; use super::win_watcher as path_watcher; // TODO: make this a top-level struct -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). `&mut Self` // carried LLVM `noalias`, so a host-fn that re-entered JS while holding it let // the optimiser cache `self.closed` etc. across the FFI call — the `*mut Self` @@ -157,7 +157,7 @@ impl FSWatchTaskPosix { fn ctx(&self) -> &FSWatcher { // BACKREF — `ctx` is the live owning FSWatcher (set right after // boxing in `init`); FSWatcher outlives all its tasks. - // R-2: `ParentRef: Deref` yields `&FSWatcher`; all + // `ParentRef: Deref` yields `&FSWatcher`; all // FSWatcher host-fns take `&self` (Cell/JsCell-backed). self.ctx.as_ref().expect("FSWatchTask.ctx unset").get() } @@ -404,7 +404,7 @@ impl FSWatchTaskWindows { // `onPathUpdateWindows` and the posix `enqueue()` path). // SAFETY: ParentRef — `ctx` is the live owning FSWatcher set at // construction; FSWatcher outlives every task it enqueues. - // R-2: `ref_task` takes `&self`; ParentRef Derefs to `&FSWatcher`. + // `ref_task` takes `&self`; ParentRef Derefs to `&FSWatcher`. if !ctx.expect("FSWatchTask.ctx unset").ref_task() { return; } @@ -426,7 +426,7 @@ impl FSWatchTaskWindows { /// this runs on JS Context Thread pub fn run(&mut self) { // BACKREF — `self.ctx` is the live owning FSWatcher (set at - // construction), outliving every task it enqueues. R-2: all FSWatcher + // construction), outliving every task it enqueues. All FSWatcher // methods below take `&self`, so a single `&FSWatcher` held across the // match is sound (aliased shared borrows are fine; the old `*mut Self` // re-derive dance is no longer needed). `ParentRef` Derefs to `&T`. @@ -496,7 +496,7 @@ impl FSWatcher { /// /// Centralises the set-once `Option<*mut c_void> → &FSWatcher` deref so the /// three watcher-backend callbacks (`on_path_update_*`, `on_update_end`) - /// stay safe at the call site. R-2: deref as shared — all `FSWatcher` + /// stay safe at the call site. Deref as shared — all `FSWatcher` /// mutation goes through `Cell`/`JsCell`. #[inline] fn from_ctx<'a>(ctx: Option<*mut c_void>) -> &'a FSWatcher { @@ -714,7 +714,7 @@ impl<'a> Arguments<'a> { } impl AbortListener for FSWatcher { - // R-2: trait sig is fixed at `&mut self`; body just reborrows as `&self` + // Trait sig is fixed at `&mut self`; body just reborrows as `&self` // (auto-deref) and calls the interior-mutable `emit_abort`. fn on_abort(&mut self, reason: JSValue) { (*self).emit_abort(reason); @@ -738,7 +738,7 @@ impl FSWatcher { /// JS-thread only. pub unsafe fn init_js(this: *mut Self, listener: JSValue) { // SAFETY: caller contract — `this` is uniquely owned and live. - // R-2: deref as shared; mutation goes through `Cell`/`JsCell`. + // Deref as shared; mutation goes through `Cell`/`JsCell`. let this_ref = unsafe { &*this }; if this_ref.persistent.get() { let vm_ctx = this_ref.vm_ctx(); @@ -780,7 +780,7 @@ impl FSWatcher { } } - /// R-2: `&self` + `Cell` for `closed` makes the old `*mut Self` + /// `&self` + `Cell` for `closed` makes the old `*mut Self` /// re-derive dance unnecessary. `listener.call_with_global_this(...)` /// re-enters JS, which can call `watcher.close()` on this same object via /// the wrapper's `m_ptr` — setting `closed = true` and `detach()`-ing. @@ -821,7 +821,7 @@ impl FSWatcher { self.close(); } - /// R-2: see `emit_abort` — `&self` + `Cell` so the trailing `close()` + /// See `emit_abort` — `&self` + `Cell` so the trailing `close()` /// observes a re-entrant `watcher.close()` from inside the listener. pub fn emit_error(&self, err: bun_sys::Error) { if self.closed.get() { @@ -930,7 +930,7 @@ impl FSWatcher { // this can be called from Watcher Thread or JS Context Thread pub fn ref_task(&self) -> bool { let _guard = self.mutex.lock_guard(); - // R-2: `closed: Cell` is `!Sync`, but `FSWatcher` itself is + // `closed: Cell` is `!Sync`, but `FSWatcher` itself is // `!Sync` (raw-pointer fields, no `unsafe impl Sync`); cross-thread // access goes through `*mut FSWatcher` in `FSWatchTask.ctx` exactly as // before. The mutex serialises this read against the JS-thread @@ -1073,7 +1073,7 @@ impl FSWatcher { pending_activity_count: AtomicU32::new(1), })); // SAFETY: `ctx` is the freshly-boxed payload; uniquely owned here. - // R-2: deref as shared; mutation goes through `JsCell`. + // Deref as shared; mutation goes through `JsCell`. let ctx_ref = unsafe { &*ctx }; // SAFETY: `ctx` is the heap-stable Box address; write provenance. ctx_ref diff --git a/src/runtime/node/node_os.rs b/src/runtime/node/node_os.rs index 648a9adbe86..c4e554aa43e 100644 --- a/src/runtime/node/node_os.rs +++ b/src/runtime/node/node_os.rs @@ -49,7 +49,7 @@ mod _impl { use bun_sys::windows::{self, libuv}; use std::io::Write as _; - // ─── local shims for upstream API gaps (Phase D) ────────────────────────── + // ─── local shims for upstream API gaps ──────────────────────────────────── /// Unified error for `cpus_impl_*` so `?` works on both `JsResult` and /// `bun_core::Error`/`bun_sys::Error`. The variant payload is discarded by diff --git a/src/runtime/node/node_zlib_binding.rs b/src/runtime/node/node_zlib_binding.rs index 3c2dc648c10..cad8807ab21 100644 --- a/src/runtime/node/node_zlib_binding.rs +++ b/src/runtime/node/node_zlib_binding.rs @@ -213,7 +213,7 @@ pub trait CompressionContext { fn update_write_result(&mut self, avail_in: &mut u32, avail_out: &mut u32); } -// R-2 (host-fn re-entrancy): every JS-exposed mixin method takes `&T`; per-field +// Host-fn re-entrancy: every JS-exposed mixin method takes `&T`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). Accessors return the // cell wrapper so the mixin can `.get()`/`.set()`/`.with_mut()` as needed. pub trait CompressionStreamImpl: Sized + Taskable + 'static { @@ -447,8 +447,8 @@ impl CompressionStream { fn async_job_run(this: *mut T) { // BACKREF — `this` is the live heap m_ctx payload (kept alive by the - // `ref_()` in `write()`); bodies use the `&self` accessor surface - // (R-2). `ParentRef` Deref collapses the per-site raw deref. + // `ref_()` in `write()`); bodies use the `&self` accessor surface. + // `ParentRef` Deref collapses the per-site raw deref. let this_ref = ParentRef::from(NonNull::new(this).expect("async_job_run: this")); let global_this: &JSGlobalObject = this_ref.global_this(); // Zig: `bunVMConcurrently()` — thread-safe accessor (skips the @@ -475,7 +475,7 @@ impl CompressionStream { /// Dispatched from `dispatch.rs` when the worker-thread `do_work()` posts /// the completion task back to the JS thread. /// - /// R-2: takes `*mut T` (full allocation provenance from `Task.ptr`) so the + /// Takes `*mut T` (full allocation provenance from `Task.ptr`) so the /// trailing `T::deref(this_ptr)` may free the box if it hits zero. All /// field access goes through `&*this_ptr` and the `&self` accessor surface; /// every accessed field is `Cell`/`JsCell`-backed so re-entry via the @@ -486,7 +486,7 @@ impl CompressionStream { /// `ref_()` in `write()` keeps it alive until the trailing `deref()`. pub unsafe fn run_from_js_thread(this_ptr: *mut T) { // BACKREF — see fn-level contract; `ParentRef` Deref gives safe `&T` - // for the `&self` accessor surface (R-2). + // for the `&self` accessor surface. let this = ParentRef::from(NonNull::new(this_ptr).expect("run_from_js_thread: this")); let global: &JSGlobalObject = this.global_this(); // SAFETY: `bun_vm()` never returns null for a Bun-owned global. @@ -758,7 +758,7 @@ impl CompressionStream { } pub fn emit_error(this: &T, global_this: &JSGlobalObject, this_value: JSValue, err_: Error) { - // R-2: `&T` over `Cell`/`JsCell`-backed fields — the onerror + // `&T` over `Cell`/`JsCell`-backed fields — the onerror // `run_callback` below runs user JS which can re-enter via a fresh // `&T` from the wrapper's `m_ctx` (e.g. `write()` flips // `write_in_progress` / `pending_*`). Interior mutability makes the @@ -851,7 +851,7 @@ impl CompressionStream { macro_rules! __compression_stream_mixin_reexports { ($native:ty) => { impl $native { - // R-2: `this: &Self` — see CompressionStreamImpl note above. + // `this: &Self` — see CompressionStreamImpl note above. #[inline] pub fn write( this: &Self, diff --git a/src/runtime/node/zlib/NativeBrotli.rs b/src/runtime/node/zlib/NativeBrotli.rs index 9881d172306..bc52200dbfa 100644 --- a/src/runtime/node/zlib/NativeBrotli.rs +++ b/src/runtime/node/zlib/NativeBrotli.rs @@ -74,7 +74,7 @@ mod _impl { // `.classes.ts`-backed: the C++ JSCell wrapper (JSNativeBrotli) is generated; // this struct is the `m_ctx` payload. Codegen provides toJS/fromJS/fromJSDirect. - // R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field + // Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). #[bun_jsc::JsClass] #[derive(bun_ptr::CellRefCounted)] diff --git a/src/runtime/node/zlib/NativeZlib.rs b/src/runtime/node/zlib/NativeZlib.rs index e213fc9f128..a9f2609e725 100644 --- a/src/runtime/node/zlib/NativeZlib.rs +++ b/src/runtime/node/zlib/NativeZlib.rs @@ -194,7 +194,7 @@ mod _impl { let err = self.stream.with_mut(|s| s.set_params(level, strategy)); if err.is_error() { - // R-2: `&self` over `Cell`/`JsCell` fields — `emit_error` → + // `&self` over `Cell`/`JsCell` fields — `emit_error` → // `run_callback` may re-enter `close()`/`reset()` via a fresh // `&Self` from `m_ctx`; interior mutability makes that sound. CompressionStream::::emit_error(self, global, frame.this(), err); diff --git a/src/runtime/node/zlib/NativeZstd.rs b/src/runtime/node/zlib/NativeZstd.rs index c9d24995f4d..a2f8ceecd70 100644 --- a/src/runtime/node/zlib/NativeZstd.rs +++ b/src/runtime/node/zlib/NativeZstd.rs @@ -29,7 +29,7 @@ mod _impl { unreachable!("WorkPoolTask scheduled before CompressionStream set its callback"); } - // R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field + // Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // `host_fn_this` shim still passes `&mut NativeZstd` — `&mut T` auto-reborrows // to `&T` so the impls below compile against either. diff --git a/src/runtime/server/HTMLBundle.rs b/src/runtime/server/HTMLBundle.rs index 66588d74d89..ecfff886382 100644 --- a/src/runtime/server/HTMLBundle.rs +++ b/src/runtime/server/HTMLBundle.rs @@ -143,7 +143,7 @@ pub type HTMLBundleRoute = Route; /// HTMLBundle.Route can only be used on one server, but is also /// reference-counted because a server can have multiple instances of the same /// html file on multiple endpoints. -// R-2 (host-fn re-entrancy): every uws/event-loop-reachable method takes +// Host-fn re-entrancy: every uws/event-loop-reachable method takes // `&self`; per-field interior mutability via `Cell` (Copy) / `JsCell` // (non-Copy). `*mut Route` is recovered from uws userdata and the // `JSBundleCompletionTask` backref while a prior `&Route` may still be on the @@ -272,7 +272,7 @@ impl Route { // bumps the count and derefs on every exit path. let _keep_alive = unsafe { bun_ptr::ScopedRef::new(this) }; // SAFETY: held alive by `_keep_alive`; single-threaded (uws JS-thread - // callback). R-2: deref as shared (`&*`) — every method below takes + // callback). Deref as shared (`&*`) — every method below takes // `&self`; mutation goes through `Cell`/`JsCell`. let route = unsafe { &*this }; @@ -289,7 +289,7 @@ impl Route { match req { AnyRequest::H1(h1) => { // S008: `uws::Request` is an `opaque_ffi!` ZST — safe deref. - // R-2: pass the raw `this` (not `route: &Route`) so + // Pass the raw `this` (not `route: &Route`) so // DevServer's `*mut Route` userdata path doesn't alias // a live shared borrow. bun_core::handle_oom(dev.respond_for_html_bundle( @@ -307,7 +307,7 @@ impl Route { } // Simpler development workflow which rebundles on every request. - // R-2: swap the state out *before* running its destructor so no + // Swap the state out *before* running its destructor so no // `&mut State` borrow into `route.state` is live across the // `StaticRoute::deref_` / `JSBundleCompletionTask::deref` calls. if matches!(route.state.get(), State::Html(_) | State::Err(_)) { @@ -720,7 +720,7 @@ impl Route { } pub fn resume_pending_responses(&self) { - // R-2: `JsCell::replace` moves the Vec out so the per-response loop + // `JsCell::replace` moves the Vec out so the per-response loop // (which writes responses and may run uws callbacks) holds no borrow // into `self.pending_responses`. let pending = self.pending_responses.replace(Vec::new()); @@ -831,10 +831,10 @@ impl PendingResponse { // PORT NOTE: reshaped for borrowck — Zig accessed this.route.pending_responses through // raw ptr; mutate via raw ptr (single-threaded). - // SAFETY: single-threaded; Route is alive (we hold a ref). R-2: deref as + // SAFETY: single-threaded; Route is alive (we hold a ref). Deref as // shared (`&*`); `pending_responses` is `JsCell`-wrapped. let route = unsafe { &*route_ptr }; - // R-2: scope the `&mut Vec` to the find+remove only — `RefCount::deref` + // Scope the `&mut Vec` to the find+remove only — `RefCount::deref` // can run `Route::drop` (which `get()`s `pending_responses`) and must // not overlap a live `with_mut` borrow. let removed = route.pending_responses.with_mut(|v| { diff --git a/src/runtime/server/NodeHTTPResponse.rs b/src/runtime/server/NodeHTTPResponse.rs index 54167d0c4c3..d888363c478 100644 --- a/src/runtime/server/NodeHTTPResponse.rs +++ b/src/runtime/server/NodeHTTPResponse.rs @@ -30,7 +30,7 @@ bun_core::declare_scope!(NodeHTTPResponse, visible); /// `__fromJSDirect` / `__create` externs into a `JsClass` impl plus an /// inherent `to_js_ptr(*mut Self, &JSGlobalObject)`; `noConstructor: true` /// in `server.classes.ts` means no `${T}__getConstructor` is exported. -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). #[bun_jsc::JsClass(no_constructor)] pub struct NodeHTTPResponse { @@ -248,7 +248,7 @@ fn any_response_is_ssl(r: &uws::AnyResponse) -> bool { // `Fn(*mut U, ...)` (capture-less); adapt to `&self` method bodies. fn on_timeout_shim(this: *mut NodeHTTPResponse, resp: uws::AnyResponse) { // SAFETY: registered with `self`'s address; live while callback is armed. - // R-2: deref as shared (`&*const`) — bodies take `&self`. + // Deref as shared (`&*const`) — bodies take `&self`. unsafe { (*this.cast_const()).on_timeout(resp) } } fn on_data_shim(this: *mut NodeHTTPResponse, chunk: &[u8], last: bool) { @@ -264,7 +264,7 @@ fn on_drain_shim(this: *mut NodeHTTPResponse, off: u64, resp: uws::AnyResponse) unsafe { (*this.cast_const()).on_drain(off, resp) } } -// R-2: `HasAutoFlusher` (which requires `fn auto_flusher(&mut self)`) is no +// `HasAutoFlusher` (which requires `fn auto_flusher(&mut self)`) is no // longer implemented here — the deferred-task registration is inlined in // `register_auto_flush` / `unregister_auto_flush` below so the whole path is // `&self`. The `DeferredRepeatingTask` trampoline that the trait would have @@ -311,7 +311,7 @@ pub mod js { } impl NodeHTTPResponse { - // ─── R-2 interior-mutability helpers ───────────────────────────────────── + // ─── Interior-mutability helpers ───────────────────────────────────────── /// Read-modify-write the packed `Cell` through `&self`. #[inline] @@ -412,7 +412,7 @@ impl NodeHTTPResponse { let mut sec_websocket_protocol_str: Option = None; let mut sec_websocket_extensions_str: Option = None; - // R-2: `JsCell::get()` projects `&UpgradeCTX`; the borrow lives until + // `JsCell::get()` projects `&UpgradeCTX`; the borrow lives until // the explicit `drop`s below (no `with_mut` on this cell overlaps). let upgrade_context: &UpgradeCTX = self.upgrade_context.get(); @@ -1075,7 +1075,7 @@ pub fn node_http_request_on_resolve( scoped_log!(NodeHTTPResponse, "onResolve"); let arguments = callframe.arguments_old::<2>(); // arguments[1] is the JSNodeHTTPResponse cell from the resolve callback. - // R-2: deref shared — `maybe_stop_reading_body`/`on_request_complete` re-enter. + // Deref shared — `maybe_stop_reading_body`/`on_request_complete` re-enter. let this: &NodeHTTPResponse = arguments.ptr[1].as_class_ref::().unwrap(); this.promise.with_mut(|p| p.deinit()); // defer this.deref(); — moved to tail. @@ -1111,7 +1111,7 @@ pub fn node_http_request_on_reject( let arguments = callframe.arguments_old::<2>(); let err = arguments.ptr[0]; // arguments[1] is the JSNodeHTTPResponse cell from the reject callback. - // R-2: deref shared — `maybe_stop_reading_body`/`on_request_complete` re-enter. + // Deref shared — `maybe_stop_reading_body`/`on_request_complete` re-enter. let this: &NodeHTTPResponse = arguments.ptr[1].as_class_ref::().unwrap(); this.promise.with_mut(|p| p.deinit()); this.maybe_stop_reading_body(bun_vm_mut(global_object), arguments.ptr[1]); @@ -1362,7 +1362,7 @@ impl NodeHTTPResponse { }); } - // PORT NOTE: re-read raw_response at each use site (R-2: methods that + // PORT NOTE: re-read raw_response at each use site (methods that // re-enter may clear it). let state = self.raw_response.get().unwrap().state(); if !state.is_response_pending() { @@ -1718,7 +1718,7 @@ impl NodeHTTPResponse { false } - // R-2: inlined `AutoFlusher::register_deferred_microtask_with_type_unchecked` + // Inlined `AutoFlusher::register_deferred_microtask_with_type_unchecked` // — that helper now takes `&T`, but this type has its own // `on_auto_flush_trampoline` (extra `self.ref_()`) so the inline body // stays. @@ -1843,13 +1843,13 @@ impl NodeHTTPResponse { let mut result: JSValue = JSValue::ZERO; let mut is_exception: bool = false; - // R-2: this method takes `&self`, so the `noalias` miscompile - // (b818e70e1c57) is structurally impossible — `&T` is `readonly`, not - // `noalias`, so re-entrant writes through other `&self` views are - // sound. No `black_box` launder is needed; it was a hard optimization - // barrier on the node:http hot path (`cork` runs on every `res.end()`) - // that forced `self` to memory and blocked inlining/regalloc of the - // cork prologue, with no equivalent in upstream Zig. + // This method takes `&self`, so the `noalias` miscompile is + // structurally impossible — `&T` is `readonly`, not `noalias`, so + // re-entrant writes through other `&self` views are sound. No + // `black_box` launder is needed; it was a hard optimization barrier on + // the node:http hot path (`cork` runs on every `res.end()`) that + // forced `self` to memory and blocked inlining/regalloc of the cork + // prologue, with no equivalent in upstream Zig. let this = bun_ptr::BackRef::from(ptr::NonNull::from(self)); // BACKREF: `this` is the live `m_ctx` heap payload; `ref_()` keeps it // alive across re-entry. diff --git a/src/runtime/server/ServerWebSocket.rs b/src/runtime/server/ServerWebSocket.rs index 82345a37eea..53bf4cbfdde 100644 --- a/src/runtime/server/ServerWebSocket.rs +++ b/src/runtime/server/ServerWebSocket.rs @@ -24,7 +24,7 @@ bun_output::declare_scope!(WebSocketServer, visible); // lives in `ServerConfig.websocket` for the server's lifetime. Raw `*const` + // SAFETY notes is the runtime shape. // -// R-2 (PORT_NOTES_PLAN): every uws/JS callback into this socket can re-enter +// noalias re-entry (see bun_ptr::LaunderedSelf): every uws/JS callback into this socket can re-enter // — `on_open` → `ws.cork(JS)` → `ws.close()` → `on_close` mutates `flags` / // `this_value` on the SAME `m_ctx`. A `&mut Self` receiver would alias under // Stacked Borrows. Receivers therefore take `&self`; per-field interior @@ -205,7 +205,7 @@ impl ServerWebSocket { self.flags.get().websocket() } - /// R-2 helper: read-modify-write the packed `Cell` through `&self`. + /// Helper: read-modify-write the packed `Cell` through `&self`. /// `Flags` is a `Copy` `u64` so the load/store pair is the same codegen as /// the old `&mut self` field write. #[inline] @@ -367,7 +367,7 @@ impl ServerWebSocket { // C++ JS wrapper (freed via `ServerWebSocketClass__finalize` → `finalize`). let this_value = unsafe { ServerWebSocket::to_js_ptr(this, global_object) }; // SAFETY: just allocated; the JS wrapper holds the box but does not - // touch the Rust fields concurrently (single JS thread). R-2: shared + // touch the Rust fields concurrently (single JS thread). Shared // borrow + `JsCell::set` — no `&mut Self` formed. let this_ref = unsafe { &*this }; this_ref @@ -384,7 +384,7 @@ impl ServerWebSocket { self.websocket().memory_cost() + mem::size_of::() } - /// R-2 (noalias re-entrancy): `&self`, NOT `&mut self`. `ws.cork(...)` + /// Noalias re-entrancy: `&self`, NOT `&mut self`. `ws.cork(...)` /// re-enters JS which can `ws.close()` / `ws.send()` on this same socket /// via the JS wrapper's `m_ptr`, flipping `flags.closed`. All state lives /// behind `Cell`/`JsCell`, so the re-entrant frame's writes are visible @@ -453,7 +453,7 @@ impl ServerWebSocket { } } - /// `&self` for the same noalias-reentry reason as `on_open` (R-2). + /// `&self` for the same noalias-reentry reason as `on_open`. pub fn on_message(&self, ws: AnyWebSocket, message: &[u8], opcode: Opcode) { bun_output::scoped_log!( WebSocketServer, @@ -532,7 +532,7 @@ impl ServerWebSocket { self.flags.get().closed() } - /// `&self` for the same noalias-reentry reason as `on_open` (R-2). + /// `&self` for the same noalias-reentry reason as `on_open`. pub fn on_drain(&self, _ws: AnyWebSocket) { bun_output::scoped_log!(WebSocketServer, "onDrain"); let handler = self.handler(); @@ -576,7 +576,7 @@ impl ServerWebSocket { } } - /// `&self` for the same noalias-reentry reason as `on_open` (R-2). + /// `&self` for the same noalias-reentry reason as `on_open`. pub fn on_ping(&self, _ws: AnyWebSocket, data: &[u8]) { bun_output::scoped_log!(WebSocketServer, "onPing: {}", bstr::BStr::new(data)); let handler = self.handler(); @@ -605,7 +605,7 @@ impl ServerWebSocket { } } - /// `&self` for the same noalias-reentry reason as `on_open` (R-2). + /// `&self` for the same noalias-reentry reason as `on_open`. pub fn on_pong(&self, _ws: AnyWebSocket, data: &[u8]) { bun_output::scoped_log!(WebSocketServer, "onPong: {}", bstr::BStr::new(data)); let handler = self.handler(); @@ -639,7 +639,7 @@ impl ServerWebSocket { } } - /// `&self` for the same noalias-reentry reason as `on_open` (R-2). + /// `&self` for the same noalias-reentry reason as `on_open`. /// Re-entrant `ws.close()` from the close handler routes through the same /// `Cell` / `JsCell`, so no `noalias` view is invalidated. pub fn on_close(&self, _ws: AnyWebSocket, code: i32, message: &[u8]) { @@ -675,7 +675,7 @@ impl ServerWebSocket { sig.unref(); } if was_not_empty { - // R-2: closure-scoped `&mut JsRef` via `JsCell::with_mut` — + // Closure-scoped `&mut JsRef` via `JsCell::with_mut` — // no raw `*mut` projection needed. this_value_cell.with_mut(|v| v.downgrade()); } @@ -1321,7 +1321,7 @@ impl ServerWebSocket { } // `passThis: true` — wrapper emitted by generated_classes.rs. - // R-2: `&self` — `websocket().end()` synchronously dispatches `on_close` + // `&self` — `websocket().end()` synchronously dispatches `on_close` // on this same `m_ctx`; a `&mut self` here would alias. pub fn close( &self, @@ -1365,7 +1365,7 @@ impl ServerWebSocket { } // `passThis: true` — wrapper emitted by generated_classes.rs. - // R-2: `&self` — `websocket().close()` synchronously dispatches `on_close`. + // `&self` — `websocket().close()` synchronously dispatches `on_close`. pub fn terminate( &self, _global_this: &JSGlobalObject, @@ -1528,7 +1528,7 @@ impl ServerWebSocket { // for `onOpen`/`onMessage`/etc. via `@hasDecl`. Rust needs an explicit trait // impl; delegate straight to the inherent methods above. impl WebSocketHandler for ServerWebSocket { - // R-2: trait keeps `*mut Self` (FFI userdata round-trip needs raw write + // Trait keeps `*mut Self` (FFI userdata round-trip needs raw write // provenance); the single `&*this` reborrow here is the ONE audited unsafe // boundary. Inherent `on_*` take `&self`, so the re-entrant JS dispatch // never stacks a `noalias` `&mut ServerWebSocket`. diff --git a/src/runtime/shell/IOWriter.rs b/src/runtime/shell/IOWriter.rs index 5d8628e3469..22402ddc100 100644 --- a/src/runtime/shell/IOWriter.rs +++ b/src/runtime/shell/IOWriter.rs @@ -910,7 +910,7 @@ impl IOWriter { return; }; // SAFETY: interp outlives every IOWriter (it owns the IO struct that - // holds the Arc). Single-threaded; R-2: `Interpreter::run` takes + // holds the Arc). Single-threaded; `Interpreter::run` takes // `&self` now — `ParentRef: Deref` yields the // shared borrow without `assume_mut()`. y.run(&interp); diff --git a/src/runtime/shell/ParsedShellScript.rs b/src/runtime/shell/ParsedShellScript.rs index b6b241de899..5129fd0a7d9 100644 --- a/src/runtime/shell/ParsedShellScript.rs +++ b/src/runtime/shell/ParsedShellScript.rs @@ -16,7 +16,7 @@ use super::{EnvMap, EnvStr, Interpreter}; // `toJS`/`fromJS`/`fromJSDirect` re-exports are provided by the // `#[bun_jsc::JsClass]` derive in Rust — do not hand-port them. -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). #[bun_jsc::JsClass(no_constructor)] pub struct ParsedShellScript { diff --git a/src/runtime/shell/interpreter.rs b/src/runtime/shell/interpreter.rs index ece70d0c254..08dc97ac72e 100644 --- a/src/runtime/shell/interpreter.rs +++ b/src/runtime/shell/interpreter.rs @@ -202,7 +202,7 @@ macro_rules! node_accessors { #[track_caller] #[allow(clippy::mut_from_ref)] pub fn $get_mut(&self, id: NodeId) -> &mut $ty { - // SAFETY: R-2 single-JS-thread invariant — see `nodes_mut`. + // SAFETY: single-JS-thread invariant — see `nodes_mut`. match unsafe { &mut self.nodes.get_mut()[id.idx()] } { Node::$variant(v) => v, other => panic!( @@ -289,7 +289,7 @@ pub const STDERR_NO: usize = 2; /// This interpreter works by basically turning the AST into a state machine so /// that execution can be suspended and resumed to support async. -// R-2 (host-fn re-entrancy): every JS-exposed method — and the entire +// Host-fn re-entrancy: every JS-exposed method — and the entire // state-machine dispatch reachable from `run_from_js` — takes `&self`. // Per-field interior mutability via `Cell` (Copy) / `JsCell` (non-Copy) makes // the noalias-based `&mut self` caching miscompile structurally impossible: @@ -879,7 +879,7 @@ macro_rules! shell_state_dispatch { } impl Interpreter { - // ─── R-2 interior-mutability helpers ───────────────────────────────────── + // ─── Interior-mutability helpers ───────────────────────────────────────── /// `&self` → `*mut Self` for ctx slots. Kept inherent (NOT via the /// `bun_ptr::AsCtxPtr` blanket trait) so `Box` callers @@ -901,7 +901,7 @@ impl Interpreter { /// Mutable projection of the node arena from `&self`. /// /// # Safety - /// R-2 single-JS-thread invariant: the state machine never holds two + /// single-JS-thread invariant: the state machine never holds two /// `&mut` into `nodes` simultaneously (borrowck previously enforced this /// via `&mut Interpreter`; that discipline is preserved at every call /// site). Do **not** hold the returned borrow across any call that may @@ -1306,7 +1306,7 @@ impl Interpreter { // unconditionally. Paired with the increment in `run_from_js`; harmless // wrap on the mini path (flag is only read from the JS GC // `hasPendingActivity()` hook). - // R-2: `&self` lets the guard borrow the atomic directly — no raw-ptr + // `&self` lets the guard borrow the atomic directly — no raw-ptr // dance needed (the previous reshape existed only for `&mut self`). struct DecrOnDrop<'a>(&'a AtomicU32); impl Drop for DecrOnDrop<'_> { @@ -3169,7 +3169,7 @@ pub fn create_shell_interpreter( let parsed_shell_script = ParsedShellScript::from_js(parsed_shell_script_js) .ok_or_else(|| global.throw(format_args!("shell: expected a ParsedShellScript")))?; - // SAFETY: from_js returned a live wrapper-owned heap pointer. R-2: deref as + // SAFETY: from_js returned a live wrapper-owned heap pointer. Deref as // shared (`&*const`) — `ParsedShellScript`'s methods/fields are `&self` + // interior-mutable, so no `&mut` is required (and forming one here would // alias if JS re-enters another host fn on the same wrapper). diff --git a/src/runtime/shell/states/Expansion.rs b/src/runtime/shell/states/Expansion.rs index d732bc1d442..9e1901b3d26 100644 --- a/src/runtime/shell/states/Expansion.rs +++ b/src/runtime/shell/states/Expansion.rs @@ -123,7 +123,7 @@ impl Expansion { loop { // Split-borrow: `me` from `nodes`, `vm_args_utf8` from its own // field, so `expand_simple_no_io` can expand `$N` without aliasing. - // R-2: both are `JsCell`-backed; `as_ptr()`/`node_mut()` project + // Both are `JsCell`-backed; `as_ptr()`/`node_mut()` project // disjoint `&mut` from `&Interpreter`. let event_loop = interp.event_loop; let command_ctx = interp.command_ctx; diff --git a/src/runtime/socket/Handlers.rs b/src/runtime/socket/Handlers.rs index 8867b87a3f6..6dd308db09c 100644 --- a/src/runtime/socket/Handlers.rs +++ b/src/runtime/socket/Handlers.rs @@ -246,7 +246,7 @@ impl Handlers { if mode == SocketMode::Server { // SAFETY: server-mode caller contract — `this` addresses the // `handlers` field of a `Listener` with whole-`Listener` - // provenance. R-2: `Listener.handlers` is `JsCell` + // provenance. `Listener.handlers` is `JsCell` // (`#[repr(transparent)]`), so the field offset equals the // inner `Handlers` address; `from_field_ptr!` arithmetic is // unchanged. Deref as shared (`&*`) — celled fields below diff --git a/src/runtime/socket/Listener.rs b/src/runtime/socket/Listener.rs index 510762471ef..2d69e061848 100644 --- a/src/runtime/socket/Listener.rs +++ b/src/runtime/socket/Listener.rs @@ -61,7 +61,7 @@ fn vm_ssl_ctx_cache() -> *mut crate::api::SSLContextCache::SSLContextCache { // `to_js(self)` impl does would invalidate that link). use crate::generated_classes::js_Listener; -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim still emits `this: &mut Listener` — `&mut T` auto-derefs to `&T` // so the impls below compile against either. @@ -1541,7 +1541,7 @@ pub fn js_add_server_name(global: &JSGlobalObject, frame: &CallFrame) -> JsResul let listener = arguments.ptr[0]; if let Some(this) = Listener::from_js(listener) { // SAFETY: from_js returned a non-null *mut Listener; the JS wrapper holds it. - // R-2: deref as shared (`&*`) — `add_server_name` takes `&Self`. + // Deref as shared (`&*`) — `add_server_name` takes `&Self`. return Listener::add_server_name( unsafe { &*this }, global, diff --git a/src/runtime/socket/SocketAddress.rs b/src/runtime/socket/SocketAddress.rs index 6e259fdcd79..ea9baf3fd59 100644 --- a/src/runtime/socket/SocketAddress.rs +++ b/src/runtime/socket/SocketAddress.rs @@ -16,7 +16,7 @@ use bun_cares_sys::c_ares as ares; // `pub const js = jsc.Codegen.JSSocketAddress;` + toJS/fromJS/fromJSDirect // → handled by the JsClass derive; codegen wires toJS/fromJS/fromJSDirect. -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; the one +// Host-fn re-entrancy: every JS-exposed method takes `&self`; the one // field written from a host_fn-reachable path (`_presentation`, lazily filled // by `address()`) is `Cell`-wrapped (`BunString` is `Copy`). `_addr` is // read-only after construction and stays bare. diff --git a/src/runtime/socket/WindowsNamedPipe.rs b/src/runtime/socket/WindowsNamedPipe.rs index 6b0b6bc0191..41ef08da6c6 100644 --- a/src/runtime/socket/WindowsNamedPipe.rs +++ b/src/runtime/socket/WindowsNamedPipe.rs @@ -1165,7 +1165,7 @@ impl WindowsNamedPipe { #[bun_uws::uws_callback(export = "WindowsNamedPipe__close")] pub fn close(&mut self) { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `SSLWrapper::shutdown` re-enters via the handler vtable // (`trigger_close_callback` → `ssl_on_close` → fresh // `&mut WindowsNamedPipe` from `m_ctx`) and writes `self.flags` / @@ -1209,7 +1209,7 @@ impl WindowsNamedPipe { #[bun_uws::uws_callback(export = "WindowsNamedPipe__shutdown")] pub fn shutdown(&mut self) { - // PORT_NOTES_PLAN R-2: see `close` above — same `noalias`-cached-`flags` + // See `close` above (bun_ptr::LaunderedSelf) — same `noalias`-cached-`flags` // miscompile across `(*w).shutdown(false)`'s re-entry (ASM-verified // PROVEN_CACHED). Launder so post-call reads of `flags`/`wrapper` are // fresh. diff --git a/src/runtime/socket/socket_body.rs b/src/runtime/socket/socket_body.rs index 188febc70da..bcb8609f50a 100644 --- a/src/runtime/socket/socket_body.rs +++ b/src/runtime/socket/socket_body.rs @@ -244,7 +244,7 @@ extern "C" fn select_alpn_callback( // set of `${Name}__fromJS`/`__create` externs, but this type maps to TWO // codegen classes (`JSTCPSocket` / `JSTLSSocket`). The codegen accessors are // hand-dispatched per-monomorphisation in the `impl` block below instead. -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim still emits `this: &mut NewSocket` — `&mut T` auto-derefs to `&T` // so the impls below compile against either. With every @@ -329,7 +329,7 @@ impl NewSocket { // `to_js`/`from_js`/`from_js_direct`. `dataSetCached`/`dataGetCached` are // emitted as `Self::data_set_cached` / `Self::data_get_cached`. - // ─── R-2 interior-mutability helpers ───────────────────────────────────── + // ─── Interior-mutability helpers ───────────────────────────────────────── /// Read-modify-write the packed `Cell` through `&self`. #[inline] @@ -356,7 +356,7 @@ impl NewSocket { // is sound for that access. unsafe { bun_ptr::RefCount::::ref_(self.as_ctx_ptr()) }; } - // R-2: takes `&self` — every mutated field is `UnsafeCell`-backed so the + // Takes `&self` — every mutated field is `UnsafeCell`-backed so the // `*mut Self` formed for `RefCount::deref` (and onward into // `deinit_and_destroy`) writes only through interior-mutable storage. The // codegen host-fn shim still hands us a `&mut Self`-derived borrow whose @@ -729,7 +729,7 @@ impl NewSocket { /// slot holds the unique heap allocation); JS-thread only. pub unsafe fn on_writable(this: *mut Self, _socket: SocketHandler) { jsc::mark_binding!(); - // SAFETY (whole body): per fn contract; R-2 — every field is + // SAFETY (whole body): per fn contract; every field is // `Cell`/`JsCell`, so a single shared reborrow is sufficient and no // borrow spans `callback.call`. let this: &Self = unsafe { &*this }; @@ -783,7 +783,7 @@ impl NewSocket { /// `this` points at a live `NewSocket`; JS-thread only. pub unsafe fn on_timeout(this: *mut Self, _socket: SocketHandler) { jsc::mark_binding!(); - // SAFETY (whole body): per fn contract; R-2 shared reborrow. + // SAFETY (whole body): per fn contract; shared reborrow. let this: &Self = unsafe { &*this }; if this.socket.get().is_detached() { return; @@ -853,7 +853,7 @@ impl NewSocket { /// # Safety /// `this` points at a live `NewSocket`; JS-thread only. pub unsafe fn handle_connect_error(this: *mut Self, errno: c_int) -> JsResult<()> { - // SAFETY (whole body): per fn contract; R-2 — shared reborrow, all + // SAFETY (whole body): per fn contract; shared reborrow, all // mutated fields are `Cell`/`JsCell`. let this: &Self = unsafe { &*this }; let handlers = this.get_handlers(); @@ -1155,7 +1155,7 @@ impl NewSocket { /// # Safety /// `this` points at a live `NewSocket`; JS-thread only. pub unsafe fn on_open(this: *mut Self, socket: SocketHandler) { - // SAFETY (whole body): per fn contract; R-2 — shared reborrow, all + // SAFETY (whole body): per fn contract; shared reborrow, all // mutated fields are `Cell`/`JsCell`. let this_ptr = this; let this: &Self = unsafe { &*this }; @@ -1326,7 +1326,7 @@ impl NewSocket { /// `this` points at a live `NewSocket`; JS-thread only. pub unsafe fn on_end(this: *mut Self, _socket: SocketHandler) { jsc::mark_binding!(); - // SAFETY (whole body): per fn contract; R-2 shared reborrow. + // SAFETY (whole body): per fn contract; shared reborrow. let this: &Self = unsafe { &*this }; if this.socket.get().is_detached() { return; @@ -1380,7 +1380,7 @@ impl NewSocket { ssl_error: uws::us_bun_verify_error_t, ) -> JsResult<()> { jsc::mark_binding!(); - // SAFETY (whole body): per fn contract; R-2 shared reborrow. + // SAFETY (whole body): per fn contract; shared reborrow. let this: &Self = unsafe { &*this }; this.update_flags(|f| f.insert(Flags::HANDSHAKE_COMPLETE)); this.socket.set(s); @@ -1494,7 +1494,7 @@ impl NewSocket { reason: Option<*mut c_void>, ) -> JsResult<()> { jsc::mark_binding!(); - // SAFETY (whole body): per fn contract; R-2 shared reborrow. + // SAFETY (whole body): per fn contract; shared reborrow. let this: &Self = unsafe { &*this }; let handlers = this.get_handlers(); log!( @@ -1625,7 +1625,7 @@ impl NewSocket { /// `this` points at a live `NewSocket`; JS-thread only. pub unsafe fn on_data(this: *mut Self, s: SocketHandler, data: &[u8]) { jsc::mark_binding!(); - // SAFETY (whole body): per fn contract; R-2 shared reborrow. + // SAFETY (whole body): per fn contract; shared reborrow. let this: &Self = unsafe { &*this }; this.socket.set(s); if this.socket.get().is_detached() { @@ -2152,7 +2152,7 @@ impl NewSocket { let _ = self .buffered_data_for_node_net .with_mut(|b| b.append_slice(buffer.slice())); - // R-2: `write_maybe_corked` takes `&self` and does not touch + // `write_maybe_corked` takes `&self` and does not touch // `buffered_data_for_node_net`, so a `JsCell::get()` projection // is valid for the duration of the call. let rc = self.write_maybe_corked(self.buffered_data_for_node_net.get().slice()); @@ -2410,7 +2410,7 @@ impl NewSocket { } fn internal_flush(&self) { - // R-2: every mutated field is `Cell`/`JsCell`, so `&self` carries no + // Every mutated field is `Cell`/`JsCell`, so `&self` carries no // `noalias` for them and the previous `black_box` launder (which // mitigated ASM-verified PROVEN_CACHED stale loads of // `bytes_written`/`flags`/`buffered_data_for_node_net` across the diff --git a/src/runtime/socket/udp_socket.rs b/src/runtime/socket/udp_socket.rs index 621d4caf9fc..fff0ae9f957 100644 --- a/src/runtime/socket/udp_socket.rs +++ b/src/runtime/socket/udp_socket.rs @@ -455,7 +455,7 @@ pub mod js { ); } -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim (`generated_classes.rs`) still passes `this: &mut UDPSocket` until the // `sharedThis: true` regen lands — `&mut T` auto-derefs to `&T` so the impls @@ -491,7 +491,7 @@ impl UDPSocket { /// heap-allocated `UDPSocket` in [`udp_socket`] via /// `uws::udp::Socket::create(.., user_data = this_ptr)` and remains live /// until `on_close` (uws guarantees no callback after close). All mutated - /// fields are `Cell`/`JsCell`, so a shared borrow is sufficient (R-2). + /// fields are `Cell`/`JsCell`, so a shared borrow is sufficient. #[inline] fn from_uws<'a>(socket: *mut uws::udp::Socket) -> &'a UDPSocket { // `Socket` is an `opaque_ffi!` ZST — `opaque_mut` is the safe deref. @@ -517,7 +517,7 @@ impl UDPSocket { closed: Cell::new(false), connect_info: Cell::new(None), }); - // SAFETY: just allocated above; we are the sole owner. R-2: shared + // SAFETY: just allocated above; we are the sole owner. Shared // borrow — every mutated field is `Cell`/`JsCell`. let this = unsafe { &*this_ptr }; @@ -534,7 +534,7 @@ impl UDPSocket { // SAFETY: `ptr` came from `heap::alloc` above and ownership has been // transferred to the JS wrapper; the guard only fires on the early-return // error paths below, on the same stack frame, so the allocation is live. - // R-2: shared borrow — mutation through `Cell`/`JsCell`. + // Shared borrow — mutation through `Cell`/`JsCell`. let this = unsafe { &*ptr }; this.closed.set(true); // Hoist before `(*socket).close()`: that call SYNCHRONOUSLY re-enters @@ -1586,7 +1586,7 @@ impl UDPSocket { }; // `(*socket).close()` SYNCHRONOUSLY invokes `on_close` (udp.c:110 // `s->on_close(s)`), which re-derives `&UDPSocket` from the uws - // user pointer. R-2: with `&self` + `Cell`/`JsCell` the sibling + // user pointer. With `&self` + `Cell`/`JsCell` the sibling // shared borrow is sound; the (idempotent) downgrade is hoisted // because `on_close` repeats it. Spec: udp_socket.zig:915-920. this.this_value.with_mut(|r| r.downgrade()); @@ -1730,7 +1730,7 @@ impl UDPSocket { let args = call_frame.arguments_old::<2>(); // `as_class_ref` is the safe `&T` downcast (encapsulates `&*from_js`); - // mutation goes through `Cell`, so a shared borrow suffices (R-2). + // mutation goes through `Cell`, so a shared borrow suffices. let Some(this) = call_frame.this().as_class_ref::() else { return Err( global_this.throw_invalid_arguments(format_args!("Expected UDPSocket as 'this'")) @@ -1787,7 +1787,7 @@ impl UDPSocket { call_frame: &CallFrame, ) -> JsResult { // `as_class_ref` is the safe `&T` downcast (encapsulates `&*from_js`); - // mutation goes through `Cell`, so a shared borrow suffices (R-2). + // mutation goes through `Cell`, so a shared borrow suffices. let Some(this) = call_frame.this().as_class_ref::() else { return Err( global_object.throw_invalid_arguments(format_args!("Expected UDPSocket as 'this'")) diff --git a/src/runtime/test_runner/ScopeFunctions.rs b/src/runtime/test_runner/ScopeFunctions.rs index 45e80f1aea2..4e8e06ff71d 100644 --- a/src/runtime/test_runner/ScopeFunctions.rs +++ b/src/runtime/test_runner/ScopeFunctions.rs @@ -50,7 +50,7 @@ pub enum Mode { Test, } -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`. All three +// Host-fn re-entrancy: every JS-exposed method takes `&self`. All three // fields are written exactly once in `create_unbound` and never mutated again, // so no `Cell`/`JsCell` wrapping is needed — the type is read-only after // construction. `generic_if`/`generic_extend`/`fn_each`/`call_as_function` all @@ -164,7 +164,7 @@ pub fn call_as_function(global: &JSGlobalObject, frame: &CallFrame) -> JsResult< }; // SAFETY: `from_js` returned non-null; the JS wrapper keeps the boxed // ScopeFunctions alive for the duration of this call (we hold `frame.this()`). - // R-2: deref as shared (`&*const`) — every field is read-only after + // Deref as shared (`&*const`) — every field is read-only after // `create_unbound`, and the body re-enters JS (get_length / array_iterator / // bind / enqueue) which can form fresh `&ScopeFunctions` to the same object. let this: &ScopeFunctions = unsafe { &*this_ptr.cast_const() }; @@ -211,7 +211,7 @@ pub fn call_as_function(global: &JSGlobalObject, frame: &CallFrame) -> JsResult< // PORT NOTE: Zig keeps a parallel `ArrayList(Strong)` to root each element across // the format_label/bind allocations below. `bun_jsc::MarkedArgumentBuffer` only - // exposes a scoped-closure constructor (no `as_slice`/`len`), so for Phase D we + // exposes a scoped-closure constructor (no `as_slice`/`len`), so we // use a plain `Vec` mirroring Zig's `args_list_raw`. The outer `iter` // keeps `this.each` alive; per-element rooting is a TODO once Strong // lands in bun_jsc. diff --git a/src/runtime/test_runner/expect.rs b/src/runtime/test_runner/expect.rs index 1191482d4bd..52c94636f31 100644 --- a/src/runtime/test_runner/expect.rs +++ b/src/runtime/test_runner/expect.rs @@ -48,7 +48,7 @@ pub trait FlagsGetCached { /// https://jestjs.io/docs/expect // To support async tests, we need to track the test ID -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; the only +// Host-fn re-entrancy: every JS-exposed method takes `&self`; the only // field mutated post-construction (`flags`, via the `.not`/`.resolves`/`.rejects` // chaining getters) is `Cell`-wrapped so the codegen shim can hand out a shared // `&*m_ctx` borrow without aliasing UB. `parent` and `custom_label` are @@ -210,7 +210,7 @@ impl Flags { } impl Expect { - /// R-2 helper: read-modify-write the packed `Cell` through `&self`. + /// Helper: read-modify-write the packed `Cell` through `&self`. #[inline] pub fn update_flags(&self, f: impl FnOnce(&mut Flags)) { let mut v = self.flags.get(); @@ -342,7 +342,7 @@ impl Expect { // PORT NOTE: `host_fn(getter)` shim passes `(&Self, &JSGlobalObject)` only, // but these getters also need `this_value` (returned to JS for chaining). - // The shim is omitted (codegen owns the actual link name). R-2: mutation + // The shim is omitted (codegen owns the actual link name). Mutation // of `flags` goes through `Cell` so the receiver is `&Self`. pub fn get_not(this: &Self, this_value: JSValue, _global: &JSGlobalObject) -> JSValue { this.update_flags(|f| f.set_not(!f.not())); @@ -1584,7 +1584,7 @@ impl Expect { return ExpectCustomAsymmetricMatcher::create(global_this, call_frame, matcher_fn); }; // SAFETY: from_js returned a non-null live m_ctx pointer owned by the JS wrapper. - // R-2: deref as shared (`&*`) — `process_promise` below may re-enter JS (await on a + // Deref as shared (`&*`) — `process_promise` below may re-enter JS (await on a // thenable's user-defined `then`), which can call another matcher on this same // `expect()` chain; aliased `&Expect` is sound, aliased `&mut Expect` is not. let expect = unsafe { &*expect_ptr }; @@ -1801,7 +1801,7 @@ impl Expect { /// RAII guard returned by [`Expect::post_match_guard`]. Holds an `&Expect` for the /// duration of a matcher body and runs `post_match` on drop — the Rust shape of Zig's /// `defer this.postMatch(globalThis)` shared by every `expect().toX()` matcher. -/// R-2: shared borrow only (no `DerefMut`); all `Expect` methods reachable from a +/// Shared borrow only (no `DerefMut`); all `Expect` methods reachable from a /// matcher body take `&self`. pub struct PostMatchGuard<'a> { expect: &'a Expect, @@ -1990,7 +1990,7 @@ impl ExpectStatic { pub trait AsymmetricMatcherClass { fn invoke(global_this: &JSGlobalObject, call_frame: &CallFrame) -> JsResult; fn from_js_ptr(value: JSValue) -> Option<*mut Self>; - /// R-2: each asymmetric-matcher payload exposes its `Cell` so + /// Each asymmetric-matcher payload exposes its `Cell` so /// `ExpectStatic::create_asymmetric_matcher_with_flags` can patch it /// post-construction without forming `&mut Self`. fn flags_cell(&self) -> &Cell; @@ -2582,7 +2582,7 @@ impl ExpectArrayContaining { /// /// Reference: `AsymmetricMatcher` in https://github.com/jestjs/jest/blob/main/packages/expect/src/types.ts /// (but only created for *custom* matchers, as built-ins have their own classes) -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`. The only +// Host-fn re-entrancy: every JS-exposed method takes `&self`. The only // field, `flags`, is set once at construction (`create()`) and never written // thereafter, so it stays a bare `Flags` (no `Cell` needed). Both host-fns // call into user JS (`execute_impl` → `execute_custom_matcher`, `custom_print` diff --git a/src/runtime/test_runner/pretty_format.rs b/src/runtime/test_runner/pretty_format.rs index 77ab5c6f553..00ec0c03106 100644 --- a/src/runtime/test_runner/pretty_format.rs +++ b/src/runtime/test_runner/pretty_format.rs @@ -1729,7 +1729,7 @@ impl<'a> Formatter<'a> { return Ok(()); } else if let Some(build) = value.as_::() { // SAFETY: see Response branch above. `write_format` is - // `&self` post-R-2, so a shared borrow is sufficient. + // `&self`, so a shared borrow is sufficient. let build = unsafe { &*build }; let mut bridge = AsFmt::new(&mut *writer.ctx); if build diff --git a/src/runtime/timer/mod.rs b/src/runtime/timer/mod.rs index d14bbf4d48c..b20141a37eb 100644 --- a/src/runtime/timer/mod.rs +++ b/src/runtime/timer/mod.rs @@ -1,14 +1,10 @@ //! Timer subsystem: setTimeout/setInterval/setImmediate scheduling and the //! event-loop timer heap. //! -//! Structs + state machines are real. JS-facing method bodies -//! (`set_timeout`/`clear_timer`/`warn_invalid_countdown`/etc.) remain -//! ``-gated on `bun_jsc` (commented out in Cargo.toml). -//! `All::insert`/`remove`/`update`/`get_timeout`/`drain_timers` — the surface -//! `EventLoop::auto_tick` blocks on — are real. -//! -//! Full earlier drafts are preserved gated under ` mod *_draft` -//! so this file can be diffed against `Timer.rs` once `bun_jsc` is green. +//! Structs + state machines and `All::insert`/`remove`/`update`/`get_timeout`/ +//! `drain_timers` — the surface `EventLoop::auto_tick` blocks on — live here. +//! JS-facing method bodies (`set_timeout`/`clear_timer`/ +//! `warn_invalid_countdown`/etc.) live in `Timer.rs`. use core::mem::offset_of; @@ -875,7 +871,7 @@ impl All { /// Called from `EventLoop::auto_tick` to compute the epoll/kqueue timeout. /// Returns `true` if `spec` was written. /// - /// PORT NOTE (b2): `vm` is erased per §Dispatch (the caller is in + /// PORT NOTE: `vm` is erased (the caller is in /// `bun_jsc::event_loop` which can't name `bun_runtime`). The two reads /// it needs — `event_loop.immediate_tasks.len()` and the QUIC tick — are /// passed in pre-computed until the cycle is broken. @@ -1126,16 +1122,10 @@ impl All { } } -// ─── JS-facing surface (gated on bun_jsc) ──────────────────────────────────── +// ─── JS-facing surface ─────────────────────────────────────────────────────── // `set_timeout`/`set_interval`/`set_immediate`/`sleep`/`clear_*` and the -// host_fn export thunks all need `JSGlobalObject::bun_vm()`, +// host_fn export thunks live in `Timer.rs`; they need `JSGlobalObject::bun_vm()`, // `JSValue::to_number()`, `bun_core::String::transfer_to_js()`, etc. -// Kept gated until `bun_jsc.workspace = true` is re-enabled. - -// TODO(port): JS-facing surface (`set_timeout`/`set_interval`/...) lives in -// `Timer.rs` and is wired via `#[cfg(feature = "jsc")]` once `bun_jsc` is -// re-enabled. The placeholder `include!` was non-compilable; removed. -impl All {} // ─── enums / value types ───────────────────────────────────────────────────── diff --git a/src/runtime/timer/timer_object_internals.rs b/src/runtime/timer/timer_object_internals.rs index b6b79dfd3a1..0e714fcbca2 100644 --- a/src/runtime/timer/timer_object_internals.rs +++ b/src/runtime/timer/timer_object_internals.rs @@ -40,7 +40,7 @@ pub struct TimerObjectInternals { } impl TimerObjectInternals { - /// Read-modify-write `self.flags` through the `Cell` (R-2: `flags` is + /// Read-modify-write `self.flags` through the `Cell` (`flags` is /// `Cell` so the write is interior-mutable, callable from /// `&self` host-fns that re-enter JS). #[inline] diff --git a/src/runtime/valkey_jsc/js_valkey.rs b/src/runtime/valkey_jsc/js_valkey.rs index 62aefe5950e..0aac1e039a0 100644 --- a/src/runtime/valkey_jsc/js_valkey.rs +++ b/src/runtime/valkey_jsc/js_valkey.rs @@ -75,7 +75,7 @@ impl AnySocketIsClosed for uws::AnySocket { /// Scope-guarded `ref/deref` over a raw pointer — sidesteps the /// `scopeguard`-captures-`&self` borrowck conflict that pervades this file. /// Mirrors Zig's `defer this.deref()` which had no aliasing restriction. -// R-2: takes `*const` now that every `JSValkeyClient` method is `&self`; +// Takes `*const` now that every `JSValkeyClient` method is `&self`; // `deref()` (and `ref_()`) already only need a shared receiver. #[inline] fn deref_guard( @@ -376,7 +376,7 @@ impl SubscriptionCtx { /// Valkey client wrapper for JavaScript // PORT NOTE: `#[bun_jsc::JsClass]` is hand-rolled in `mod.rs` (the codegen // macro's 2-arg `constructor` shim doesn't fit the `js_this` flow here). -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim still emits `this: &mut RedisClient` — `&mut T` // auto-derefs to `&T` so the impls below compile against either. `JsCell` is @@ -461,7 +461,7 @@ impl JSValkeyClient { self.client.get().vm } - // ─── R-2 interior-mutability helpers ──────────────────────────────────── + // ─── Interior-mutability helpers ──────────────────────────────────────── /// Mutable projection of the inner protocol client through `&self`. /// @@ -472,7 +472,7 @@ impl JSValkeyClient { #[inline] #[allow(clippy::mut_from_ref)] pub(super) fn client_mut(&self) -> &mut valkey::ValkeyClient { - // SAFETY: R-2 single-JS-thread invariant (see `JsCell` docs). The + // SAFETY: single-JS-thread invariant (see `JsCell` docs). The // `&mut` is fresh per call site; reentrancy through // `ValkeyClient::parent()` forms a shared `&JSValkeyClient` only. unsafe { self.client.get_mut() } diff --git a/src/runtime/valkey_jsc/valkey.rs b/src/runtime/valkey_jsc/valkey.rs index 2d4973a3df4..5f7aae5d407 100644 --- a/src/runtime/valkey_jsc/valkey.rs +++ b/src/runtime/valkey_jsc/valkey.rs @@ -388,7 +388,7 @@ fn reader_pos(reader: &protocol::ValkeyReader<'_>) -> usize { // SAFETY: `ValkeyClient` lives at `JSValkeyClient.client` (intrusive embed via // `container_of`). `JsCell` is `#[repr(transparent)]`, so the -// field offset is unchanged. R-2: shared `&` only — every `JSValkeyClient` +// field offset is unchanged. Shared `&` only — every `JSValkeyClient` // method this reaches is `&self`. bun_core::impl_field_parent! { ValkeyClient => JSValkeyClient.client; fn parent; } diff --git a/src/runtime/webcore.rs b/src/runtime/webcore.rs index d21c7cf3060..60a267d1d0a 100644 --- a/src/runtime/webcore.rs +++ b/src/runtime/webcore.rs @@ -127,7 +127,7 @@ use bun_event_loop::deferred_task_queue::DeferredRepeatingTask; #[derive(Debug, Default)] pub struct AutoFlusher { /// `Cell` so register/unregister can be called from `&self` callbacks - /// (R-2 §provenance — see `FileSink::on_write`). + /// (see `FileSink::on_write`). pub registered: core::cell::Cell, } @@ -229,7 +229,7 @@ impl AutoFlusher { impl HasAutoFlusher for file_sink::FileSink { #[inline] fn auto_flusher(&self) -> &AutoFlusher { - // R-2: `auto_flusher` is `JsCell`; `JsCell::get` yields `&T`. + // `auto_flusher` is `JsCell`; `JsCell::get` yields `&T`. self.auto_flusher.get() } fn on_auto_flush(this: *mut Self) -> bool { @@ -262,7 +262,7 @@ impl HasAutoFlusher #[path = "webcore/headers_ref.rs"] pub mod headers_ref; -// ─── un-gated core types (cycle-5: Body/Blob/Response/Request real) ────────── +// ─── core types: Body / Blob / Response / Request ──────────────────────────── #[path = "webcore/Blob.rs"] pub mod blob; pub use blob::Any as AnyBlob; diff --git a/src/runtime/webcore/Blob.rs b/src/runtime/webcore/Blob.rs index 713eb63edef..b804ce8d327 100644 --- a/src/runtime/webcore/Blob.rs +++ b/src/runtime/webcore/Blob.rs @@ -3529,7 +3529,7 @@ impl BlobExt for Blob { // if cfg!(debug_assertions) { debug_assert!(self.is_heap_allocated()); } self.calculate_estimated_byte_size(); - // R-2: `&self` receiver, but the FFI shims take `*mut Blob` (the + // `&self` receiver, but the FFI shims take `*mut Blob` (the // heap-allocated `m_ctx` pointer). `self` *is* that allocation (caller // contract), so the const→mut cast is the original `Blob::new` provenance. let this = std::ptr::from_ref::(self).cast_mut(); diff --git a/src/runtime/webcore/Body.rs b/src/runtime/webcore/Body.rs index ebe6f0d9960..13c4a90e4cb 100644 --- a/src/runtime/webcore/Body.rs +++ b/src/runtime/webcore/Body.rs @@ -86,7 +86,7 @@ bun_core::declare_scope!(BodyValueBufferer, visible); // TODO(port): `bun.JSTerminated!T` is a narrower error set than `bun.JSError`; using JsResult for now. type JsTerminated = jsc::JsResult; -// R-2 (host-fn re-entrancy): `Body` is embedded inline in JS-exposed +// Host-fn re-entrancy: `Body` is embedded inline in JS-exposed // `Response` (and aliased via `HiveRef` in `Request`). Every BodyMixin host // fn takes `&self` and projects `&mut Value` through this `JsCell`; the // `UnsafeCell` inside suppresses LLVM `noalias` on `&Body` so a re-entrant @@ -112,7 +112,7 @@ impl Body { } } - /// R-2 interior-mutability projection: `&self` → `&mut Value`. + /// Interior-mutability projection: `&self` → `&mut Value`. /// Single-JS-thread invariant (see `JsCell`) makes this sound; keep the /// returned borrow short and do not hold it across a call that re-enters /// JS and may touch this same body. @@ -1706,11 +1706,11 @@ pub fn extract(global_this: &JSGlobalObject, value: JSValue) -> JsResult { /// Implementers supply `get_body_value`, `get_fetch_headers`, `get_form_data_encoding`, /// and optionally override `get_body_readable_stream` (Zig `@hasDecl` check). /// -/// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`. The +/// Host-fn re-entrancy: every JS-exposed method takes `&self`. The /// codegen shim still emits `this: &mut T` — `&mut T` /// auto-derefs to `&T` so the impls below compile against either. pub trait BodyMixin: BodyOwnerJs + Sized { - /// R-2 interior-mutability boundary: implementors project `&mut Value` + /// Interior-mutability boundary: implementors project `&mut Value` /// from `&self` via `JsCell` (Response) or a raw `NonNull` deref (Request); /// see [`Body::value_mut`]. Single-JS-thread invariant — keep the borrow /// short and do not hold it across a call that re-enters JS. @@ -2269,7 +2269,7 @@ impl<'a> Drop for ValueBufferer<'a> { // stream_buffer dropped automatically if let Some(byte_stream) = self.byte_stream { // Kept alive by `readable_stream_ref` while set — satisfies the - // `BackRef` outlives-holder invariant. R-2: `unpipe_without_deref` + // `BackRef` outlives-holder invariant. `unpipe_without_deref` // takes `&self` (interior-mutable). bun_ptr::BackRef::from(byte_stream).unpipe_without_deref(); } @@ -2623,7 +2623,7 @@ impl<'a> ValueBufferer<'a> { webcore::readable_stream::Source::Bytes(byte_stream_ptr) => { // BACKREF: see `Source::bytes()` — payload owned by the // readable stream, kept alive via `self.readable_stream_ref` - // above. R-2: all touched fields are interior-mutable. + // above. All touched fields are interior-mutable. let byte_stream = stream.ptr.bytes().expect("matched Bytes"); debug_assert!(byte_stream.pipe.get().ctx.is_none()); debug_assert!(self.byte_stream.is_none()); diff --git a/src/runtime/webcore/ByteStream.rs b/src/runtime/webcore/ByteStream.rs index 667783d526e..b1a1c35fd95 100644 --- a/src/runtime/webcore/ByteStream.rs +++ b/src/runtime/webcore/ByteStream.rs @@ -12,7 +12,7 @@ use crate::webcore::{blob, readable_stream}; bun_output::declare_scope!(ByteStream, visible); -/// R-2 (`sharedThis`): every JS-reachable inherent method takes `&self` so a +/// `sharedThis`: every JS-reachable inherent method takes `&self` so a /// re-entrant JS call (e.g. `pending.run()` → JS → `onPull`) cannot stack two /// `&mut ByteStream`. Fields mutated on those paths are wrapped in `Cell` /// (Copy scalars / raw ptrs) or [`JsCell`] (non-Copy). `high_water_mark` / @@ -74,7 +74,7 @@ impl readable_stream::SourceContext for ByteStream { const SUPPORTS_REF: bool = false; crate::source_context_codegen!(js_BytesInternalReadableStreamSource); - // R-2: trait sigs are fixed at `&mut self` (shared with the other + // Trait sigs are fixed at `&mut self` (shared with the other // `SourceContext` impls); `&mut T` auto-derefs to `&T` so each body // forwards to the `&self` inherent method below. fn on_start(&mut self) -> streams::Start { @@ -117,7 +117,7 @@ impl ByteStream { } /// Init-time reset (Zig: write into `undefined`). Runs before the JS - /// wrapper exists, so `&mut self` is sound here (R-2 exemption). + /// wrapper exists, so `&mut self` is sound here. pub fn setup(&mut self) { // Called immediately after `ByteStream::default()` construction (Zig // wrote into `undefined`); the old value owns nothing the new one @@ -188,7 +188,7 @@ impl ByteStream { ); self.has_received_last_chunk.set(stream.is_done()); - // R-2: snapshot `pipe` (two `Option` fields) — `on_pipe` re-enters + // Snapshot `pipe` (two `Option` fields) — `on_pipe` re-enters // its handler, which may call back into `ByteStream` (e.g. `drain`); no // `JsCell` borrow may be live across that call. let (pipe_ctx, pipe_fn) = { @@ -208,7 +208,7 @@ impl ByteStream { bun_output::scoped_log!(ByteStream, "ByteStream.onData err action.reject()"); let global = self.parent_const().global_this(); - // R-2: move the action out of the cell *before* calling + // Move the action out of the cell *before* calling // `reject` (which resolves a JS promise and may re-enter). let mut action = self.buffer_action.replace(None).unwrap(); let res = action.reject(global, err.clone()); @@ -335,7 +335,7 @@ impl ByteStream { bun_output::scoped_log!(ByteStream, "ByteStream.onData pending.run()"); - // R-2: `Pending::run` resolves a JS promise (re-enters JS); the + // `Pending::run` resolves a JS promise (re-enters JS); the // `with_mut` borrow is `UnsafeCell`-backed so `noalias` is // suppressed on `&self`, which is the load-bearing fix vs the old // `&mut self` form. @@ -421,7 +421,7 @@ impl ByteStream { if !self.buffer.get().is_empty() { debug_assert!(self.value().is_empty()); // == .zero - // R-2: confine the `&mut Vec` to a `with_mut` so no `JsCell` + // Confine the `&mut Vec` to a `with_mut` so no `JsCell` // borrow escapes the copy. The result tuple drives the rest. let (to_write, remaining_in_buffer_len) = self.buffer.with_mut(|b| { let to_write = (b.len() - self.offset.get()).min(buffer.len()); @@ -465,7 +465,7 @@ impl ByteStream { self.pending_buffer.set(std::ptr::from_mut::<[u8]>(buffer)); self.set_value(view); - // R-2: `JsCell::as_ptr` yields the stable `*mut Pending` that the + // `JsCell::as_ptr` yields the stable `*mut Pending` that the // returned `streams::Result::Pending` raw-backref needs. streams::Result::Pending(self.pending.as_ptr()) // TODO(port): `streams::Result::Pending` carries `*streams.Result.Pending` in Zig (raw @@ -513,7 +513,7 @@ impl ByteStream { /// `ReadableStreamSource`; teardown is driven by the GC finalizer via `Source::finalize`, /// which calls this. Per §JSC, `.classes.ts` payloads use `finalize`, not `deinit`/`Drop`. /// - /// R-2: stays `&mut self` — this is the destructor path (called once from + /// Stays `&mut self` — this is the destructor path (called once from /// `SourceContext::deinit_fn(&mut self)` after the ref-count hits zero), so /// no JS re-entry can alias `self`; and `parent().deinit()` needs unique /// `Box` provenance. diff --git a/src/runtime/webcore/FileReader.rs b/src/runtime/webcore/FileReader.rs index b7fecd377f8..9ab87ea253a 100644 --- a/src/runtime/webcore/FileReader.rs +++ b/src/runtime/webcore/FileReader.rs @@ -22,7 +22,7 @@ bun_core::declare_scope!(FileReader, visible); // Represented as unbounded `&mut [u8]` / `&[u8]` here to keep function bodies // readable; TODO(refactor): replace with a proper raw-slice wrapper (BACKREF lifetime). -// R-2 (host-fn re-entrancy): every JS-exposed / vtable-reachable method takes +// Host-fn re-entrancy: every JS-exposed / vtable-reachable method takes // `&self`; per-field interior mutability via `Cell` (Copy) / `JsCell` (non- // Copy). The `SourceContext` trait and `BufferedReaderParent` shims still // hand in `&mut Self` / `*mut Self` until those layers are migrated — `&mut T` @@ -282,7 +282,7 @@ impl Lazy { // `bun.io.BufferedReader.init(@This())` — vtable parent. Maps the Zig // `onReadChunk`/`onReaderDone`/`onReaderError`/`loop`/`eventLoop` decls. // -// R-2: every mutated field on `FileReader` is `Cell`/`JsCell`/`UnsafeCell`- +// Every mutated field on `FileReader` is `Cell`/`JsCell`/`UnsafeCell`- // backed, so materializing `&FileReader` via `(&*this)` does not assert Unique // over any byte the caller may have borrowed (SharedReadWrite root); the // inherent impls re-derive any reader access through `reader()` @@ -330,7 +330,7 @@ impl FileReader { // `Source`; the Zig writes `this.* = FileReader{...}` then reads `parent()`. Note the // Zig struct literal omits `event_loop` (no default) — likely dead code or relies on // a quirk; preserved as-is. - // R-2: kept `&mut self` — init-time constructor that runs before any + // Kept `&mut self` — init-time constructor that runs before any // host-fn could re-enter; `*self =` requires unique access. pub fn setup(&mut self, fd: Fd) { *self = FileReader { @@ -353,7 +353,7 @@ impl FileReader { let was_lazy = !matches!(self.lazy.get(), Lazy::None); let mut pollable = false; let mut file_type = FileType::File; - // R-2: move the `Lazy` out of the cell up-front (it's reset to `None` + // Move the `Lazy` out of the cell up-front (it's reset to `None` // on every path through the original `if let` body) so the `StoreRef` // is owned locally and the cell borrow is released immediately. if let Lazy::Blob(store) = self.lazy.replace(Lazy::None) { @@ -607,7 +607,7 @@ impl FileReader { let reader_buffer: *mut Vec = self.reader().buffer(); if !self.read_inside_on_pull.get().is_none() { - // R-2: `with_mut` projects `&mut ReadDuringJSOnPullResult` from + // `with_mut` projects `&mut ReadDuringJSOnPullResult` from // `&self`; `self.buffered` is a disjoint `JsCell` so nested access // inside the closure is sound. self.read_inside_on_pull.with_mut(|riop| match riop { @@ -1065,7 +1065,7 @@ impl readable_stream::SourceContext for FileReader { const NAME: &'static str = "File"; const SUPPORTS_REF: bool = true; crate::source_context_codegen!(js_FileInternalReadableStreamSource); - // R-2: trait sigs are still `&mut self` (shared with ByteBlobLoader/ + // Trait sigs are still `&mut self` (shared with ByteBlobLoader/ // ByteStream — separate migration); the inherent impls take `&self`, so // these forward via auto-deref. The `&mut` here is what the codegen shim // currently emits; once `NewSource` is celled the trait flips to `&self` diff --git a/src/runtime/webcore/FileSink.rs b/src/runtime/webcore/FileSink.rs index 2fb3729b1b1..a5c4106b8eb 100644 --- a/src/runtime/webcore/FileSink.rs +++ b/src/runtime/webcore/FileSink.rs @@ -27,7 +27,7 @@ bun_core::declare_scope!(FileSink, visible); // FileSink // ─────────────────────────────────────────────────────────────────────────── -// R-2 (`&mut self` host-fn re-entrancy → noalias UB): JS-reachable host-fns +// Host-fn re-entrancy (`&mut self` → noalias UB): JS-reachable host-fns // take `&self` and mutate via `Cell`/`JsCell`. Init-time / `finalize` paths // keep `&mut self` for write+dealloc provenance (they reach `FileSink::deref` // which may `heap::take`) — those derive `&mut self` from the codegen shim's @@ -681,7 +681,7 @@ impl FileSink { // PORT NOTE: reshaped for borrowck — Zig passed `self` + a closure that // mutated `self.force_sync`. Split into a local capture and apply after. - // R-2: out-params for `bun_io::open_for_writing` are local then `Cell::set`. + // Out-params for `bun_io::open_for_writing` are local then `Cell::set`. let mut force_sync_out = self.force_sync.get(); let mut pollable_out = self.pollable.get(); let mut is_socket_out = self.is_socket.get(); diff --git a/src/runtime/webcore/ReadableStream.rs b/src/runtime/webcore/ReadableStream.rs index 59617fec7ad..e7e3b8ff5ce 100644 --- a/src/runtime/webcore/ReadableStream.rs +++ b/src/runtime/webcore/ReadableStream.rs @@ -191,7 +191,7 @@ impl ReadableStream { } Source::File(_) => { // BACKREF: see `Source::file()` — payload valid while stream alive. - // R-2: `lazy`/`started` are `JsCell`/`Cell`; shared borrow suffices. + // `lazy`/`started` are `JsCell`/`Cell`; shared borrow suffices. let blobby = self.ptr.file().expect("matched File"); if let webcore::file_reader::Lazy::Blob(store) = blobby.lazy.get() { // `store.clone()` carries the +1 that Zig's explicit `blob.store.?.ref()` @@ -551,7 +551,7 @@ impl Source { /// The pointer is the JS wrapper's `m_ctx` heap allocation returned by /// `ReadableStreamTag__tagged` and is non-null and live while the owning /// `ReadableStream` JSValue is rooted (caller's `Strong`/stack root) — the - /// BACKREF outlives-holder invariant. R-2: every `ByteStream` field touched + /// BACKREF outlives-holder invariant. Every `ByteStream` field touched /// through this borrow is `Cell`/`JsCell`-backed, so re-entrant JS that /// re-derives a fresh `&ByteStream` from `m_ctx` aliases shared-only. /// @@ -571,7 +571,7 @@ impl Source { /// /// Same invariant as [`bytes`](Self::bytes): the pointer is the JS /// wrapper's `m_ctx` heap allocation, non-null and live while the owning - /// `ReadableStream` JSValue is rooted. R-2: every `FileReader` field + /// `ReadableStream` JSValue is rooted. Every `FileReader` field /// touched through this borrow is `Cell`/`JsCell`-backed, so re-entrant JS /// that re-derives a fresh `&FileReader` from `m_ctx` aliases shared-only. #[inline] @@ -677,7 +677,7 @@ pub struct NewSource { // TODO(port): lifetime — TSV class UNKNOWN pub close_ctx: Option>, pub close_jsvalue: bun_jsc::strong::Optional, - /// R-2: cleared via `&self` from `FetchTasklet::clear_stream_cancel_handler` + /// Cleared via `&self` from `FetchTasklet::clear_stream_cancel_handler` /// (through `ByteStream::parent_const`), so interior-mutable. pub cancel_handler: Cell)>>, pub cancel_ctx: Cell>, @@ -688,7 +688,7 @@ pub struct NewSource { // SAFETY: this is the self-wrapper JSValue (points at the JSCell that owns this m_ctx). // Kept alive by the wrapper itself; zeroed in finalize() before sweep. pub this_jsvalue: JSValue, - /// R-2: written by `&self` context methods (`ByteStream::to_any_blob`, + /// Written by `&self` context methods (`ByteStream::to_any_blob`, /// `ByteBlobLoader::to_any_blob`) via `parent_const()`, so interior-mutable. pub is_closed: Cell, } diff --git a/src/runtime/webcore/Request.rs b/src/runtime/webcore/Request.rs index a7b0687660a..f472bba6194 100644 --- a/src/runtime/webcore/Request.rs +++ b/src/runtime/webcore/Request.rs @@ -76,7 +76,7 @@ const _: () = { } }; -/// R-2 (`sharedThis`): every JS-facing host-fn takes `&Request` (not +/// `sharedThis`: every JS-facing host-fn takes `&Request` (not /// `&mut Request`) so re-entrant JS calls cannot stack two `&mut` to the same /// instance. Fields mutated by host-fns are wrapped in `Cell` (Copy scalars) /// or `JsCell` (Drop types). Both are `#[repr(transparent)]`, so `#[repr(C)]` @@ -219,17 +219,17 @@ impl Request { /// Zig: `&this.#body.value`. /// - /// R-2: `&self` → `&mut` through the slot's raw pointer. The slot is shared + /// `&self` → `&mut` through the slot's raw pointer. The slot is shared /// with `RequestContext.request_body` but never `&mut`-borrowed concurrently /// (single-threaded event-loop sequencing). Keep the borrow short. #[inline] #[allow(clippy::mut_from_ref)] pub(crate) fn body_value_mut(&self) -> &mut BodyValue { - // SAFETY: see R-2 invariant above. + // SAFETY: see noalias re-entry invariant above. unsafe { &mut (*self.body.as_ptr()).value } } - /// R-2: short-hand for `unsafe { self.headers.get_mut() }`. The + /// Short-hand for `unsafe { self.headers.get_mut() }`. The /// single-JS-thread invariant (see `JsCell` docs) means no other /// `&mut Option` is live for the duration of the borrow. #[inline] @@ -523,7 +523,7 @@ impl Request { pub fn to_js(&self, global_object: &JSGlobalObject) -> JSValue { self.calculate_estimated_byte_size(); - // R-2: `to_js_unchecked` stores `self` as the C++ `m_ctx` payload (an + // `to_js_unchecked` stores `self` as the C++ `m_ctx` payload (an // opaque `void*` never deref'd as `&mut Request` on the C++ side), so // forming `*mut` from `&self` here is provenance-safe. let js_value = js_gen::to_js_unchecked( diff --git a/src/runtime/webcore/Response.rs b/src/runtime/webcore/Response.rs index 98ada44239f..d440def1876 100644 --- a/src/runtime/webcore/Response.rs +++ b/src/runtime/webcore/Response.rs @@ -173,7 +173,7 @@ pub fn from_js_direct(value: JSValue) -> Option<*mut Response> { // tier (Response lives in a higher crate); the macro casts at the boundary. bun_jsc::impl_js_class_via_generated!(Response => bun_jsc::generated::JSResponse); -/// R-2 (`sharedThis`): every JS-facing host-fn takes `&Response` (not +/// `sharedThis`: every JS-facing host-fn takes `&Response` (not /// `&mut Response`) so re-entrant JS calls cannot stack two `&mut` to the same /// instance. Fields mutated by host-fns are therefore wrapped in `Cell` (Copy /// scalars) or `JsCell` (non-Copy `body`/`init`/`url`/`js_ref`). Both are @@ -362,7 +362,7 @@ impl Response { self.init.get().headers.as_deref() } - /// R-2 `JsCell` escape hatch — single-JS-thread invariant. Centralises the + /// `JsCell` escape hatch — single-JS-thread invariant. Centralises the /// `unsafe { self.init.get_mut() }` deref so the four call sites /// ([`get_init_headers_mut`], [`header`], [`get_or_create_headers`], /// [`get_content_type`]) read it as a plain `&mut Init`. @@ -399,14 +399,14 @@ impl Response { this.reported_estimated_size.get() } - /// R-2: returns `&mut BodyValue` from `&self` via the `JsCell` escape + /// Returns `&mut BodyValue` from `&self` via the `JsCell` escape /// hatch. Callers must keep the borrow short and not hold it across calls /// that may re-enter a `Response` host-fn (which could project a second /// `&mut` to the same `body`). #[inline] #[allow(clippy::mut_from_ref)] pub fn get_body_value(&self) -> &mut BodyValue { - // R-2: both `Response.body` and `Body.value` are `JsCell` — + // Both `Response.body` and `Body.value` are `JsCell` — // single-JS-thread interior-mutability boundary. See `Body::value_mut`. self.body.get().value_mut() } @@ -453,7 +453,7 @@ impl Response { self.calculate_estimated_byte_size(); // `bun_jsc::generated::JSResponse::to_js` ⇒ `Response__create` (C++ // shim). Payload type is erased (`*mut ()`) at the bun_jsc tier. - // R-2: cast through `*const` then `.cast_mut()` so the payload pointer + // Cast through `*const` then `.cast_mut()` so the payload pointer // (which the C++ side stores into `m_ctx`) is derived from `&self` // without forging a `&mut`. let js_value = js::to_js( @@ -540,7 +540,7 @@ mod _jsc_host_fns { let body: &mut BodyValue = 'brk: { if let Some(response) = this_value.as_class_ref::() { - // R-2: `get_body_value` projects `&mut` via `JsCell`. + // `get_body_value` projects `&mut` via `JsCell`. break 'brk response.get_body_value(); } else if let Some(request) = this_value.as_class_ref::() { break 'brk request.get_body_value(); @@ -599,7 +599,7 @@ impl Response { // PORT NOTE: reshaped for borrowck — `FetchHeaders::fast_get` takes // `&mut self` (FFI writes through an out-param), so we return the // owned `ZigString` instead of a borrowed slice. Callers do - // `.slice()` themselves. R-2 escape hatch via `init_mut()`. + // `.slice()` themselves. Escape hatch via `init_mut()`. self.init_mut().headers.as_mut()?.fast_get(name) } @@ -645,7 +645,7 @@ impl Response { #[allow(clippy::mut_from_ref)] fn get_or_create_headers(&self, global_this: &JSGlobalObject) -> JsResult<&mut HeadersRef> { - // R-2 escape hatch via `init_mut()` — the returned `&mut HeadersRef` + // Escape hatch via `init_mut()` — the returned `&mut HeadersRef` // borrows `self.init`; callers (`get_headers`, `construct_*`) do not // hold the borrow across calls that re-enter Response host-fns. let init = self.init_mut(); @@ -672,7 +672,7 @@ impl Response { } pub fn get_content_type(&self) -> JsResult> { - // R-2 escape hatch via `init_mut()` — `fast_get` (FFI out-param write) + // Escape hatch via `init_mut()` — `fast_get` (FFI out-param write) // does not re-enter JS. if let Some(headers) = self.init_mut().headers.as_mut() { if let Some(value) = headers.fast_get(HTTPHeaderName::ContentType) { @@ -823,7 +823,7 @@ impl Response { writer.write_str("\n")?; formatter.reset_line(); - // SAFETY: R-2 `JsCell` escape hatch — `Body::write_format` takes + // SAFETY: `JsCell` escape hatch — `Body::write_format` takes // `&mut self`; single-JS-thread invariant. unsafe { self.body.get_mut() } .write_format::(&mut *formatter, writer)?; diff --git a/src/runtime/webcore/ResumableSink.rs b/src/runtime/webcore/ResumableSink.rs index 64cb16d6d03..5f82fffa154 100644 --- a/src/runtime/webcore/ResumableSink.rs +++ b/src/runtime/webcore/ResumableSink.rs @@ -197,7 +197,7 @@ impl ResumableSink ResumableSink`; shared deref + `.set()`. + // holds it. `pipe` is `JsCell`; shared deref + `.set()`. if let Some(bytes) = stream_.ptr.bytes() { bytes.pipe.set(Pipe::default()); } diff --git a/src/runtime/webcore/TextDecoder.rs b/src/runtime/webcore/TextDecoder.rs index 093000f2615..016d8012676 100644 --- a/src/runtime/webcore/TextDecoder.rs +++ b/src/runtime/webcore/TextDecoder.rs @@ -26,7 +26,7 @@ impl Buffered { } } -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (all written fields are `Copy`). #[bun_jsc::JsClass] pub struct TextDecoder { diff --git a/src/runtime/webcore/TextEncoderStreamEncoder.rs b/src/runtime/webcore/TextEncoderStreamEncoder.rs index 3cc7acc9b7e..cdde0b13200 100644 --- a/src/runtime/webcore/TextEncoderStreamEncoder.rs +++ b/src/runtime/webcore/TextEncoderStreamEncoder.rs @@ -7,7 +7,7 @@ use bun_simdutf_sys::simdutf; bun_output::declare_scope!(TextEncoderStreamEncoder, visible); -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; the single +// Host-fn re-entrancy: every JS-exposed method takes `&self`; the single // mutable field is `Cell>` (Copy). #[derive(Default)] #[bun_jsc::JsClass] diff --git a/src/runtime/webcore/fetch/FetchTasklet.rs b/src/runtime/webcore/fetch/FetchTasklet.rs index 39da4882d03..2aa3a815e50 100644 --- a/src/runtime/webcore/fetch/FetchTasklet.rs +++ b/src/runtime/webcore/fetch/FetchTasklet.rs @@ -1432,7 +1432,7 @@ impl FetchTasklet { fn clear_stream_cancel_handler(&mut self) { if let Some(readable) = self.readable_stream_ref.get(&self.global_this) { if let Some(bytes) = readable.ptr.bytes() { - // R-2: project to the parent `NewSource` via `&self`; the two + // Project to the parent `NewSource` via `&self`; the two // fields are `Cell`-wrapped for exactly this caller. let source = bytes.parent_const(); source.cancel_handler.set(None); diff --git a/src/runtime/webcore/s3/client.rs b/src/runtime/webcore/s3/client.rs index a453c8561c4..aece71573d4 100644 --- a/src/runtime/webcore/s3/client.rs +++ b/src/runtime/webcore/s3/client.rs @@ -786,7 +786,7 @@ pub fn upload_stream( // types per arm. Manual unroll once both have a `.pending` accessor. ReadableStreamPtr::Bytes(_) => { // BACKREF: see `Source::bytes()` — payload live while the - // ReadableStream JS wrapper is rooted. R-2: `pending` is `JsCell`. + // ReadableStream JS wrapper is rooted. `pending` is `JsCell`. let stream = readable_stream.ptr.bytes().expect("matched Bytes"); if matches!( stream.pending.get().result, @@ -814,7 +814,7 @@ pub fn upload_stream( } ReadableStreamPtr::File(_) => { // BACKREF: see `Source::file()` — payload live while the - // ReadableStream JS wrapper is rooted. R-2: `pending` is `JsCell`. + // ReadableStream JS wrapper is rooted. `pending` is `JsCell`. let stream = readable_stream.ptr.file().expect("matched File"); if matches!( stream.pending.get().result, @@ -1146,7 +1146,7 @@ pub fn readable_stream( if let Some(readable) = self_.readable_stream_ref.get(&self_.global) { // BACKREF: see `Source::bytes()` — payload live while the - // readable stream is rooted. R-2: `&` — `on_data` re-enters JS. + // readable stream is rooted. `&` — `on_data` re-enters JS. if let Some(bytes) = readable.ptr.bytes() { if let Some(err) = request_err { bytes.on_data(crate::webcore::streams::StreamResult::Err( @@ -1181,7 +1181,7 @@ pub fn readable_stream( fn clear_stream_cancel_handler(&mut self) { if let Some(readable) = self.readable_stream_ref.get(&self.global) { // BACKREF: see `Source::bytes()` — payload live while the - // readable stream is rooted. R-2: shared deref + `Cell::set`. + // readable stream is rooted. Shared deref + `Cell::set`. if let Some(bytes) = readable.ptr.bytes() { let source = bytes.parent_const(); source.cancel_handler.set(None); diff --git a/src/runtime/webcore/s3/multipart.rs b/src/runtime/webcore/s3/multipart.rs index ddc40e91213..cb70f3afa92 100644 --- a/src/runtime/webcore/s3/multipart.rs +++ b/src/runtime/webcore/s3/multipart.rs @@ -594,7 +594,7 @@ impl MultiPartUpload { self.state = State::Finished; (self.callback)(S3UploadResult::Failure(err), self.callback_context)?; - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `self.callback` (promise reject → JS) re-enters via the JS // wrapper's `*mut MultiPartUpload` and may write `*self`. Nothing // derived from `self` is passed to the callback, so LLVM is diff --git a/src/runtime/webcore/streams.rs b/src/runtime/webcore/streams.rs index 84d50daf19e..11acdc6dec5 100644 --- a/src/runtime/webcore/streams.rs +++ b/src/runtime/webcore/streams.rs @@ -2001,7 +2001,7 @@ impl HTTPServerWritable { // at scope exit (AFTER resolve, which may reenter JS and mutate `wrote`). Read it here, // not before the call. // - // R-2 noalias mitigation (PORT_NOTES_PLAN R-2; precedent + // noalias mitigation (see bun_ptr::LaunderedSelf; precedent // `b818e70e1c57` NodeHTTPResponse::cork): `&mut self` is `noalias` // and `resolve()` receives nothing derived from `self`, so LLVM is // licensed to forward the `self.wrote` read used in the diff --git a/src/semver/lib.rs b/src/semver/lib.rs index d3a95d8f6b9..1e6bbf2074c 100644 --- a/src/semver/lib.rs +++ b/src/semver/lib.rs @@ -579,7 +579,7 @@ pub mod semver_string { Pointer::from_bits(masked) } - // PORT NOTE: `toJS` deleted — lives in bun_semver_jsc (tier-6; deferred to Pass C). + // PORT NOTE: `toJS` deleted — lives in bun_semver_jsc (tier-6). // String must be a pointer because we reference it as a slice. It will become a dead pointer if it is copied. #[inline] diff --git a/src/sourcemap/Cargo.toml b/src/sourcemap/Cargo.toml index 4c0a9ec287e..fceff47260f 100644 --- a/src/sourcemap/Cargo.toml +++ b/src/sourcemap/Cargo.toml @@ -30,10 +30,6 @@ bun_alloc.workspace = true bun_base64.workspace = true bun_core.workspace = true bun_collections.workspace = true -# TODO(b2-blocked): bun_parsers — json::parse signature is live; wire in -# once parse_json un-gates (currently blocked on bun_ast::Source lifetime, -# not on bun_parsers). -# bun_parsers.workspace = true bun_io.workspace = true # bun_js_parser not needed: parse_json uses the T2 value-subset Expr from # bun_ast::js_ast (what bun_parsers::json::parse returns). diff --git a/src/sourcemap_jsc/Cargo.toml b/src/sourcemap_jsc/Cargo.toml index 5723496827a..2c959373e3b 100644 --- a/src/sourcemap_jsc/Cargo.toml +++ b/src/sourcemap_jsc/Cargo.toml @@ -28,8 +28,9 @@ bun_jsc.workspace = true bun_ast.workspace = true bun_options_types.workspace = true bun_paths.workspace = true -# bun_runtime — only used in BakeSourceProvider::get_external_data, which is -# re-gated on bun_runtime::bake::production::PerThread. Dep dropped to keep -# this crate's transitive surface minimal during B-2. +# bun_runtime intentionally not depended on — bun_runtime already depends on +# this crate, so adding it here would create a cycle. The one consumer of +# `bun_runtime::bake::production::PerThread` (`BakeSourceProvider::get_external_data`) +# reaches it through the `bun_jsc::RuntimeHooks` vtable instead. bun_sourcemap.workspace = true bun_wyhash.workspace = true diff --git a/src/sql_jsc/Cargo.toml b/src/sql_jsc/Cargo.toml index 810e8974e9c..6d6ff9f40aa 100644 --- a/src/sql_jsc/Cargo.toml +++ b/src/sql_jsc/Cargo.toml @@ -30,10 +30,10 @@ bun_event_loop.workspace = true bun_jsc.workspace = true bun_ptr.workspace = true bun_sha_hmac.workspace = true -# TODO(b2-blocked): bun_runtime fails to compile (concurrent B-2 work — -# `strings::to_lower_ascii_stack` missing in EVP.rs). The only consumer here -# is `postgres::sasl::SASL::compute_salted_password` (PBKDF2), whose body is -# gated until bun_runtime is green again. +# bun_runtime intentionally not depended on — bun_runtime already depends on +# this crate, so adding it here would create a direct cycle. The only would-be +# consumer, `postgres::sasl::SASL::compute_salted_password` (PBKDF2), inlines +# the BoringSSL call instead; see the PORT NOTE in SASL.rs. # bun_runtime.workspace = true bun_sql.workspace = true bun_uws.workspace = true diff --git a/src/sql_jsc/mysql.rs b/src/sql_jsc/mysql.rs index 2c915e971eb..14f78969e0e 100644 --- a/src/sql_jsc/mysql.rs +++ b/src/sql_jsc/mysql.rs @@ -28,8 +28,7 @@ pub fn create_binding(global_object: &JSGlobalObject) -> JSValue { // ────────────────────────────────────────────────────────────────────────── // Submodule tree (files use PascalCase basenames, mirroring the Zig sources; -// wired via `#[path]`). Heavy modules remain ``-gated until their lower- -// tier deps land — see per-module `TODO(port)` markers. +// wired via `#[path]`). // ────────────────────────────────────────────────────────────────────────── #[path = "mysql/MySQLContext.rs"] diff --git a/src/sql_jsc/mysql/JSMySQLConnection.rs b/src/sql_jsc/mysql/JSMySQLConnection.rs index 4cde5fdc749..eb9139a65c2 100644 --- a/src/sql_jsc/mysql/JSMySQLConnection.rs +++ b/src/sql_jsc/mysql/JSMySQLConnection.rs @@ -41,7 +41,7 @@ use bun_core::time::NS_PER_MS; // `impl crate::jsc::JsClass` below forwards to those. `crate::jsc` re-exports // `bun_jsc::{JSGlobalObject, CallFrame, JSValue}`, so the types are identical; // switching to the derive is a mechanical follow-up, not a layering blocker. -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim still emits `this: &mut JSMySQLConnection` — `&mut T` auto-derefs // to `&T` so the impls below compile against either. @@ -159,7 +159,7 @@ impl JSMySQLConnection { impl HasAutoFlush for JSMySQLConnection { fn on_auto_flush(this: *mut Self) -> bool { // `this` is the live `*mut JSMySQLConnection` registered with the - // deferred-task queue; the queue runs on the JS thread. R-2: deref as + // deferred-task queue; the queue runs on the JS thread. Deref as // shared — `on_auto_flush` body takes `&self`. `ParentRef` (lifetime- // erased `&T`) centralises the backref deref under its own invariant. ParentRef::from(core::ptr::NonNull::new(this).expect("auto-flush ctx non-null")) @@ -168,7 +168,7 @@ impl HasAutoFlush for JSMySQLConnection { } impl JSMySQLConnection { - // ─── R-2 interior-mutability helpers ──────────────────────────────────── + // ─── Interior-mutability helpers ──────────────────────────────────────── /// Mutable projection of the inner protocol connection through `&self`. /// @@ -180,7 +180,7 @@ impl JSMySQLConnection { #[inline] #[allow(clippy::mut_from_ref)] pub(crate) fn connection_mut(&self) -> &mut my_sql_connection::MySQLConnection { - // SAFETY: R-2 single-JS-thread invariant (see `JsCell` docs). The + // SAFETY: single-JS-thread invariant (see `JsCell` docs). The // `&mut` is fresh per call site; reentrancy through // `MySQLConnection::get_js_connection()` forms a shared // `&JSMySQLConnection` only. @@ -621,7 +621,7 @@ impl JSMySQLConnection { )), })); // `heap::into_raw` is `Box::into_raw` — never null. `ParentRef` wraps - // the freshly-boxed allocation as a lifetime-erased `&Self` (R-2: every + // the freshly-boxed allocation as a lifetime-erased `&Self` (every // field is interior-mutable, so shared access suffices for the writes // below); we hold the only reference. let this = ParentRef::from(core::ptr::NonNull::new(ptr).expect("heap::into_raw non-null")); @@ -707,7 +707,7 @@ impl JSMySQLConnection { ) -> JsResult { this.stop_timers(); - // Zig `defer this.updateReferenceType();` — R-2: `&Self` is `Copy`, so + // Zig `defer this.updateReferenceType();` — `&Self` is `Copy`, so // the scopeguard closure captures a shared reborrow and the body's // `connection_mut()` borrow is non-overlapping. scopeguard::defer! { @@ -795,7 +795,7 @@ impl JSMySQLConnection { let _ref = self.ref_guard(); scopeguard::defer! { // `_ref` has not yet dropped, so `*p` is still live; `ParentRef` - // yields a fresh `&Self` per access (R-2: every callee is `&self`). + // yields a fresh `&Self` per access (every callee is `&self`). if p.vm().is_shutting_down() { p.connection_mut().close(); } else { @@ -1104,7 +1104,7 @@ impl SocketHandler { scopeguard::defer! { // `_ref` has not yet dropped, so `*p` is still live; `ParentRef` - // yields a fresh `&JSMySQLConnection` per access (R-2: every + // yields a fresh `&JSMySQLConnection` per access (every // callee is `&self`). // reset the connection timeout after we're done processing the data p.reset_connection_timeout(); diff --git a/src/sql_jsc/mysql/JSMySQLQuery.rs b/src/sql_jsc/mysql/JSMySQLQuery.rs index 87238028d15..f35fdbf33e1 100644 --- a/src/sql_jsc/mysql/JSMySQLQuery.rs +++ b/src/sql_jsc/mysql/JSMySQLQuery.rs @@ -30,7 +30,7 @@ bun_core::define_scoped_log!(debug, MySQLQuery); // from this crate's local `crate::jsc::*` mirror types until `crate::jsc` // becomes `pub use bun_jsc as jsc;` (see lib.rs TODO). Re-enable then. // -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim still emits `this: &mut JSMySQLQuery` — `&mut T` auto-derefs to `&T` // so the impls below compile against either. @@ -149,7 +149,7 @@ impl JSMySQLQuery { )), })); // `heap::into_raw` is `Box::into_raw` — never null. Uniquely owned here - // until handed to the JS wrapper. R-2: every field is interior-mutable, + // until handed to the JS wrapper. Every field is interior-mutable, // so a shared `ParentRef` deref is sufficient even for the writes below. let this = ParentRef::from(NonNull::new(this_ptr).expect("heap::into_raw non-null")); @@ -183,7 +183,7 @@ impl JSMySQLQuery { } // `from_js_ref` wraps the m_ctx payload in a `ParentRef` — the backing // JSC wrapper is rooted by `arguments[0]` for this frame, satisfying the - // `ParentRef` outlives-holder invariant. R-2: shared `&` only — every + // `ParentRef` outlives-holder invariant. Shared `&` only — every // `MySQLConnection` method reached below is `&self` post-migration. let Some(connection) = js_mysql_connection::from_js_ref(arguments[0]) else { return Err(global_object.throw(format_args!("connection must be a MySQLConnection"))); @@ -273,7 +273,7 @@ impl JSMySQLQuery { // allocation outlives the closure body. let _guard = self.ref_guard(); let is_last_result = result.is_last_result; - // R-2: `&Self` is `Copy`; the guard captures it by value and runs on + // `&Self` is `Copy`; the guard captures it by value and runs on // every exit path (defer). All mutation is `JsCell`-backed. let _downgrade = scopeguard::guard(self, move |s| { if s.this_value.get().is_not_empty() && is_last_result { @@ -368,7 +368,7 @@ impl JSMySQLQuery { // `ref_guard` brackets re-entry; drops *after* `_downgrade` so the // allocation outlives the closure body. let _guard = self.ref_guard(); - // R-2: `&Self` is `Copy`; the guard captures it by value and runs on + // `&Self` is `Copy`; the guard captures it by value and runs on // every exit path (defer). All mutation is `JsCell`-backed. let _downgrade = scopeguard::guard(self, |s| { if s.this_value.get().is_not_empty() { @@ -441,7 +441,7 @@ impl JSMySQLQuery { } let global_object: &JSGlobalObject = self.global_object(); self.this_value.with_mut(|v| v.upgrade(global_object)); - // R-2: errdefer rollback — `&Self` is `Copy`; the guard captures it by + // Errdefer rollback — `&Self` is `Copy`; the guard captures it by // value, mutation is `JsCell`-backed, and `into_inner` disarms on the // success path below. let errguard = scopeguard::guard(self, |s| { @@ -451,14 +451,14 @@ impl JSMySQLQuery { let columns_value = self.get_columns().unwrap_or(JSValue::UNDEFINED); let binding_value = self.get_binding().unwrap_or(JSValue::UNDEFINED); - // R-2: `JsCell::with_mut` scopes the `&mut MySQLQuery` to the closure + // `JsCell::with_mut` scopes the `&mut MySQLQuery` to the closure // body. `run_query` may run user JS (binding getters), which could // re-enter another host-fn on this `JSMySQLQuery`; that re-entrant call // would form a fresh `&Self` — sound, since the noalias attribute is // suppressed by the `UnsafeCell` in `JsCell`. A re-entrant `with_mut` // on `self.query` would still alias; `set_mode_from_js` is the only // such path and is not reachable from a binding getter in well-formed - // SQL usage. This mirrors the pre-R-2 behaviour but with the *outer* + // SQL usage. This mirrors the previous `&mut self` behaviour but with the *outer* // `&mut self` UB structurally eliminated. if let Err(err) = self .query diff --git a/src/sql_jsc/mysql/MySQLConnection.rs b/src/sql_jsc/mysql/MySQLConnection.rs index 6257ec41355..ba2bc7019b4 100644 --- a/src/sql_jsc/mysql/MySQLConnection.rs +++ b/src/sql_jsc/mysql/MySQLConnection.rs @@ -964,7 +964,7 @@ impl MySQLConnection { // Send a default packet as a placeholder until ErrorPacket // grows Clone or a borrowed-variant overload lands. // - // R-2: `on_error_packet` is `&self`; route through the + // `on_error_packet` is `&self`; route through the // audited `js_connection_ref()` container_of accessor (one // centralised unsafe). `*self` sits inside the parent's // `JsCell`, so re-entrant `connection_mut()` does not alias @@ -1234,7 +1234,7 @@ impl MySQLConnection { self.queue.mark_as_ready_for_query(); self.queue.mark_current_request_as_finished(request); - // R-2: `on_error_packet` is `&self`; `js_connection_ref()` is + // `on_error_packet` is `&self`; `js_connection_ref()` is // the audited container_of accessor (one centralised unsafe). // The `&JSMySQLConnection` it yields lives only for this call — // identical footprint to the prior `(*ptr).on_error_packet()` @@ -1259,7 +1259,7 @@ impl MySQLConnection { // PORT NOTE: reshaped for borrowck — `request` comes from `self.queue` so // passing `&mut self` alongside `&mut JSMySQLQuery` would alias. `request` - // is `&JSMySQLQuery` (R-2: fully interior-mutable, so a shared borrow is + // is `&JSMySQLQuery` (fully interior-mutable, so a shared borrow is // sound across the re-entrant `on_query_result` callback). The statement is // re-fetched via the single-unsafe `request.get_statement()` accessor at // each touch point so no `&mut MySQLStatement` spans the re-entrant @@ -1289,7 +1289,7 @@ impl MySQLConnection { // Short-lived borrow via the audited accessor; dropped before the // re-entrant `on_query_result` call below. let result_count = request.get_statement().map_or(0, |s| s.result_count); - // R-2: `on_query_result` is `&self`; `js_connection_ref()` is the + // `on_query_result` is `&self`; `js_connection_ref()` is the // audited container_of accessor. The `&JSMySQLConnection` lives only for // this call (same footprint as the prior `(*ptr).on_query_result()` // temporary). `*self` sits inside the parent's `JsCell` (`UnsafeCell`), @@ -1360,7 +1360,7 @@ impl MySQLConnection { self.queue.mark_as_ready_for_query(); self.queue.mark_current_request_as_finished(request); - // R-2: `on_error_packet` is `&self`; route through the audited + // `on_error_packet` is `&self`; route through the audited // `js_connection_ref()` container_of accessor. `*self` lives // inside the parent's `JsCell`, so re-entrant `connection_mut()` // does not alias this outer shared borrow. @@ -1488,7 +1488,7 @@ impl MySQLConnection { return Ok(()); } - // R-2: `on_result_row` is `&self`; route through the audited + // `on_result_row` is `&self`; route through the audited // `js_connection_ref()` container_of accessor. The // `&JSMySQLConnection` is held only for this call (identical // footprint to the prior `(*ptr).on_result_row()` temporary); diff --git a/src/sql_jsc/mysql/MySQLRequestQueue.rs b/src/sql_jsc/mysql/MySQLRequestQueue.rs index 3d465bde410..cea31b5536d 100644 --- a/src/sql_jsc/mysql/MySQLRequestQueue.rs +++ b/src/sql_jsc/mysql/MySQLRequestQueue.rs @@ -115,7 +115,7 @@ impl MySQLRequestQueue { /// checked at the boundary), so a function-level guard adds nothing — /// caller liveness/provenance is the `ParentRef` contract. pub fn advance(connection: *mut MySQLConnection) { - // R-2: every `JSMySQLConnection` method reached below is `&self` + // Every `JSMySQLConnection` method reached below is `&self` // (interior mutability), so a `ParentRef` (yields `&T` only) collapses // the per-site `unsafe { (*connection).… }` / `&*connection` derefs. let conn_ref = @@ -137,7 +137,7 @@ impl MySQLRequestQueue { let request: *mut JSMySQLQuery = queue_ref.requests.get().peek_item(offset); // Queue holds a ref on every request; pointer is non-null and // live. `JSMySQLQuery` is a separate heap allocation — never - // aliases the queue or `*connection`. R-2: `ParentRef` yields + // aliases the queue or `*connection`. `ParentRef` yields // `&T` only — every method body is `&self` (interior mutability). let req = ParentRef::from(NonNull::new(request).expect("queue item non-null")); @@ -179,7 +179,7 @@ impl MySQLRequestQueue { // `Cell`-wrapped fields — overlapping shared reads are sound. if let Err(err) = req.run(conn_ref.get()) { debug!("run failed"); - // R-2: `on_error` takes `&self`. + // `on_error` takes `&self`. conn_ref.on_error(Some(req.get()), err); if offset == 0 { queue_ref.requests.with_mut(|q| q.discard(1)); @@ -191,14 +191,14 @@ impl MySQLRequestQueue { } if req.is_being_prepared() { debug!("isBeingPrepared"); - // R-2: `reset_connection_timeout` takes `&self`; touches + // `reset_connection_timeout` takes `&self`; touches // timer state outside the queue. conn_ref.reset_connection_timeout(); queue_ref.is_ready_for_query.set(false); queue_ref.waiting_to_prepare.set(true); break 'advance; } else if req.is_running() { - // R-2: `reset_connection_timeout` takes `&self`; touches + // `reset_connection_timeout` takes `&self`; touches // timer state outside the queue. conn_ref.reset_connection_timeout(); debug!("isRunning after run"); @@ -231,7 +231,7 @@ impl MySQLRequestQueue { let request: *mut JSMySQLQuery = queue_ref.requests.get().peek_item(0); // Queue holds a ref on every request (taken in `add()`), so the // pointer is non-null and live. Separate heap allocation — never - // aliases the queue. R-2: `ParentRef` yields `&T` only; every method + // aliases the queue. `ParentRef` yields `&T` only; every method // body reached below is `&self` (interior mutability). let req = ParentRef::from(NonNull::new(request).expect("queue item non-null")); // An item may be in the success or failed state and still be inside the queue (see deinit later comments) @@ -264,7 +264,7 @@ impl MySQLRequestQueue { pub fn add(&mut self, request: *mut JSMySQLQuery) { debug!("add"); // Caller passes a live JSMySQLQuery; we ref() it before storing. - // R-2: `ParentRef` yields `&T` only — every method body reached below + // `ParentRef` yields `&T` only — every method body reached below // is `&self` (interior mutability). let req = ParentRef::from(NonNull::new(request).expect("add: request non-null")); if req.is_being_prepared() { @@ -301,7 +301,7 @@ impl MySQLRequestQueue { /// replaces the per-caller `unsafe { &*ptr }` / `ScopedRef::new(ptr)` pair. /// The queue holds a ref on every stored request, so the pointee is live; /// `JSMySQLQuery` is a separate heap allocation (never aliases the queue or - /// its embedding connection) and is fully interior-mutable (R-2: every + /// its embedding connection) and is fully interior-mutable (every /// method is `&self`), so a shared `&JSMySQLQuery` derived via `Deref` is /// sound across `&mut self` on the connection. /// @@ -326,7 +326,7 @@ impl MySQLRequestQueue { while let Some(request) = requests.read_item() { // Queue held a ref on every request; pointer is non-null and live - // until `deref()`. R-2: `ParentRef` yields `&T` only — every method + // until `deref()`. `ParentRef` yields `&T` only — every method // body reached below is `&self`. let req = ParentRef::from(NonNull::new(request).expect("queue item non-null")); // Zig: defer request.deref() — moved to end of loop body; no early @@ -351,7 +351,7 @@ impl Drop for MySQLRequestQueue { // self.requests. read_item() peeks+discards in one &mut call. while let Some(request) = self.requests.with_mut(|q| q.read_item()) { // Queue held a ref on every request; pointer is non-null and live - // until `deref()`. R-2: `ParentRef` yields `&T` only. + // until `deref()`. `ParentRef` yields `&T` only. let req = ParentRef::from(NonNull::new(request).expect("queue item non-null")); // We cannot touch JS here req.mark_as_failed(); diff --git a/src/sql_jsc/postgres.rs b/src/sql_jsc/postgres.rs index e3e566e954f..9a20cbce19f 100644 --- a/src/sql_jsc/postgres.rs +++ b/src/sql_jsc/postgres.rs @@ -20,8 +20,7 @@ pub fn create_binding(global_object: &JSGlobalObject) -> JSValue { // ────────────────────────────────────────────────────────────────────────── // Submodule tree (files use PascalCase basenames, mirroring the Zig sources; -// wired via `#[path]`). Heavy modules remain ``-gated until their lower- -// tier deps land — see per-module `TODO(port)` markers. +// wired via `#[path]`). // ────────────────────────────────────────────────────────────────────────── #[path = "postgres/SASL.rs"] diff --git a/src/sql_jsc/postgres/PostgresSQLConnection.rs b/src/sql_jsc/postgres/PostgresSQLConnection.rs index 6039ec5591a..5778ab25595 100644 --- a/src/sql_jsc/postgres/PostgresSQLConnection.rs +++ b/src/sql_jsc/postgres/PostgresSQLConnection.rs @@ -83,7 +83,7 @@ impl jsc::JsClass for PostgresSQLConnection { use crate::jsc::verify_error_to_js; // -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). `&mut self` // carried LLVM `noalias`, but JS callbacks (promise rejections, on_close, // query results) can re-enter via a fresh `&mut Self` from `m_ctx` and mutate @@ -183,7 +183,7 @@ bun_event_loop::impl_timer_owner!(PostgresSQLConnection; ); impl PostgresSQLConnection { - // ─── R-2 interior-mutability helpers ───────────────────────────────────── + // ─── Interior-mutability helpers ───────────────────────────────────────── /// Read-modify-write the packed `Cell` through `&self`. #[inline] @@ -303,7 +303,7 @@ impl HasAutoFlush for PostgresSQLConnection { // `this` is the live `PostgresSQLConnection` registered with the // deferred-task queue (via `register_auto_flusher`, which passes // `self.as_ctx_ptr()` — never null); the queue runs on the JS thread. - // R-2: `ParentRef` yields `&T` only — body takes `&self`. + // `ParentRef` yields `&T` only — body takes `&self`. let this = ParentRef::from(NonNull::new(this).expect("auto-flush ctx non-null")); this.on_auto_flush_impl() } @@ -1303,7 +1303,7 @@ pub fn call(global_object: &JSGlobalObject, callframe: &CallFrame) -> JsResult) { - // R-2: `&self` carries no `noalias`; every field accessed below is + // `&self` carries no `noalias`; every field accessed below is // `Cell`/`JsCell`-backed, so re-entrant JS callbacks (promise reject → // user `.catch()` → new query enqueue) that mutate `self.requests` - // through a fresh `&Self` from `m_ctx` are sound. The previous - // black_box launder (b818e70e1c57-style) is no longer needed. - // The connection is kept alive by the caller's `ref_and_close` ref - // bracket for the duration of this loop, so re-entry never frees `*self`. + // through a fresh `&Self` from `m_ctx` are sound — no `black_box` + // launder is needed. The connection is kept alive by the caller's + // `ref_and_close` ref bracket for the duration of this loop, so + // re-entry never frees `*self`. while self.requests.get().readable_length() > 0 { let request_ptr: *mut PostgresSQLQuery = self.requests.get().peek_item(0); // Queue invariant: every stored pointer is non-null and live - // (refcount ≥ 1 held by the queue). R-2: `ParentRef` yields `&T` + // (refcount ≥ 1 held by the queue). `ParentRef` yields `&T` // only — `PostgresSQLQuery` is Cell/JsCell-backed. Raw `*mut` // retained for `discard_request` below. let request = ParentRef::from(NonNull::new(request_ptr).expect("queue item non-null")); @@ -1613,7 +1613,7 @@ impl PostgresSQLConnection { /// Shared borrow of the queue's head request, if any. /// /// The queue holds an intrusive ref on every `*mut PostgresSQLQuery` it - /// stores; `PostgresSQLQuery` is `Cell`/`JsCell`-backed (R-2), so a shared + /// stores; `PostgresSQLQuery` is `Cell`/`JsCell`-backed, so a shared /// `&` is sound even across re-entrant JS. Returned as a [`ParentRef`] /// (lifetime-erased `&T` via safe `Deref`) — same shape as /// `clean_up_requests`/`advance` already use for queue items, so the @@ -1674,7 +1674,7 @@ impl PostgresSQLConnection { // PORT NOTE: Zig's `Writer.connection: *PostgresSQLConnection` is a // backref (LIFETIMES.tsv BACKREF). The connection strictly outlives any Writer -// (Writers are only constructed via `self.writer()` and never stored). R-2: +// (Writers are only constructed via `self.writer()` and never stored). // `BackRef` (shared) — `write_buffer` is a `JsCell`, so mutation routes through // `with_mut`/`get_mut`. #[derive(Clone, Copy)] @@ -1735,7 +1735,7 @@ impl PostgresSQLConnection { // PORT NOTE: Zig's `Reader.connection: *PostgresSQLConnection` is a // backref (LIFETIMES.tsv BACKREF). `PostgresRequest::on_data` passes both -// `&PostgresSQLConnection` and a `NewReader` into `on()`. R-2: `BackRef` +// `&PostgresSQLConnection` and a `NewReader` into `on()`. `BackRef` // (shared) — `read_buffer`/`last_message_start` are `JsCell`/`Cell`. #[derive(Clone, Copy)] pub struct Reader { @@ -1885,7 +1885,7 @@ impl PostgresSQLConnection { while $self.requests.get().readable_length() > 0 { let result_ptr = $self.requests.get().peek_item(0); // Queue invariant: every stored pointer is non-null and - // live (refcount ≥ 1 held by the queue). R-2: `ParentRef` + // live (refcount ≥ 1 held by the queue). `ParentRef` // yields `&T` only — `PostgresSQLQuery` is Cell/JsCell-backed. let result = ParentRef::from(NonNull::new(result_ptr).expect("queue item non-null")); // An item may be in the success or failed state and still be inside the queue (see deinit later comments) @@ -1916,7 +1916,7 @@ impl PostgresSQLConnection { let req_ptr: *mut PostgresSQLQuery = self.requests.get().peek_item(offset); // Queue invariant: every stored pointer is non-null and live - // (refcount ≥ 1 held by the queue). R-2: `ParentRef` yields `&T` + // (refcount ≥ 1 held by the queue). `ParentRef` yields `&T` // only — `PostgresSQLQuery` is Cell/JsCell-backed. let req = ParentRef::from(NonNull::new(req_ptr).expect("queue item non-null")); match req.status.get() { diff --git a/src/sql_jsc/postgres/PostgresSQLQuery.rs b/src/sql_jsc/postgres/PostgresSQLQuery.rs index 6334663a752..244d1728373 100644 --- a/src/sql_jsc/postgres/PostgresSQLQuery.rs +++ b/src/sql_jsc/postgres/PostgresSQLQuery.rs @@ -33,7 +33,7 @@ pub use crate::jsc::codegen::JSPostgresSQLQuery as js; pub use js::to_js; // -// R-2 (host-fn re-entrancy): every JS-exposed method takes `&self`; per-field +// Host-fn re-entrancy: every JS-exposed method takes `&self`; per-field // interior mutability via `Cell` (Copy) / `JsCell` (non-Copy). The codegen // shim still emits `this: &mut PostgresSQLQuery` — // `&mut T` auto-derefs to `&T` so the impls below compile against either. @@ -137,7 +137,7 @@ impl Status { impl PostgresSQLQuery { // `ref_()`/`deref()` provided by `#[derive(CellRefCounted)]`. - // ─── R-2 interior-mutability helpers ───────────────────────────────────── + // ─── Interior-mutability helpers ───────────────────────────────────────── /// Read-modify-write the `Cell` through `&self`. #[inline] @@ -216,7 +216,7 @@ impl PostgresSQLQuery { global_object: &JSGlobalObject, queries_array: JSValue, ) { - // R-2: every field touched below is `Cell`/`JsCell`-backed, so `&self` + // Every field touched below is `Cell`/`JsCell`-backed, so `&self` // is sufficient and `noalias` is suppressed. `ScopedRef` brackets the // JS-re-entrant `run_callback` so a re-entrant `deref()` cannot free // `*self` mid-body. @@ -253,7 +253,7 @@ impl PostgresSQLQuery { } pub fn on_js_error(&self, err: JSValue, global_object: &JSGlobalObject) { - // R-2: see `on_write_fail` — `&self` + Cell/JsCell, ScopedRef brackets re-entry. + // See `on_write_fail` — `&self` + Cell/JsCell, ScopedRef brackets re-entry. let _deref = self.ref_guard(); self.status.set(Status::Fail); let Some(this_value) = self.this_value.get().try_get() else { @@ -310,7 +310,7 @@ impl PostgresSQLQuery { connection: JSValue, is_last: bool, ) { - // R-2: see `on_write_fail` — `&self` + Cell/JsCell, ScopedRef brackets re-entry. + // See `on_write_fail` — `&self` + Cell/JsCell, ScopedRef brackets re-entry. let _deref = self.ref_guard(); self.status.set(if is_last { Status::Success @@ -520,7 +520,7 @@ impl PostgresSQLQuery { global_object: &JSGlobalObject, callframe: &CallFrame, ) -> JsResult { - // R-2: `this` is the live m_ctx payload for `callframe.this()`; the JS + // `this` is the live m_ctx payload for `callframe.this()`; the JS // wrapper is on-stack so GC cannot finalize it. Every mutated field is // `Cell`/`JsCell`-backed, so `&Self` suffices. The pointer pushed into // `connection.requests` is derived via `core::ptr::from_ref(this).cast_mut()` @@ -531,7 +531,7 @@ impl PostgresSQLQuery { // `from_js_ref` wraps the m_ctx payload in a `ParentRef` — the JS wrapper // is on-stack (rooted by `arguments[0]`) so GC cannot finalize it for the // duration of this call, satisfying the `ParentRef` outlives-holder - // invariant. R-2: shared borrow — every connection field accessed below is + // invariant. Shared borrow — every connection field accessed below is // `Cell`/`JsCell`. let Some(connection) = postgres_sql_connection::js::from_js_ref(arguments[0]) else { return Err( diff --git a/src/sql_jsc/postgres/SASL.rs b/src/sql_jsc/postgres/SASL.rs index 6f8e14cd5ea..809b557e9c1 100644 --- a/src/sql_jsc/postgres/SASL.rs +++ b/src/sql_jsc/postgres/SASL.rs @@ -69,8 +69,9 @@ impl SASL { // Zig: `jsc.API.Bun.Crypto.EVP.pbkdf2` (src/runtime/api/crypto.zig). // PORT NOTE: `bun_runtime::crypto::EVP::pbkdf2` is a thin wrapper over // BoringSSL's `PKCS5_PBKDF2_HMAC` with `EVP_sha256`. Inlined here to - // avoid the `bun_runtime` dep (which would create a cycle through - // `bun_jsc`); `bun_boringssl_sys` is already a direct dependency. + // avoid a `bun_runtime` dep — `bun_runtime` already depends on + // `bun_sql_jsc`, so that would be a direct cycle; `bun_boringssl_sys` + // is already a direct dependency. use bun_boringssl_sys as boringssl; use core::ffi::c_uint; diff --git a/src/sys/lib.rs b/src/sys/lib.rs index 824af497256..756cc0fa162 100644 --- a/src/sys/lib.rs +++ b/src/sys/lib.rs @@ -1428,9 +1428,10 @@ impl Tag { pub const getrlimit: Tag = Tag(105); pub const setrlimit: Tag = Tag(106); // PORT NOTE: sys.zig folds `inotify_init1`/`inotify_add_watch` under the - // generic `.watch` tag; `INotifyWatcher.rs` was ported against the - // draft-b1 enum that had a distinct `.inotify` variant. Alias to `.watch` - // so the JS-facing `err.syscall == "watch"` string stays node-compatible. + // generic `.watch` tag; `INotifyWatcher.rs` was written against an earlier + // version of this enum that had a distinct `.inotify` variant. Alias to + // `.watch` so the JS-facing `err.syscall == "watch"` string stays + // node-compatible. pub const inotify: Tag = Tag::watch; /// `@tagName(self)` — must match sys.zig spelling exactly (JS-facing @@ -9041,7 +9042,7 @@ pub fn fetch_cache_directory_path() -> Vec { } // ────────────────────────────────────────────────────────────────────────── -// OUTPUT_SINK — bun_core's stderr vtable, installed by us at init (B-0 hook). +// OUTPUT_SINK — bun_core's stderr vtable, installed by us at init. // ────────────────────────────────────────────────────────────────────────── /// `bun_core::output::QuietWriter` is an opaque `[*mut (); 4]`. We stash the diff --git a/src/url/Cargo.toml b/src/url/Cargo.toml index 8dbdc992077..cff7f4eb8f9 100644 --- a/src/url/Cargo.toml +++ b/src/url/Cargo.toml @@ -22,7 +22,7 @@ bitflags.workspace = true bun_alloc.workspace = true bun_core.workspace = true bun_collections.workspace = true -# TODO(b1): bun_io gated — crate does not compile yet; local Write stub in lib.rs +# bun_io intentionally not depended on; lib.rs uses `bun_core::io::Write` directly. # bun_io.workspace = true bun_paths.workspace = true bun_wyhash.workspace = true diff --git a/src/uws/lib.rs b/src/uws/lib.rs index ebd6642647e..594f2d1be46 100644 --- a/src/uws/lib.rs +++ b/src/uws/lib.rs @@ -254,7 +254,7 @@ pub mod ssl_wrapper { /// snake_case→CamelCase rewriter (e.g. `http_jsc`). pub type SslWrapper = SSLWrapper; - /// `Cell`-backed bitfield so the R-2 noalias-laundered self-backref (see + /// `Cell`-backed bitfield so the noalias-laundered self-backref (see /// [`SSLWrapper::r`]) can read AND write flags through a shared `&Self` /// borrow — collapses the `unsafe { (*this).flags.set_X(..) }` pattern in /// `shutdown` / `update_handshake_state` / `handle_writing` into safe @@ -576,7 +576,7 @@ pub mod ssl_wrapper { /// fast_shutdown = true, this will also fully close both read and /// write directions. pub fn shutdown(&mut self, fast_shutdown: bool) -> bool { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `trigger_handshake_callback` / `trigger_close_callback` invoke // the user-supplied handler vtable (`handlers.on_close` / // `on_handshake`) which can re-enter via a fresh `&mut SSLWrapper` @@ -847,7 +847,7 @@ pub mod ssl_wrapper { /// Update the handshake state. Returns true if we can call handle_reading. fn update_handshake_state(&mut self) -> bool { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `shutdown()` / `trigger_close_callback()` / // `trigger_handshake_callback()` invoke the user-supplied handler // vtable which can re-enter via a fresh `&mut SSLWrapper` from the @@ -1067,7 +1067,7 @@ pub mod ssl_wrapper { } fn handle_writing(&mut self, buffer: &mut [u8; BUFFER_SIZE]) { - // PORT_NOTES_PLAN R-2: `&mut self` carries LLVM `noalias`, but + // noalias re-entry (see bun_ptr::LaunderedSelf): `&mut self` carries LLVM `noalias`, but // `trigger_wanna_write_callback` invokes the user-supplied // `handlers.write` which can re-enter via a fresh // `&mut SSLWrapper` from the owning socket and `deinit()` (sets