From d3b6af9588f1fe22c91a5330e3f62fd7b2316393 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 29 Aug 2026 18:31:08 +0000 Subject: [PATCH 1/9] Remove dead code found by a gc-sections relink: Zig-port bindgen adapters, unused error impls, dead C++ bindings A relink of the debug build with --gc-sections --print-gc-sections lists every function nothing in the final binary references. This removes the ones that are dead on every platform: - src/jsc/bindgen.rs: the Zig-port Bindgen adapters (BindgenStrongAny, BindgenNull, BindgenOptional, BindgenString, BindgenArray, ExternTaggedUnion2, ExternUnion2, ExternArrayList) and their only users Strong::adopt, bun_alloc::realloc_raw, and the WTFString alias with its ExternalSharedDescriptor impl. - src/codegen/bindgenv2: the Zig type emitters (bindgenType, zigType, optionalZigType, CodeStyle, toZigNamespace). The generator only emits C++. - Hand-written ErrName impls on 15 crate error types that nothing calls through the trait, the unused Display impls on bun_md::ParserError, bun_jsc::SystemError and HTMLImportManifest, Appender::append_lower_case and its impls, MaxHeapScope Deref impls, BitSet::set_intersection, Builtins::{from_executable,len,is_empty,modules}, AbortSignal::detach. - jest.classes.ts: call: true on the seven noConstructor Expect classes only emitted an unused thunk and extern declaration. - C++: the unused node:crypto key helpers keyFromString, passphraseFromBufferSource and the 4/6-argument parseKeyFormat/parseKeyType overloads, the WebCore::JSErrorHandler class, rejectPromiseWithGetterTypeError, toJSNewlyCreated(Ref), two validateInteger instantiations, and the uWS run()/listen(port, cb) entry points with their uws_app_run/uws_app_listen C wrappers. --- packages/bun-uws/src/App.h | 11 - packages/bun-uws/src/Loop.h | 12 +- src/ast/error.rs | 6 - src/bun_alloc/MaxHeapAllocator.rs | 18 +- src/bun_alloc/lib.rs | 20 -- src/bun_core/external_shared.rs | 22 -- src/bun_core/lib.rs | 2 +- src/bun_core/string/immutable.rs | 3 +- src/bun_core/string/wtf.rs | 6 - src/bun_core/wtf.rs | 2 +- src/bundler/HTMLImportManifest.rs | 16 -- src/codegen/bindgenv2/internal/any.ts | 17 +- src/codegen/bindgenv2/internal/array.ts | 8 +- src/codegen/bindgenv2/internal/base.ts | 18 -- src/codegen/bindgenv2/internal/dictionary.ts | 7 - src/codegen/bindgenv2/internal/enumeration.ts | 15 +- src/codegen/bindgenv2/internal/interfaces.ts | 20 +- src/codegen/bindgenv2/internal/optional.ts | 36 +-- src/codegen/bindgenv2/internal/primitives.ts | 50 +--- src/codegen/bindgenv2/internal/string.ts | 20 +- src/codegen/bindgenv2/internal/union.ts | 31 +- src/codegen/bindgenv2/script.ts | 22 -- src/collections/bit_set.rs | 18 -- src/crash_handler/error.rs | 6 - src/dotenv/error.rs | 6 - src/exe_format/builtins.rs | 19 +- src/exe_format/error.rs | 6 - src/install/NetworkTask.rs | 13 +- src/io/error.rs | 17 -- src/js_parser/error.rs | 6 - src/js_parser_jsc/error.rs | 6 - src/js_printer/error.rs | 6 - src/jsc/AbortSignal.rs | 5 - src/jsc/Strong.rs | 10 - src/jsc/SystemError.rs | 42 --- src/jsc/bindgen.rs | 266 +----------------- src/jsc/bindings/JSDOMExceptionHandling.cpp | 5 - src/jsc/bindings/JSDOMExceptionHandling.h | 1 - src/jsc/bindings/NodeValidator.cpp | 2 - src/jsc/bindings/blob.cpp | 12 - src/jsc/bindings/blob.h | 2 - src/jsc/bindings/node/crypto/CryptoUtil.cpp | 157 ----------- src/jsc/bindings/node/crypto/CryptoUtil.h | 4 - src/jsc/bindings/webcore/EventEmitter.cpp | 1 - src/jsc/bindings/webcore/EventTarget.cpp | 2 - src/jsc/bindings/webcore/JSDOMAttribute.h | 2 - src/jsc/bindings/webcore/JSErrorHandler.cpp | 122 -------- src/jsc/bindings/webcore/JSErrorHandler.h | 48 ---- src/jsc/virtual_machine_exports.rs | 1 - src/libarchive/error.rs | 19 -- src/md/parser.rs | 8 - src/options_types/error.rs | 6 - src/ptr/lib.rs | 2 +- src/resolver/fs.rs | 9 +- src/resolver/lib.rs | 16 -- src/runtime/cli/pm_diff_command.rs | 5 - src/runtime/test_runner/expect.rs | 7 - src/runtime/test_runner/jest.classes.ts | 14 +- src/shell_parser/error.rs | 6 - src/sourcemap/error.rs | 6 - src/spawn_sys/error.rs | 6 - src/standalone_graph/error.rs | 6 - src/uws_sys/libuwsockets.cpp | 39 --- 63 files changed, 27 insertions(+), 1269 deletions(-) delete mode 100644 src/jsc/bindings/webcore/JSErrorHandler.cpp delete mode 100644 src/jsc/bindings/webcore/JSErrorHandler.h diff --git a/packages/bun-uws/src/App.h b/packages/bun-uws/src/App.h index f2444a46bbde..57649f4def51 100644 --- a/packages/bun-uws/src/App.h +++ b/packages/bun-uws/src/App.h @@ -737,12 +737,6 @@ struct TemplatedApp { return std::move(*this); } - /* Port, callback */ - TemplatedApp &&listen(int port, MoveOnlyFunction &&handler) { - handler(httpContext ? trackListenSocket(httpContext->listen(sslCtxOrNull(), nullptr, port, 0)) : nullptr); - return std::move(*this); - } - /* Port, options, callback */ TemplatedApp &&listen(int port, int options, MoveOnlyFunction &&handler) { handler(httpContext ? trackListenSocket(httpContext->listen(sslCtxOrNull(), nullptr, port, options)) : nullptr); @@ -778,11 +772,6 @@ struct TemplatedApp { httpContext->enableNodeHttpCompat(); } - TemplatedApp &&run() { - uWS::run(); - return std::move(*this); - } - TemplatedApp &&setUsingCustomExpectHandler(bool value) { httpContext->getSocketContextData()->flags.usingCustomExpectHandler = value; return std::move(*this); diff --git a/packages/bun-uws/src/Loop.h b/packages/bun-uws/src/Loop.h index e6c73e9508f7..8e736ead8d39 100644 --- a/packages/bun-uws/src/Loop.h +++ b/packages/bun-uws/src/Loop.h @@ -19,7 +19,7 @@ #ifndef UWS_LOOP_H #define UWS_LOOP_H -/* The loop is lazily created per-thread and run with run() */ +/* The loop is lazily created per-thread */ #include "LoopData.h" #include @@ -189,18 +189,8 @@ struct Loop { us_wakeup_loop((us_loop_t *) this); } - /* Actively block and run this loop */ - void run() { - us_loop_run((us_loop_t *) this); - } - }; -/* Can be called from any thread to run the thread local loop */ -inline void run() { - Loop::get()->run(); -} - } #endif // UWS_LOOP_H diff --git a/src/ast/error.rs b/src/ast/error.rs index ddcc801b2027..2bf0b5d27940 100644 --- a/src/ast/error.rs +++ b/src/ast/error.rs @@ -19,10 +19,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/bun_alloc/MaxHeapAllocator.rs b/src/bun_alloc/MaxHeapAllocator.rs index 8421ac53cb8b..27e261805619 100644 --- a/src/bun_alloc/MaxHeapAllocator.rs +++ b/src/bun_alloc/MaxHeapAllocator.rs @@ -44,26 +44,12 @@ impl MaxHeapAllocator { } } -/// RAII guard returned by [`MaxHeapAllocator::scope`]. Derefs to the underlying -/// allocator so callers can hand out `&mut MaxHeapAllocator` (or a derived -/// `&dyn Allocator`) for the duration of the scope, and resets it on drop. +/// RAII guard returned by [`MaxHeapAllocator::scope`]. Holds the allocator +/// for the duration of the scope and resets it on drop. pub struct MaxHeapScope<'a> { inner: &'a mut MaxHeapAllocator, } -impl core::ops::Deref for MaxHeapScope<'_> { - type Target = MaxHeapAllocator; - fn deref(&self) -> &Self::Target { - self.inner - } -} - -impl core::ops::DerefMut for MaxHeapScope<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.inner - } -} - impl Drop for MaxHeapScope<'_> { fn drop(&mut self) { self.inner.reset(); diff --git a/src/bun_alloc/lib.rs b/src/bun_alloc/lib.rs index 64a4a3b40677..3516ef5e781c 100644 --- a/src/bun_alloc/lib.rs +++ b/src/bun_alloc/lib.rs @@ -568,26 +568,6 @@ unsafe impl core::alloc::GlobalAlloc for Mimalloc { } } -/// Resize a mimalloc-owned buffer, taking a raw pointer for callers that -/// cannot soundly materialize a `&mut [u8]` over their buffer (e.g. it contains -/// uninitialized or padding bytes). Returns the new base pointer; -/// `min(old_size, new_size)` prefix bytes are preserved. -/// -/// # Safety -/// `ptr` must be a live allocation from the default (mimalloc) allocator with -/// alignment ≤ `MI_MAX_ALIGN_SIZE`. After return, `ptr` is invalidated. -pub unsafe fn realloc_raw( - ptr: *mut u8, - new_size: usize, -) -> core::result::Result<*mut u8, AllocError> { - // SAFETY: caller guarantees `ptr` is a mimalloc-owned block. - let new_ptr = unsafe { mimalloc::mi_realloc(ptr.cast(), new_size) }; - if new_ptr.is_null() { - return Err(AllocError); - } - Ok(new_ptr.cast::()) -} - // ────────────────────────────────────────────────────────────────────────── // Symbols hoisted DOWN into T0 so higher tiers can re-import without cycles. // ────────────────────────────────────────────────────────────────────────── diff --git a/src/bun_core/external_shared.rs b/src/bun_core/external_shared.rs index 0951f44e7396..a5498d13fec6 100644 --- a/src/bun_core/external_shared.rs +++ b/src/bun_core/external_shared.rs @@ -83,25 +83,3 @@ impl Drop for ExternalShared { unsafe { T::ext_deref(self.ptr.as_ptr()) }; } } - -// ────────────────────────────────────────────────────────────────────────── -// `WTF::StringImpl` descriptor — lives here (not `bun_string`) because the -// struct is defined in `bun_alloc` and the trait here; orphan rule requires -// one of them to be local. `bun_ptr` already depends on `bun_alloc`. -// ────────────────────────────────────────────────────────────────────────── - -// SAFETY: ref/deref delegate to JSC's WTF::StringImpl atomic refcount via FFI; -// the pointee remains valid while count > 0 (JSC contract). -unsafe impl ExternalSharedDescriptor for bun_alloc::WTFStringImplStruct { - unsafe fn ext_ref(this: *mut Self) { - // SAFETY: caller guarantees `this` is a live WTFStringImpl. - unsafe { (*this).r#ref() } - } - unsafe fn ext_deref(this: *mut Self) { - // SAFETY: caller guarantees `this` is a live WTFStringImpl. - unsafe { (*this).deref() } - } -} - -/// Behaves like `WTF::Ref`. -pub type WTFString = ExternalShared; diff --git a/src/bun_core/lib.rs b/src/bun_core/lib.rs index c5b8d48c6220..98d56395814d 100644 --- a/src/bun_core/lib.rs +++ b/src/bun_core/lib.rs @@ -69,7 +69,7 @@ pub use string::{StringPointer, Tag, slice_to_nul}; // merge would otherwise cycle). The original crates re-export these. // ────────────────────────────────────────────────────────────────────────── pub mod external_shared; -pub use external_shared::{ExternalShared, ExternalSharedDescriptor, WTFString}; +pub use external_shared::{ExternalShared, ExternalSharedDescriptor}; pub mod bounded_array; pub use bounded_array::{BoundedArray, BoundedArrayAligned}; diff --git a/src/bun_core/string/immutable.rs b/src/bun_core/string/immutable.rs index deaf6b132ab7..a0f673a5c310 100644 --- a/src/bun_core/string/immutable.rs +++ b/src/bun_core/string/immutable.rs @@ -873,10 +873,9 @@ impl StringOrTinyString { } } -/// Trait for the `Appender` parameter on `StringOrTinyString::init*_append_if_needed`. +/// Trait for the `Appender` parameter on `StringOrTinyString::init_append_if_needed`. pub trait Appender { fn append(&mut self, s: &[u8]) -> Result<&[u8], AllocError>; - fn append_lower_case(&mut self, s: &[u8]) -> Result<&[u8], AllocError>; } pub use crate::strings_impl::{ascii_lowercase_buf, copy_lowercase}; diff --git a/src/bun_core/string/wtf.rs b/src/bun_core/string/wtf.rs index b604e2bc9234..4a2c4f02bf49 100644 --- a/src/bun_core/string/wtf.rs +++ b/src/bun_core/string/wtf.rs @@ -4,12 +4,6 @@ use crate::strings; // The struct layout lives in `bun_alloc` (lowest-tier crate). pub use bun_alloc::{WTFStringImpl, WTFStringImplPtr, WTFStringImplStruct}; -/// Behaves like `WTF::Ref`. The -/// [`crate::external_shared::ExternalSharedDescriptor`] impl lives alongside -/// the trait in `bun_core::external_shared` (orphan rule: trait owner gets -/// the impl since the type is foreign — defined in `bun_alloc`). -pub use crate::external_shared::WTFString; - /// Extension methods on [`WTFStringImplStruct`] that depend on /// `bun_core` types ([`Utf8Bytes`], `crate::ZBox`) or /// `crate::strings::*` transcoding. Kept as a trait because the struct is diff --git a/src/bun_core/wtf.rs b/src/bun_core/wtf.rs index 506fc908632b..52670bf92e19 100644 --- a/src/bun_core/wtf.rs +++ b/src/bun_core/wtf.rs @@ -56,5 +56,5 @@ pub fn parse_es5_date(buf: &[u8]) -> Result { // `bun_core::wtf::parse_double` (formerly `bun_core::wtf::parse_double`) // resolves unchanged. pub use crate::string::wtf::{ - InvalidCharacter, WTFString, WTFStringImpl, WTFStringImplExt, WTFStringImplStruct, parse_double, + InvalidCharacter, WTFStringImpl, WTFStringImplExt, WTFStringImplStruct, parse_double, }; diff --git a/src/bundler/HTMLImportManifest.rs b/src/bundler/HTMLImportManifest.rs index e09d11c65af2..6839725490bb 100644 --- a/src/bundler/HTMLImportManifest.rs +++ b/src/bundler/HTMLImportManifest.rs @@ -59,22 +59,6 @@ pub struct HTMLImportManifest<'a> { pub(crate) linker_graph: &'a LinkerGraph<'a>, } -impl<'a> fmt::Display for HTMLImportManifest<'a> { - fn fmt(&self, writer: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut adapter = FmtAdapter::new(writer); - match write( - self.index, - self.graph, - self.linker_graph, - self.chunks, - &mut adapter, - ) { - Ok(()) => Ok(()), - Err(_) => Err(fmt::Error), - } - } -} - fn write_entry_item( writer: &mut W, input: &[u8], diff --git a/src/codegen/bindgenv2/internal/any.ts b/src/codegen/bindgenv2/internal/any.ts index 024d175805ad..c1d3ea9c8862 100644 --- a/src/codegen/bindgenv2/internal/any.ts +++ b/src/codegen/bindgenv2/internal/any.ts @@ -1,15 +1,9 @@ -import { CodeStyle, Type } from "./base"; +import { Type } from "./base"; export const RawAny = new (class extends Type { get idlType() { return "::Bun::IDLRawAny"; } - get bindgenType() { - return "bindgen.BindgenRawAny"; - } - zigType(style?: CodeStyle) { - return "bun.bun_js.jsc.JSValue"; - } toCpp(value: any): string { throw RangeError("`RawAny` cannot have a default value"); } @@ -19,15 +13,6 @@ export const StrongAny = new (class extends Type { get idlType() { return "::Bun::Bindgen::IDLStrongAny"; } - get bindgenType() { - return "bindgen.BindgenStrongAny"; - } - zigType(style?: CodeStyle) { - return "bun.bun_js.jsc.Strong"; - } - optionalZigType(style?: CodeStyle) { - return this.zigType(style) + ".Optional"; - } toCpp(value: any): string { throw RangeError("`StrongAny` cannot have a default value"); } diff --git a/src/codegen/bindgenv2/internal/array.ts b/src/codegen/bindgenv2/internal/array.ts index 51444b8c6c53..d6080817c216 100644 --- a/src/codegen/bindgenv2/internal/array.ts +++ b/src/codegen/bindgenv2/internal/array.ts @@ -1,5 +1,5 @@ import { hasRawAny } from "./any"; -import { CodeStyle, Type } from "./base"; +import { Type } from "./base"; export abstract class ArrayType extends Type {} @@ -11,12 +11,6 @@ export function Array(elemType: Type): ArrayType { get idlType() { return `::Bun::IDLArray<${elemType.idlType}>`; } - get bindgenType() { - return `bindgen.BindgenArray(${elemType.bindgenType})`; - } - zigType(style?: CodeStyle) { - return `bun.collections.ArrayListDefault(${elemType.zigType(style)})`; - } toCpp(value: any[]): string { const args = `${value.map(elem => elemType.toCpp(elem)).join(", ")}`; return `${this.idlType}::ImplementationType { ${args} }`; diff --git a/src/codegen/bindgenv2/internal/base.ts b/src/codegen/bindgenv2/internal/base.ts index 51c76d7b40e6..445921cb147f 100644 --- a/src/codegen/bindgenv2/internal/base.ts +++ b/src/codegen/bindgenv2/internal/base.ts @@ -1,9 +1,6 @@ import util from "node:util"; import type { NullableType, OptionalType } from "./optional"; -/** Default is "compact". */ -export type CodeStyle = "compact" | "pretty"; - export abstract class Type { /** Treats `undefined` as a not-provided value. */ get optional(): OptionalType { @@ -16,21 +13,6 @@ export abstract class Type { } abstract readonly idlType: string; - abstract readonly bindgenType: string; - - /** - * This can be overridden to make the generated code clearer. If overridden, it must return an - * expression that evaluates to the same type as `${this.bindgenType}.ZigType`; it should not - * actually change the type. - */ - zigType(style?: CodeStyle): string { - return this.bindgenType + ".ZigType"; - } - - /** This must be overridden if a custom `OptionalZigType` is defined. */ - optionalZigType(style?: CodeStyle): string { - return `?${this.zigType(style)}`; - } /** Converts a JS value into a C++ expression. Used for default values. */ abstract toCpp(value: any): string; diff --git a/src/codegen/bindgenv2/internal/dictionary.ts b/src/codegen/bindgenv2/internal/dictionary.ts index 529e46042fa4..b2159175f04a 100644 --- a/src/codegen/bindgenv2/internal/dictionary.ts +++ b/src/codegen/bindgenv2/internal/dictionary.ts @@ -1,7 +1,6 @@ import { hasRawAny, isAny } from "./any"; import { addIndent, - CodeStyle, dedent, headersForTypes, joinIndented, @@ -70,12 +69,6 @@ export function dictionary( get idlType() { return `::Bun::Bindgen::Generated::IDL${name}`; } - get bindgenType() { - return `bindgen_generated.internal.${name}`; - } - zigType(style?: CodeStyle) { - return `bindgen_generated.${name}`; - } get dependencies() { return fullMembers.map(m => m.type); } diff --git a/src/codegen/bindgenv2/internal/enumeration.ts b/src/codegen/bindgenv2/internal/enumeration.ts index 502487717b3f..2f11f8d950bc 100644 --- a/src/codegen/bindgenv2/internal/enumeration.ts +++ b/src/codegen/bindgenv2/internal/enumeration.ts @@ -1,13 +1,6 @@ import assert from "node:assert"; import util from "node:util"; -import { - CodeStyle, - joinIndented, - NamedType, - reindent, - toASCIILiteral, - toQuotedLiteral, -} from "./base"; +import { joinIndented, NamedType, reindent, toASCIILiteral, toQuotedLiteral } from "./base"; abstract class EnumType extends NamedType {} @@ -61,12 +54,6 @@ export function enumeration( get idlType() { return `::Bun::Bindgen::Generated::IDL${name}`; } - get bindgenType() { - return `bindgen_generated.internal.${name}`; - } - zigType(style?: CodeStyle) { - return `bindgen_generated.${name}`; - } toCpp(value: string): string { const index = valueMap.get(value); if (index == null) { diff --git a/src/codegen/bindgenv2/internal/interfaces.ts b/src/codegen/bindgenv2/internal/interfaces.ts index 21584ba0f4ef..25ef474f8274 100644 --- a/src/codegen/bindgenv2/internal/interfaces.ts +++ b/src/codegen/bindgenv2/internal/interfaces.ts @@ -1,18 +1,9 @@ -import { CodeStyle, Type } from "./base"; +import { Type } from "./base"; export const ArrayBuffer = new (class extends Type { get idlType() { return `::Bun::IDLArrayBufferRef`; } - get bindgenType() { - return `bindgen.BindgenArrayBuffer`; - } - zigType(style?: CodeStyle) { - return "bun.bun_js.jsc.JSCArrayBuffer.Ref"; - } - optionalZigType(style?: CodeStyle) { - return this.zigType(style) + ".Optional"; - } toCpp(value: any): string { throw RangeError("default values for `ArrayBuffer` are not supported"); } @@ -22,15 +13,6 @@ export const Blob = new (class extends Type { get idlType() { return `::Bun::IDLBlobRef`; } - get bindgenType() { - return `bindgen.BindgenBlob`; - } - zigType(style?: CodeStyle) { - return "bun.bun_js.webcore.Blob.Ref"; - } - optionalZigType(style?: CodeStyle) { - return this.zigType(style) + ".Optional"; - } toCpp(value: any): string { throw RangeError("default values for `Blob` are not supported"); } diff --git a/src/codegen/bindgenv2/internal/optional.ts b/src/codegen/bindgenv2/internal/optional.ts index b18a1a398e60..19e80aa259ca 100644 --- a/src/codegen/bindgenv2/internal/optional.ts +++ b/src/codegen/bindgenv2/internal/optional.ts @@ -1,9 +1,5 @@ import { isAny } from "./any"; -import { CodeStyle, Type } from "./base"; - -function bindgenOptional(payload: Type): string { - return `bindgen.BindgenOptional(${payload.bindgenType})`; -} +import { Type } from "./base"; export abstract class OptionalType extends Type {} @@ -16,12 +12,6 @@ export function optional(payload: Type): OptionalType { get idlType() { return `::WebCore::IDLOptional<${payload.idlType}>`; } - get bindgenType() { - return bindgenOptional(payload); - } - zigType(style?: CodeStyle) { - return payload.optionalZigType(style); - } toCpp(value: any): string { if (value === undefined) { return `::WebCore::IDLOptional<${payload.idlType}>::nullValue()`; @@ -46,12 +36,6 @@ export function nullable(payload: Type): NullableType { get idlType() { return `::WebCore::IDLNullable<${payload.idlType}>`; } - get bindgenType() { - return bindgenOptional(payload); - } - zigType(style?: CodeStyle) { - return payload.optionalZigType(style); - } toCpp(value: any): string { if (value == null) { return `::WebCore::IDLNullable<${payload.idlType}>::nullValue()`; @@ -69,12 +53,6 @@ export function looseNullable(payload: Type): LooseNullableType { get idlType() { return `::Bun::IDLLooseNullable<${payload.idlType}>`; } - get bindgenType() { - return bindgenOptional(payload); - } - zigType(style?: CodeStyle) { - return payload.optionalZigType(style); - } toCpp(value: any): string { if (!value) { return `::Bun::IDLLooseNullable<${payload.idlType}>::nullValue()`; @@ -89,12 +67,6 @@ const Undefined = new (class extends Type { get idlType() { return `::Bun::IDLStrictUndefined`; } - get bindgenType() { - return `bindgen.BindgenNull`; - } - zigType(style?: CodeStyle) { - return "void"; - } toCpp(value: undefined): string { return `{}`; } @@ -105,12 +77,6 @@ const Null = new (class extends Type { get idlType() { return `::Bun::IDLStrictNull`; } - get bindgenType() { - return `bindgen.BindgenNull`; - } - zigType(style?: CodeStyle) { - return "void"; - } toCpp(value: null): string { return `nullptr`; } diff --git a/src/codegen/bindgenv2/internal/primitives.ts b/src/codegen/bindgenv2/internal/primitives.ts index 1a8bfec31b8a..92caff4d2e8c 100644 --- a/src/codegen/bindgenv2/internal/primitives.ts +++ b/src/codegen/bindgenv2/internal/primitives.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import util from "node:util"; -import { CodeStyle, Type } from "./base"; +import { Type } from "./base"; export const bool = new (class extends Type { /** Converts to a boolean, as if by calling `Boolean`. */ @@ -11,12 +11,6 @@ export const bool = new (class extends Type { get idlType() { return "::Bun::IDLStrictBoolean"; } - get bindgenType() { - return `bindgen.BindgenBool`; - } - zigType(style?: CodeStyle) { - return "bool"; - } toCpp(value: boolean): string { assert(typeof value === "boolean"); return value ? "true" : "false"; @@ -27,12 +21,6 @@ export const LooseBool = new (class extends Type { get idlType() { return "::WebCore::IDLBoolean"; } - get bindgenType() { - return bool.bindgenType; - } - zigType(style?: CodeStyle) { - return bool.zigType(style); - } toCpp(value: boolean): string { return bool.toCpp(value); } @@ -54,12 +42,6 @@ function makeUnsignedType(width: number): IntegerType { get idlType() { return `::Bun::IDLStrictInteger<${this.cppType}>`; } - get bindgenType() { - return `bindgen.BindgenU${width}`; - } - zigType(style?: CodeStyle) { - return `u${width}`; - } get cppType() { return `::std::uint${width}_t`; } @@ -85,12 +67,6 @@ function makeSignedType(width: number): IntegerType { get idlType() { return `::Bun::IDLStrictInteger<${this.cppType}>`; } - get bindgenType() { - return `bindgen.BindgenI${width}`; - } - zigType(style?: CodeStyle) { - return `i${width}`; - } get cppType() { return `::std::int${width}_t`; } @@ -127,12 +103,6 @@ function makeLooseIntegerType(strict: IntegerType): LooseIntegerType { get idlType() { return `::Bun::IDLLooseInteger<${strict.cppType}>`; } - get bindgenType() { - return strict.bindgenType; - } - zigType(style?: CodeStyle) { - return strict.zigType(style); - } toCpp(value: number | bigint): string { return strict.toCpp(value); } @@ -176,12 +146,6 @@ export const f64 = new (class extends Type { get idlType() { return "::Bun::IDLStrictDouble"; } - get bindgenType() { - return `bindgen.BindgenF64`; - } - zigType(style?: CodeStyle) { - return `f64`; - } toCpp(value: number): string { assert(typeof value === "number"); if (Number.isNaN(value)) { @@ -200,12 +164,6 @@ export const FiniteF64 = new (class extends Type { get idlType() { return "::Bun::IDLFiniteDouble"; } - get bindgenType() { - return f64.bindgenType; - } - zigType(style?: CodeStyle) { - return f64.zigType(style); - } toCpp(value: number): string { assert(typeof value === "number"); if (!Number.isFinite(value)) throw RangeError("number must be finite"); @@ -217,12 +175,6 @@ export const LooseF64 = new (class extends Type { get idlType() { return "::WebCore::IDLUnrestrictedDouble"; } - get bindgenType() { - return f64.bindgenType; - } - zigType(style?: CodeStyle) { - return f64.zigType(style); - } toCpp(value: number): string { return f64.toCpp(value); } diff --git a/src/codegen/bindgenv2/internal/string.ts b/src/codegen/bindgenv2/internal/string.ts index 48c7f867666b..687c13464e78 100644 --- a/src/codegen/bindgenv2/internal/string.ts +++ b/src/codegen/bindgenv2/internal/string.ts @@ -1,5 +1,5 @@ import assert from "node:assert"; -import { CodeStyle, Type, toASCIILiteral } from "./base"; +import { Type, toASCIILiteral } from "./base"; export const String = new (class extends Type { /** Converts to a string, as if by calling `String`. */ @@ -10,15 +10,6 @@ export const String = new (class extends Type { get idlType() { return "::Bun::IDLStrictString"; } - get bindgenType() { - return "bindgen.BindgenString"; - } - zigType(style?: CodeStyle) { - return "bun.string.WTFString"; - } - optionalZigType(style?: CodeStyle) { - return this.zigType(style) + ".Optional"; - } toCpp(value: string): string { assert(typeof value === "string"); return toASCIILiteral(value); @@ -29,15 +20,6 @@ export const LooseString = new (class extends Type { get idlType() { return "::Bun::IDLDOMString"; } - get bindgenType() { - return String.bindgenType; - } - zigType(style?: CodeStyle) { - return String.zigType(style); - } - optionalZigType(style?: CodeStyle) { - return String.optionalZigType(style); - } toCpp(value: string): string { return String.toCpp(value); } diff --git a/src/codegen/bindgenv2/internal/union.ts b/src/codegen/bindgenv2/internal/union.ts index 7f9fe8f6b61c..4b7851e2b279 100644 --- a/src/codegen/bindgenv2/internal/union.ts +++ b/src/codegen/bindgenv2/internal/union.ts @@ -1,14 +1,5 @@ import assert from "node:assert"; -import { - CodeStyle, - dedent, - headersForTypes, - joinIndented, - NamedType, - reindent, - Type, - validateName, -} from "./base"; +import { headersForTypes, NamedType, reindent, Type, validateName } from "./base"; export interface NamedAlternatives { readonly [name: string]: Type; @@ -66,20 +57,6 @@ export function union( get idlType() { return getUnionType(); } - get bindgenType() { - return `bindgen.BindgenUnion(&.{ ${alternatives.map(a => a.bindgenType).join(", ")} })`; - } - zigType(style?: CodeStyle) { - if (style !== "pretty") { - return `bun.meta.TaggedUnion(&.{ ${alternatives.map(a => a.zigType()).join(", ")} })`; - } - return dedent(`bun.meta.TaggedUnion(&.{ - ${joinIndented( - 10, - alternatives.map(a => a.zigType("pretty") + ","), - )} - })`); - } get dependencies() { return Object.freeze(alternatives); } @@ -103,12 +80,6 @@ export function union( get idlType() { return `::Bun::Bindgen::Generated::IDL${name}`; } - get bindgenType() { - return `bindgen_generated.internal.${name}`; - } - zigType(style?: CodeStyle) { - return `bindgen_generated.${name}`; - } get dependencies() { return Object.freeze(alternatives); } diff --git a/src/codegen/bindgenv2/script.ts b/src/codegen/bindgenv2/script.ts index 11a58315e3fd..2c85d7c54629 100755 --- a/src/codegen/bindgenv2/script.ts +++ b/src/codegen/bindgenv2/script.ts @@ -42,17 +42,6 @@ function cppSourcePath(type: NamedType): string { return `${codegenPath}/Generated${type.name}.cpp`; } -function toZigNamespace(name: string): string { - const result = name - .replace(/([^A-Z_])([A-Z])/g, "$1_$2") - .replace(/([A-Z])([A-Z][a-z])/g, "$1_$2") - .toLowerCase(); - if (result === name) { - return result + "_namespace"; - } - return result; -} - /** Must name every file generate() writes: the build declares these as the outputs of the generate step. */ function listOutputs(): void { const outputs: string[] = []; @@ -64,8 +53,6 @@ function listOutputs(): void { } function generate(): void { - const names = new Set(); - const namedExports = getNamedExports(); { const namedDependencies = new Set(); @@ -89,15 +76,6 @@ function generate(): void { } for (const type of namedExports) { - const zigNamespace = toZigNamespace(type.name); - const size = names.size; - names.add(type.name); - names.add(zigNamespace); - if (names.size !== size + 2) { - console.error(`error: duplicate name: ${type.name}`); - process.exit(1); - } - const cppHeader = type.cppHeader; const cppSource = type.cppSource; if (cppHeader) { diff --git a/src/collections/bit_set.rs b/src/collections/bit_set.rs index 2bba0fb36d56..7876309802e8 100644 --- a/src/collections/bit_set.rs +++ b/src/collections/bit_set.rs @@ -376,15 +376,6 @@ impl ArrayBitSet { } } - /// Performs an intersection of two bit sets, and stores the - /// result in the first one. - pub(crate) fn set_intersection(&mut self, other: &Self) { - debug_assert_eq!(self.masks.len(), other.masks.len()); - for (mask, alt) in self.masks.iter_mut().zip(other.masks.iter()) { - *mask &= *alt; - } - } - /// Returns true iff the first bit set is the subset of the second one. pub(crate) fn subset_of(&self, other: &Self) -> bool { self.masks @@ -1103,15 +1094,6 @@ impl AutoBitSet { } } - /// `self &= other`. Both sets must have the same arm (same bit length). - pub fn set_intersection(&mut self, other: &AutoBitSet) { - match (self, other) { - (AutoBitSet::Static(a), AutoBitSet::Static(b)) => a.set_intersection(b), - (AutoBitSet::Dynamic(a), AutoBitSet::Dynamic(b)) => a.set_intersection(b), - _ => unreachable!("AutoBitSet::set_intersection: mismatched bit lengths"), - } - } - /// Is every bit of `self` also set in `other`? pub fn subset_of(&self, other: &AutoBitSet) -> bool { match (self, other) { diff --git a/src/crash_handler/error.rs b/src/crash_handler/error.rs index 674667131341..f52c135da564 100644 --- a/src/crash_handler/error.rs +++ b/src/crash_handler/error.rs @@ -40,10 +40,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/dotenv/error.rs b/src/dotenv/error.rs index f9f9020050e5..fe2d3f56f731 100644 --- a/src/dotenv/error.rs +++ b/src/dotenv/error.rs @@ -22,10 +22,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/exe_format/builtins.rs b/src/exe_format/builtins.rs index ad4c6ee016b1..089e2d0f0375 100644 --- a/src/exe_format/builtins.rs +++ b/src/exe_format/builtins.rs @@ -65,11 +65,6 @@ pub struct Builtins<'a> { } impl<'a> Builtins<'a> { - /// Locate and parse the builtins section of an ELF, Mach-O or PE executable image. - pub fn from_executable(file: &'a [u8]) -> Result { - Self::parse(find_section(file)?) - } - /// Parse a builtins section (header onward). Trailing bytes past the blob are ignored. pub fn parse(section: &'a [u8]) -> Result { use BuiltinsError::Invalid; @@ -133,15 +128,7 @@ impl<'a> Builtins<'a> { }) } - /// Number of JS internal modules; ids `0..len()` are InternalModuleRegistry field indices. - pub fn len(&self) -> u32 { - self.count - } - - pub fn is_empty(&self) -> bool { - self.count == 0 - } - + /// Module ids `0..count` are InternalModuleRegistry field indices. pub fn module(&self, id: u32) -> Option> { if id >= self.count { return None; @@ -174,10 +161,6 @@ impl<'a> Builtins<'a> { let deps = self.deps; (start..end).map(move |i| u16_at(deps, i * 2) as u32) } - - pub fn modules(&self) -> impl Iterator> + '_ { - (0..self.count).filter_map(move |id| self.module(id)) - } } fn u32_at(bytes: &[u8], offset: usize) -> u32 { diff --git a/src/exe_format/error.rs b/src/exe_format/error.rs index 99eeb7ee83a2..18f13f296528 100644 --- a/src/exe_format/error.rs +++ b/src/exe_format/error.rs @@ -22,10 +22,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/install/NetworkTask.rs b/src/install/NetworkTask.rs index fe70b5b5e4b2..d79d7d8ed321 100644 --- a/src/install/NetworkTask.rs +++ b/src/install/NetworkTask.rs @@ -18,17 +18,13 @@ use crate::npm::{self as npm, PackageManifest}; use crate::{ExtractTarball, PackageManager, PatchTask, TarballStream, Task}; // Adapter so `StringOrTinyString::init_append_if_needed` can intern overflow -// names into the resolver's filename arena. The bun_sys-level `FilenameStore` exposes `append` / -// `append_lower_case` but doesn't itself implement `strings::Appender` (that -// impl lives in `bun_resolver`, which this crate can't reach without a cycle). +// names into the resolver's filename arena. `FilenameStore` exposes `append` +// but doesn't itself implement `strings::Appender`. pub struct FilenameStoreAppender<'a>(pub(crate) &'a FilenameStore); impl strings::Appender for FilenameStoreAppender<'_> { fn append(&mut self, s: &[u8]) -> Result<&[u8], bun_alloc::AllocError> { self.0.append(s) } - fn append_lower_case(&mut self, s: &[u8]) -> Result<&[u8], bun_alloc::AllocError> { - self.0.append_lower_case(s) - } } /// Convenience: returns an `Appender` over the global filename store. @@ -457,11 +453,6 @@ impl From for crate::Error { } } } -impl bun_core::output::ErrName for ForManifestError { - fn name(&self) -> &[u8] { - <&'static str>::from(self).as_bytes() - } -} impl NetworkTask { pub(crate) fn for_manifest( diff --git a/src/io/error.rs b/src/io/error.rs index adb8e638a7cd..ac66c1ceed52 100644 --- a/src/io/error.rs +++ b/src/io/error.rs @@ -8,21 +8,4 @@ pub enum Error { Sys(#[from] bun_errno::SystemErrno), } -impl Error { - #[allow(clippy::trivially_copy_pass_by_ref)] - pub(crate) fn name(&self) -> &'static str { - match self { - Self::MachportCreationFailed => "MachportCreationFailed", - Self::Unexpected => "Unexpected", - Self::Sys(e) => <&'static str>::from(e), - } - } -} - -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/js_parser/error.rs b/src/js_parser/error.rs index 84940d674ca7..a2c40814bc4a 100644 --- a/src/js_parser/error.rs +++ b/src/js_parser/error.rs @@ -38,10 +38,4 @@ impl From for Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/js_parser_jsc/error.rs b/src/js_parser_jsc/error.rs index 9e95c384424e..9426fed36a09 100644 --- a/src/js_parser_jsc/error.rs +++ b/src/js_parser_jsc/error.rs @@ -43,10 +43,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/js_printer/error.rs b/src/js_printer/error.rs index c5fcf5d54d62..fca23d167da7 100644 --- a/src/js_printer/error.rs +++ b/src/js_printer/error.rs @@ -25,10 +25,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/jsc/AbortSignal.rs b/src/jsc/AbortSignal.rs index 5e5e64bb4e05..d8081b4d7bb4 100644 --- a/src/jsc/AbortSignal.rs +++ b/src/jsc/AbortSignal.rs @@ -168,11 +168,6 @@ impl AbortSignal { WebCore__AbortSignal__unref(self) } - pub fn detach(&self, ctx: *mut c_void) { - self.clean_native_bindings(ctx); - self.unref(); - } - /// Lifetime: the returned pointer is borrowed from the JS wrapper and is /// valid only while `value` remains reachable. Use [`AbortSignal::ref_from_js`] /// to take refcounted ownership instead. diff --git a/src/jsc/Strong.rs b/src/jsc/Strong.rs index 58d2540773e5..49533182462a 100644 --- a/src/jsc/Strong.rs +++ b/src/jsc/Strong.rs @@ -34,16 +34,6 @@ impl Strong { debug_assert!(!new_value.is_empty()); Impl::set(self.handle, global, new_value); } - - /// Adopt an `Impl` handle allocated externally (e.g. by C++ bindgen glue), - /// taking ownership. The handle will be destroyed on `Drop`. - /// - /// # Safety - /// `handle` must have been produced by `Bun__StrongRef__new` (or equivalent) - /// and must not be owned by any other `Strong`/`Optional`. - pub(crate) unsafe fn adopt(handle: NonNull) -> Strong { - Strong { handle } - } } impl Drop for Strong { diff --git a/src/jsc/SystemError.rs b/src/jsc/SystemError.rs index 5ff665b86157..cfe9e9b66198 100644 --- a/src/jsc/SystemError.rs +++ b/src/jsc/SystemError.rs @@ -1,5 +1,4 @@ use core::ffi::c_int; -use core::fmt; use bun_core::String; @@ -152,44 +151,3 @@ pub fn verify_error_to_js( fallback.to_error_instance(global) } - -impl fmt::Display for SystemError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Note: `bun_core::pretty_fmt!` expands color tags in the format - // string at compile time for both the colored and uncolored variants; - // the runtime ANSI-support check selects between them via if/else. - if !self.path.is_empty() { - // TODO: remove this hardcoding - if bun_core::Output::enable_ansi_colors_stderr() { - write!( - f, - // bun.Output.prettyFmt("{f}: {f}: {f} ({f}())", true) - bun_core::pretty_fmt!("{}: {}: {} ({}())", true), - self.code, self.path, self.message, self.syscall, - ) - } else { - write!( - f, - bun_core::pretty_fmt!("{}: {}: {} ({}())", false), - self.code, self.path, self.message, self.syscall, - ) - } - } else { - // TODO: remove this hardcoding - if bun_core::Output::enable_ansi_colors_stderr() { - write!( - f, - // bun.Output.prettyFmt("{f}: {f} ({f}())", true) - bun_core::pretty_fmt!("{}: {} ({}())", true), - self.code, self.message, self.syscall, - ) - } else { - write!( - f, - bun_core::pretty_fmt!("{}: {} ({}())", false), - self.code, self.message, self.syscall, - ) - } - } - } -} diff --git a/src/jsc/bindgen.rs b/src/jsc/bindgen.rs index 996671297db0..ed2b4e95cfe1 100644 --- a/src/jsc/bindgen.rs +++ b/src/jsc/bindgen.rs @@ -1,18 +1,4 @@ -use core::ffi::c_uint; use core::marker::PhantomData; -use core::mem::{ManuallyDrop, align_of, size_of}; -use core::ptr::NonNull; - -use crate::{self as jsc, Strong}; -use bun_core::{WTFString, WTFStringImplStruct}; - -// `BindgenArray::convert_from_extern` reuses C++-allocated buffers by adopting -// them into `Vec` even when `align_of::() != align_of::()`. -// That is only sound because mimalloc's `mi_free` ignores the allocation layout; -// the Rust `GlobalAlloc::dealloc` contract would otherwise be violated. The C++ side -// (`ExternVectorTraits.h`) always allocates with `mi_malloc`, so when the global -// allocator is not mimalloc the reuse path is skipped and the fallback frees the -// C++ buffer with `mi_free` directly. // ────────────────────────────────────────────────────────────────────────── // A `Bindgen` adapter supplies associated `ZigType`/`ExternType` plus @@ -24,8 +10,7 @@ pub trait Bindgen { type ExternType; /// `true` when `ZigType` and `ExternType` are layout-identical. - /// Enables `BindgenArray`'s - /// allocation-reuse fast path. Defaults to `false`; override per adapter. + /// Defaults to `false`; override per adapter. const SAME_REPR: bool = false; fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType; @@ -42,252 +27,3 @@ impl Bindgen for BindgenTrivial { extern_value } } - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenStrongAny; - -impl Bindgen for BindgenStrongAny { - type ZigType = Strong; - // `?*jsc.Strong.Impl` — must be single-word for #[repr(C)] union placement, so - // `Option>` (niche-optimized), NOT `Option<*mut T>` (two words). - type ExternType = Option>; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - // SAFETY: bindgen contract — C++ passes a freshly-allocated Strong handle - // whose ownership is transferred to Rust here. - unsafe { Strong::adopt(extern_value.expect("non-null")) } - } -} - -// ────────────────────────────────────────────────────────────────────────── - -/// This represents both `IDLNull` and `IDLMonostateUndefined`. -pub struct BindgenNull; - -impl Bindgen for BindgenNull { - type ZigType = (); - type ExternType = u8; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - let _ = extern_value; - } -} - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenOptional(PhantomData); - -// Wrap in `ExternTaggedUnion<(u8, Child::ExternType)>` and produce -// `Option`. -impl Bindgen for BindgenOptional { - type ZigType = Option; - type ExternType = ExternTaggedUnion2; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - if extern_value.tag == 0 { - return None; - } - debug_assert_eq!(extern_value.tag, 1); - // SAFETY: tag == 1 means the `_1` arm of the union is initialized. - Some(Child::convert_from_extern(unsafe { - ManuallyDrop::into_inner(extern_value.data._1) - })) - } -} - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenString; - -impl Bindgen for BindgenString { - type ZigType = WTFString; - // `?bun.string.WTFStringImpl` — `Option>` for single-word FFI layout. - type ExternType = Option>; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - // SAFETY: bindgen contract — C++ passes a `StringImpl*` with one ref already - // taken for us; `adopt` consumes that ref. - unsafe { WTFString::adopt(extern_value.expect("non-null").as_ptr()) } - } -} - -// ────────────────────────────────────────────────────────────────────────── -// BindgenUnion / ExternTaggedUnion / ExternUnion -// -// These are generated per arity (or by a proc-macro from the bindgen codegen). -// ────────────────────────────────────────────────────────────────────────── - -// The bindgen TS codegen emits a concrete `enum` + `#[repr(C)]` union pair -// per call site rather than a generic Rust combinator (see -// `src/jsc/generated.rs`). This marker type exists for documentation parity. - -/// `extern struct { data: ExternUnion(field_types), tag: u8 }` -/// -/// We provide fixed-arity instantiations; the 2-ary case is the only -/// one used directly in this file (by `BindgenOptional`). Higher arities are -/// emitted by codegen alongside their consumers. -#[repr(C)] -pub struct ExternTaggedUnion2 { - pub(crate) data: ExternUnion2, - pub(crate) tag: u8, -} - -/// Union fields are wrapped in `ManuallyDrop` so non-`Copy` payloads -/// (e.g. nested `ExternTaggedUnion2`, `ExternArrayList`) are permitted without -/// trait bounds. There is no auto-drop — the active arm must be dropped -/// explicitly by whoever knows the tag. -#[repr(C)] -pub union ExternUnion2 { - pub _0: ManuallyDrop, - pub(crate) _1: ManuallyDrop, -} - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenArray(PhantomData); - -impl Bindgen for BindgenArray { - type ZigType = bun_collections::ArrayListDefault; - type ExternType = ExternArrayList; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - let length = usize::try_from(extern_value.length).expect("int cast"); - let capacity = usize::try_from(extern_value.capacity).expect("int cast"); - - if extern_value.data.is_null() { - return Self::ZigType::init(); - } - let data = extern_value.data; - debug_assert!( - length <= capacity, - "length ({}) should not exceed capacity ({})", - length, - capacity, - ); - // SAFETY: C++ side guarantees `data` points to `capacity` elements with - // `length` initialized; allocation came from mimalloc (when `USE_MIMALLOC`). - let unmanaged: Vec = - unsafe { Vec::from_raw_parts(data, length, capacity) }; - - if !bun_alloc::USE_MIMALLOC { - // Don't reuse memory in this case; it would be freed by the wrong allocator. - } else if size_of::() == size_of::() - && align_of::() == align_of::() - // Rust has no stable type-equality test in generic context, so this - // fast-path is gated on the `const SAME_REPR: bool` opt-in: it only - // fires when the bindgen codegen has proven layout identity. - && Child::SAME_REPR - { - // The layouts are identical, so the Vec is returned as-is. - let (ptr, len, cap) = { - let mut v = ManuallyDrop::new(unmanaged); - (v.as_mut_ptr(), v.len(), v.capacity()) - }; - // SAFETY: `SAME_REPR` ⇒ same layout; `from_raw_parts` round-trip. - let reused: Vec = - unsafe { Vec::from_raw_parts(ptr.cast::(), len, cap) }; - return Self::ZigType::from_unmanaged(reused); - } else if size_of::() <= size_of::() - && align_of::() <= bun_alloc::mimalloc::MI_MAX_ALIGN_SIZE - { - // We can reuse the allocation, but we still need to convert the elements. - // - // Materializing a `&mut [u8]` over the full capacity would assert that - // every byte — including uninitialized tail elements and `ExternType` - // padding — is a valid `u8`, which is UB. Work entirely through raw - // `*mut u8` and `ptr::copy_nonoverlapping` instead; no reference to - // the storage is ever formed. - let mut v = ManuallyDrop::new(unmanaged); - let mut storage_ptr: *mut u8 = v.as_mut_ptr().cast::(); - let storage_len = v.capacity() * size_of::(); - - // Convert the elements. - for i in 0..length { - // Byte-wise copy: this is an in-place reinterpretation of - // overlapping element slots, so each element is copied out - // before conversion. - let mut old_elem = core::mem::MaybeUninit::::uninit(); - // SAFETY: source range lies within the mimalloc block and holds a - // valid (C++-initialized) `ExternType` for `i < length`. - unsafe { - core::ptr::copy_nonoverlapping( - storage_ptr.add(i * size_of::()), - old_elem.as_mut_ptr().cast::(), - size_of::(), - ); - } - // SAFETY: bytes for element `i` were just copied from initialized storage. - let new_elem = ManuallyDrop::new(Child::convert_from_extern(unsafe { - old_elem.assume_init() - })); - // SAFETY: dest range lies within the block; `size_of ZigType <= - // size_of ExternType` so slot `i` of the new layout never overruns - // slot `i` of the old layout (and never clobbers slot `i+1`). - unsafe { - core::ptr::copy_nonoverlapping( - (&raw const *new_elem).cast::(), - storage_ptr.add(i * size_of::()), - size_of::(), - ); - } - } - - let new_size_is_multiple = - size_of::() % size_of::() == 0; - let new_capacity = if new_size_is_multiple { - capacity * (size_of::() / size_of::()) - } else { - let new_capacity = storage_len / size_of::(); - let new_alloc_size = new_capacity * size_of::(); - if new_alloc_size != storage_len { - // Allocation isn't a multiple of `size_of::()`; we have to - // resize it. - // SAFETY: `storage_ptr` is the original mimalloc block (the - // `USE_MIMALLOC` guard above gates entry to this path); shrinking - // with `mi_realloc` preserves the prefix bytes. - storage_ptr = bun_core::handle_oom(unsafe { - bun_alloc::realloc_raw(storage_ptr, new_alloc_size) - }); - } - new_capacity - }; - - let items_ptr = storage_ptr.cast::(); - // SAFETY: `storage_ptr` is aligned to ≥ `MI_MAX_ALIGN_SIZE` ≥ - // `align_of::()`; the first `length` slots were just written - // with valid `ZigType` values; the block is mimalloc-owned and the - // global allocator is mimalloc (the `if !bun_alloc::USE_MIMALLOC` - // guard above gates entry to this path), so `Vec`'s eventual dealloc - // — even with `ZigType`'s layout — routes to `mi_free`, which - // ignores layout. - let new_unmanaged: Vec = - unsafe { Vec::from_raw_parts(items_ptr, length, new_capacity) }; - return Self::ZigType::from_unmanaged(new_unmanaged); - } - - // Fallback: allocate fresh, convert, free old. `data` was `mi_malloc`'d - // by the C++ side regardless of the Rust global allocator, so free it - // with `mi_free` directly instead of `Vec::drop`. - let mut result = bun_core::handle_oom(Self::ZigType::init_capacity(length)); - let mut unmanaged = ManuallyDrop::new(unmanaged); - for item in unmanaged.iter_mut() { - // SAFETY: each slot holds a C++-initialized `ExternType`; `ManuallyDrop` ensures it isn't read twice. - result.append_assume_capacity(Child::convert_from_extern(unsafe { - core::ptr::read(item) - })); - } - // SAFETY: `data` is the live `mi_malloc`'d block from `ExternVectorTraits::convertToExtern`. - unsafe { bun_alloc::mimalloc::mi_free(data.cast()) }; - result - } -} - -#[repr(C)] -pub struct ExternArrayList { - // Single-word nullable pointer. `Option<*mut T>` has no niche - // (two words) and would break the C ABI; use raw `*mut T` and check `.is_null()`. - pub(crate) data: *mut Child, - pub(crate) length: c_uint, - pub(crate) capacity: c_uint, -} diff --git a/src/jsc/bindings/JSDOMExceptionHandling.cpp b/src/jsc/bindings/JSDOMExceptionHandling.cpp index 20e67624c799..37c96c958b31 100644 --- a/src/jsc/bindings/JSDOMExceptionHandling.cpp +++ b/src/jsc/bindings/JSDOMExceptionHandling.cpp @@ -260,11 +260,6 @@ void throwNonFiniteTypeError(JSGlobalObject& lexicalGlobalObject, JSC::ThrowScop throwTypeError(&lexicalGlobalObject, scope, "The provided value is non-finite"_s); } -JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::JSGlobalObject& lexicalGlobalObject, const JSC::ClassInfo* classInfo, JSC::PropertyName attributeName) -{ - return createRejectedPromiseWithTypeError(lexicalGlobalObject, JSC::makeDOMAttributeGetterTypeErrorMessage(classInfo->className, String(attributeName.uid())), RejectedPromiseWithTypeErrorCause::NativeGetter); -} - String makeThisTypeErrorMessage(ASCIILiteral interfaceName, ASCIILiteral functionName) { return makeString("Can only call "_s, interfaceName, '.', functionName, " on instances of "_s, interfaceName); diff --git a/src/jsc/bindings/JSDOMExceptionHandling.h b/src/jsc/bindings/JSDOMExceptionHandling.h index c6c7bf156a3d..47285d8ba47a 100644 --- a/src/jsc/bindings/JSDOMExceptionHandling.h +++ b/src/jsc/bindings/JSDOMExceptionHandling.h @@ -53,7 +53,6 @@ String makeThisTypeErrorMessage(ASCIILiteral interfaceName, ASCIILiteral functio WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral interfaceName, ASCIILiteral attributeName); -WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::JSGlobalObject&, const JSC::ClassInfo*, JSC::PropertyName attributeName); WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise&, ASCIILiteral interfaceName, ASCIILiteral operationName); WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::JSGlobalObject&, ASCIILiteral interfaceName, ASCIILiteral operationName); diff --git a/src/jsc/bindings/NodeValidator.cpp b/src/jsc/bindings/NodeValidator.cpp index 7a52d8fe26d4..62f4c8bfa19b 100644 --- a/src/jsc/bindings/NodeValidator.cpp +++ b/src/jsc/bindings/NodeValidator.cpp @@ -645,9 +645,7 @@ JSC::EncodedJSValue V::validateObject(JSC::ThrowScope& scope, JSC::JSGlobalObjec // // -template JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, JSC::JSValue name, JSC::JSValue min, JSC::JSValue max, size_t* out); template JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, JSC::JSValue name, JSC::JSValue min, JSC::JSValue max, ssize_t* out); -template JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, JSC::JSValue name, JSC::JSValue min, JSC::JSValue max, uint32_t* out); template JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, ASCIILiteral name, JSC::JSValue min, JSC::JSValue max, int32_t* out); template JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, ASCIILiteral name, JSC::JSValue min, JSC::JSValue max, size_t* out); template JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, ASCIILiteral name, JSC::JSValue min, JSC::JSValue max, ssize_t* out); diff --git a/src/jsc/bindings/blob.cpp b/src/jsc/bindings/blob.cpp index 798b867d345d..f1736900e239 100644 --- a/src/jsc/bindings/blob.cpp +++ b/src/jsc/bindings/blob.cpp @@ -14,18 +14,6 @@ JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* g return JSC::JSValue::decode(Blob__create(lexicalGlobalObject, Blob__dupe(impl.impl()))); } -JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, Ref&& impl) -{ - auto fileNameStr = impl->fileName(); - BunString filename = Bun::toString(fileNameStr); - - JSC::EncodedJSValue encoded = Blob__create(lexicalGlobalObject, impl->impl()); - JSBlob* blob = uncheckedDowncast(JSC::JSValue::decode(encoded)); - Blob__setAsFile(blob->wrapped(), &filename); - - return JSC::JSValue::decode(encoded); -} - size_t Blob::memoryCost() const { return sizeof(Blob) + JSBlob::memoryCost(impl()); diff --git a/src/jsc/bindings/blob.h b/src/jsc/bindings/blob.h index 631861a37ae6..a722db7a248b 100644 --- a/src/jsc/bindings/blob.h +++ b/src/jsc/bindings/blob.h @@ -96,7 +96,5 @@ class Blob : public RefCounted { JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, Blob&); inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, Blob* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } -JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref&&); -inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } } diff --git a/src/jsc/bindings/node/crypto/CryptoUtil.cpp b/src/jsc/bindings/node/crypto/CryptoUtil.cpp index f0f752c2688c..b815c7c9255d 100644 --- a/src/jsc/bindings/node/crypto/CryptoUtil.cpp +++ b/src/jsc/bindings/node/crypto/CryptoUtil.cpp @@ -211,163 +211,6 @@ WebCore::BufferEncodingType getEncodingDefaultBuffer(JSGlobalObject* globalObjec return parseEnumerationFromView(encodingString).value_or(BufferEncodingType::buffer); } -std::optional keyFromString(JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, const WTF::StringView& keyView, JSValue passphraseValue) -{ - ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig config; - config.format = ncrypto::EVPKeyPointer::PKFormatType::PEM; - - config.passphrase = passphraseFromBufferSource(lexicalGlobalObject, scope, passphraseValue); - RETURN_IF_EXCEPTION(scope, std::nullopt); - - UTF8View keyUtf8(keyView); - - auto keySpan = keyUtf8.span(); - - ncrypto::Buffer ncryptoBuf { - .data = reinterpret_cast(keySpan.data()), - .len = keySpan.size(), - }; - ncrypto::ClearErrorOnReturn clearErrorOnReturn; - - auto res = ncrypto::EVPKeyPointer::TryParsePrivateKey(config, ncryptoBuf); - if (res) { - ncrypto::EVPKeyPointer keyPtr(WTF::move(res.value)); - return keyPtr; - } - - if (res.error.value() == ncrypto::EVPKeyPointer::PKParseError::NEED_PASSPHRASE) { - Bun::ERR::MISSING_PASSPHRASE(scope, lexicalGlobalObject, "Passphrase required for encrypted key"_s); - return std::nullopt; - } - - throwCryptoError(lexicalGlobalObject, scope, res.openssl_error.value_or(0), "Failed to read private key"_s); - return std::nullopt; -} - -ncrypto::EVPKeyPointer::PKFormatType parseKeyFormat(JSC::JSGlobalObject* globalObject, JSValue formatValue, WTF::ASCIILiteral optionName, std::optional defaultFormat) -{ - auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - - if (formatValue.isUndefined() && defaultFormat) { - return defaultFormat.value(); - } - - if (!formatValue.isString()) { - Bun::ERR::INVALID_ARG_VALUE(scope, globalObject, optionName, formatValue); - return {}; - } - - WTF::String formatStr = formatValue.toWTFString(globalObject); - RETURN_IF_EXCEPTION(scope, {}); - - if (formatStr == "pem"_s) { - return ncrypto::EVPKeyPointer::PKFormatType::PEM; - } - - if (formatStr == "der"_s) { - return ncrypto::EVPKeyPointer::PKFormatType::DER; - } - - if (formatStr == "jwk"_s) { - return ncrypto::EVPKeyPointer::PKFormatType::JWK; - } - - if (formatStr == "raw-public"_s) { - return ncrypto::EVPKeyPointer::PKFormatType::RawPublic; - } - - if (formatStr == "raw-private"_s) { - return ncrypto::EVPKeyPointer::PKFormatType::RawPrivate; - } - - if (formatStr == "raw-seed"_s) { - return ncrypto::EVPKeyPointer::PKFormatType::RawSeed; - } - - Bun::ERR::INVALID_ARG_VALUE(scope, globalObject, optionName, formatValue); - return {}; -} - -std::optional parseKeyType(JSC::JSGlobalObject* globalObject, JSValue typeValue, bool required, WTF::StringView keyType, std::optional isPublic, WTF::ASCIILiteral optionName) -{ - auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - - if (typeValue.isUndefined() && !required) { - return std::nullopt; - } - - if (!typeValue.isString()) { - Bun::ERR::INVALID_ARG_VALUE(scope, globalObject, optionName, typeValue); - return std::nullopt; - } - - WTF::String typeStr = typeValue.toWTFString(globalObject); - RETURN_IF_EXCEPTION(scope, std::nullopt); - - if (typeStr == "pkcs1"_s) { - if (keyType && keyType != "rsa"_s) { - Bun::ERR::CRYPTO_INCOMPATIBLE_KEY_OPTIONS(scope, globalObject, "pkcs1"_s, "can only be used for RSA keys"_s); - return std::nullopt; - } - return ncrypto::EVPKeyPointer::PKEncodingType::PKCS1; - } else if (typeStr == "spki"_s && isPublic != false) { - return ncrypto::EVPKeyPointer::PKEncodingType::SPKI; - } else if (typeStr == "pkcs8"_s && isPublic != true) { - return ncrypto::EVPKeyPointer::PKEncodingType::PKCS8; - } else if (typeStr == "sec1"_s && isPublic != true) { - if (keyType && keyType != "ec"_s) { - Bun::ERR::CRYPTO_INCOMPATIBLE_KEY_OPTIONS(scope, globalObject, "sec1"_s, "can only be used for EC keys"_s); - return std::nullopt; - } - return ncrypto::EVPKeyPointer::PKEncodingType::SEC1; - } - - Bun::ERR::INVALID_ARG_VALUE(scope, globalObject, optionName, typeValue); - return std::nullopt; -} - -std::optional passphraseFromBufferSource(JSC::JSGlobalObject* globalObject, ThrowScope& scope, JSValue input) -{ - if (input.isUndefinedOrNull()) { - return std::nullopt; - } - - if (input.isString()) { - WTF::String passphraseStr = input.toWTFString(globalObject); - RETURN_IF_EXCEPTION(scope, std::nullopt); - - UTF8View utf8(passphraseStr); - - auto span = utf8.span(); - if (auto ptr = ncrypto::DataPointer::Alloc(span.size())) { - memcpy(ptr.get(), span.data(), span.size()); - return WTF::move(ptr); - } - - throwOutOfMemoryError(globalObject, scope); - return std::nullopt; - } - - if (auto* array = dynamicDowncast(input)) { - if (array->isDetached()) { - throwTypeError(globalObject, scope, "passphrase must not be detached"_s); - return std::nullopt; - } - - auto length = array->byteLength(); - if (auto ptr = ncrypto::DataPointer::Alloc(length)) { - memcpy(ptr.get(), array->vector(), length); - return WTF::move(ptr); - } - - throwOutOfMemoryError(globalObject, scope); - return std::nullopt; - } - - throwTypeError(globalObject, scope, "passphrase must be a Buffer or string"_s); - return std::nullopt; -} - JSValue createCryptoError(JSC::JSGlobalObject* globalObject, ThrowScope& scope, uint32_t err, const char* message) { JSC::VM& vm = globalObject->vm(); diff --git a/src/jsc/bindings/node/crypto/CryptoUtil.h b/src/jsc/bindings/node/crypto/CryptoUtil.h index 3e35a40745e4..4dba6ed31bb4 100644 --- a/src/jsc/bindings/node/crypto/CryptoUtil.h +++ b/src/jsc/bindings/node/crypto/CryptoUtil.h @@ -48,11 +48,7 @@ EncodedJSValue encode(JSGlobalObject* lexicalGlobalObject, ThrowScope& scope, st // void CheckThrow(JSC::JSGlobalObject* globalObject, SignBase::Error error); JSC::JSValue unsignedBigIntToBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, JSValue bigIntValue, ASCIILiteral name); WebCore::BufferEncodingType getEncodingDefaultBuffer(JSGlobalObject* globalObject, ThrowScope& scope, JSValue encodingValue); -std::optional keyFromString(JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, const WTF::StringView& keyView, JSValue passphraseValue); -ncrypto::EVPKeyPointer::PKFormatType parseKeyFormat(JSC::JSGlobalObject* globalObject, JSValue formatValue, WTF::ASCIILiteral optionName, std::optional defaultFormat = std::nullopt); -std::optional parseKeyType(JSC::JSGlobalObject* globalObject, JSValue typeValue, bool required, WTF::StringView keyType, std::optional isPublic, WTF::ASCIILiteral optionName); bool isArrayBufferOrView(JSValue value); -std::optional passphraseFromBufferSource(JSC::JSGlobalObject* globalObject, JSC::ThrowScope& scope, JSValue input); JSValue createCryptoError(JSC::JSGlobalObject* globalObject, ThrowScope& scope, uint32_t err, const char* message); void throwCryptoError(JSC::JSGlobalObject* globalObject, JSC::ThrowScope& scope, uint32_t err, const char* message = nullptr); std::optional getIntOption(JSC::JSGlobalObject* globalObject, JSC::ThrowScope&, JSValue options, WTF::ASCIILiteral name); diff --git a/src/jsc/bindings/webcore/EventEmitter.cpp b/src/jsc/bindings/webcore/EventEmitter.cpp index f511c5500242..26bd10900733 100644 --- a/src/jsc/bindings/webcore/EventEmitter.cpp +++ b/src/jsc/bindings/webcore/EventEmitter.cpp @@ -5,7 +5,6 @@ #include "DOMWrapperWorld.h" #include "EventNames.h" -#include "JSErrorHandler.h" #include "JSEventListener.h" #include #include diff --git a/src/jsc/bindings/webcore/EventTarget.cpp b/src/jsc/bindings/webcore/EventTarget.cpp index 873462b3a5c8..df1d17f0a767 100644 --- a/src/jsc/bindings/webcore/EventTarget.cpp +++ b/src/jsc/bindings/webcore/EventTarget.cpp @@ -39,7 +39,6 @@ #include "DOMWrapperWorld.h" #include "EventNames.h" #include "EventTargetConcrete.h" -#include "JSErrorHandler.h" #include "JSEventListener.h" #include #include @@ -167,7 +166,6 @@ void EventTarget::setAttributeEventListener(const AtomString& eventType, JSC::JS addEventListener(eventType, JSMaybeErrorEventListener::create(*asObject(listener), jsEventTarget, true, isolatedWorld), {}); } -template void EventTarget::setAttributeEventListener(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget); template void EventTarget::setAttributeEventListener(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget); JSEventListener* EventTarget::attributeEventListener(const AtomString& eventType, DOMWrapperWorld& isolatedWorld) diff --git a/src/jsc/bindings/webcore/JSDOMAttribute.h b/src/jsc/bindings/webcore/JSDOMAttribute.h index 064514e31253..6f3c6bbe3fd6 100644 --- a/src/jsc/bindings/webcore/JSDOMAttribute.h +++ b/src/jsc/bindings/webcore/JSDOMAttribute.h @@ -65,8 +65,6 @@ class IDLAttribute { if (!thisObject) [[unlikely]] { if constexpr (shouldThrow == CastedThisErrorBehavior::Throw) return JSC::throwVMDOMAttributeGetterTypeError(&lexicalGlobalObject, throwScope, JSClass::info(), attributeName); - else if constexpr (shouldThrow == CastedThisErrorBehavior::RejectPromise) - RELEASE_AND_RETURN(throwScope, rejectPromiseWithGetterTypeError(lexicalGlobalObject, JSClass::info(), attributeName)); else return JSC::JSValue::encode(JSC::jsUndefined()); } diff --git a/src/jsc/bindings/webcore/JSErrorHandler.cpp b/src/jsc/bindings/webcore/JSErrorHandler.cpp deleted file mode 100644 index e7571a185aae..000000000000 --- a/src/jsc/bindings/webcore/JSErrorHandler.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * Copyright (C) 2013-2018 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSErrorHandler.h" - -// #include "Document.h" -#include "ErrorEvent.h" -#include "Event.h" -#include "JSDOMConvertNumbers.h" -#include "JSDOMConvertStrings.h" -#include "JSEvent.h" -#include -#include - -namespace WebCore { -using namespace JSC; - -inline JSErrorHandler::JSErrorHandler(JSObject& listener, JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) - : JSEventListener(&listener, &wrapper, isAttribute, CreatedFromMarkup::No, world) -{ -} - -Ref JSErrorHandler::create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) -{ - return adoptRef(*new JSErrorHandler(listener, wrapper, isAttribute, world)); -} - -JSErrorHandler::~JSErrorHandler() = default; - -void JSErrorHandler::handleEvent(ScriptExecutionContext& scriptExecutionContext, Event& event) -{ - if (!is(event)) - return JSEventListener::handleEvent(scriptExecutionContext, event); - - VM& vm = scriptExecutionContext.vm(); - JSLockHolder lock(vm); - - JSObject* jsFunction = this->ensureJSFunction(scriptExecutionContext); - if (!jsFunction) - return; - - auto* isolatedWorld = this->isolatedWorld(); - if (!isolatedWorld) [[unlikely]] - return; - - auto* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *isolatedWorld); - if (!globalObject) - return; - - auto callData = getCallData(jsFunction); - if (callData.type != CallData::Type::None) { - Ref protectedThis(*this); - - RefPtr savedEvent; - // auto* jsFunctionWindow = dynamicDowncast( jsFunction->globalObject()); - // if (jsFunctionWindow) { - // savedEvent = jsFunctionWindow->currentEvent(); - - // // window.event should not be set when the target is inside a shadow tree, as per the DOM specification. - // if (!event.currentTargetIsInShadowTree()) - // jsFunctionWindow->setCurrentEvent(&event); - // } - - auto& errorEvent = downcast(event); - - MarkedArgumentBuffer args; - args.append(toJS(*globalObject, errorEvent.message())); - args.append(toJS(*globalObject, errorEvent.filename())); - args.append(toJS(errorEvent.lineno())); - args.append(toJS(errorEvent.colno())); - args.append(errorEvent.error(*globalObject)); - ASSERT(!args.hasOverflowed()); - - // JSExecState::instrumentFunction(&scriptExecutionContext, callData); - - NakedPtr exception; - JSValue returnValue = JSC::profiledCall(globalObject, JSC::ProfilingReason::Other, jsFunction, callData, globalObject, args, exception); - - // InspectorInstrumentation::didCallFunction(&scriptExecutionContext); - - // if (jsFunctionWindow) - // jsFunctionWindow->setCurrentEvent(savedEvent.get()); - - if (exception) - reportException(globalObject, exception); - else { - if (returnValue.isTrue()) - event.preventDefault(); - } - } -} - -} // namespace WebCore diff --git a/src/jsc/bindings/webcore/JSErrorHandler.h b/src/jsc/bindings/webcore/JSErrorHandler.h deleted file mode 100644 index d32c55a86106..000000000000 --- a/src/jsc/bindings/webcore/JSErrorHandler.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * Copyright (C) 2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "JSEventListener.h" - -namespace WebCore { - -class JSErrorHandler final : public JSEventListener { -public: - static Ref create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); - virtual ~JSErrorHandler(); - -private: - JSErrorHandler(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); - void handleEvent(ScriptExecutionContext&, Event&) final; -}; - -} // namespace WebCore diff --git a/src/jsc/virtual_machine_exports.rs b/src/jsc/virtual_machine_exports.rs index 74c1fb6ecbc3..21df16a9ee13 100644 --- a/src/jsc/virtual_machine_exports.rs +++ b/src/jsc/virtual_machine_exports.rs @@ -294,7 +294,6 @@ pub fn remove_source_provider_source_map( .remove_source_provider(opaque_source_provider, slice.slice()); } -#[crate::host_fn(export = "Bun__setSyntheticAllocationLimitForTesting")] pub fn Bun__setSyntheticAllocationLimitForTesting( global: &JSGlobalObject, frame: &CallFrame, diff --git a/src/libarchive/error.rs b/src/libarchive/error.rs index cb0a621e96f7..a3834d35e11a 100644 --- a/src/libarchive/error.rs +++ b/src/libarchive/error.rs @@ -12,25 +12,6 @@ pub enum Error { Paths(#[from] bun_paths::Error), } -impl Error { - #[allow(clippy::trivially_copy_pass_by_ref)] - pub(crate) fn name(&self) -> &'static str { - match self { - Self::Fail => "Fail", - Self::Sys(e) => <&'static str>::from(e), - Self::Alloc(_) => "OutOfMemory", - Self::MakeLibUvOwned(e) => <&'static str>::from(e), - Self::Paths(e) => e.name(), - } - } -} - -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - impl From for Error { fn from(e: bun_sys::Error) -> Self { Self::Sys(e.into()) diff --git a/src/md/parser.rs b/src/md/parser.rs index 251784a12fb7..45fbcbf86723 100644 --- a/src/md/parser.rs +++ b/src/md/parser.rs @@ -126,14 +126,6 @@ pub enum ParserError { bun_core::oom_from_alloc!(ParserError); -impl core::fmt::Display for ParserError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.write_str(<&'static str>::from(*self)) - } -} - -impl core::error::Error for ParserError {} - /// The longest `OFF`-typed fixed lookahead the parser performs from an /// in-bounds offset: the ` &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/ptr/lib.rs b/src/ptr/lib.rs index bfc818cbd971..945c85057fb5 100644 --- a/src/ptr/lib.rs +++ b/src/ptr/lib.rs @@ -29,7 +29,7 @@ pub use js_cell::JsCell; // impl moved down to `bun_core::external_shared` (cycle-break for the // `bun_string → bun_core` merge); re-exported here unchanged. pub use bun_core::external_shared; -pub use bun_core::{ExternalShared, ExternalSharedDescriptor, WTFString}; +pub use bun_core::{ExternalShared, ExternalSharedDescriptor}; // `cast_fn_ptr` and `RawSlice` likewise moved to `bun_core`; re-export. pub use bun_core::{RawSlice, cast_fn_ptr}; diff --git a/src/resolver/fs.rs b/src/resolver/fs.rs index 9dcbc0fb40ac..c3f0b298671f 100644 --- a/src/resolver/fs.rs +++ b/src/resolver/fs.rs @@ -41,7 +41,7 @@ bun_alloc::bss_list! { pub entry_store_backing : Entry, preallocate::counts::FIL /// Pre-resolved `FilenameStore` appender for the `readdir` hot loop. /// -/// `::append` re-evaluates `filename_store_backing()` +/// `FilenameStore::append` re-evaluates `filename_store_backing()` /// (a `bss_singleton!` accessor: `Once::call_once` + `AtomicPtr::load`) on every /// call. `add_entry` runs once per directory entry, so for the /// @material-ui/icons-style 11,000-entry directories that's 11,000+ redundant @@ -71,13 +71,6 @@ impl strings::Appender for FilenameStoreAppender { // (never freed); `Interned` is the canonical proof type for this widen. Ok(unsafe { bun_ptr::Interned::assume(r) }.as_bytes()) } - #[inline] - fn append_lower_case(&mut self, s: &[u8]) -> core::result::Result<&[u8], AllocError> { - // SAFETY: see `append`. - let r = unsafe { FilenameStoreBacking::append_lower_case(self.backing, s)? }; - // SAFETY: see `append`. - Ok(unsafe { bun_ptr::Interned::assume(r) }.as_bytes()) - } } // dirname_store/filename_store are &'static singletons — diff --git a/src/resolver/lib.rs b/src/resolver/lib.rs index b6bd2cf6127f..0c28e90a384c 100644 --- a/src/resolver/lib.rs +++ b/src/resolver/lib.rs @@ -718,22 +718,6 @@ pub mod fs { use bun_sys::Fd; use bun_threading::Mutex; - // `StringOrTinyString::init*_append_if_needed` needs an `Appender`; route the - // ZST `FilenameStore` handle through to the backing `BSSStringList` singleton. - impl strings::Appender for &FilenameStore { - fn append(&mut self, s: &[u8]) -> core::result::Result<&[u8], bun_alloc::AllocError> { - // Route through the inherent method (which already handles the - // singleton deref + `'static` widening) instead of open-coding it. - FilenameStore::append(self, s) - } - fn append_lower_case( - &mut self, - s: &[u8], - ) -> core::result::Result<&[u8], bun_alloc::AllocError> { - FilenameStore::append_lower_case(self, s) - } - } - // Port of `threadlocal var temp_entries_option: EntriesOption = undefined` — // `read_directory*` returns a pointer into this when the entry-cache is // disabled or the path is `mark_not_found`. `RefCell` (not `UnsafeCell`) so diff --git a/src/runtime/cli/pm_diff_command.rs b/src/runtime/cli/pm_diff_command.rs index ab5379c35adb..b6ddb9bd0752 100644 --- a/src/runtime/cli/pm_diff_command.rs +++ b/src/runtime/cli/pm_diff_command.rs @@ -843,11 +843,6 @@ impl bun_core::strings::Appender for BumpAppender<'_> { fn append(&mut self, s: &[u8]) -> Result<&[u8], bun_alloc::AllocError> { Ok(self.0.alloc_slice_copy(s)) } - fn append_lower_case(&mut self, s: &[u8]) -> Result<&[u8], bun_alloc::AllocError> { - let out = self.0.alloc_slice_copy(s); - out.make_ascii_lowercase(); - Ok(out) - } } fn registry_get( diff --git a/src/runtime/test_runner/expect.rs b/src/runtime/test_runner/expect.rs index 3daeb9471ffe..21012da69bfd 100644 --- a/src/runtime/test_runner/expect.rs +++ b/src/runtime/test_runner/expect.rs @@ -2309,7 +2309,6 @@ pub struct ExpectAnything { } impl ExpectAnything { - // extern shim emitted by `#[bun_jsc::JsClass]` codegen (TypeClass__construct/__call); bare `#[host_fn]` cannot target an associated fn without a receiver. pub fn call(global_this: &JSGlobalObject, _: &CallFrame) -> JsResult { let anything_js_value = ExpectAnything { flags: Cell::new(Flags::default()) }.to_js(global_this); anything_js_value.ensure_still_alive(); @@ -2326,7 +2325,6 @@ pub struct ExpectStringMatching { } impl ExpectStringMatching { - // extern shim emitted by `#[bun_jsc::JsClass]` codegen (TypeClass__construct/__call); bare `#[host_fn]` cannot target an associated fn without a receiver. pub fn call(global_this: &JSGlobalObject, call_frame: &CallFrame) -> JsResult { let args = call_frame.arguments(); @@ -2353,7 +2351,6 @@ pub struct ExpectCloseTo { } impl ExpectCloseTo { - // extern shim emitted by `#[bun_jsc::JsClass]` codegen (TypeClass__construct/__call); bare `#[host_fn]` cannot target an associated fn without a receiver. pub fn call(global_this: &JSGlobalObject, call_frame: &CallFrame) -> JsResult { let args = call_frame.arguments(); @@ -2393,7 +2390,6 @@ pub struct ExpectObjectContaining { } impl ExpectObjectContaining { - // extern shim emitted by `#[bun_jsc::JsClass]` codegen (TypeClass__construct/__call); bare `#[host_fn]` cannot target an associated fn without a receiver. pub fn call(global_this: &JSGlobalObject, call_frame: &CallFrame) -> JsResult { let args = call_frame.arguments(); @@ -2420,7 +2416,6 @@ pub struct ExpectStringContaining { } impl ExpectStringContaining { - // extern shim emitted by `#[bun_jsc::JsClass]` codegen (TypeClass__construct/__call); bare `#[host_fn]` cannot target an associated fn without a receiver. pub fn call(global_this: &JSGlobalObject, call_frame: &CallFrame) -> JsResult { let args = call_frame.arguments(); @@ -2447,7 +2442,6 @@ pub struct ExpectAny { } impl ExpectAny { - // extern shim emitted by `#[bun_jsc::JsClass]` codegen (TypeClass__construct/__call); bare `#[host_fn]` cannot target an associated fn without a receiver. pub fn call(global_this: &JSGlobalObject, call_frame: &CallFrame) -> JsResult { let arguments = call_frame.arguments(); @@ -2489,7 +2483,6 @@ pub struct ExpectArrayContaining { } impl ExpectArrayContaining { - // extern shim emitted by `#[bun_jsc::JsClass]` codegen (TypeClass__construct/__call); bare `#[host_fn]` cannot target an associated fn without a receiver. pub fn call(global_this: &JSGlobalObject, call_frame: &CallFrame) -> JsResult { let args = call_frame.arguments(); diff --git a/src/runtime/test_runner/jest.classes.ts b/src/runtime/test_runner/jest.classes.ts index 570d16f38a4c..6434fc9be292 100644 --- a/src/runtime/test_runner/jest.classes.ts +++ b/src/runtime/test_runner/jest.classes.ts @@ -5,7 +5,7 @@ export default [ name: "ExpectAnything", construct: false, noConstructor: true, - call: true, + call: false, finalize: true, JSType: "0b11101110", configurable: false, @@ -16,7 +16,7 @@ export default [ name: "ExpectAny", construct: false, noConstructor: true, - call: true, + call: false, finalize: true, JSType: "0b11101110", values: ["constructorValue"], @@ -28,7 +28,7 @@ export default [ name: "ExpectCloseTo", construct: false, noConstructor: true, - call: true, + call: false, finalize: true, JSType: "0b11101110", values: ["numberValue", "digitsValue"], @@ -40,7 +40,7 @@ export default [ name: "ExpectObjectContaining", construct: false, noConstructor: true, - call: true, + call: false, finalize: true, JSType: "0b11101110", values: ["objectValue"], @@ -52,7 +52,7 @@ export default [ name: "ExpectStringContaining", construct: false, noConstructor: true, - call: true, + call: false, finalize: true, JSType: "0b11101110", values: ["stringValue"], @@ -64,7 +64,7 @@ export default [ name: "ExpectStringMatching", construct: false, noConstructor: true, - call: true, + call: false, finalize: true, JSType: "0b11101110", values: ["testValue"], @@ -76,7 +76,7 @@ export default [ name: "ExpectArrayContaining", construct: false, noConstructor: true, - call: true, + call: false, finalize: true, JSType: "0b11101110", values: ["arrayValue"], diff --git a/src/shell_parser/error.rs b/src/shell_parser/error.rs index 65e57cb68c73..66642a9aa5b9 100644 --- a/src/shell_parser/error.rs +++ b/src/shell_parser/error.rs @@ -34,10 +34,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/sourcemap/error.rs b/src/sourcemap/error.rs index 75ee0e57a5d0..8acb8604938e 100644 --- a/src/sourcemap/error.rs +++ b/src/sourcemap/error.rs @@ -80,10 +80,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/spawn_sys/error.rs b/src/spawn_sys/error.rs index cbedd198037c..f50c66f8b53b 100644 --- a/src/spawn_sys/error.rs +++ b/src/spawn_sys/error.rs @@ -13,10 +13,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/standalone_graph/error.rs b/src/standalone_graph/error.rs index 14ea8649d2ab..5068d461a761 100644 --- a/src/standalone_graph/error.rs +++ b/src/standalone_graph/error.rs @@ -54,10 +54,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/uws_sys/libuwsockets.cpp b/src/uws_sys/libuwsockets.cpp index 5c1e40665e62..0bdc9d3ddf24 100644 --- a/src/uws_sys/libuwsockets.cpp +++ b/src/uws_sys/libuwsockets.cpp @@ -344,20 +344,6 @@ extern "C" } } - void uws_app_run(int ssl, uws_app_t *app) - { - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - uwsApp->run(); - } - else - { - uWS::App *uwsApp = (uWS::App *)app; - uwsApp->run(); - } - } - void uws_app_close(int ssl, uws_app_t *app) { if (ssl) @@ -412,31 +398,6 @@ extern "C" } } - void uws_app_listen(int ssl, uws_app_t *app, int port, - uws_listen_handler handler, void *user_data) - { - uws_app_listen_config_t config; - config.port = port; - config.host = nullptr; - config.options = 0; - - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - uwsApp->listen(port, [handler, - user_data](struct us_listen_socket_t *listen_socket) - { handler((struct us_listen_socket_t *)listen_socket, user_data); }); - } - else - { - uWS::App *uwsApp = (uWS::App *)app; - - uwsApp->listen(port, [handler, - user_data](struct us_listen_socket_t *listen_socket) - { handler((struct us_listen_socket_t *)listen_socket, user_data); }); - } - } - void uws_app_listen_with_config(int ssl, uws_app_t *app, const char *host, uint16_t port, int32_t options, uws_listen_handler handler, void *user_data) From 4a963937329be4456d9c15a1938f07a8cbbe824d Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 29 Aug 2026 18:58:19 +0000 Subject: [PATCH 2/9] Keep the uWS run()/listen() C wrappers until their Rust callers go src/uws_sys/App.rs still declares uws_app_run and uws_app_listen. Removing only the C++ definitions leaves dangling extern declarations. --- packages/bun-uws/src/App.h | 11 ++++++++++ packages/bun-uws/src/Loop.h | 12 ++++++++++- src/uws_sys/libuwsockets.cpp | 39 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/packages/bun-uws/src/App.h b/packages/bun-uws/src/App.h index 57649f4def51..f2444a46bbde 100644 --- a/packages/bun-uws/src/App.h +++ b/packages/bun-uws/src/App.h @@ -737,6 +737,12 @@ struct TemplatedApp { return std::move(*this); } + /* Port, callback */ + TemplatedApp &&listen(int port, MoveOnlyFunction &&handler) { + handler(httpContext ? trackListenSocket(httpContext->listen(sslCtxOrNull(), nullptr, port, 0)) : nullptr); + return std::move(*this); + } + /* Port, options, callback */ TemplatedApp &&listen(int port, int options, MoveOnlyFunction &&handler) { handler(httpContext ? trackListenSocket(httpContext->listen(sslCtxOrNull(), nullptr, port, options)) : nullptr); @@ -772,6 +778,11 @@ struct TemplatedApp { httpContext->enableNodeHttpCompat(); } + TemplatedApp &&run() { + uWS::run(); + return std::move(*this); + } + TemplatedApp &&setUsingCustomExpectHandler(bool value) { httpContext->getSocketContextData()->flags.usingCustomExpectHandler = value; return std::move(*this); diff --git a/packages/bun-uws/src/Loop.h b/packages/bun-uws/src/Loop.h index 8e736ead8d39..e6c73e9508f7 100644 --- a/packages/bun-uws/src/Loop.h +++ b/packages/bun-uws/src/Loop.h @@ -19,7 +19,7 @@ #ifndef UWS_LOOP_H #define UWS_LOOP_H -/* The loop is lazily created per-thread */ +/* The loop is lazily created per-thread and run with run() */ #include "LoopData.h" #include @@ -189,8 +189,18 @@ struct Loop { us_wakeup_loop((us_loop_t *) this); } + /* Actively block and run this loop */ + void run() { + us_loop_run((us_loop_t *) this); + } + }; +/* Can be called from any thread to run the thread local loop */ +inline void run() { + Loop::get()->run(); +} + } #endif // UWS_LOOP_H diff --git a/src/uws_sys/libuwsockets.cpp b/src/uws_sys/libuwsockets.cpp index 0bdc9d3ddf24..5c1e40665e62 100644 --- a/src/uws_sys/libuwsockets.cpp +++ b/src/uws_sys/libuwsockets.cpp @@ -344,6 +344,20 @@ extern "C" } } + void uws_app_run(int ssl, uws_app_t *app) + { + if (ssl) + { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->run(); + } + else + { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->run(); + } + } + void uws_app_close(int ssl, uws_app_t *app) { if (ssl) @@ -398,6 +412,31 @@ extern "C" } } + void uws_app_listen(int ssl, uws_app_t *app, int port, + uws_listen_handler handler, void *user_data) + { + uws_app_listen_config_t config; + config.port = port; + config.host = nullptr; + config.options = 0; + + if (ssl) + { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->listen(port, [handler, + user_data](struct us_listen_socket_t *listen_socket) + { handler((struct us_listen_socket_t *)listen_socket, user_data); }); + } + else + { + uWS::App *uwsApp = (uWS::App *)app; + + uwsApp->listen(port, [handler, + user_data](struct us_listen_socket_t *listen_socket) + { handler((struct us_listen_socket_t *)listen_socket, user_data); }); + } + } + void uws_app_listen_with_config(int ssl, uws_app_t *app, const char *host, uint16_t port, int32_t options, uws_listen_handler handler, void *user_data) From 7a75645e507f1877aa21cc1764e761f3c6d73af2 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 29 Aug 2026 18:59:41 +0000 Subject: [PATCH 3/9] Shorten two doc comments --- src/bun_alloc/MaxHeapAllocator.rs | 3 +-- src/install/NetworkTask.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bun_alloc/MaxHeapAllocator.rs b/src/bun_alloc/MaxHeapAllocator.rs index 27e261805619..8a73d8eaa7e2 100644 --- a/src/bun_alloc/MaxHeapAllocator.rs +++ b/src/bun_alloc/MaxHeapAllocator.rs @@ -44,8 +44,7 @@ impl MaxHeapAllocator { } } -/// RAII guard returned by [`MaxHeapAllocator::scope`]. Holds the allocator -/// for the duration of the scope and resets it on drop. +/// RAII guard returned by [`MaxHeapAllocator::scope`]; resets the allocator on drop. pub struct MaxHeapScope<'a> { inner: &'a mut MaxHeapAllocator, } diff --git a/src/install/NetworkTask.rs b/src/install/NetworkTask.rs index d79d7d8ed321..408733e57fe8 100644 --- a/src/install/NetworkTask.rs +++ b/src/install/NetworkTask.rs @@ -18,8 +18,7 @@ use crate::npm::{self as npm, PackageManifest}; use crate::{ExtractTarball, PackageManager, PatchTask, TarballStream, Task}; // Adapter so `StringOrTinyString::init_append_if_needed` can intern overflow -// names into the resolver's filename arena. `FilenameStore` exposes `append` -// but doesn't itself implement `strings::Appender`. +// names into the resolver's filename arena. pub struct FilenameStoreAppender<'a>(pub(crate) &'a FilenameStore); impl strings::Appender for FilenameStoreAppender<'_> { fn append(&mut self, s: &[u8]) -> Result<&[u8], bun_alloc::AllocError> { From 80b894e17d6df11a36dc6928024cd51e9141b554 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 29 Aug 2026 23:44:25 +0000 Subject: [PATCH 4/9] Delete the rest of src/jsc/bindgen.rs, five more unused ErrName impls, and ten inert host_fn shims The remaining Bindgen trait and BindgenTrivial adapter had no users either. The ErrName impls on the bun_brotli, bun_clap, bun_css, bun_router and bun_uws_sys error types are never called through the trait. A bare #[bun_jsc::host_fn] on a function that dispatch_js2native.rs calls directly only emits an unused __jsc_host_* shim. define() now rejects call: true together with noConstructor: true, since the constructor class is the only consumer of the call target. --- src/brotli/error.rs | 6 ------ src/clap/error.rs | 6 ------ src/codegen/class-definitions.ts | 5 +++++ src/css/crate_error.rs | 6 ------ src/jsc/bindgen.rs | 29 ----------------------------- src/jsc/bun_string_jsc.rs | 3 --- src/jsc/event_loop.rs | 1 - src/jsc/generated.rs | 8 ++++---- src/jsc/lib.rs | 2 -- src/patch_jsc/testing.rs | 15 ++------------- src/router/error.rs | 16 ---------------- src/sys_jsc/error_jsc.rs | 3 --- src/uws_sys/error.rs | 18 ------------------ 13 files changed, 11 insertions(+), 107 deletions(-) delete mode 100644 src/jsc/bindgen.rs diff --git a/src/brotli/error.rs b/src/brotli/error.rs index 2b38bb1a5d19..470661681b24 100644 --- a/src/brotli/error.rs +++ b/src/brotli/error.rs @@ -26,10 +26,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/clap/error.rs b/src/clap/error.rs index 3bab9a99ffad..b1f72a7c5aa4 100644 --- a/src/clap/error.rs +++ b/src/clap/error.rs @@ -19,12 +19,6 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - impl From for Error { fn from(e: crate::streaming::ArgError) -> Self { match e { diff --git a/src/codegen/class-definitions.ts b/src/codegen/class-definitions.ts index 3b8e12a13109..74969d05527c 100644 --- a/src/codegen/class-definitions.ts +++ b/src/codegen/class-definitions.ts @@ -248,6 +248,11 @@ export function define( ...rest } = {} as Partial, ): ClassDefinition { + if (call && rest.noConstructor) { + throw new Error( + `${rest.name}: \`call: true\` has no effect with \`noConstructor: true\` (the constructor is what gets the call target)`, + ); + } if (inspectCustom) { proto.inspectCustom = { fn: "inspectCustom", diff --git a/src/css/crate_error.rs b/src/css/crate_error.rs index 9d8c5e04ff3b..a01d34f012e1 100644 --- a/src/css/crate_error.rs +++ b/src/css/crate_error.rs @@ -19,10 +19,4 @@ impl Error { } } -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/jsc/bindgen.rs b/src/jsc/bindgen.rs deleted file mode 100644 index ed2b4e95cfe1..000000000000 --- a/src/jsc/bindgen.rs +++ /dev/null @@ -1,29 +0,0 @@ -use core::marker::PhantomData; - -// ────────────────────────────────────────────────────────────────────────── -// A `Bindgen` adapter supplies associated `ZigType`/`ExternType` plus -// `convert_from_extern`. -// ────────────────────────────────────────────────────────────────────────── - -pub trait Bindgen { - type ZigType; - type ExternType; - - /// `true` when `ZigType` and `ExternType` are layout-identical. - /// Defaults to `false`; override per adapter. - const SAME_REPR: bool = false; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType; -} - -pub struct BindgenTrivial(PhantomData); - -impl Bindgen for BindgenTrivial { - type ZigType = T; - type ExternType = T; - const SAME_REPR: bool = true; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - extern_value - } -} diff --git a/src/jsc/bun_string_jsc.rs b/src/jsc/bun_string_jsc.rs index 7874020393c6..bf02d3ab99ad 100644 --- a/src/jsc/bun_string_jsc.rs +++ b/src/jsc/bun_string_jsc.rs @@ -209,7 +209,6 @@ pub fn parse_date(this: &String, global_object: &JSGlobalObject) -> JsResult JsResult { let input_value = call_frame.argument(0); @@ -229,7 +228,6 @@ pub fn js_escape_reg_exp(global: &JSGlobalObject, call_frame: &CallFrame) -> JsR create_utf8_for_js(global, &buf) } -#[bun_jsc::host_fn] pub fn js_escape_reg_exp_for_package_name_matching( global: &JSGlobalObject, call_frame: &CallFrame, @@ -262,7 +260,6 @@ pub mod unicode_testing_apis { /// Exercises the `sentinel = true` path of `toUTF16AllocForReal`, which is /// otherwise only reachable from Windows-only `bun build --compile` /// metadata code. - #[bun_jsc::host_fn] pub fn to_utf16_alloc_sentinel( global_this: &JSGlobalObject, callframe: &CallFrame, diff --git a/src/jsc/event_loop.rs b/src/jsc/event_loop.rs index bbb01de0335c..d87ac3db76a0 100644 --- a/src/jsc/event_loop.rs +++ b/src/jsc/event_loop.rs @@ -1329,7 +1329,6 @@ impl EventLoop { } /// Testing API to expose event loop state -#[bun_jsc::host_fn] pub fn get_active_tasks(global_object: &JSGlobalObject, _frame: &CallFrame) -> JsResult { // fields and call &-methods on it for the duration of this host fn. let vm_ref = global_object.bun_vm(); diff --git a/src/jsc/generated.rs b/src/jsc/generated.rs index eb5123bf1906..be869572e421 100644 --- a/src/jsc/generated.rs +++ b/src/jsc/generated.rs @@ -158,7 +158,7 @@ impl ExternOptional { } } -/// `bindgen.ExternArrayList(T)` — `extern struct { data: ?[*]T, length: c_uint, +/// Extern layout of a C++ vector handed to Rust: `{ data: ?[*]T, length: c_uint, /// capacity: c_uint }`. // Clone/Copy: bitwise OK — FFI mirror of a C++ buffer; Rust treats it as a // borrowed view and adopts ownership exactly once at the call site. @@ -178,8 +178,8 @@ fn adopt_string(ptr: RawWTFStringImpl) -> GenString { #[inline] fn adopt_opt_string(ptr: RawWTFStringImpl) -> GenOpt { - // `BindgenOptional(BindgenString).ExternType` is `?WTFStringImpl` — single-word - // nullable ptr (custom `OptionalExternType`), NOT an `ExternTaggedUnion`. + // An optional string crosses as a single-word nullable `WTFStringImpl` + // pointer, not as a tagged union. GenOpt(if ptr.is_null() { None } else { @@ -444,7 +444,7 @@ struct ExternSSLConfigFile { #[repr(C)] #[derive(Clone, Copy)] union ExternSSLConfigFileData { - _0: u8, // BindgenNull + _0: u8, // null / undefined arm _1: RawWTFStringImpl, _2: GenArrayBuffer, _3: GenBlob, diff --git a/src/jsc/lib.rs b/src/jsc/lib.rs index 03faa8dec0e7..4f3a238167b5 100644 --- a/src/jsc/lib.rs +++ b/src/jsc/lib.rs @@ -458,8 +458,6 @@ pub mod zig_stack_trace; #[path = "AsyncModule.rs"] pub mod async_module; -#[path = "bindgen.rs"] -pub mod bindgen; #[path = "bindgen_test.rs"] pub mod bindgen_test; #[path = "BunCPUProfiler.rs"] diff --git a/src/patch_jsc/testing.rs b/src/patch_jsc/testing.rs index 3bfe8452f7db..bedf69730a67 100644 --- a/src/patch_jsc/testing.rs +++ b/src/patch_jsc/testing.rs @@ -8,9 +8,6 @@ use bun_sys::{Fd, FdExt}; pub(crate) struct TestingAPIs; impl TestingAPIs { - // `#[bun_jsc::host_fn]` Free-kind shim emits an unqualified - // `fn_name(g, f)` call, so it cannot wrap an associated fn. The C-ABI - // shim is emitted at module scope below (`__jsc_host_*`). pub(crate) fn make_diff(global: &JSGlobalObject, frame: &CallFrame) -> JsResult { // SAFETY: `bun_vm()` never returns null for a Bun-owned global; the VM // outlives this call frame. @@ -176,26 +173,18 @@ impl Drop for ApplyArgs { } // ────────────────────────────────────────────────────────────────────────── -// C-ABI host-fn shims -// -// `#[bun_jsc::host_fn]` (Free kind) emits an unqualified `fn_name(g, f)` call -// in its generated shim body, so it can't wrap an associated fn directly. -// These module-scope thunks forward to `TestingAPIs::*` so the proc-macro can -// generate the JSC-calling-convention `__jsc_host_*` exports the codegen side -// links against. +// Free-fn entry points for `dispatch_js2native.rs`, whose `pub use` cannot +// name an associated fn. // ────────────────────────────────────────────────────────────────────────── -#[bun_jsc::host_fn] pub fn patch_make_diff(global: &JSGlobalObject, frame: &CallFrame) -> JsResult { TestingAPIs::make_diff(global, frame) } -#[bun_jsc::host_fn] pub fn patch_apply(global: &JSGlobalObject, frame: &CallFrame) -> JsResult { TestingAPIs::apply(global, frame) } -#[bun_jsc::host_fn] pub fn patch_parse(global: &JSGlobalObject, frame: &CallFrame) -> JsResult { TestingAPIs::parse(global, frame) } diff --git a/src/router/error.rs b/src/router/error.rs index 57cddd0a59bd..62b851e37878 100644 --- a/src/router/error.rs +++ b/src/router/error.rs @@ -6,20 +6,4 @@ pub enum Error { Alloc(#[from] bun_alloc::AllocError), } -impl Error { - #[allow(clippy::trivially_copy_pass_by_ref)] - pub(crate) fn name(&self) -> &'static str { - match self { - Self::Sys(e) => <&'static str>::from(e), - Self::Alloc(_) => "OutOfMemory", - } - } -} - -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; diff --git a/src/sys_jsc/error_jsc.rs b/src/sys_jsc/error_jsc.rs index 323dc8ee0e89..4035ceae1472 100644 --- a/src/sys_jsc/error_jsc.rs +++ b/src/sys_jsc/error_jsc.rs @@ -47,7 +47,6 @@ pub mod TestingAPIs { /// values that filter drivers and cloud-sync placeholders return in the /// wild (STATUS_CANNOT_DELETE etc.) and verify they map to a sensible /// errno rather than `UNKNOWN`. Windows-only; returns `undefined` elsewhere. - #[bun_jsc::host_fn] pub fn translate_nt_status_to_e( global: &JSGlobalObject, frame: &CallFrame, @@ -76,7 +75,6 @@ pub mod TestingAPIs { /// Exposes libuv -> `bun.sys.E` translation so tests can feed out-of-range /// negative values and verify it does not panic. Windows-only. - #[bun_jsc::host_fn] pub fn translate_uv_error_to_e( global: &JSGlobalObject, frame: &CallFrame, @@ -109,7 +107,6 @@ pub mod TestingAPIs { /// `libc` crate's `sigaction`/`sigset_t` directly, which already has the /// correct per-target layout (bionic included), so this is a sanity check /// rather than a fix-carrier. - #[bun_jsc::host_fn] pub fn sigaction_layout(global: &JSGlobalObject, _frame: &CallFrame) -> JsResult { #[cfg(not(unix))] { diff --git a/src/uws_sys/error.rs b/src/uws_sys/error.rs index ed719e357493..2e86ee76581f 100644 --- a/src/uws_sys/error.rs +++ b/src/uws_sys/error.rs @@ -10,22 +10,4 @@ pub enum Error { Sys(#[from] bun_errno::SystemErrno), } -impl Error { - #[allow(clippy::trivially_copy_pass_by_ref)] - pub(crate) fn name(&self) -> &'static str { - match self { - Self::RequestBodyTooLarge => "RequestBodyTooLarge", - Self::FailedToOpenSocket => "FailedToOpenSocket", - Self::Alloc(_) => "OutOfMemory", - Self::Sys(e) => <&'static str>::from(e), - } - } -} - -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - pub type Result = core::result::Result; From 1bc40a277276a652aad1d424036db2093df43be4 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 29 Aug 2026 23:46:18 +0000 Subject: [PATCH 5/9] Trim two comments --- src/jsc/generated.rs | 2 -- src/patch_jsc/testing.rs | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/jsc/generated.rs b/src/jsc/generated.rs index be869572e421..c86984a0302a 100644 --- a/src/jsc/generated.rs +++ b/src/jsc/generated.rs @@ -178,8 +178,6 @@ fn adopt_string(ptr: RawWTFStringImpl) -> GenString { #[inline] fn adopt_opt_string(ptr: RawWTFStringImpl) -> GenOpt { - // An optional string crosses as a single-word nullable `WTFStringImpl` - // pointer, not as a tagged union. GenOpt(if ptr.is_null() { None } else { diff --git a/src/patch_jsc/testing.rs b/src/patch_jsc/testing.rs index bedf69730a67..78bc9fd918f9 100644 --- a/src/patch_jsc/testing.rs +++ b/src/patch_jsc/testing.rs @@ -172,10 +172,7 @@ impl Drop for ApplyArgs { } } -// ────────────────────────────────────────────────────────────────────────── -// Free-fn entry points for `dispatch_js2native.rs`, whose `pub use` cannot -// name an associated fn. -// ────────────────────────────────────────────────────────────────────────── +// Free-fn entry points: `dispatch_js2native.rs` re-exports these with `pub use`, which cannot name an associated fn. pub fn patch_make_diff(global: &JSGlobalObject, frame: &CallFrame) -> JsResult { TestingAPIs::make_diff(global, frame) From eeba22a4f460aecd418c297a0062a4860afeb098 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 30 Aug 2026 05:51:13 +0000 Subject: [PATCH 6/9] Reject RejectPromise getters at compile time in IDLAttribute::get The RejectPromise branch is gone, so a getter instantiated with that behavior would fall through to the ReturnEarly path and return undefined. The static_assert turns that into a build error. --- src/jsc/bindings/webcore/JSDOMAttribute.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jsc/bindings/webcore/JSDOMAttribute.h b/src/jsc/bindings/webcore/JSDOMAttribute.h index 6f3c6bbe3fd6..de5bb290b878 100644 --- a/src/jsc/bindings/webcore/JSDOMAttribute.h +++ b/src/jsc/bindings/webcore/JSDOMAttribute.h @@ -54,6 +54,7 @@ class IDLAttribute { template static JSC::EncodedJSValue get(JSC::JSGlobalObject& lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName attributeName) { + static_assert(shouldThrow != CastedThisErrorBehavior::RejectPromise, "IDLAttribute::get has no RejectPromise path; no getter uses it"); auto throwScope = DECLARE_THROW_SCOPE(JSC::getVM(&lexicalGlobalObject)); if constexpr (shouldThrow == CastedThisErrorBehavior::Assert) { From 5a3d66d8063bbade731fc06d012d339c218e7096 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 30 Aug 2026 05:54:26 +0000 Subject: [PATCH 7/9] Test that define() rejects call: true on a class without a constructor --- test/internal/class-definitions.test.ts | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 test/internal/class-definitions.test.ts diff --git a/test/internal/class-definitions.test.ts b/test/internal/class-definitions.test.ts new file mode 100644 index 000000000000..d0c024e98f64 --- /dev/null +++ b/test/internal/class-definitions.test.ts @@ -0,0 +1,56 @@ +/** + * `define()` in src/codegen/class-definitions.ts is the input validator for + * every `*.classes.ts` file that generate-classes.ts turns into C++ and Rust. + * + * `call: true` hands the generated `JSConstructor` a call target, so + * `Name(...)` without `new` constructs an instance. With `noConstructor: true` + * no constructor class is generated, and the flag only emitted a thunk and an + * extern declaration that nothing referenced. `define()` rejects that + * combination so the inert flag cannot come back. + */ +import { describe, expect, test } from "bun:test"; + +import { define } from "../../src/codegen/class-definitions.ts"; +import jestClasses from "../../src/runtime/test_runner/jest.classes.ts"; + +describe("define()", () => { + test("rejects call: true on a class without a constructor", () => { + expect(() => + define({ + name: "NoCtor", + noConstructor: true, + call: true, + klass: {}, + proto: {}, + }), + ).toThrow("NoCtor: `call: true` has no effect with `noConstructor: true`"); + }); + + test("accepts a callable class that has a constructor", () => { + const def = define({ + name: "WithCtor", + construct: true, + call: true, + klass: {}, + proto: {}, + }); + expect(def).toMatchObject({ name: "WithCtor", call: true, construct: true }); + }); + + test("accepts a non-callable class without a constructor", () => { + const def = define({ + name: "NoCtor", + noConstructor: true, + call: false, + finalize: true, + klass: {}, + proto: {}, + }); + expect(def).toMatchObject({ name: "NoCtor", call: false, noConstructor: true }); + }); + + test("only the jest classes with a constructor are callable", () => { + expect(jestClasses.filter(def => def.noConstructor && def.call).map(def => def.name)).toEqual([]); + expect(jestClasses.filter(def => def.call).map(def => def.name)).toEqual(["Expect", "ExpectTypeOf"]); + }); +}); From a33b7ec7cc86c37034989fe8cc7e74e03207bf9b Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 30 Aug 2026 06:13:13 +0000 Subject: [PATCH 8/9] Drop an assertion the define() guard already makes unreachable --- src/jsc/bindgen.rs | 293 ++++++++++++++++++++ src/jsc/bindings/webcore/JSErrorHandler.cpp | 122 ++++++++ src/jsc/bindings/webcore/JSErrorHandler.h | 48 ++++ test/internal/class-definitions.test.ts | 1 - 4 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 src/jsc/bindgen.rs create mode 100644 src/jsc/bindings/webcore/JSErrorHandler.cpp create mode 100644 src/jsc/bindings/webcore/JSErrorHandler.h diff --git a/src/jsc/bindgen.rs b/src/jsc/bindgen.rs new file mode 100644 index 000000000000..996671297db0 --- /dev/null +++ b/src/jsc/bindgen.rs @@ -0,0 +1,293 @@ +use core::ffi::c_uint; +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, align_of, size_of}; +use core::ptr::NonNull; + +use crate::{self as jsc, Strong}; +use bun_core::{WTFString, WTFStringImplStruct}; + +// `BindgenArray::convert_from_extern` reuses C++-allocated buffers by adopting +// them into `Vec` even when `align_of::() != align_of::()`. +// That is only sound because mimalloc's `mi_free` ignores the allocation layout; +// the Rust `GlobalAlloc::dealloc` contract would otherwise be violated. The C++ side +// (`ExternVectorTraits.h`) always allocates with `mi_malloc`, so when the global +// allocator is not mimalloc the reuse path is skipped and the fallback frees the +// C++ buffer with `mi_free` directly. + +// ────────────────────────────────────────────────────────────────────────── +// A `Bindgen` adapter supplies associated `ZigType`/`ExternType` plus +// `convert_from_extern`. +// ────────────────────────────────────────────────────────────────────────── + +pub trait Bindgen { + type ZigType; + type ExternType; + + /// `true` when `ZigType` and `ExternType` are layout-identical. + /// Enables `BindgenArray`'s + /// allocation-reuse fast path. Defaults to `false`; override per adapter. + const SAME_REPR: bool = false; + + fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType; +} + +pub struct BindgenTrivial(PhantomData); + +impl Bindgen for BindgenTrivial { + type ZigType = T; + type ExternType = T; + const SAME_REPR: bool = true; + + fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { + extern_value + } +} + +// ────────────────────────────────────────────────────────────────────────── + +pub struct BindgenStrongAny; + +impl Bindgen for BindgenStrongAny { + type ZigType = Strong; + // `?*jsc.Strong.Impl` — must be single-word for #[repr(C)] union placement, so + // `Option>` (niche-optimized), NOT `Option<*mut T>` (two words). + type ExternType = Option>; + + fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { + // SAFETY: bindgen contract — C++ passes a freshly-allocated Strong handle + // whose ownership is transferred to Rust here. + unsafe { Strong::adopt(extern_value.expect("non-null")) } + } +} + +// ────────────────────────────────────────────────────────────────────────── + +/// This represents both `IDLNull` and `IDLMonostateUndefined`. +pub struct BindgenNull; + +impl Bindgen for BindgenNull { + type ZigType = (); + type ExternType = u8; + + fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { + let _ = extern_value; + } +} + +// ────────────────────────────────────────────────────────────────────────── + +pub struct BindgenOptional(PhantomData); + +// Wrap in `ExternTaggedUnion<(u8, Child::ExternType)>` and produce +// `Option`. +impl Bindgen for BindgenOptional { + type ZigType = Option; + type ExternType = ExternTaggedUnion2; + + fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { + if extern_value.tag == 0 { + return None; + } + debug_assert_eq!(extern_value.tag, 1); + // SAFETY: tag == 1 means the `_1` arm of the union is initialized. + Some(Child::convert_from_extern(unsafe { + ManuallyDrop::into_inner(extern_value.data._1) + })) + } +} + +// ────────────────────────────────────────────────────────────────────────── + +pub struct BindgenString; + +impl Bindgen for BindgenString { + type ZigType = WTFString; + // `?bun.string.WTFStringImpl` — `Option>` for single-word FFI layout. + type ExternType = Option>; + + fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { + // SAFETY: bindgen contract — C++ passes a `StringImpl*` with one ref already + // taken for us; `adopt` consumes that ref. + unsafe { WTFString::adopt(extern_value.expect("non-null").as_ptr()) } + } +} + +// ────────────────────────────────────────────────────────────────────────── +// BindgenUnion / ExternTaggedUnion / ExternUnion +// +// These are generated per arity (or by a proc-macro from the bindgen codegen). +// ────────────────────────────────────────────────────────────────────────── + +// The bindgen TS codegen emits a concrete `enum` + `#[repr(C)]` union pair +// per call site rather than a generic Rust combinator (see +// `src/jsc/generated.rs`). This marker type exists for documentation parity. + +/// `extern struct { data: ExternUnion(field_types), tag: u8 }` +/// +/// We provide fixed-arity instantiations; the 2-ary case is the only +/// one used directly in this file (by `BindgenOptional`). Higher arities are +/// emitted by codegen alongside their consumers. +#[repr(C)] +pub struct ExternTaggedUnion2 { + pub(crate) data: ExternUnion2, + pub(crate) tag: u8, +} + +/// Union fields are wrapped in `ManuallyDrop` so non-`Copy` payloads +/// (e.g. nested `ExternTaggedUnion2`, `ExternArrayList`) are permitted without +/// trait bounds. There is no auto-drop — the active arm must be dropped +/// explicitly by whoever knows the tag. +#[repr(C)] +pub union ExternUnion2 { + pub _0: ManuallyDrop, + pub(crate) _1: ManuallyDrop, +} + +// ────────────────────────────────────────────────────────────────────────── + +pub struct BindgenArray(PhantomData); + +impl Bindgen for BindgenArray { + type ZigType = bun_collections::ArrayListDefault; + type ExternType = ExternArrayList; + + fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { + let length = usize::try_from(extern_value.length).expect("int cast"); + let capacity = usize::try_from(extern_value.capacity).expect("int cast"); + + if extern_value.data.is_null() { + return Self::ZigType::init(); + } + let data = extern_value.data; + debug_assert!( + length <= capacity, + "length ({}) should not exceed capacity ({})", + length, + capacity, + ); + // SAFETY: C++ side guarantees `data` points to `capacity` elements with + // `length` initialized; allocation came from mimalloc (when `USE_MIMALLOC`). + let unmanaged: Vec = + unsafe { Vec::from_raw_parts(data, length, capacity) }; + + if !bun_alloc::USE_MIMALLOC { + // Don't reuse memory in this case; it would be freed by the wrong allocator. + } else if size_of::() == size_of::() + && align_of::() == align_of::() + // Rust has no stable type-equality test in generic context, so this + // fast-path is gated on the `const SAME_REPR: bool` opt-in: it only + // fires when the bindgen codegen has proven layout identity. + && Child::SAME_REPR + { + // The layouts are identical, so the Vec is returned as-is. + let (ptr, len, cap) = { + let mut v = ManuallyDrop::new(unmanaged); + (v.as_mut_ptr(), v.len(), v.capacity()) + }; + // SAFETY: `SAME_REPR` ⇒ same layout; `from_raw_parts` round-trip. + let reused: Vec = + unsafe { Vec::from_raw_parts(ptr.cast::(), len, cap) }; + return Self::ZigType::from_unmanaged(reused); + } else if size_of::() <= size_of::() + && align_of::() <= bun_alloc::mimalloc::MI_MAX_ALIGN_SIZE + { + // We can reuse the allocation, but we still need to convert the elements. + // + // Materializing a `&mut [u8]` over the full capacity would assert that + // every byte — including uninitialized tail elements and `ExternType` + // padding — is a valid `u8`, which is UB. Work entirely through raw + // `*mut u8` and `ptr::copy_nonoverlapping` instead; no reference to + // the storage is ever formed. + let mut v = ManuallyDrop::new(unmanaged); + let mut storage_ptr: *mut u8 = v.as_mut_ptr().cast::(); + let storage_len = v.capacity() * size_of::(); + + // Convert the elements. + for i in 0..length { + // Byte-wise copy: this is an in-place reinterpretation of + // overlapping element slots, so each element is copied out + // before conversion. + let mut old_elem = core::mem::MaybeUninit::::uninit(); + // SAFETY: source range lies within the mimalloc block and holds a + // valid (C++-initialized) `ExternType` for `i < length`. + unsafe { + core::ptr::copy_nonoverlapping( + storage_ptr.add(i * size_of::()), + old_elem.as_mut_ptr().cast::(), + size_of::(), + ); + } + // SAFETY: bytes for element `i` were just copied from initialized storage. + let new_elem = ManuallyDrop::new(Child::convert_from_extern(unsafe { + old_elem.assume_init() + })); + // SAFETY: dest range lies within the block; `size_of ZigType <= + // size_of ExternType` so slot `i` of the new layout never overruns + // slot `i` of the old layout (and never clobbers slot `i+1`). + unsafe { + core::ptr::copy_nonoverlapping( + (&raw const *new_elem).cast::(), + storage_ptr.add(i * size_of::()), + size_of::(), + ); + } + } + + let new_size_is_multiple = + size_of::() % size_of::() == 0; + let new_capacity = if new_size_is_multiple { + capacity * (size_of::() / size_of::()) + } else { + let new_capacity = storage_len / size_of::(); + let new_alloc_size = new_capacity * size_of::(); + if new_alloc_size != storage_len { + // Allocation isn't a multiple of `size_of::()`; we have to + // resize it. + // SAFETY: `storage_ptr` is the original mimalloc block (the + // `USE_MIMALLOC` guard above gates entry to this path); shrinking + // with `mi_realloc` preserves the prefix bytes. + storage_ptr = bun_core::handle_oom(unsafe { + bun_alloc::realloc_raw(storage_ptr, new_alloc_size) + }); + } + new_capacity + }; + + let items_ptr = storage_ptr.cast::(); + // SAFETY: `storage_ptr` is aligned to ≥ `MI_MAX_ALIGN_SIZE` ≥ + // `align_of::()`; the first `length` slots were just written + // with valid `ZigType` values; the block is mimalloc-owned and the + // global allocator is mimalloc (the `if !bun_alloc::USE_MIMALLOC` + // guard above gates entry to this path), so `Vec`'s eventual dealloc + // — even with `ZigType`'s layout — routes to `mi_free`, which + // ignores layout. + let new_unmanaged: Vec = + unsafe { Vec::from_raw_parts(items_ptr, length, new_capacity) }; + return Self::ZigType::from_unmanaged(new_unmanaged); + } + + // Fallback: allocate fresh, convert, free old. `data` was `mi_malloc`'d + // by the C++ side regardless of the Rust global allocator, so free it + // with `mi_free` directly instead of `Vec::drop`. + let mut result = bun_core::handle_oom(Self::ZigType::init_capacity(length)); + let mut unmanaged = ManuallyDrop::new(unmanaged); + for item in unmanaged.iter_mut() { + // SAFETY: each slot holds a C++-initialized `ExternType`; `ManuallyDrop` ensures it isn't read twice. + result.append_assume_capacity(Child::convert_from_extern(unsafe { + core::ptr::read(item) + })); + } + // SAFETY: `data` is the live `mi_malloc`'d block from `ExternVectorTraits::convertToExtern`. + unsafe { bun_alloc::mimalloc::mi_free(data.cast()) }; + result + } +} + +#[repr(C)] +pub struct ExternArrayList { + // Single-word nullable pointer. `Option<*mut T>` has no niche + // (two words) and would break the C ABI; use raw `*mut T` and check `.is_null()`. + pub(crate) data: *mut Child, + pub(crate) length: c_uint, + pub(crate) capacity: c_uint, +} diff --git a/src/jsc/bindings/webcore/JSErrorHandler.cpp b/src/jsc/bindings/webcore/JSErrorHandler.cpp new file mode 100644 index 000000000000..e7571a185aae --- /dev/null +++ b/src/jsc/bindings/webcore/JSErrorHandler.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2013-2018 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSErrorHandler.h" + +// #include "Document.h" +#include "ErrorEvent.h" +#include "Event.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSEvent.h" +#include +#include + +namespace WebCore { +using namespace JSC; + +inline JSErrorHandler::JSErrorHandler(JSObject& listener, JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) + : JSEventListener(&listener, &wrapper, isAttribute, CreatedFromMarkup::No, world) +{ +} + +Ref JSErrorHandler::create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) +{ + return adoptRef(*new JSErrorHandler(listener, wrapper, isAttribute, world)); +} + +JSErrorHandler::~JSErrorHandler() = default; + +void JSErrorHandler::handleEvent(ScriptExecutionContext& scriptExecutionContext, Event& event) +{ + if (!is(event)) + return JSEventListener::handleEvent(scriptExecutionContext, event); + + VM& vm = scriptExecutionContext.vm(); + JSLockHolder lock(vm); + + JSObject* jsFunction = this->ensureJSFunction(scriptExecutionContext); + if (!jsFunction) + return; + + auto* isolatedWorld = this->isolatedWorld(); + if (!isolatedWorld) [[unlikely]] + return; + + auto* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *isolatedWorld); + if (!globalObject) + return; + + auto callData = getCallData(jsFunction); + if (callData.type != CallData::Type::None) { + Ref protectedThis(*this); + + RefPtr savedEvent; + // auto* jsFunctionWindow = dynamicDowncast( jsFunction->globalObject()); + // if (jsFunctionWindow) { + // savedEvent = jsFunctionWindow->currentEvent(); + + // // window.event should not be set when the target is inside a shadow tree, as per the DOM specification. + // if (!event.currentTargetIsInShadowTree()) + // jsFunctionWindow->setCurrentEvent(&event); + // } + + auto& errorEvent = downcast(event); + + MarkedArgumentBuffer args; + args.append(toJS(*globalObject, errorEvent.message())); + args.append(toJS(*globalObject, errorEvent.filename())); + args.append(toJS(errorEvent.lineno())); + args.append(toJS(errorEvent.colno())); + args.append(errorEvent.error(*globalObject)); + ASSERT(!args.hasOverflowed()); + + // JSExecState::instrumentFunction(&scriptExecutionContext, callData); + + NakedPtr exception; + JSValue returnValue = JSC::profiledCall(globalObject, JSC::ProfilingReason::Other, jsFunction, callData, globalObject, args, exception); + + // InspectorInstrumentation::didCallFunction(&scriptExecutionContext); + + // if (jsFunctionWindow) + // jsFunctionWindow->setCurrentEvent(savedEvent.get()); + + if (exception) + reportException(globalObject, exception); + else { + if (returnValue.isTrue()) + event.preventDefault(); + } + } +} + +} // namespace WebCore diff --git a/src/jsc/bindings/webcore/JSErrorHandler.h b/src/jsc/bindings/webcore/JSErrorHandler.h new file mode 100644 index 000000000000..d32c55a86106 --- /dev/null +++ b/src/jsc/bindings/webcore/JSErrorHandler.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSEventListener.h" + +namespace WebCore { + +class JSErrorHandler final : public JSEventListener { +public: + static Ref create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); + virtual ~JSErrorHandler(); + +private: + JSErrorHandler(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); + void handleEvent(ScriptExecutionContext&, Event&) final; +}; + +} // namespace WebCore diff --git a/test/internal/class-definitions.test.ts b/test/internal/class-definitions.test.ts index d0c024e98f64..cdc690cffa91 100644 --- a/test/internal/class-definitions.test.ts +++ b/test/internal/class-definitions.test.ts @@ -50,7 +50,6 @@ describe("define()", () => { }); test("only the jest classes with a constructor are callable", () => { - expect(jestClasses.filter(def => def.noConstructor && def.call).map(def => def.name)).toEqual([]); expect(jestClasses.filter(def => def.call).map(def => def.name)).toEqual(["Expect", "ExpectTypeOf"]); }); }); From 1379860dd777936e2b7e2ef155714897aa265a91 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 30 Aug 2026 06:27:25 +0000 Subject: [PATCH 9/9] Delete bindgen.rs and JSErrorHandler again The previous commit re-added them by accident. --- src/jsc/bindgen.rs | 293 -------------------- src/jsc/bindings/webcore/JSErrorHandler.cpp | 122 -------- src/jsc/bindings/webcore/JSErrorHandler.h | 48 ---- 3 files changed, 463 deletions(-) delete mode 100644 src/jsc/bindgen.rs delete mode 100644 src/jsc/bindings/webcore/JSErrorHandler.cpp delete mode 100644 src/jsc/bindings/webcore/JSErrorHandler.h diff --git a/src/jsc/bindgen.rs b/src/jsc/bindgen.rs deleted file mode 100644 index 996671297db0..000000000000 --- a/src/jsc/bindgen.rs +++ /dev/null @@ -1,293 +0,0 @@ -use core::ffi::c_uint; -use core::marker::PhantomData; -use core::mem::{ManuallyDrop, align_of, size_of}; -use core::ptr::NonNull; - -use crate::{self as jsc, Strong}; -use bun_core::{WTFString, WTFStringImplStruct}; - -// `BindgenArray::convert_from_extern` reuses C++-allocated buffers by adopting -// them into `Vec` even when `align_of::() != align_of::()`. -// That is only sound because mimalloc's `mi_free` ignores the allocation layout; -// the Rust `GlobalAlloc::dealloc` contract would otherwise be violated. The C++ side -// (`ExternVectorTraits.h`) always allocates with `mi_malloc`, so when the global -// allocator is not mimalloc the reuse path is skipped and the fallback frees the -// C++ buffer with `mi_free` directly. - -// ────────────────────────────────────────────────────────────────────────── -// A `Bindgen` adapter supplies associated `ZigType`/`ExternType` plus -// `convert_from_extern`. -// ────────────────────────────────────────────────────────────────────────── - -pub trait Bindgen { - type ZigType; - type ExternType; - - /// `true` when `ZigType` and `ExternType` are layout-identical. - /// Enables `BindgenArray`'s - /// allocation-reuse fast path. Defaults to `false`; override per adapter. - const SAME_REPR: bool = false; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType; -} - -pub struct BindgenTrivial(PhantomData); - -impl Bindgen for BindgenTrivial { - type ZigType = T; - type ExternType = T; - const SAME_REPR: bool = true; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - extern_value - } -} - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenStrongAny; - -impl Bindgen for BindgenStrongAny { - type ZigType = Strong; - // `?*jsc.Strong.Impl` — must be single-word for #[repr(C)] union placement, so - // `Option>` (niche-optimized), NOT `Option<*mut T>` (two words). - type ExternType = Option>; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - // SAFETY: bindgen contract — C++ passes a freshly-allocated Strong handle - // whose ownership is transferred to Rust here. - unsafe { Strong::adopt(extern_value.expect("non-null")) } - } -} - -// ────────────────────────────────────────────────────────────────────────── - -/// This represents both `IDLNull` and `IDLMonostateUndefined`. -pub struct BindgenNull; - -impl Bindgen for BindgenNull { - type ZigType = (); - type ExternType = u8; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - let _ = extern_value; - } -} - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenOptional(PhantomData); - -// Wrap in `ExternTaggedUnion<(u8, Child::ExternType)>` and produce -// `Option`. -impl Bindgen for BindgenOptional { - type ZigType = Option; - type ExternType = ExternTaggedUnion2; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - if extern_value.tag == 0 { - return None; - } - debug_assert_eq!(extern_value.tag, 1); - // SAFETY: tag == 1 means the `_1` arm of the union is initialized. - Some(Child::convert_from_extern(unsafe { - ManuallyDrop::into_inner(extern_value.data._1) - })) - } -} - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenString; - -impl Bindgen for BindgenString { - type ZigType = WTFString; - // `?bun.string.WTFStringImpl` — `Option>` for single-word FFI layout. - type ExternType = Option>; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - // SAFETY: bindgen contract — C++ passes a `StringImpl*` with one ref already - // taken for us; `adopt` consumes that ref. - unsafe { WTFString::adopt(extern_value.expect("non-null").as_ptr()) } - } -} - -// ────────────────────────────────────────────────────────────────────────── -// BindgenUnion / ExternTaggedUnion / ExternUnion -// -// These are generated per arity (or by a proc-macro from the bindgen codegen). -// ────────────────────────────────────────────────────────────────────────── - -// The bindgen TS codegen emits a concrete `enum` + `#[repr(C)]` union pair -// per call site rather than a generic Rust combinator (see -// `src/jsc/generated.rs`). This marker type exists for documentation parity. - -/// `extern struct { data: ExternUnion(field_types), tag: u8 }` -/// -/// We provide fixed-arity instantiations; the 2-ary case is the only -/// one used directly in this file (by `BindgenOptional`). Higher arities are -/// emitted by codegen alongside their consumers. -#[repr(C)] -pub struct ExternTaggedUnion2 { - pub(crate) data: ExternUnion2, - pub(crate) tag: u8, -} - -/// Union fields are wrapped in `ManuallyDrop` so non-`Copy` payloads -/// (e.g. nested `ExternTaggedUnion2`, `ExternArrayList`) are permitted without -/// trait bounds. There is no auto-drop — the active arm must be dropped -/// explicitly by whoever knows the tag. -#[repr(C)] -pub union ExternUnion2 { - pub _0: ManuallyDrop, - pub(crate) _1: ManuallyDrop, -} - -// ────────────────────────────────────────────────────────────────────────── - -pub struct BindgenArray(PhantomData); - -impl Bindgen for BindgenArray { - type ZigType = bun_collections::ArrayListDefault; - type ExternType = ExternArrayList; - - fn convert_from_extern(extern_value: Self::ExternType) -> Self::ZigType { - let length = usize::try_from(extern_value.length).expect("int cast"); - let capacity = usize::try_from(extern_value.capacity).expect("int cast"); - - if extern_value.data.is_null() { - return Self::ZigType::init(); - } - let data = extern_value.data; - debug_assert!( - length <= capacity, - "length ({}) should not exceed capacity ({})", - length, - capacity, - ); - // SAFETY: C++ side guarantees `data` points to `capacity` elements with - // `length` initialized; allocation came from mimalloc (when `USE_MIMALLOC`). - let unmanaged: Vec = - unsafe { Vec::from_raw_parts(data, length, capacity) }; - - if !bun_alloc::USE_MIMALLOC { - // Don't reuse memory in this case; it would be freed by the wrong allocator. - } else if size_of::() == size_of::() - && align_of::() == align_of::() - // Rust has no stable type-equality test in generic context, so this - // fast-path is gated on the `const SAME_REPR: bool` opt-in: it only - // fires when the bindgen codegen has proven layout identity. - && Child::SAME_REPR - { - // The layouts are identical, so the Vec is returned as-is. - let (ptr, len, cap) = { - let mut v = ManuallyDrop::new(unmanaged); - (v.as_mut_ptr(), v.len(), v.capacity()) - }; - // SAFETY: `SAME_REPR` ⇒ same layout; `from_raw_parts` round-trip. - let reused: Vec = - unsafe { Vec::from_raw_parts(ptr.cast::(), len, cap) }; - return Self::ZigType::from_unmanaged(reused); - } else if size_of::() <= size_of::() - && align_of::() <= bun_alloc::mimalloc::MI_MAX_ALIGN_SIZE - { - // We can reuse the allocation, but we still need to convert the elements. - // - // Materializing a `&mut [u8]` over the full capacity would assert that - // every byte — including uninitialized tail elements and `ExternType` - // padding — is a valid `u8`, which is UB. Work entirely through raw - // `*mut u8` and `ptr::copy_nonoverlapping` instead; no reference to - // the storage is ever formed. - let mut v = ManuallyDrop::new(unmanaged); - let mut storage_ptr: *mut u8 = v.as_mut_ptr().cast::(); - let storage_len = v.capacity() * size_of::(); - - // Convert the elements. - for i in 0..length { - // Byte-wise copy: this is an in-place reinterpretation of - // overlapping element slots, so each element is copied out - // before conversion. - let mut old_elem = core::mem::MaybeUninit::::uninit(); - // SAFETY: source range lies within the mimalloc block and holds a - // valid (C++-initialized) `ExternType` for `i < length`. - unsafe { - core::ptr::copy_nonoverlapping( - storage_ptr.add(i * size_of::()), - old_elem.as_mut_ptr().cast::(), - size_of::(), - ); - } - // SAFETY: bytes for element `i` were just copied from initialized storage. - let new_elem = ManuallyDrop::new(Child::convert_from_extern(unsafe { - old_elem.assume_init() - })); - // SAFETY: dest range lies within the block; `size_of ZigType <= - // size_of ExternType` so slot `i` of the new layout never overruns - // slot `i` of the old layout (and never clobbers slot `i+1`). - unsafe { - core::ptr::copy_nonoverlapping( - (&raw const *new_elem).cast::(), - storage_ptr.add(i * size_of::()), - size_of::(), - ); - } - } - - let new_size_is_multiple = - size_of::() % size_of::() == 0; - let new_capacity = if new_size_is_multiple { - capacity * (size_of::() / size_of::()) - } else { - let new_capacity = storage_len / size_of::(); - let new_alloc_size = new_capacity * size_of::(); - if new_alloc_size != storage_len { - // Allocation isn't a multiple of `size_of::()`; we have to - // resize it. - // SAFETY: `storage_ptr` is the original mimalloc block (the - // `USE_MIMALLOC` guard above gates entry to this path); shrinking - // with `mi_realloc` preserves the prefix bytes. - storage_ptr = bun_core::handle_oom(unsafe { - bun_alloc::realloc_raw(storage_ptr, new_alloc_size) - }); - } - new_capacity - }; - - let items_ptr = storage_ptr.cast::(); - // SAFETY: `storage_ptr` is aligned to ≥ `MI_MAX_ALIGN_SIZE` ≥ - // `align_of::()`; the first `length` slots were just written - // with valid `ZigType` values; the block is mimalloc-owned and the - // global allocator is mimalloc (the `if !bun_alloc::USE_MIMALLOC` - // guard above gates entry to this path), so `Vec`'s eventual dealloc - // — even with `ZigType`'s layout — routes to `mi_free`, which - // ignores layout. - let new_unmanaged: Vec = - unsafe { Vec::from_raw_parts(items_ptr, length, new_capacity) }; - return Self::ZigType::from_unmanaged(new_unmanaged); - } - - // Fallback: allocate fresh, convert, free old. `data` was `mi_malloc`'d - // by the C++ side regardless of the Rust global allocator, so free it - // with `mi_free` directly instead of `Vec::drop`. - let mut result = bun_core::handle_oom(Self::ZigType::init_capacity(length)); - let mut unmanaged = ManuallyDrop::new(unmanaged); - for item in unmanaged.iter_mut() { - // SAFETY: each slot holds a C++-initialized `ExternType`; `ManuallyDrop` ensures it isn't read twice. - result.append_assume_capacity(Child::convert_from_extern(unsafe { - core::ptr::read(item) - })); - } - // SAFETY: `data` is the live `mi_malloc`'d block from `ExternVectorTraits::convertToExtern`. - unsafe { bun_alloc::mimalloc::mi_free(data.cast()) }; - result - } -} - -#[repr(C)] -pub struct ExternArrayList { - // Single-word nullable pointer. `Option<*mut T>` has no niche - // (two words) and would break the C ABI; use raw `*mut T` and check `.is_null()`. - pub(crate) data: *mut Child, - pub(crate) length: c_uint, - pub(crate) capacity: c_uint, -} diff --git a/src/jsc/bindings/webcore/JSErrorHandler.cpp b/src/jsc/bindings/webcore/JSErrorHandler.cpp deleted file mode 100644 index e7571a185aae..000000000000 --- a/src/jsc/bindings/webcore/JSErrorHandler.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * Copyright (C) 2013-2018 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSErrorHandler.h" - -// #include "Document.h" -#include "ErrorEvent.h" -#include "Event.h" -#include "JSDOMConvertNumbers.h" -#include "JSDOMConvertStrings.h" -#include "JSEvent.h" -#include -#include - -namespace WebCore { -using namespace JSC; - -inline JSErrorHandler::JSErrorHandler(JSObject& listener, JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) - : JSEventListener(&listener, &wrapper, isAttribute, CreatedFromMarkup::No, world) -{ -} - -Ref JSErrorHandler::create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) -{ - return adoptRef(*new JSErrorHandler(listener, wrapper, isAttribute, world)); -} - -JSErrorHandler::~JSErrorHandler() = default; - -void JSErrorHandler::handleEvent(ScriptExecutionContext& scriptExecutionContext, Event& event) -{ - if (!is(event)) - return JSEventListener::handleEvent(scriptExecutionContext, event); - - VM& vm = scriptExecutionContext.vm(); - JSLockHolder lock(vm); - - JSObject* jsFunction = this->ensureJSFunction(scriptExecutionContext); - if (!jsFunction) - return; - - auto* isolatedWorld = this->isolatedWorld(); - if (!isolatedWorld) [[unlikely]] - return; - - auto* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *isolatedWorld); - if (!globalObject) - return; - - auto callData = getCallData(jsFunction); - if (callData.type != CallData::Type::None) { - Ref protectedThis(*this); - - RefPtr savedEvent; - // auto* jsFunctionWindow = dynamicDowncast( jsFunction->globalObject()); - // if (jsFunctionWindow) { - // savedEvent = jsFunctionWindow->currentEvent(); - - // // window.event should not be set when the target is inside a shadow tree, as per the DOM specification. - // if (!event.currentTargetIsInShadowTree()) - // jsFunctionWindow->setCurrentEvent(&event); - // } - - auto& errorEvent = downcast(event); - - MarkedArgumentBuffer args; - args.append(toJS(*globalObject, errorEvent.message())); - args.append(toJS(*globalObject, errorEvent.filename())); - args.append(toJS(errorEvent.lineno())); - args.append(toJS(errorEvent.colno())); - args.append(errorEvent.error(*globalObject)); - ASSERT(!args.hasOverflowed()); - - // JSExecState::instrumentFunction(&scriptExecutionContext, callData); - - NakedPtr exception; - JSValue returnValue = JSC::profiledCall(globalObject, JSC::ProfilingReason::Other, jsFunction, callData, globalObject, args, exception); - - // InspectorInstrumentation::didCallFunction(&scriptExecutionContext); - - // if (jsFunctionWindow) - // jsFunctionWindow->setCurrentEvent(savedEvent.get()); - - if (exception) - reportException(globalObject, exception); - else { - if (returnValue.isTrue()) - event.preventDefault(); - } - } -} - -} // namespace WebCore diff --git a/src/jsc/bindings/webcore/JSErrorHandler.h b/src/jsc/bindings/webcore/JSErrorHandler.h deleted file mode 100644 index d32c55a86106..000000000000 --- a/src/jsc/bindings/webcore/JSErrorHandler.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * Copyright (C) 2017 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "JSEventListener.h" - -namespace WebCore { - -class JSErrorHandler final : public JSEventListener { -public: - static Ref create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); - virtual ~JSErrorHandler(); - -private: - JSErrorHandler(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); - void handleEvent(ScriptExecutionContext&, Event&) final; -}; - -} // namespace WebCore