Skip to content
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
d03c6a3
ci: instrument being able to run leaksanitizer
nektro Jul 17, 2025
e8e6558
put local dev behind a flag
nektro Jul 17, 2025
8d4cf9b
better name for arrays
nektro Jul 21, 2025
a895f90
Merge remote-tracking branch 'origin/main' into nektro-patch-42406
nektro Jul 21, 2025
7029aef
Merge branch 'main' into nektro-patch-42406
nektro Jul 23, 2025
fbed7c0
Merge remote-tracking branch 'origin/main' into nektro-patch-42406
nektro Sep 11, 2025
f3fa3eb
pass an empty file
nektro Sep 11, 2025
36feff7
temp: ci: disable non-asan platforms
nektro Sep 11, 2025
30ff5aa
add this to make the debugger behave better
nektro Sep 12, 2025
a9ebde2
fix test-require-symlink crash
nektro Sep 12, 2025
99c316e
pass node:buffer
nektro Sep 13, 2025
efbbfdc
new tests missing from the skip list
nektro Sep 13, 2025
3ee795b
pass more
nektro Sep 13, 2025
ad6a2ad
didnt mean to commit that
nektro Sep 13, 2025
ce755ab
node:crypto
nektro Sep 13, 2025
75d40ef
node:dns
nektro Sep 13, 2025
f7e2a43
node:dgram
nektro Sep 13, 2025
d22e139
node:child_process
nektro Sep 13, 2025
c771087
node:console
nektro Sep 13, 2025
6531fb2
node:events
nektro Sep 13, 2025
00d6c5b
node:fs
nektro Sep 13, 2025
171a6e0
node:stream
nektro Sep 14, 2025
8a5f5b1
node:timers
nektro Sep 14, 2025
7969fcf
node:tls
nektro Sep 14, 2025
7e89c83
node:util
nektro Sep 14, 2025
a620f52
node:v8
nektro Sep 14, 2025
c5ccf75
node:vm
nektro Sep 14, 2025
459d0c8
node:whatwg
nektro Sep 14, 2025
017fd84
node:zlib
nektro Sep 14, 2025
fc38487
node:readline
nektro Sep 15, 2025
4341c38
node:path
nektro Sep 15, 2025
5366a89
node:module
nektro Sep 15, 2025
2f1ce85
node:http
nektro Sep 15, 2025
e005bb9
node:http2
nektro Sep 15, 2025
62ce40a
sequential
nektro Sep 15, 2025
fade5b6
node:assert
nektro Sep 15, 2025
25d90a7
node:cluster
nektro Sep 16, 2025
2c81e85
tidy
nektro Sep 16, 2025
8bce714
parallel
nektro Sep 16, 2025
d1a2daf
Merge branch 'main' into nektro-patch-42406
nektro Sep 16, 2025
9485456
merge fix
nektro Sep 16, 2025
31e3b1d
fix jsc warning from asan
nektro Sep 16, 2025
c1c7583
try a different option, previous one killed ci stacktraces
nektro Sep 16, 2025
c87efbe
more
nektro Sep 16, 2025
1a63062
more
nektro Sep 16, 2025
c8c189b
more
nektro Sep 16, 2025
cdca5da
more
nektro Sep 17, 2025
168765a
more
nektro Sep 17, 2025
1f71f62
better group these
nektro Sep 17, 2025
6aa3b77
address ci
nektro Sep 17, 2025
5e24ffc
bring these back
nektro Sep 17, 2025
ea46225
Merge remote-tracking branch 'origin/main' into nektro-patch-42406
nektro Sep 17, 2025
6a71526
address ci
nektro Sep 17, 2025
7522659
more
nektro Sep 17, 2025
f3231f5
address ci
nektro Sep 17, 2025
4dd02bd
address ci
nektro Sep 17, 2025
ec46bea
address review
nektro Sep 18, 2025
a2f5f19
add a way to make sure it's working
nektro Sep 18, 2025
3b2b969
address review
nektro Sep 19, 2025
300f321
use OPENSSL_clear_free over OPENSSL_free
nektro Sep 19, 2025
4b881a4
make getThreadLocalDefault be default_allocator when asan is on
nektro Sep 19, 2025
220c02c
address ci
nektro Sep 19, 2025
fd3eefc
use raii
nektro Sep 19, 2025
23d61e6
Delete test/js/bun/test/parallel/test-bun-env.js
Jarred-Sumner Sep 19, 2025
6125c16
tidy
nektro Sep 19, 2025
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
11 changes: 10 additions & 1 deletion .vscode/launch.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions misctools/lldb/init.lldb
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ command script import -c bun_pretty_printer.py

