Skip to content
Open
Show file tree
Hide file tree
Changes from 95 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
f8734c7
process: reject partial property descriptors on process.env
cirospaciari Jul 18, 2026
5c8028f
test: quarantine worker-terminate ASAN crashes, matching main
cirospaciari Jul 20, 2026
7ef097b
worker: hold an exception scope while populating process.env
cirospaciari Jul 20, 2026
19227b9
worker: validate execArgv against a real flag policy table (+2 tests)
cirospaciari Jul 22, 2026
608e06c
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 22, 2026
6c0412a
worker: allow Bun run-surface flags in execArgv and NODE_OPTIONS
cirospaciari Jul 22, 2026
4d05af1
ci: keep the binary size allowance on the stack tip [allow size]
cirospaciari Jul 22, 2026
a2c7d8d
Merge ciro/worker-threads-node-tests into claude/process-env-descript…
cirospaciari Jul 22, 2026
6a6c7d2
ci: keep the binary size allowance on the stack tip [allow size]
cirospaciari Jul 22, 2026
2fdb75a
worker: take the JSLock before installing globalThis.gc
cirospaciari Jul 22, 2026
54baff8
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 22, 2026
52f6889
worker: cover the full process.execArgv surface in the execArgv policy
cirospaciari Jul 22, 2026
7f26d4d
ci: rebuild [allow size]
cirospaciari Jul 23, 2026
0bd590d
worker: split glued short-flag values in execArgv like the CLI parser
cirospaciari Jul 23, 2026
b07212e
worker/env: chain short execArgv flags like the CLI parser; no phanto…
cirospaciari Jul 23, 2026
7ce8a68
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
5c7c5b3
worker: chain short flags in NODE_OPTIONS validation too
cirospaciari Jul 23, 2026
4698960
process.env: reject valueless data descriptors and symbol keys like n…
cirospaciari Jul 23, 2026
5798e87
process: normalize glued short flags when building process.execArgv
cirospaciari Jul 23, 2026
11bb858
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
e2ba2d4
process: scope execArgv short-flag normalization to the bun/node entr…
cirospaciari Jul 23, 2026
12b617a
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
31b3953
Delete flaky GC-observation node tests (#35182)
Jarred-Sumner Jul 22, 2026
c545cec
process: close the -br/run gaps in execArgv short-flag normalization
robobun Jul 24, 2026
f359442
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 24, 2026
5e87cc7
clippy: use ? now that push_normalized_short_token returns Option
robobun Jul 24, 2026
d1b410e
worker: share the process.execArgv token builder with the inherit-pat…
robobun Jul 24, 2026
ebcb030
worker: honor prev_takes_value before short-chain normalization; acce…
robobun Jul 24, 2026
6068f57
test: pin the -pe execArgv round-trip
cirospaciari Jul 24, 2026
b1010fb
process.env: stringify defineProperty values like node; isolate SHARE…
robobun Jul 24, 2026
490b699
process.env: coerce defined values to strings; fail preventExtensions…
cirospaciari Jul 24, 2026
f9ac6f4
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 24, 2026
7a8bf0c
worker: only One/Many flags consume the next argv token
cirospaciari Jul 24, 2026
12d92a7
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 24, 2026
4f1552f
windowsEnv: fix defineProperty bookkeeping for always-present accesso…
cirospaciari Jul 24, 2026
1fce00b
test: pin windowsEnv defineProperty bookkeeping for always-present ac…
robobun Jul 24, 2026
01d9f03
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 24, 2026
e8a82b8
test: drop stale bookkeeping for the GC-observation tests deleted by …
robobun Jul 24, 2026
cec7675
test: run the windowsEnv special-accessor defineProperty check in a p…
robobun Jul 24, 2026
f38b64b
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 24, 2026
409d44d
test: drop the orphaned comment block for the deleted tls memleak entry
robobun Jul 24, 2026
42233c1
Merge remote-tracking branch 'origin/ciro/worker-threads-node-tests' …
robobun Aug 3, 2026
d7b446a
worker: use AUTO_PARAMS directly in table_map after #36184 made the s…
robobun Aug 3, 2026
bdfa422
Worker.cpp: guard WebWorker__dispatchError/dispatchErrorWithValue aga…
robobun Aug 3, 2026
cb25e5d
web_worker: clear the pending TerminationException (not just the requ…
robobun Aug 3, 2026
9f100bf
trim comments to <=3 lines, cite spec/node source
robobun Aug 3, 2026
4da9c57
Revert the shutdown clear_termination_exception swap
robobun Aug 3, 2026
9c8c3a4
Merge remote-tracking branch 'origin/ciro/worker-threads-node-tests' …
robobun Aug 3, 2026
462ca19
Merge remote-tracking branch 'origin/ciro/worker-threads-node-tests' …
robobun Aug 3, 2026
e623e6c
Merge remote-tracking branch 'origin/ciro/worker-threads-node-tests' …
robobun Aug 4, 2026
af68afa
clippy: SAFETY comment for us_loop_idle_ns raw call from 388af0e9
robobun Aug 4, 2026
1ade7f3
Merge remote-tracking branch 'origin/ciro/worker-threads-node-tests' …
robobun Aug 4, 2026
21c5d62
Merge branch 'main' into claude/process-env-descriptor-validation
cirospaciari Aug 5, 2026
bd9ab18
Merge branch 'ciro/worker-threads-node-tests' into claude/process-env…
cirospaciari Aug 5, 2026
3bb4d69
Merge branch 'main' into claude/process-env-descriptor-validation
robobun Aug 7, 2026
e75f5ab
Merge branch 'ciro/worker-threads-node-tests' into claude/process-env…
cirospaciari Aug 7, 2026
451b70a
worker_exec_argv: route the = split through strings::index_of_char_usize
cirospaciari Aug 7, 2026
846e516
windows: wrap a worker's env snapshot in the windowsEnv proxy
robobun Aug 7, 2026
8ce6a4c
process.env: refuse preventExtensions on the main-thread map and the …
robobun Aug 7, 2026
dae59d4
retitle the Windows accessor test for the post-merge reject semantics…
robobun Aug 7, 2026
80485f4
Merge branch 'ciro/worker-threads-node-tests' into claude/process-env…
cirospaciari Aug 7, 2026
80f9d48
Merge branch 'ciro/worker-threads-node-tests' into claude/process-env…
cirospaciari Aug 7, 2026
945f6c3
env maps: align symbol-key handling across put/defineProperty and pla…
robobun Aug 7, 2026
c198cfe
Trim comments to node-source/spec references
robobun Aug 7, 2026
18dfe4a
Merge branch 'ciro/worker-threads-node-tests' into claude/process-env…
robobun Aug 7, 2026
bb2f2c4
NODE_OPTIONS: consume a required flag's next token unconditionally
robobun Aug 8, 2026
c52ec62
env: match node's Symbol conversion message on the regular map's put …
robobun Aug 8, 2026
bcf6f06
Merge remote-tracking branch 'origin/ciro/worker-threads-node-tests' …
robobun Aug 16, 2026
9797b85
worker: acknowledge the manufactured TerminationException; stop befor…
robobun Aug 16, 2026
29bfe3b
windows worker env: check and propagate like the POSIX arm instead of…
robobun Aug 16, 2026
c5e31ec
worker: tokenize compile-exec-argv with the same helper process.execA…
robobun Aug 16, 2026
9423635
Merge remote-tracking branch 'origin/ciro/worker-threads-node-tests' …
robobun Aug 16, 2026
df50bae
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 16, 2026
2fe062b
ci: retrigger
robobun Aug 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/bun-usockets/src/crypto/root_certs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ extern "C" void BUN__warn__extra_ca_load_failed(const char* filename, const char
// Forward declarations for platform-specific functions
// (Actual implementations are in platform-specific files)

// External variable from Zig CLI arguments
// External variables from the CLI arguments
extern "C" bool Bun__Node__UseSystemCA;
extern "C" bool Bun__Node__NoUseSystemCA;

// Helper function to check if system CA should be used
// Checks both CLI flag (--use-system-ca) and environment variable (NODE_USE_SYSTEM_CA=1)
static bool us_should_use_system_ca() {
// --no-use-system-ca is the one thing that overrides NODE_USE_SYSTEM_CA, so a
// flag whose purpose is to restrict trust actually restricts it.
if (Bun__Node__NoUseSystemCA) {
return false;
}
// Check CLI flag first
if (Bun__Node__UseSystemCA) {
return true;
Expand Down
16 changes: 16 additions & 0 deletions packages/bun-usockets/src/eventing/epoll_kqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,13 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout
}
}

/* Only ticks that really park are timed, so a busy loop pays nothing and a
* parked one pays two vDSO reads against a syscall it was making anyway.
* Publish the entry so a cross-thread reader can add the in-progress park. */
const uint64_t idle_start_ns = will_idle_inside_event_loop ? us_internal_monotonic_ns() : 0;
if (will_idle_inside_event_loop)
__atomic_store_n(&loop->data.idle_entry_ns, idle_start_ns, __ATOMIC_SEQ_CST);

/* Fetch ready polls */
#ifdef LIBUS_USE_EPOLL
/* A zero timespec already has a fast path in ep_poll (fs/eventpoll.c):
Expand All @@ -491,6 +498,15 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout
timeout);
#endif

if (will_idle_inside_event_loop) {
/* Clock read first so zero+add are adjacent seq_cst ops: a reader between them under-counts
* (bounded by one park) rather than double-counts. seq_cst — release would not order the add
* before the store on ARM. */
uint64_t now = us_internal_monotonic_ns();
__atomic_store_n(&loop->data.idle_entry_ns, 0, __ATOMIC_SEQ_CST);
__atomic_add_fetch(&loop->data.idle_ns, now - idle_start_ns, __ATOMIC_SEQ_CST);
}

/* Before anything can allocate again. */
if (handed_off)
mi_on_thread_idle_end();
Expand Down
4 changes: 4 additions & 0 deletions packages/bun-usockets/src/eventing/libuv.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ struct us_loop_t *us_create_loop(void *hint,

loop->uv_loop = hint ? hint : uv_loop_new();
loop->is_default = hint != 0;
/* Without this libuv never accumulates provider_idle_time, so
* uv_metrics_idle_time() — and performance.eventLoopUtilization() — read 0.
* node enables it unconditionally too (node.cc, node_worker.cc). */
uv_loop_configure(loop->uv_loop, UV_METRICS_IDLE_TIME);

loop->uv_pre = us_malloc(sizeof(uv_prepare_t));
uv_prepare_init(loop->uv_loop, loop->uv_pre);
Expand Down
3 changes: 3 additions & 0 deletions packages/bun-usockets/src/internal/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ uint64_t us_internal_monotonic_ns(void);
long long us_internal_sweep_timeout_ns(struct us_loop_t *loop);
void us_internal_sweep_if_due(struct us_loop_t *loop);
#endif
/* Nanoseconds this loop has spent parked, including a park in progress. Safe
* from another thread. Both platforms: Rust calls it ungated. */
uint64_t us_loop_idle_ns(struct us_loop_t *loop);
void us_internal_free_closed_sockets(us_loop_r loop);
void us_internal_loop_link_group(struct us_loop_t *loop, struct us_socket_group_t *group);
void us_internal_loop_unlink_group(struct us_loop_t *loop, struct us_socket_group_t *group);
Expand Down
9 changes: 9 additions & 0 deletions packages/bun-usockets/src/internal/loop_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ struct us_internal_loop_data_t {
* for lsquic's time-driven state. POSIX folds the deadline into the
* epoll_pwait2 timeout via getTimeout() instead. */
struct us_timer_t *quic_timer;
#endif
#ifndef LIBUS_USE_LIBUV
/* Nanoseconds parked, for eventLoopUtilization(). Read cross-thread —
* __atomic_* only. MIRRORED in src/uws_sys/InternalLoopData.rs: this struct
* is us_loop_t's first member, so a field here shifts num_polls. */
unsigned long long idle_ns;
/* Monotonic ns the current park began, 0 when not parked: a mid-park reader
* must add (now - entry) or it sees a stale total. So does libuv. */
unsigned long long idle_entry_ns;
#endif
struct us_socket_group_t *iterator;
char *recv_buf;
Expand Down
20 changes: 20 additions & 0 deletions packages/bun-usockets/src/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,26 @@ void us_internal_sweep_if_due(struct us_loop_t *loop) {
#endif


/* Nanoseconds this loop has spent parked, for performance.eventLoopUtilization().
* Safe to call from another thread. */
uint64_t us_loop_idle_ns(struct us_loop_t *loop) {
#ifdef LIBUS_USE_LIBUV
return uv_metrics_idle_time(loop->uv_loop);
#else
uint64_t idle = __atomic_load_n(&loop->data.idle_ns, __ATOMIC_SEQ_CST);
/* Parked right now? The total is only folded in when the park ends, so add
* the in-progress interval — otherwise a mid-park reader sees a stale idle
* and over-reports active. Same as libuv's uv_metrics_idle_time. */
uint64_t entry = __atomic_load_n(&loop->data.idle_entry_ns, __ATOMIC_SEQ_CST);
if (entry > 0) {
uint64_t now = us_internal_monotonic_ns();
if (now > entry)
idle += now - entry;
}
return idle;
#endif
}

void us_internal_loop_data_init(struct us_loop_t *loop, void (*wakeup_cb)(struct us_loop_t *loop),
void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop)) {
// We allocate with calloc, so we only need to initialize the specific fields in use.
Expand Down
1 change: 1 addition & 0 deletions src/clap/comptime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ impl<Id> ComptimeClap<Id> {
diagnostic: opt.diagnostic,
state: streaming::State::Normal,
positional: None,
short_aliases: opt.short_aliases,
};

while let Some(arg) = stream.next()? {
Expand Down
6 changes: 6 additions & 0 deletions src/clap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ impl Default for Help {
pub struct ParseOptions<'a> {
pub diagnostic: Option<&'a mut Diagnostic>,
pub stop_after_positional_at: usize,
/// Whole-token rewrites applied only where a token is being classified as a
/// flag, never to an option's value or a `--` target. Node keeps its own
/// aliases on exactly that branch (node_options-inl.h).
pub short_aliases: &'static [(&'static [u8], &'static [u8])],
}

// Help/usage/error rendering — none of this is on the cold-start hot chain
Expand Down Expand Up @@ -455,6 +459,7 @@ pub fn parse<Id: 'static>(
ParseOptions {
diagnostic: opt.diagnostic,
stop_after_positional_at: opt.stop_after_positional_at,
short_aliases: opt.short_aliases,
},
)?;
Ok(Args { clap })
Expand All @@ -474,6 +479,7 @@ pub fn parse_with_table<Id: 'static>(
ParseOptions {
diagnostic: opt.diagnostic,
stop_after_positional_at: opt.stop_after_positional_at,
short_aliases: opt.short_aliases,
},
)?;
Ok(Args { clap })
Expand Down
13 changes: 12 additions & 1 deletion src/clap/streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub struct StreamingClap<'p, 'a, Id, ArgIterator> {
pub(crate) state: State<'a>,
pub(crate) positional: Option<&'p clap::Param<Id>>,
pub(crate) diagnostic: Option<&'p mut clap::Diagnostic>,
pub(crate) short_aliases: &'static [(&'static [u8], &'static [u8])],
}

// ArgIterator is the
Expand Down Expand Up @@ -300,9 +301,17 @@ where
}

fn parse_next_arg(&mut self) -> Result<Option<ArgInfo<'a>>, ArgError> {
let Some(full_arg) = self.iter.next() else {
let Some(mut full_arg) = self.iter.next() else {
return Ok(None);
};
// Only tokens reaching here are being read as flags: option values and
// `--` targets are pulled straight off `iter`, so they stay verbatim.
for (from, to) in self.short_aliases {
if full_arg == *from {
full_arg = to;
break;
}
}
if full_arg == b"--" || full_arg == b"-" {
return Ok(Some(ArgInfo {
arg: full_arg,
Expand Down Expand Up @@ -354,6 +363,7 @@ mod tests {
remain: args_strings,
};
let mut c = StreamingClap::<u8, args::SliceIterator> {
short_aliases: &[],
params,
iter: &mut iter,
state: State::Normal,
Expand Down Expand Up @@ -386,6 +396,7 @@ mod tests {
remain: args_strings,
};
let mut c = StreamingClap::<u8, args::SliceIterator> {
short_aliases: &[],
params,
iter: &mut iter,
state: State::Normal,
Expand Down
1 change: 1 addition & 0 deletions src/install/PackageManager/CommandLineArguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,7 @@ Full documentation is available at <magenta>https://bun.com/docs/cli/pm#scan<r>.
clap::ParseOptions {
diagnostic: Some(&mut diag),
stop_after_positional_at: 0,
..Default::default()
},
) {
Ok(a) => {
Expand Down
22 changes: 18 additions & 4 deletions src/js/builtins/ProcessObjectInternals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,13 +528,27 @@ export function windowsEnv(
return typeof p !== "symbol" ? delete internalEnv[k] : false;
},
defineProperty(_, p, attributes) {
if (typeof p === "symbol") {
// JSProcessEnvMap rejects symbol keys (after descriptor validation),
// matching node; no bookkeeping applies.
return $Object.$defineProperty(internalEnv, p, attributes);
}
const k = String(p).toUpperCase();
$assert(typeof p === "string"); // proxy is only string and symbol. the symbol would have thrown by now
if (!(k in internalEnv) && !envMapList.includes(p)) {
// Same predicate as the set trap: `k in internalEnv` would be always-true
// for the DontEnum TZ/TLS/proxy CustomAccessors and drop them from ownKeys.
const isNewKey = !envMapList.includes(p) && !envMapList.some(x => x.toUpperCase() === k);
// Define before bookkeeping: JSProcessEnvMap may throw on a partial data
// descriptor, and a rejected define must not leave a phantom envMapList key.
const r = $Object.$defineProperty(internalEnv, k, attributes);
if (isNewKey) {
envMapList.push(p);
}
editWindowsEnvVar(k, internalEnv[k]);
return $Object.$defineProperty(internalEnv, k, attributes);
// String-coerce: the data path is coerced natively, but an accessor
// descriptor (deliberate divergence) installs a getter whose result
// reaches this read raw, and editWindowsEnvVar requires string|null.
const v = internalEnv[k];
editWindowsEnvVar(k, v == null ? null : String(v));
return r;
},
getOwnPropertyDescriptor(target, p) {
if (typeof p === "string") {
Expand Down
14 changes: 3 additions & 11 deletions src/js/internal/async_hooks_tick.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
// Bridge between node:async_hooks createHook() and the process.nextTick
// queue (builtins/ProcessObjectInternals.ts). Enabled `init` hooks are pushed
// into `tickInitHooks` so the nextTick hot path pays only an array-length
// check when no hook is enabled.
//
// The array identity must stay stable (push/splice only, never reassign):
// the nextTick closure captures it once at setup.
//
// Currently only TickObject `init` events are delivered (enough for
// console.log/stream.write tick-coalescing tests); promise, timer and native
// resource events are still unimplemented.
// Bridge between createHook() and process.nextTick: enabled `init` hooks live in `tickInitHooks` so the
// hot path pays only an array-length check. Array identity is stable (push/splice only) — nextTick captures it once.
// Only TickObject and WORKER `init` events are delivered; other resource types are unimplemented.
const tickInitHooks = [];
let nextAsyncId = 1;

Expand Down
27 changes: 27 additions & 0 deletions src/js/internal/perf/event_loop_utilization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Shared by perf_hooks and worker_threads; see https://github.com/nodejs/node/blob/main/lib/internal/perf/event_loop_utilization.js
// `elu` is [elapsedSinceLoopStartMs, idleMs] or null before the loop turns (node's `loopStart <= 0` branch → {0,0,0}).
// Divisions are unguarded: node returns NaN for a zero total, collapsing to 0 would diverge.
function internalEventLoopUtilization(elu, util1, util2) {
if (elu === null) {
return { idle: 0, active: 0, utilization: 0 };
}

if (util2) {
const idle = util1.idle - util2.idle;
const active = util1.active - util2.active;
return { idle, active, utilization: active / (idle + active) };
}

const idle = elu[1];
const active = elu[0] - idle;

if (!util1) {
return { idle, active, utilization: active / (idle + active) };
}

const idleDelta = idle - util1.idle;
const activeDelta = active - util1.active;
return { idle: idleDelta, active: activeDelta, utilization: activeDelta / (idleDelta + activeDelta) };
}

export default { internalEventLoopUtilization };
15 changes: 7 additions & 8 deletions src/js/node/async_hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,16 +495,14 @@ function createHook(hook) {
throw $ERR_ASYNC_CALLBACK("hook.promiseResolve");

let enabledInit;
return {
const asyncHook = {
enable() {
if (init !== undefined && enabledInit === undefined) {
// init is delivered for TickObject resources (process.nextTick);
// other resource types are still unimplemented.
// Per-instance wrapper: two hooks registered with the same init
// function must stay independently removable (removal is by
// identity, and removing the other instance's entry would reorder
// its callback relative to unrelated hooks).
enabledInit = (asyncId, type, triggerAsyncId, resource) => init(asyncId, type, triggerAsyncId, resource);
// Only TickObject and WORKER init are delivered. Per-instance wrapper so two hooks with the
// same init stay independently removable. node calls init as a method on the AsyncHook
// (https://github.com/nodejs/node/blob/main/lib/internal/async_hooks.js), so `this.disable()` works.
enabledInit = (asyncId, type, triggerAsyncId, resource) =>
init.$call(asyncHook, asyncId, type, triggerAsyncId, resource);
require("internal/async_hooks_tick").tickInitHooks.push(enabledInit);
}
if (before !== undefined || after !== undefined || destroy !== undefined || promiseResolve !== undefined) {
Expand All @@ -531,6 +529,7 @@ function createHook(hook) {
return this;
},
};
return asyncHook;
}

const executionAsyncIdNotImpl = createWarning(
Expand Down
13 changes: 7 additions & 6 deletions src/js/node/perf_hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,13 @@ function createPerformanceNodeTiming() {
return object;
}

function eventLoopUtilization(_utilization1, _utilization2) {
return {
idle: 0,
active: 0,
utilization: 0,
};
// [elapsedSinceLoopStartMs, idleMs] for this thread's loop, or null before it
// has turned.
const getLoopELU = $newRustFunction("bun.rs", "getLoopELU", 0);
const { internalEventLoopUtilization } = require("internal/perf/event_loop_utilization");

function eventLoopUtilization(utilization1, utilization2) {
return internalEventLoopUtilization(getLoopELU(), utilization1, utilization2);
}

const { PerformanceResourceTiming } = globalThis;
Expand Down
7 changes: 5 additions & 2 deletions src/js/node/tls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1683,8 +1683,11 @@ function cacheDefaultCACertificates() {
ArrayPrototypePush.$call(defaultCACertificates, bundled[i]);
}

// Include system certificates when --use-system-ca is set or NODE_USE_SYSTEM_CA=1
if (getUseSystemCA() || process.env.NODE_USE_SYSTEM_CA === "1") {
// --use-system-ca / --no-use-system-ca are per-thread and explicit; only when
// neither was given does NODE_USE_SYSTEM_CA decide. node lets the env var win
// under --use-bundled-ca but not under --no-use-system-ca.
const useSystemCA = getUseSystemCA();
if (useSystemCA === true || (useSystemCA === undefined && process.env.NODE_USE_SYSTEM_CA === "1")) {
const system = cacheSystemCACertificates();
for (let i = 0; i < system.length; ++i) {
ArrayPrototypePush.$call(defaultCACertificates, system[i]);
Expand Down
Loading