Added 'await using sql = new SQL(options)' to all tests that were missing SQL instance creation:
- Escapes, null for int, Helpers in Transaction, Undefined values throws, Null sets to null
- Result is array, Create table, Drop table, null, Unsigned Integer, Signed Integer
- Double, String, MediumInt/Int24, Boolean/TinyInt/BIT, Date, Timestamp, JSON
- bulk insert nested sql()
This fixes ReferenceError: sql is not defined errors that occurred after removing the global SQL instance.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace direct Docker spawning with docker-compose services
- Use mysql_tls and mysql_plain services from docker-compose
- Fix options object to use lazy evaluation for container info
- Remove docker build step as mysql_tls is now built by docker-compose
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add missing PostgreSQL roles (bun_sql_test_md5, bun_sql_test_scram) to init script
- Fix MySQL image configuration to handle building mysql_tls service
- Remove --quiet-pull flag to show Docker pull progress
- Add CI preparation script to pre-pull and build images
- Add helper methods for image management (pullImages, buildServices, prepareImages)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove 2s sleep from S3 test - not needed with proper health checks
- Add health check to MinIO service in docker-compose.yml
- MinIO now uses 'mc ready local' to verify service readiness
- Docker compose --wait handles the waiting automatically
- Remove custom Docker container management (startContainer, waitForPostgres, findRandomPort)
- Use docker-compose helper module for container lifecycle
- Switch from postgres_auth to postgres_plain for broader compatibility
- Add host parameter to all connection configurations
- Remove unused imports (exec, promisify, dockerCLI)
This eliminates ~60 lines of Docker management code and makes the tests
more reliable by using the centralized health-checked infrastructure.
This PR consolidates all Docker-based test services into a centralized docker-compose
setup, eliminating per-test container spawning that was causing CI flakiness and
increased costs.
## Problem
- Tests were spawning individual Docker containers for each test suite
- Container startup race conditions caused intermittent test failures
- Docker resource exhaustion ("all predefined address pools have been fully subnetted")
- Redundant container creation increased CI runtime and costs
- No proper health checking led to "Connection refused" errors
## Solution
Implemented a unified docker-compose infrastructure with:
- Centralized service definitions for all test databases and services
- Proper health checks that block until services are ready
- Dynamic port allocation (except Autobahn which requires fixed port 9002)
- Reusable containers across test runs
- Smart health check configuration (only runs during startup, not continuously)
## Changes
### New Docker Infrastructure (`test/docker/`)
- `docker-compose.yml`: Defines all test services with health checks
- `index.ts`: TypeScript helper for programmatic service management
- `config/`: Service configuration files (PostgreSQL auth, Autobahn config)
- `init-scripts/`: Database initialization scripts
- CI script for pre-pulling images to warm Docker cache
### Service Configurations
- **PostgreSQL** (3 variants): plain, TLS, auth
- Health check: `pg_isready -U postgres`
- Dynamic port mapping
- Initialization scripts for test databases and users
- **MySQL** (3 variants): plain, native_password, TLS
- Health check: `mysqladmin ping`
- MySQL 8.0 for native_password (8.4 removed --default-authentication-plugin)
- Fixed user creation issue in auth tests
- **Redis/Valkey** (2 variants): plain, unified (TLS + Unix socket)
- Dynamic port mapping
- Unix socket support for local connections
- **MinIO** (S3-compatible storage)
- Automatic bucket creation
- Dynamic port mapping for both API and console
- **Autobahn** (WebSocket compliance test suite)
- Fixed port 9002 (required due to Host header validation)
- FIXME added for future WebSocket Host header customization
### Test Harness Updates
- `describeWithContainer()` signature changed from `(port: number)` to `(container: { port: number; host: string })`
- Uses `beforeAll()` to ensure container readiness
- Integrates with docker-compose helper module
- Default project name: `bun-test-services`
### Health Check Strategy
- Health checks configured with `interval: 1h` to effectively disable after startup
- `docker compose up --wait` blocks until services are healthy
- `start_period` gives services time to initialize before health checks begin
- Eliminates unreliable `sleep()` calls
## Test Results
All tests passing with new infrastructure:
- PostgreSQL: 792 tests ✅
- MySQL: 184 tests ✅
- Redis/Valkey: 304 tests ✅
- MinIO/S3: 276 tests ✅
- **Total: 1,556 tests passing**
## Performance Improvements
- Container startup: ~5-7s (once per test run) vs ~3-5s per test suite
- Eliminated redundant container creation
- Reduced Docker network allocation pressure
- Tests run faster due to container reuse
## Migration Details
### PostgreSQL Tests
- All variants working (plain, TLS, auth)
- Proper user creation with different auth methods
- TLS certificates mounted correctly
### MySQL Tests
- Fixed "Operation CREATE USER failed" by adding DROP USER IF EXISTS
- Fixed permission issues (GRANT on correct database)
- Downgraded from MySQL 8.4 to 8.0 for native_password plugin support
### S3/MinIO Tests
- Replaced direct Docker spawning with docker-compose
- Automatic bucket creation via `mc` command in container
- 276 S3 tests passing without modifications
### Known Issues
- Autobahn WebSocket tests cause Bun crash (pre-existing bug: `ASSERTION FAILED: m_pendingActivityCount > 0`)
- This is a Bun runtime issue, not related to Docker infrastructure
## Benefits
✅ Eliminates CI flakiness from container startup races
✅ Reduces CI costs through container reuse
✅ Consistent test environment across all runs
✅ Proper service readiness detection
✅ Easier local development (services persist between runs)
✅ No more Docker subnet exhaustion
## Testing
```bash
# Run individual test suites
bun bd test test/js/sql/sql-mysql.test.ts
bun bd test test/js/sql/sql-postgres.test.ts
bun bd test test/js/bun/s3/s3.test.ts
# All services use the same project
docker compose -p bun-test-services ps
```
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
### What does this PR do?
Updating documentation for `bun create next-app` to be just as the
latest version of `create next-app`.
* App Router is no longer experimental
* TailwindCSS has been added
### How did you verify your code works?
I verified the changes by making sure the it's correct.
## Summary
- Removes unused function and class expression names when
`--minify-syntax` is enabled during bundling
- Adds `--keep-names` flag to preserve original names when minifying
- Matches esbuild's minification behavior
## Problem
When minifying with `--minify-syntax`, Bun was keeping function and
class expression names even when they were never referenced, resulting
in larger bundle sizes compared to esbuild.
**Before:**
```js
export var AB = function A() { };
// Bun output: var AB = function A() {};
// esbuild output: var AB = function() {};
```
## Solution
This PR adds logic to remove unused function and class expression names
during minification, matching esbuild's behavior. Names are only removed
when:
- `--minify-syntax` is enabled
- Bundling is enabled (not transform-only mode)
- The scope doesn't contain direct eval (which could reference the name
dynamically)
- The symbol's usage count is 0
Additionally, a `--keep-names` flag has been added to preserve original
names when desired (useful for debugging or runtime reflection).
## Testing
- Updated existing test in `bundler_minify.test.ts`
- All transpiler tests pass
- Manually verified output matches esbuild for various cases
## Examples
```bash
# Without --keep-names (names removed)
bun build --minify-syntax input.js
# var AB = function() {}
# With --keep-names (names preserved)
bun build --minify-syntax --keep-names input.js
# var AB = function A() {}
```
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
### What does this PR do?
The goal of this PR is to introduce PUB/SUB functionality to the
built-in Redis client. Based on the fact that the current Redis API does
not appear to have compatibility with `io-redis` or `redis-node`, I've
decided to do away with existing APIs and API compatibility with these
existing libraries.
I have decided to base my implementation on the [`redis-node` pub/sub
API](https://github.com/redis/node-redis/blob/master/docs/pub-sub.md).
### How did you verify your code works?
I've written a set of unit tests to hopefully catch the major use-cases
of this feature. They all appear to pass:
<img width="368" height="71" alt="image"
src="https://github.com/user-attachments/assets/36527386-c8fe-47f6-b69a-a11d4b614fa0"
/>
#### Future Improvements
I would have a lot more confidence in our Redis implementation if we
tested it with a test suite running over a network which emulates a high
network failure rate. There are large amounts of edge cases that are
worthwhile to grab, but I think we can roll that out in a future PR.
### Future Tasks
- [ ] Tests over flaky network
- [ ] Use the custom private members over `_<member>`.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Alistair Smith <hi@alistair.sh>
Fixes#6934Fixes#7390
This PR also adds a test case for checking matchers, including when they
should fail
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
This PR makes connection string parsing more sensible in Bun.SQL,
without breaking the default fallback of postgres
Added some tests checking for connection string precedence
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
## Summary
- Fixes#22481 where `Socket.write()` was throwing
"Stream._isArrayBufferView is not a function" when passed a Uint8Array
- The helper methods were being added to the wrong Stream export
- Now adds them directly to the Stream constructor in
`internal/streams/legacy.ts` where they're actually used
## Test plan
- Added regression test in `test/regression/issue/22481.test.ts`
- Test verifies that sockets can write Uint8Array, Buffer, and other
TypedArray views
- All tests pass with the fix
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
### What does this PR do?
Since `JSBundlerPlugin` did not inherit from `JSDestructibleObject`, it
did not call the destructor. This means it never called the destructor
on `BundlerPlugin`, which means it leaked the WTF::Vector of RegExp and
strings.
This adds a small `WriteBarrierList` abstraction that is a
`WriteBarrier` guarded by the owning `JSCell`'s `cellLock()` that has a
`visitChildren` function. This also removes two usages of `JSC::Strong`
on the `Zig::GlboalObject` and replaces them with the
`WriteBarrierList`.
### How did you verify your code works?
Added a test. The test did not previously fail. But it's still good to
have a test that checks the onLoad callbacks are finalized.
## Summary
Implements the `typeof undefined === 'u'` minification optimization from
esbuild in Bun's minifier, and fixes dead code elimination (DCE) for
typeof comparisons with string literals.
### Part 1: Minification Optimization
This optimization transforms:
- `typeof x === "undefined"` → `typeof x > "u"`
- `typeof x !== "undefined"` → `typeof x < "u"`
- `typeof x == "undefined"` → `typeof x > "u"`
- `typeof x != "undefined"` → `typeof x < "u"`
Also handles flipped operands (`"undefined" === typeof x`).
### Part 2: DCE Fix for Typeof Comparisons
Fixed dead code elimination to properly handle typeof comparisons with
strings (e.g., `typeof x <= 'u'`). These patterns can now be correctly
eliminated when they reference unbound identifiers that would throw
ReferenceErrors.
## Before/After
### Minification
Before:
```javascript
console.log(typeof x === "undefined");
```
After:
```javascript
console.log(typeof x > "u");
```
### Dead Code Elimination
Before (incorrectly kept):
```javascript
var REMOVE_1 = typeof x <= 'u' ? x : null;
```
After (correctly eliminated):
```javascript
// removed
```
## Implementation
### Minification
- Added `tryOptimizeTypeofUndefined` function in
`src/ast/visitBinaryExpression.zig`
- Handles all 4 equality operators and both operand orders
- Only optimizes when both sides match the expected pattern (typeof
expression + "undefined" string)
- Replaces "undefined" with "u" and changes operators to `>` (for
equality) or `<` (for inequality)
### DCE Improvements
- Extended `isSideEffectFreeUnboundIdentifierRef` in `src/ast/P.zig` to
handle comparison operators (`<`, `>`, `<=`, `>=`)
- Added comparison operators to `simplifyUnusedExpr` in
`src/ast/SideEffects.zig`
- Now correctly identifies when typeof comparisons guard against
undefined references
## Test Plan
✅ Added comprehensive test in `test/bundler/bundler_minify.test.ts` that
verifies:
- All 8 variations work correctly (4 operators × 2 operand orders)
- Cases that shouldn't be optimized are left unchanged
- Matches esbuild's behavior exactly using inline snapshots
✅ DCE test `dce/DCETypeOfCompareStringGuardCondition` now passes:
- Correctly eliminates dead code with typeof comparison patterns
- Maintains compatibility with esbuild's DCE behavior
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
## Summary
Fixes#12548 - TypeScript syntax doesn't work in BunPlugin when using
`loader: 'ts'`
## The Problem
When creating a virtual module with `build.module()` and specifying
`loader: 'ts'`, TypeScript syntax like `import { type TSchema }` would
fail to parse with errors like:
```
error: Expected "}" but found "TSchema"
error: Expected "from" but found "}"
```
The same code worked fine when using `loader: 'tsx'`, indicating the
TypeScript parser wasn't being configured correctly for `.ts` files.
## Root Cause
The bug was caused by an enum value mismatch between C++ and Zig:
### Before (Incorrect)
- **C++ (`headers-handwritten.h`)**: `jsx=0, js=1, ts=2, tsx=3, ...`
- **Zig API (`api/schema.zig`)**: `jsx=1, js=2, ts=3, tsx=4, ...`
- **Zig Internal (`options.zig`)**: `jsx=0, js=1, ts=2, tsx=3, ...`
When a plugin returned `loader: 'ts'`, the C++ code correctly parsed the
string "ts" and set `BunLoaderTypeTS=2`. However, when this value was
passed to Zig's `Bun__transpileVirtualModule` function (which expects
`api.Loader`), the value `2` was interpreted as `api.Loader.js` instead
of `api.Loader.ts`, causing the TypeScript parser to not be enabled.
### Design Context
The codebase has two loader enum systems by design:
- **`api.Loader`**: External API interface used for C++/Zig
communication
- **`options.Loader`**: Internal representation used within Zig
The conversion between them happens via `options.Loader.fromAPI()` and
`.toAPI()` functions. The C++ layer should use `api.Loader` values since
that's what the interface functions expect.
## The Fix
1. **Aligned enum values**: Updated the `BunLoaderType` constants in
`headers-handwritten.h` to match the values in `api/schema.zig`,
ensuring C++ and Zig agree on the enum values
2. **Removed unnecessary assertion**: Removed the assertion that
`plugin_runner` must be non-null for virtual modules, as it's not
actually required for modules created via `build.module()`
3. **Added regression test**: Created comprehensive test in
`test/regression/issue/12548.test.ts` that verifies TypeScript syntax
works correctly with the `'ts'` loader
## Testing
### New Tests Pass
- ✅ `test/regression/issue/12548.test.ts` - 2 tests verifying TypeScript
type imports work with `'ts'` loader
### Existing Tests Still Pass
- ✅ `test/js/bun/plugin/plugins.test.ts` - 28 pass
- ✅ `test/bundler/bundler_plugin.test.ts` - 52 pass
- ✅ `test/bundler/bundler_loader.test.ts` - 27 pass
- ✅ `test/bundler/esbuild/loader.test.ts` - 10 pass
- ✅ `test/bundler/bundler_plugin_chain.test.ts` - 13 pass
### Manual Verification
```javascript
// This now works correctly with loader: 'ts'
Bun.plugin({
setup(build) {
build.module('hi', () => ({
contents: "import { type TSchema } from '@sinclair/typebox'",
loader: 'ts', // ✅ Works now (previously failed)
}))
},
})
```
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
- Fixed napi_strict_equals to use JavaScript === operator semantics
instead of Object.is()
- Added missing recv parameter validation in napi_call_function
- Fixed napi_create_array_with_length boundary handling to match Node.js
behavior
## Changes
### napi_strict_equals
- Changed from isSameValue (Object.is semantics) to isStrictEqual (===
semantics)
- Now correctly implements JavaScript strict equality: NaN !== NaN and
-0 === 0
- Added new JSC binding JSC__JSValue__isStrictEqual to support this
### napi_call_function
- Added NAPI_CHECK_ARG(env, recv) validation to match Node.js behavior
- Prevents crashes when recv parameter is null/undefined
### napi_create_array_with_length
- Fixed boundary value handling for negative and oversized lengths
- Now correctly clamps negative signed values to 0 (e.g., when size_t
0x80000000 becomes negative in i32)
- Matches Node.js V8 implementation which casts size_t to int then
clamps to min 0
## Test plan
- [x] Added comprehensive C++ tests in
test/napi/napi-app/standalone_tests.cpp
- [x] Added corresponding JavaScript tests in test/napi/napi.test.ts
- [x] Tests verify:
- Strict equality semantics (NaN, -0/0, normal values)
- Null recv parameter handling
- Array creation with boundary values (negative, oversized, edge cases)
🤖 Generated with [Claude Code](https://claude.ai/code)
### What does this PR do?
Replaces usages of `jsDoubleNumber` with `jsNumber` in places where the
value is likely to be either a double or strict int32. `jsNumber` will
decide to use `NumberTag` or `EncodeAsDouble`.
If the number is used in a lot of arithmetic this could boost
performance (related #18585).
### How did you verify your code works?
CI
## Summary
Fixes#22475
`cookie.isExpired()` was incorrectly returning `false` for cookies with
`Expires` set to Unix epoch (Thu, 01 Jan 1970 00:00:00 GMT).
## The Problem
The bug had two parts:
1. **In `Cookie::isExpired()`**: The condition `m_expires < 1`
incorrectly treated Unix epoch (0) as a session cookie instead of an
expired cookie.
2. **In `Cookie::parse()`**: When parsing date strings that evaluate to
0 (Unix epoch), the code used implicit boolean conversion which treated
0 as false, preventing the expires value from being set.
## The Fix
- Removed the `m_expires < 1` check from `isExpired()`, keeping only the
check for `emptyExpiresAtValue` to identify session cookies
- Fixed date parsing to use `std::isfinite()` instead of implicit
boolean conversion, properly handling Unix epoch (0)
## Test Plan
- Added regression test in `test/regression/issue/22475.test.ts`
covering Unix epoch and edge cases
- All existing cookie tests pass (`bun bd test test/js/bun/cookie/`)
- Manually tested the reported issue from #22475
```javascript
const cookies = [
'a=; Expires=Thu, 01 Jan 1970 00:00:00 GMT',
'b=; Expires=Thu, 01 Jan 1970 00:00:01 GMT'
];
for (const _cookie of cookies) {
const cookie = new Bun.Cookie(_cookie);
console.log(cookie.name, cookie.expires, cookie.isExpired());
}
```
Now correctly outputs:
```
a 1970-01-01T00:00:00.000Z true
b 1970-01-01T00:00:01.000Z true
```
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
The constructor was using `isUtf8` instead of `isAscii`.
Instead of this change maybe we should remove the constructors for
`isAscii` and `isUtf8`. It looks like we do this for most native
functions, but would be more breaking than correcting the current bug.
### How did you verify your code works?
Added a test
### What does this PR do?
Fix request body streaming in node-fetch wrapper.
### How did you verify your code works?
Added a test that previously failed
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
This PR implements the `--workspaces` flag for the `bun run` command,
allowing scripts to be run in all workspace packages as defined in the
`"workspaces"` field in package.json.
Fixes the infinite loop issue reported in
https://github.com/threepointone/bun-workspace-bug-repro
## Changes
- Added `--workspaces` flag to run scripts in all workspace packages
- Added `--if-present` flag to gracefully skip packages without the
script
- Root package is excluded when using `--workspaces` to prevent infinite
recursion
- Added comprehensive tests for the new functionality
## Usage
```bash
# Run "test" script in all workspace packages
bun run --workspaces test
# Skip packages that don't have the script
bun run --workspaces --if-present build
# Combine with filters
bun run --filter="@scope/*" test
```
## Behavior
The `--workspaces` flag must come **before** the script name (matching
npm's behavior):
- ✅ `bun run --workspaces test`
- ❌ `bun run test --workspaces` (treated as passthrough to script)
## Test Plan
- [x] Added test cases in `test/cli/run/workspaces.test.ts`
- [x] Verified fix for infinite loop issue in
https://github.com/threepointone/bun-workspace-bug-repro
- [x] Tested with `--if-present` flag
- [x] All tests pass locally
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
Fixes compatibility issue with Node.js libraries that use
`Object.assign(promise, childProcess)` pattern, specifically `tinyspawn`
(used by `youtube-dl-exec`).
## Problem
In Node.js, child process stdio properties (`stdin`, `stdout`, `stderr`,
`stdio`) are enumerable own properties that can be copied by
`Object.assign()`. In Bun, they were non-enumerable getters on the
prototype, causing `Object.assign()` to fail copying them.
This broke libraries like:
- `tinyspawn` - uses `Object.assign(promise, childProcess)` to merge
properties
- `youtube-dl-exec` - depends on tinyspawn internally
## Solution
Make stdio properties enumerable own properties during spawn while
preserving:
- ✅ Lazy initialization (streams created only when accessed)
- ✅ Original getter functionality and caching
- ✅ Performance (minimal overhead)
## Testing
- Added comprehensive regression tests
- Verified compatibility with `tinyspawn` and `youtube-dl-exec`
- Existing child_process tests still pass
## Related
- Fixes: https://github.com/microlinkhq/youtube-dl-exec/issues/246🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
This PR implements `perf_hooks.monitorEventLoopDelay()` for Node.js
compatibility, enabling monitoring of event loop delays and collection
of performance metrics via histograms.
Fixes#17650
## Implementation Details
### JavaScript Layer (`perf_hooks.ts`)
- Added `IntervalHistogram` class with:
- `enable()` / `disable()` methods with proper state tracking
- `reset()` method to clear histogram data
- Properties: `min`, `max`, `mean`, `stddev`, `exceeds`, `percentiles`
- `percentile(p)` method with validation
- Full input validation matching Node.js behavior (TypeError vs
RangeError)
### C++ Bindings (`JSNodePerformanceHooksHistogramPrototype.cpp`)
- `jsFunction_monitorEventLoopDelay` - Creates histogram for event loop
monitoring
- `jsFunction_enableEventLoopDelay` - Enables monitoring and starts
timer
- `jsFunction_disableEventLoopDelay` - Disables monitoring and stops
timer
- `JSNodePerformanceHooksHistogram_recordDelay` - Records delay
measurements
### Zig Implementation (`EventLoopDelayMonitor.zig`)
- Embedded `EventLoopTimer` that fires periodically based on resolution
- Tracks last fire time and calculates delay between expected vs actual
- Records delays > 0 to the histogram
- Integrates seamlessly with existing Timer system
## Testing
✅ All tests pass:
- Custom test suite with 8 comprehensive tests
- Adapted Node.js core test for full compatibility
- Tests cover enable/disable behavior, percentiles, error handling, and
delay recording
## Test plan
- [x] Run `bun test
test/js/node/perf_hooks/test-monitorEventLoopDelay.test.js`
- [x] Run adapted Node.js test
`test/js/node/test/sequential/test-performance-eventloopdelay-adapted.test.js`
- [x] Verify proper error handling for invalid arguments
- [x] Confirm delay measurements are recorded correctly
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
### What does this PR do?
update harness.ts
### How did you verify your code works?
CI
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>