command script delete btjs
command alias btjs p {printf("gathering btjs trace...\n");printf("%s\n", (char*)dumpBtjsTrace())}

# do not pass SIGHUP on to child process. it is often not the real error and the stop point will be nonsensical.
process handle -p false -s false -n true SIGHUP
65 changes: 52 additions & 13 deletions scripts/runner.node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ function getTestExpectations() {
return expectations;
}

const skipArray = (() => {
const skipsForExceptionValidation = (() => {
const path = join(cwd, "test/no-validate-exceptions.txt");
if (!existsSync(path)) {
return [];
Expand All @@ -309,13 +309,32 @@ const skipArray = (() => {
.filter(line => !line.startsWith("#") && line.length > 0);
})();

const skipsForLeaksan = (() => {
const path = join(cwd, "test/no-validate-leaksan.txt");
if (!existsSync(path)) {
return [];
}
return readFileSync(path, "utf-8")
.split("\n")
.filter(line => !line.startsWith("#") && line.length > 0);
})();
Comment on lines +312 to +320

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be easier if these lists were held in an importable .js file so the loader handles this for us.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if its okay with you i'd like to do this in a followup and convert both lists

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but good idea


Comment thread
nektro marked this conversation as resolved.
/**
* Returns whether we should validate exception checks running the given test
* @param {string} test
* @returns {boolean}
*/
const shouldValidateExceptions = test => {
return !(skipArray.includes(test) || skipArray.includes("test/" + test));
return !(skipsForExceptionValidation.includes(test) || skipsForExceptionValidation.includes("test/" + test));
};
Comment thread
nektro marked this conversation as resolved.

/**
* Returns whether we should validate exception checks running the given test
* @param {string} test
* @returns {boolean}
Comment thread
nektro marked this conversation as resolved.
*/
const shouldValidateLeakSan = test => {
return !(skipsForLeaksan.includes(test) || skipsForLeaksan.includes("test/" + test));
};

/**
Expand Down Expand Up @@ -400,7 +419,9 @@ async function runTests() {

const okResults = [];
const flakyResults = [];
const flakyResultsTitles = [];
const failedResults = [];
const failedResultsTitles = [];
const maxAttempts = 1 + (parseInt(options["retries"]) || 0);

const parallelism = options["parallel"] ? availableParallelism() : 1;
Expand Down Expand Up @@ -436,6 +457,7 @@ async function runTests() {
if (ok) {
if (failure) {
flakyResults.push(failure);
flakyResultsTitles.push(title);
} else {
okResults.push(result);
}
Expand All @@ -455,6 +477,7 @@ async function runTests() {
if (attempt >= maxAttempts || isAlwaysFailure(error)) {
flaky = false;
failedResults.push(failure);
failedResultsTitles.push(title);
break;
}
}
Expand Down Expand Up @@ -567,6 +590,12 @@ async function runTests() {
env.BUN_JSC_validateExceptionChecks = "1";
env.BUN_JSC_dumpSimulatedThrows = "1";
}
if ((basename(execPath).includes("asan") || !isCI) && shouldValidateLeakSan(testPath)) {
env.BUN_DESTRUCT_VM_ON_EXIT = "1";
env.ASAN_OPTIONS = "allow_user_segv_handler=1:disable_coredump=0:detect_leaks=1";
// prettier-ignore
env.LSAN_OPTIONS = `malloc_context_size=100:print_suppressions=0:suppressions=${process.cwd()}/test/leaksan.supp`;
}
Comment thread
nektro marked this conversation as resolved.
return runTest(title, async () => {
const { ok, error, stdout, crashes } = await spawnBun(execPath, {
cwd: cwd,
Expand Down Expand Up @@ -809,14 +838,14 @@ async function runTests() {

if (failedResults.length) {
console.log(`${getAnsi("red")}Failing Tests:${getAnsi("reset")}`);
for (const { testPath } of failedResults) {
for (const testPath of failedResultsTitles) {
console.log(`${getAnsi("red")}- ${testPath}${getAnsi("reset")}`);
}
}

if (flakyResults.length) {
console.log(`${getAnsi("yellow")}Flaky Tests:${getAnsi("reset")}`);
for (const { testPath } of flakyResults) {
for (const testPath of flakyResultsTitles) {
console.log(`${getAnsi("yellow")}- ${testPath}${getAnsi("reset")}`);
}
}
Expand Down Expand Up @@ -1094,7 +1123,7 @@ async function spawnBun(execPath, { args, cwd, timeout, env, stdout, stderr }) {
: { BUN_ENABLE_CRASH_REPORTING: "0" }),
};

if (basename(execPath).includes("asan")) {
if (basename(execPath).includes("asan") && bunEnv.ASAN_OPTIONS === undefined) {
bunEnv.ASAN_OPTIONS = "allow_user_segv_handler=1:disable_coredump=0";
}

Expand Down Expand Up @@ -1250,17 +1279,17 @@ async function spawnBun(execPath, { args, cwd, timeout, env, stdout, stderr }) {
*
* @param {string} execPath
* @param {string} testPath
* @param {object} [options]
* @param {string} [options.cwd]
* @param {string[]} [options.args]
* @param {object} [opts]
* @param {string} [opts.cwd]
* @param {string[]} [opts.args]
Comment thread
nektro marked this conversation as resolved.
* @returns {Promise<TestResult>}
*/
async function spawnBunTest(execPath, testPath, options = { cwd }) {
async function spawnBunTest(execPath, testPath, opts = { cwd }) {
const timeout = getTestTimeout(testPath);
const perTestTimeout = Math.ceil(timeout / 2);
const absPath = join(options["cwd"], testPath);
const absPath = join(opts["cwd"], testPath);
const isReallyTest = isTestStrict(testPath) || absPath.includes("vendor");
const args = options["args"] ?? [];
const args = opts["args"] ?? [];

const testArgs = ["test", ...args, `--timeout=${perTestTimeout}`];

Expand Down Expand Up @@ -1291,10 +1320,16 @@ async function spawnBunTest(execPath, testPath, options = { cwd }) {
env.BUN_JSC_validateExceptionChecks = "1";
env.BUN_JSC_dumpSimulatedThrows = "1";
}
if ((basename(execPath).includes("asan") || !isCI) && shouldValidateLeakSan(relative(cwd, absPath))) {
env.BUN_DESTRUCT_VM_ON_EXIT = "1";
env.ASAN_OPTIONS = "allow_user_segv_handler=1:disable_coredump=0:detect_leaks=1";
// prettier-ignore
env.LSAN_OPTIONS = `malloc_context_size=100:print_suppressions=0:suppressions=${process.cwd()}/test/leaksan.supp`;
}

const { ok, error, stdout, crashes } = await spawnBun(execPath, {
args: isReallyTest ? testArgs : [...args, absPath],
cwd: options["cwd"],
cwd: opts["cwd"],
timeout: isReallyTest ? timeout : 30_000,
env,
stdout: options.stdout,
Expand Down Expand Up @@ -1528,7 +1563,11 @@ function isNodeTest(path) {
return false;
}
const unixPath = path.replaceAll(sep, "/");
return unixPath.includes("js/node/test/parallel/") || unixPath.includes("js/node/test/sequential/");
return (
unixPath.includes("js/node/test/parallel/") ||
unixPath.includes("js/node/test/sequential/") ||
unixPath.includes("js/bun/test/parallel/")
);
}

/**
Expand Down
1 change: 1 addition & 0 deletions scripts/utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2808,6 +2808,7 @@ export function endGroup() {
} else {
console.groupEnd();
}
console.log();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Necessary?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes because when ASAN is tripped it doesnt print a trailing newline before exiting the program

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be serialized into a code comment so that the next person doesn't delete the seemingly extraneous console.log

}

export function printEnvironment() {
Expand Down
33 changes: 33 additions & 0 deletions src/allocators.zig
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ pub fn BSSList(comptime ValueType: type, comptime _count: anytype) type {
this.data[index] = item;
return &this.data[index];
}

pub fn deinit(this: *OverflowBlock) void {
if (this.prev) |p| p.deinit();
bun.default_allocator.destroy(this);
Comment thread
nektro marked this conversation as resolved.
}
};

const Self = @This();
Expand Down Expand Up @@ -264,6 +269,12 @@ pub fn BSSList(comptime ValueType: type, comptime _count: anytype) type {
return instance;
}

pub fn deinit(self: *Self) void {
self.head.deinit();
bun.default_allocator.destroy(instance);
loaded = false;
}

pub fn isOverflowing() bool {
return instance.used >= @as(u16, count);
}
Expand Down Expand Up @@ -350,6 +361,12 @@ pub fn BSSStringList(comptime _count: usize, comptime _item_length: usize) type
return instance;
}

pub fn deinit(self: *const Self) void {
_ = self;
bun.default_allocator.destroy(instance);
loaded = false;
}

pub inline fn isOverflowing() bool {
return instance.slice_buf_used >= @as(u16, count);
}
Expand Down Expand Up @@ -530,6 +547,12 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, comptime store_
return instance;
}

pub fn deinit(self: *Self) void {
self.index.deinit(self.allocator);
bun.default_allocator.destroy(instance);
loaded = false;
}

pub fn isOverflowing() bool {
return instance.backing_buf_used >= @as(u16, count);
}
Expand Down Expand Up @@ -653,6 +676,10 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, comptime store_
// }

}

pub fn values(self: *Self) []ValueType {
return (&self.backing_buf)[0..self.backing_buf_used];
}
};
if (!store_keys) {
return BSSMapType;
Expand Down Expand Up @@ -684,6 +711,12 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, comptime store_
return instance;
}

pub fn deinit(self: *Self) void {
self.map.deinit();
bun.default_allocator.destroy(instance);
instance_loaded = false;
}

pub fn isOverflowing() bool {
return instance.map.backing_buf_used >= count;
}
Expand Down
4 changes: 2 additions & 2 deletions src/bun.js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub const Run = struct {
vm.preload = ctx.preloads;
vm.argv = ctx.passthrough;
vm.arena = &run.arena;
vm.allocator = arena.allocator();
vm.allocator = vm.arena.allocator();

b.options.install = ctx.install;
b.resolver.opts.install = ctx.install;
Expand Down Expand Up @@ -185,7 +185,7 @@ pub const Run = struct {
vm.preload = ctx.preloads;
vm.argv = ctx.passthrough;
vm.arena = &run.arena;
vm.allocator = arena.allocator();
vm.allocator = vm.arena.allocator();

if (ctx.runtime_options.eval.script.len > 0) {
const script_source = try bun.default_allocator.create(logger.Source);
Expand Down
4 changes: 3 additions & 1 deletion src/bun.js/VirtualMachine.zig
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,10 @@ extern fn Zig__GlobalObject__destructOnExit(*JSGlobalObject) void;

pub fn globalExit(this: *VirtualMachine) noreturn {
if (this.shouldDestructMainThreadOnExit()) {
if (this.eventLoop().forever_timer) |t| t.deinit(true);
Zig__GlobalObject__destructOnExit(this.global);
this.transpiler.deinit();
this.gc_controller.deinit();
this.deinit();
}
bun.Global.exit(this.exit_handler.exit_code);
Expand Down Expand Up @@ -1915,7 +1918,6 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer
}
}

// TODO:
pub fn deinit(this: *VirtualMachine) void {
this.auto_killer.deinit();

Expand Down
6 changes: 3 additions & 3 deletions src/bun.js/api/BunObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1814,7 +1814,7 @@ pub const JSZstd = struct {
output = try allocator.realloc(output, compressed_size);
}

return jsc.JSValue.createBuffer(globalThis, output, bun.default_allocator);
return jsc.JSValue.createBuffer(globalThis, output);
}

pub fn decompressSync(globalThis: *JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
Expand Down Expand Up @@ -1849,7 +1849,7 @@ pub const JSZstd = struct {
// mimalloc doesn't care about the self-reported size of the slice.
output.len = actual_size;

return jsc.JSValue.createBuffer(globalThis, output, bun.default_allocator);
return jsc.JSValue.createBuffer(globalThis, output);
}

// --- Async versions ---
Expand Down Expand Up @@ -1951,7 +1951,7 @@ pub const JSZstd = struct {
}

const output_slice = this.output;
const buffer_value = jsc.JSValue.createBuffer(globalThis, output_slice, bun.default_allocator);
const buffer_value = jsc.JSValue.createBuffer(globalThis, output_slice);
this.output = &[_]u8{};
promise.resolve(globalThis, buffer_value);
}
Expand Down
2 changes: 1 addition & 1 deletion src/bun.js/api/FFIObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ pub fn toBuffer(
return jsc.JSValue.createBufferWithCtx(globalThis, slice, ctx, callback);
}

return jsc.JSValue.createBuffer(globalThis, slice, null);
return jsc.JSValue.createBuffer(globalThis, slice);
},
Comment thread
nektro marked this conversation as resolved.
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/bun.js/api/JSTranspiler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@ fn namedExportsToJS(global: *JSGlobalObject, named_exports: *JSAst.Ast.NamedExpo
});
var i: usize = 0;
while (named_exports_iter.next()) |entry| {
names[i] = bun.String.cloneUTF8(entry.key_ptr.*);
names[i] = bun.String.fromBytes(entry.key_ptr.*);
i += 1;
}
return bun.String.toJSArray(global, names);
Expand Down
4 changes: 2 additions & 2 deletions src/bun.js/api/bun/socket.zig
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ pub fn NewSocket(comptime ssl: bool) type {
};
}

pub fn getRemoteAddress(this: *This, globalThis: *jsc.JSGlobalObject) JSValue {
pub fn getRemoteAddress(this: *This, globalThis: *jsc.JSGlobalObject) bun.JSError!JSValue {
if (this.socket.isDetached()) {
return .js_undefined;
}
Expand All @@ -846,7 +846,7 @@ pub fn NewSocket(comptime ssl: bool) type {
};

const text = bun.fmt.formatIp(address, &text_buf) catch unreachable;
return ZigString.init(text).toJS(globalThis);
return bun.String.createUTF8ForJS(globalThis, text);
}

pub fn getRemotePort(this: *This, _: *jsc.JSGlobalObject) JSValue {
Expand Down
2 changes: 1 addition & 1 deletion src/bun.js/api/bun/socket/tls_socket_functions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ noinline fn getSSLException(globalThis: *jsc.JSGlobalObject, defaultMessage: []c
const message = output_buf[0..written];
zig_str = ZigString.init(bun.handleOom(std.fmt.allocPrint(bun.default_allocator, "OpenSSL {s}", .{message})));
var encoded_str = zig_str.withEncoding();
encoded_str.mark();
encoded_str.markGlobal();

// We shouldn't *need* to do this but it's not entirely clear.
BoringSSL.ERR_clear_error();
Expand Down
2 changes: 1 addition & 1 deletion src/bun.js/api/crypto/PBKDF2.zig
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub const Job = struct {

const output_slice = this.output;
assert(output_slice.len == @as(usize, @intCast(this.pbkdf2.length)));
const buffer_value = jsc.JSValue.createBuffer(globalThis, output_slice, bun.default_allocator);
const buffer_value = jsc.JSValue.createBuffer(globalThis, output_slice);
this.output = &[_]u8{};
promise.resolve(globalThis, buffer_value);
}
Expand Down
Loading