diff --git a/.vscode/launch.json b/.vscode/launch.json index bdeb6c497a..72be0b1e41 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,6 +25,9 @@ // "BUN_JSC_validateExceptionChecks": "1", // "BUN_JSC_dumpSimulatedThrows": "1", // "BUN_JSC_unexpectedExceptionStackTraceLimit": "20", + // "BUN_DESTRUCT_VM_ON_EXIT": "1", + // "ASAN_OPTIONS": "allow_user_segv_handler=1:disable_coredump=0:detect_leaks=1", + // "LSAN_OPTIONS": "malloc_context_size=100:print_suppressions=1:suppressions=${workspaceFolder}/test/leaksan.supp", }, "console": "internalConsole", "sourceMap": { @@ -57,11 +60,17 @@ "name": "bun run [file]", "program": "${workspaceFolder}/build/debug/bun-debug", "args": ["${file}"], - "cwd": "${fileDirname}", + "cwd": "${workspaceFolder}", "env": { "FORCE_COLOR": "0", "BUN_DEBUG_QUIET_LOGS": "1", "BUN_GARBAGE_COLLECTOR_LEVEL": "2", + // "BUN_JSC_validateExceptionChecks": "1", + // "BUN_JSC_dumpSimulatedThrows": "1", + // "BUN_JSC_unexpectedExceptionStackTraceLimit": "20", + // "BUN_DESTRUCT_VM_ON_EXIT": "1", + // "ASAN_OPTIONS": "allow_user_segv_handler=1:disable_coredump=0:detect_leaks=1", + // "LSAN_OPTIONS": "malloc_context_size=100:print_suppressions=1:suppressions=${workspaceFolder}/test/leaksan.supp", }, "console": "internalConsole", "sourceMap": { diff --git a/misctools/lldb/init.lldb b/misctools/lldb/init.lldb index 7a14334232..777696671f 100644 --- a/misctools/lldb/init.lldb +++ b/misctools/lldb/init.lldb @@ -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 diff --git a/scripts/runner.node.mjs b/scripts/runner.node.mjs index 9fbb19d7ce..74e451a55f 100755 --- a/scripts/runner.node.mjs +++ b/scripts/runner.node.mjs @@ -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 []; @@ -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); +})(); + /** * 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)); +}; + +/** + * Returns whether we should validate exception checks running the given test + * @param {string} test + * @returns {boolean} + */ +const shouldValidateLeakSan = test => { + return !(skipsForLeaksan.includes(test) || skipsForLeaksan.includes("test/" + test)); }; /** @@ -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; @@ -436,6 +457,7 @@ async function runTests() { if (ok) { if (failure) { flakyResults.push(failure); + flakyResultsTitles.push(title); } else { okResults.push(result); } @@ -455,6 +477,7 @@ async function runTests() { if (attempt >= maxAttempts || isAlwaysFailure(error)) { flaky = false; failedResults.push(failure); + failedResultsTitles.push(title); break; } } @@ -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`; + } return runTest(title, async () => { const { ok, error, stdout, crashes } = await spawnBun(execPath, { cwd: cwd, @@ -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")}`); } } @@ -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"; } @@ -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] * @returns {Promise} */ -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}`]; @@ -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, @@ -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/") + ); } /** diff --git a/scripts/utils.mjs b/scripts/utils.mjs index 3f7ea67757..7e8705673b 100755 --- a/scripts/utils.mjs +++ b/scripts/utils.mjs @@ -2808,6 +2808,7 @@ export function endGroup() { } else { console.groupEnd(); } + console.log(); } export function printEnvironment() { diff --git a/src/allocators.zig b/src/allocators.zig index ccc1d09ac6..a4d0992a75 100644 --- a/src/allocators.zig +++ b/src/allocators.zig @@ -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); + } }; const Self = @This(); @@ -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); } @@ -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); } @@ -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); } @@ -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; @@ -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; } diff --git a/src/allocators/MimallocArena.zig b/src/allocators/MimallocArena.zig index 0b6a646b86..59b81d9e4d 100644 --- a/src/allocators/MimallocArena.zig +++ b/src/allocators/MimallocArena.zig @@ -124,6 +124,7 @@ pub fn borrow(self: Self) Borrowed { /// It uses pthread_getspecific to do that. /// We can save those extra calls if we just do it once in here pub fn getThreadLocalDefault() std.mem.Allocator { + if (bun.Environment.enable_asan) return bun.default_allocator; return Borrowed.getDefault().allocator(); } diff --git a/src/bun.js.zig b/src/bun.js.zig index 337045915e..437c653c38 100644 --- a/src/bun.js.zig +++ b/src/bun.js.zig @@ -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; @@ -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); diff --git a/src/bun.js/VirtualMachine.zig b/src/bun.js/VirtualMachine.zig index 10591ec0e3..6f1637f0cd 100644 --- a/src/bun.js/VirtualMachine.zig +++ b/src/bun.js/VirtualMachine.zig @@ -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); @@ -1915,7 +1918,6 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer } } -// TODO: pub fn deinit(this: *VirtualMachine) void { this.auto_killer.deinit(); diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 2256d48a3d..006b0d72e7 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -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 { @@ -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 --- @@ -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); } diff --git a/src/bun.js/api/FFIObject.zig b/src/bun.js/api/FFIObject.zig index 0cdc3c54b8..b00bbf88cb 100644 --- a/src/bun.js/api/FFIObject.zig +++ b/src/bun.js/api/FFIObject.zig @@ -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); }, } } diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index bafedf0888..395daf0cda 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -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); diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 7d8b5bb6a5..9372b6c1d1 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -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; } @@ -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 { diff --git a/src/bun.js/api/bun/socket/tls_socket_functions.zig b/src/bun.js/api/bun/socket/tls_socket_functions.zig index b1ea070bdc..94e4f9d906 100644 --- a/src/bun.js/api/bun/socket/tls_socket_functions.zig +++ b/src/bun.js/api/bun/socket/tls_socket_functions.zig @@ -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(); diff --git a/src/bun.js/api/crypto/PBKDF2.zig b/src/bun.js/api/crypto/PBKDF2.zig index 8ef641bac1..3fed8e6042 100644 --- a/src/bun.js/api/crypto/PBKDF2.zig +++ b/src/bun.js/api/crypto/PBKDF2.zig @@ -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); } diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 22e5e90dc3..ec60a78a7b 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -546,8 +546,6 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d allocator: std.mem.Allocator, poll_ref: Async.KeepAlive = .{}, - cached_hostname: bun.String = bun.String.empty, - flags: packed struct(u3) { deinit_scheduled: bool = false, terminated: bool = false, @@ -1368,38 +1366,35 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d return url.toJSDOMURL(globalThis); } - pub fn getHostname(this: *ThisServer, globalThis: *JSGlobalObject) jsc.JSValue { + pub fn getHostname(this: *ThisServer, globalThis: *JSGlobalObject) !jsc.JSValue { switch (this.config.address) { .unix => return .js_undefined, - else => {}, + .tcp => {}, } - - if (this.cached_hostname.isEmpty()) { + { if (this.listener) |listener| { var buf: [1024]u8 = [_]u8{0} ** 1024; if (listener.socket().remoteAddress(buf[0..1024])) |addr| { if (addr.len > 0) { - this.cached_hostname = bun.String.cloneUTF8(addr); + return bun.String.createUTF8ForJS(globalThis, addr); } } } - - if (this.cached_hostname.isEmpty()) { + { switch (this.config.address) { .tcp => |tcp| { if (tcp.hostname) |hostname| { - this.cached_hostname = bun.String.cloneUTF8(bun.sliceTo(hostname, 0)); + return bun.String.createUTF8ForJS(globalThis, bun.sliceTo(hostname, 0)); } else { - this.cached_hostname = bun.String.createAtomASCII("localhost"); + return bun.String.static("localhost").toJS(globalThis); } }, - else => {}, + .unix => unreachable, } } } - - return this.cached_hostname.toJS(globalThis); + @panic("unreachable"); } pub fn getProtocol(this: *ThisServer, globalThis: *JSGlobalObject) jsc.JSValue { @@ -1593,7 +1588,6 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d // However, when the JS VM terminates, it hypothetically might not call stopListening this.notifyInspectorServerStopped(); - this.cached_hostname.deref(); this.all_closed_promise.deinit(); for (this.user_routes.items) |*user_route| { user_route.deinit(); diff --git a/src/bun.js/api/server/NodeHTTPResponse.zig b/src/bun.js/api/server/NodeHTTPResponse.zig index 8207977a07..bc322f087e 100644 --- a/src/bun.js/api/server/NodeHTTPResponse.zig +++ b/src/bun.js/api/server/NodeHTTPResponse.zig @@ -593,7 +593,7 @@ pub fn drainRequestBody(this: *NodeHTTPResponse, globalObject: *jsc.JSGlobalObje fn drainBufferedRequestBodyFromPause(this: *NodeHTTPResponse, globalObject: *jsc.JSGlobalObject) ?jsc.JSValue { if (this.buffered_request_body_data_during_pause.len > 0) { - const result = jsc.JSValue.createBuffer(globalObject, this.buffered_request_body_data_during_pause.slice(), bun.default_allocator); + const result = jsc.JSValue.createBuffer(globalObject, this.buffered_request_body_data_during_pause.slice()); this.buffered_request_body_data_during_pause = .{}; return result; } diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 5363987dab..36e596261d 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -72,7 +72,6 @@ #include #include #include -#include #else #include #include diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 9e399feffb..2ee12580ac 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -14,6 +14,7 @@ #include "DOMURL.h" #include "ZigGlobalObject.h" #include "IDLTypes.h" +#include "mimalloc.h" #include #include @@ -40,8 +41,6 @@ #include "wtf/text/StringImpl.h" #include "wtf/text/StringToIntegerConversion.h" -extern "C" void mi_free(void* ptr); - using namespace JSC; extern "C" BunString BunString__fromBytes(const char* bytes, size_t length); @@ -169,7 +168,11 @@ JSC::JSString* toJS(JSC::JSGlobalObject* globalObject, BunString bunString) return JSC::jsString(globalObject->vm(), Zig::toStringStatic(bunString.impl.zig)); } - return Zig::toJSStringGC(bunString.impl.zig, globalObject); + if (bunString.tag == BunStringTag::ZigString) { + return Zig::toJSStringGC(bunString.impl.zig, globalObject); + } + + UNREACHABLE(); } BunString toString(const char* bytes, size_t length) diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 10b8722e82..34a11d5f53 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -340,7 +340,6 @@ public: JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalObject* lexicalGlobalObject, char* ptr, size_t length, void* ctx, JSTypedArrayBytesDeallocator bytesDeallocator) { - JSC::JSUint8Array* uint8Array = nullptr; auto* globalObject = defaultGlobalObject(lexicalGlobalObject); @@ -348,9 +347,9 @@ JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalO auto scope = DECLARE_CATCH_SCOPE(lexicalGlobalObject->vm()); if (length > 0) [[likely]] { - auto buffer = ArrayBuffer::createFromBytes({ reinterpret_cast(ptr), length }, createSharedTask([ctx, bytesDeallocator](void* p) { - if (bytesDeallocator) - bytesDeallocator(p, ctx); + ASSERT(bytesDeallocator); + auto buffer = ArrayBuffer::createFromBytes({ reinterpret_cast(ptr), length }, createSharedTask([=](void* p) { + bytesDeallocator(p, ctx); })); uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(buffer), 0, length); diff --git a/src/bun.js/bindings/JSValue.zig b/src/bun.js/bindings/JSValue.zig index 4887d49f85..40a46b492a 100644 --- a/src/bun.js/bindings/JSValue.zig +++ b/src/bun.js/bindings/JSValue.zig @@ -553,14 +553,10 @@ pub const JSValue = enum(i64) { extern fn JSBuffer__bufferFromLength(*JSGlobalObject, i64) JSValue; /// Must come from globally-allocated memory if allocator is not null - pub fn createBuffer(globalObject: *JSGlobalObject, slice: []u8, allocator: ?std.mem.Allocator) JSValue { + pub fn createBuffer(globalObject: *JSGlobalObject, slice: []u8) JSValue { jsc.markBinding(@src()); @setRuntimeSafety(false); - if (allocator) |alloc| { - return JSBuffer__bufferFromPointerAndLengthAndDeinit(globalObject, slice.ptr, slice.len, alloc.ptr, jsc.array_buffer.MarkedArrayBuffer_deallocator); - } else { - return JSBuffer__bufferFromPointerAndLengthAndDeinit(globalObject, slice.ptr, slice.len, null, null); - } + return JSBuffer__bufferFromPointerAndLengthAndDeinit(globalObject, slice.ptr, slice.len, null, jsc.array_buffer.MarkedArrayBuffer_deallocator); } extern fn JSC__JSValue__createUninitializedUint8Array(globalObject: *JSGlobalObject, len: usize) JSValue; diff --git a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp index f97aa42103..bd52a53344 100644 --- a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp +++ b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp @@ -1,4 +1,3 @@ -#include "mimalloc.h" #include "root.h" #include "JavaScriptCore/JSDestructibleObject.h" diff --git a/src/bun.js/bindings/ZigSourceProvider.h b/src/bun.js/bindings/ZigSourceProvider.h index 40362880f7..2379c883c4 100644 --- a/src/bun.js/bindings/ZigSourceProvider.h +++ b/src/bun.js/bindings/ZigSourceProvider.h @@ -50,8 +50,7 @@ public: return m_cachedBytecode.copyRef(); }; - void updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode&, - CodeSpecializationKind kind, const UnlinkedFunctionCodeBlock* codeBlock); + void updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode&, CodeSpecializationKind kind, const UnlinkedFunctionCodeBlock* codeBlock); void cacheBytecode(const BytecodeCacheGenerator& generator); void commitCachedBytecode(); bool isBytecodeCacheEnabled() const; diff --git a/src/bun.js/bindings/ZigString.zig b/src/bun.js/bindings/ZigString.zig index 08af14b14a..f55da9cfdb 100644 --- a/src/bun.js/bindings/ZigString.zig +++ b/src/bun.js/bindings/ZigString.zig @@ -38,12 +38,12 @@ pub const ZigString = extern struct { pub fn dupeForJS(utf8: []const u8, allocator: std.mem.Allocator) !ZigString { if (try strings.toUTF16Alloc(allocator, utf8, false, false)) |utf16| { var out = ZigString.initUTF16(utf16); - out.mark(); + out.markGlobal(); out.markUTF16(); return out; } else { var out = ZigString.init(try allocator.dupe(u8, utf8)); - out.mark(); + out.markGlobal(); return out; } } @@ -174,7 +174,7 @@ pub const ZigString = extern struct { } if (this.isGloballyAllocated()) { - out.mark(); + out.markGlobal(); } return out; @@ -513,7 +513,7 @@ pub const ZigString = extern struct { var str = init(@as([*]const u8, @alignCast(@ptrCast(slice_.ptr)))[0..slice_.len]); str.markUTF16(); if (global) { - str.mark(); + str.markGlobal(); } return str; } @@ -522,7 +522,7 @@ pub const ZigString = extern struct { pub fn from16(slice_: [*]const u16, len: usize) ZigString { var str = init(@as([*]const u8, @ptrCast(slice_))[0..len]); str.markUTF16(); - str.mark(); + str.markGlobal(); str.assertGlobal(); return str; } @@ -577,8 +577,6 @@ pub const ZigString = extern struct { bun.default_allocator.free(this.slice()); } - pub const mark = markGlobal; - pub inline fn markGlobal(this: *ZigString) void { this._unsafe_ptr_do_not_use = @as([*]const u8, @ptrFromInt(@intFromPtr(this._unsafe_ptr_do_not_use) | (1 << 62))); } @@ -728,7 +726,6 @@ pub const ZigString = extern struct { } } - extern fn ZigString__toExternalValue(this: *const ZigString, global: *JSGlobalObject) JSValue; pub fn toExternalValue(this: *const ZigString, global: *JSGlobalObject) JSValue { this.assertGlobal(); if (this.len > String.max_length()) { @@ -736,7 +733,7 @@ pub const ZigString = extern struct { global.ERR(.STRING_TOO_LONG, "Cannot create a string longer than 2^32-1 characters", .{}).throw() catch {}; // TODO: propagate? return .zero; } - return ZigString__toExternalValue(this, global); + return bun.cpp.ZigString__toExternalValue(this, global); } extern fn ZigString__toExternalValueWithCallback( diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 872ad00329..d0c8b20614 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -3167,18 +3167,16 @@ JSC::EncodedJSValue ZigString__toExternalU16(const uint16_t* arg0, size_t len, J return JSC::JSValue::encode(JSC::jsString(global->vm(), WTFMove(ref))); } -// This must be a globally allocated string -JSC::EncodedJSValue ZigString__toExternalValue(const ZigString* arg0, JSC::JSGlobalObject* arg1) -{ +// This must be a globally allocated string +[[ZIG_EXPORT(nothrow)]] JSC::EncodedJSValue ZigString__toExternalValue(const ZigString* arg0, JSC::JSGlobalObject* arg1) +{ ZigString str = *arg0; if (str.len == 0) { return JSC::JSValue::encode(JSC::jsEmptyString(arg1->vm())); } - if (Zig::isTaggedUTF16Ptr(str.ptr)) { auto ref = String(ExternalStringImpl::create({ reinterpret_cast(Zig::untag(str.ptr)), str.len }, Zig::untagVoid(str.ptr), free_global_string)); - return JSC::JSValue::encode(JSC::jsString(arg1->vm(), WTFMove(ref))); } else { auto ref = String(ExternalStringImpl::create({ Zig::untag(str.ptr), str.len }, Zig::untagVoid(str.ptr), free_global_string)); @@ -4619,7 +4617,7 @@ public: if (openingParentheses > closingParentheses) openingParentheses = WTF::notFound; - if (closingParentheses == WTF::notFound || closingParentheses == WTF::notFound) { + if (openingParentheses == WTF::notFound || closingParentheses == WTF::notFound) { offset = stack.length(); return false; } @@ -4938,12 +4936,12 @@ static void fromErrorInstance(ZigException& except, JSC::JSGlobalObject* global, } if (except.stack.frames_len == 0 && getFromSourceURL) { - JSC::JSValue sourceURL = getNonObservable(vm, global, obj, vm.propertyNames->sourceURL); if (!scope.clearExceptionExceptTermination()) [[unlikely]] return; if (sourceURL) { if (sourceURL.isString()) { + except.stack.frames_ptr[0].source_url.deref(); except.stack.frames_ptr[0].source_url = Bun::toStringRef(global, sourceURL); if (!scope.clearExceptionExceptTermination()) [[unlikely]] return; @@ -4985,6 +4983,11 @@ static void fromErrorInstance(ZigException& except, JSC::JSGlobalObject* global, } { + for (int i = 1; i < except.stack.frames_len; i++) { + auto frame = except.stack.frames_ptr[i]; + frame.function_name.deref(); + frame.source_url.deref(); + } except.stack.frames_len = 1; PropertySlot slot = PropertySlot(obj, PropertySlot::InternalMethodType::VMInquiry, &vm); except.stack.frames_ptr[0].remapped = obj->getNonIndexPropertySlot(global, names.originalLinePublicName(), slot); @@ -5451,7 +5454,10 @@ void JSC__VM__reportExtraMemory(JSC::VM* arg0, size_t arg1) arg0->heap.deprecatedReportExtraMemory(arg1); } -void JSC__VM__deinit(JSC::VM* arg1, JSC::JSGlobalObject* globalObject) {} +void JSC__VM__deinit(JSC::VM* arg1, JSC::JSGlobalObject* globalObject) +{ +} + void JSC__VM__drainMicrotasks(JSC::VM* arg0) { arg0->drainMicrotasks(); diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index ed41b88338..5020140860 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -391,8 +391,8 @@ extern "C" size_t Bun__encoding__writeUTF16(const char16_t* ptr, size_t len, uns extern "C" size_t Bun__encoding__byteLengthLatin1AsUTF8(const unsigned char* ptr, size_t len); extern "C" size_t Bun__encoding__byteLengthUTF16AsUTF8(const char16_t* ptr, size_t len); -extern "C" int64_t Bun__encoding__constructFromLatin1(void*, const unsigned char* ptr, size_t len, Encoding encoding); -extern "C" int64_t Bun__encoding__constructFromUTF16(void*, const char16_t* ptr, size_t len, Encoding encoding); +extern "C" JSC::EncodedJSValue Bun__encoding__constructFromLatin1(void*, const unsigned char* ptr, size_t len, Encoding encoding); +extern "C" JSC::EncodedJSValue Bun__encoding__constructFromUTF16(void*, const char16_t* ptr, size_t len, Encoding encoding); extern "C" void Bun__EventLoop__runCallback1(JSC::JSGlobalObject* global, JSC::EncodedJSValue callback, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue arg1); extern "C" void Bun__EventLoop__runCallback2(JSC::JSGlobalObject* global, JSC::EncodedJSValue callback, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue arg1, JSC::EncodedJSValue arg2); diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h index 620d12efa5..ce1f0af703 100644 --- a/src/bun.js/bindings/helpers.h +++ b/src/bun.js/bindings/helpers.h @@ -91,8 +91,7 @@ static const WTF::String toString(ZigString str) return !isTaggedUTF16Ptr(str.ptr) ? WTF::String(WTF::ExternalStringImpl::create({ untag(str.ptr), str.len }, untagVoid(str.ptr), free_global_string)) - : WTF::String(WTF::ExternalStringImpl::create( - { reinterpret_cast(untag(str.ptr)), str.len }, untagVoid(str.ptr), free_global_string)); + : WTF::String(WTF::ExternalStringImpl::create({ reinterpret_cast(untag(str.ptr)), str.len }, untagVoid(str.ptr), free_global_string)); } // This will fail if the string is too long. Let's make it explicit instead of an ASSERT. diff --git a/src/bun.js/bindings/node/crypto/CryptoUtil.cpp b/src/bun.js/bindings/node/crypto/CryptoUtil.cpp index 3afe1b3fdc..2c8d73c0ee 100644 --- a/src/bun.js/bindings/node/crypto/CryptoUtil.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoUtil.cpp @@ -487,14 +487,9 @@ bool convertP1363ToDER(const ncrypto::Buffer& p1363Sig, // Encode the signature in DER format auto buf = asn1_sig.encode(); - if (buf.len < 0) { - return false; - } - - if (!derBuffer.tryAppend(std::span { buf.data, buf.len })) { - return false; - } - + if (buf.len < 0) return false; + auto bsource = ByteSource::allocated(buf); + if (!derBuffer.tryAppend(bsource.span())) return false; return true; } diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index 706b1a2025..516b7cba4f 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -147,13 +147,12 @@ static WTF::String sqliteString(const char* str) return res; } -static void sqlite_free_typed_array(void* ctx, void* buf) +static void sqlite_free_typed_array(void* buf, void* ctx) { sqlite3_free((void*)buf); } -static constexpr int DEFAULT_SQLITE_FLAGS - = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; +static constexpr int DEFAULT_SQLITE_FLAGS = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; static constexpr unsigned int DEFAULT_SQLITE_PREPARE_FLAGS = SQLITE_PREPARE_PERSISTENT; static constexpr int MAX_SQLITE_PREPARE_FLAG = SQLITE_PREPARE_PERSISTENT | SQLITE_PREPARE_NORMALIZE | SQLITE_PREPARE_NO_VTAB; @@ -1280,7 +1279,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementSerialize, (JSC::JSGlobalObject * lexical return {}; } - RELEASE_AND_RETURN(scope, JSBuffer__bufferFromPointerAndLengthAndDeinit(lexicalGlobalObject, reinterpret_cast(data), static_cast(length), data, sqlite_free_typed_array)); + RELEASE_AND_RETURN(scope, JSBuffer__bufferFromPointerAndLengthAndDeinit(lexicalGlobalObject, reinterpret_cast(data), static_cast(length), NULL, sqlite_free_typed_array)); } JSC_DEFINE_HOST_FUNCTION(jsSQLStatementLoadExtensionFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) diff --git a/src/bun.js/event_loop/GarbageCollectionController.zig b/src/bun.js/event_loop/GarbageCollectionController.zig index fc18a7ac67..7b2088f93b 100644 --- a/src/bun.js/event_loop/GarbageCollectionController.zig +++ b/src/bun.js/event_loop/GarbageCollectionController.zig @@ -58,6 +58,11 @@ pub fn init(this: *GarbageCollectionController, vm: *VirtualMachine) void { this.gc_repeating_timer.set(this, onGCRepeatingTimer, gc_timer_interval, gc_timer_interval); } +pub fn deinit(this: *GarbageCollectionController) void { + this.gc_timer.deinit(true); + this.gc_repeating_timer.deinit(true); +} + pub fn scheduleGCTimer(this: *GarbageCollectionController) void { this.gc_timer_state = .scheduled; this.gc_timer.set(this, onGCTimer, 16, 0); diff --git a/src/bun.js/jsc/array_buffer.zig b/src/bun.js/jsc/array_buffer.zig index c800d67015..87bd1f59ec 100644 --- a/src/bun.js/jsc/array_buffer.zig +++ b/src/bun.js/jsc/array_buffer.zig @@ -590,7 +590,7 @@ pub const MarkedArrayBuffer = struct { } pub fn toNodeBuffer(this: *const MarkedArrayBuffer, ctx: *jsc.JSGlobalObject) jsc.JSValue { - return jsc.JSValue.createBufferWithCtx(ctx, this.buffer.byteSlice(), this.buffer.ptr, MarkedArrayBuffer_deallocator); + return jsc.JSValue.createBuffer(ctx, this.buffer.byteSlice()); } pub fn toJS(this: *const MarkedArrayBuffer, globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index d06d3d108b..ffd20551e9 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -4128,16 +4128,12 @@ pub const NodeFS = struct { .path = prefix_buf[0 .. len + 6], } }; } - return .{ - .result = bun.handleOom(jsc.ZigString.dupeForJS(bun.sliceTo(req.path, 0), bun.default_allocator)), - }; + return .initResult(bun.handleOom(jsc.ZigString.dupeForJS(bun.sliceTo(req.path, 0), bun.default_allocator))); } const rc = c.mkdtemp(prefix_buf); if (rc) |ptr| { - return .{ - .result = bun.handleOom(jsc.ZigString.dupeForJS(bun.sliceTo(ptr, 0), bun.default_allocator)), - }; + return .initResult(bun.handleOom(jsc.ZigString.dupeForJS(bun.sliceTo(ptr, 0), bun.default_allocator))); } // c.getErrno(rc) returns SUCCESS if rc is -1 so we call std.c._errno() directly diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig index 30f5651660..6f98c9bc4a 100644 --- a/src/bun.js/web_worker.zig +++ b/src/bun.js/web_worker.zig @@ -609,10 +609,10 @@ pub fn exitAndDeinit(this: *WebWorker) noreturn { loop_.internal_loop_data.jsc_vm = null; } - bun.uws.onThreadExit(); this.deinit(); if (vm_to_deinit) |vm| { + vm.gc_controller.deinit(); vm.deinit(); // NOTE: deinit here isn't implemented, so freeing workers will leak the vm. } bun.deleteAllPoolsForThreadExit(); diff --git a/src/bun.js/webcore/Blob.zig b/src/bun.js/webcore/Blob.zig index 1bc3e99e9b..4b8242bb5c 100644 --- a/src/bun.js/webcore/Blob.zig +++ b/src/bun.js/webcore/Blob.zig @@ -4433,7 +4433,7 @@ pub const Internal = struct { return out.toJS(globalThis); } else { var str = ZigString.init(this.toOwnedSlice()); - str.mark(); + str.markGlobal(); return str.toExternalValue(globalThis); } } diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig index 8356089087..65f7874196 100644 --- a/src/bun.js/webcore/encoding.zig +++ b/src/bun.js/webcore/encoding.zig @@ -50,7 +50,7 @@ export fn Bun__encoding__constructFromLatin1(globalObject: *JSGlobalObject, inpu .base64 => constructFromU8(input, len, bun.default_allocator, .base64), else => unreachable, }; - return jsc.JSValue.createBuffer(globalObject, slice, globalObject.bunVM().allocator); + return jsc.JSValue.createBuffer(globalObject, slice); } export fn Bun__encoding__constructFromUTF16(globalObject: *JSGlobalObject, input: [*]const u16, len: usize, encoding: u8) JSValue { @@ -65,7 +65,7 @@ export fn Bun__encoding__constructFromUTF16(globalObject: *JSGlobalObject, input .latin1 => constructFromU16(input, len, bun.default_allocator, .latin1), else => unreachable, }; - return jsc.JSValue.createBuffer(globalObject, slice, globalObject.bunVM().allocator); + return jsc.JSValue.createBuffer(globalObject, slice); } // for SQL statement diff --git a/src/bun.zig b/src/bun.zig index c9db8f3c1f..8caaf664e9 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -23,6 +23,7 @@ pub const debug_allocator: std.mem.Allocator = if (Environment.isDebug or Enviro debug_allocator_data.allocator else default_allocator; + pub const debug_allocator_data = struct { comptime { if (!Environment.isDebug) @compileError("only available in debug"); diff --git a/src/cli/pack_command.zig b/src/cli/pack_command.zig index 383a5cd8e2..d8b2f139d4 100644 --- a/src/cli/pack_command.zig +++ b/src/cli/pack_command.zig @@ -2527,7 +2527,7 @@ pub const bindings = struct { sha512.final(&sha512_digest); var base64_buf: [std.base64.standard.Encoder.calcSize(sha.SHA512.digest)]u8 = undefined; const encode_count = bun.simdutf.base64.encode(&sha512_digest, &base64_buf, false); - const integrity_str = String.cloneUTF8(base64_buf[0..encode_count]); + const integrity_value = try String.createUTF8ForJS(global, base64_buf[0..encode_count]); const EntryInfo = struct { pathname: String, @@ -2658,7 +2658,7 @@ pub const bindings = struct { result.put(global, "entries", entries); result.put(global, "size", JSValue.jsNumber(tarball.len)); result.put(global, "shasum", shasum_str.toJS(global)); - result.put(global, "integrity", integrity_str.toJS(global)); + result.put(global, "integrity", integrity_value); return result; } diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index 0b5acf03aa..143ce73396 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -1735,12 +1735,11 @@ pub const TestCommand = struct { const summary = reporter.summary(); if (failed_to_find_any_tests or summary.didLabelFilterOutAllTests() or summary.fail > 0 or (coverage_options.enabled and coverage_options.fractions.failing and coverage_options.fail_on_low_coverage) or !write_snapshots_success) { - Global.exit(1); + vm.exit_handler.exit_code = 1; } else if (reporter.jest.unhandled_errors_between_tests > 0) { - Global.exit(reporter.jest.unhandled_errors_between_tests); - } else { - vm.runWithAPILock(jsc.VirtualMachine, vm, jsc.VirtualMachine.globalExit); + vm.exit_handler.exit_code = 1; } + vm.runWithAPILock(jsc.VirtualMachine, vm, jsc.VirtualMachine.globalExit); } fn runEventLoopForWatch(vm: *jsc.VirtualMachine) void { diff --git a/src/codegen/bundle-modules.ts b/src/codegen/bundle-modules.ts index 46a99d44ac..429b37c2b1 100644 --- a/src/codegen/bundle-modules.ts +++ b/src/codegen/bundle-modules.ts @@ -340,14 +340,13 @@ JSValue InternalModuleRegistry::createInternalModuleById(JSGlobalObject* globalO // JS internal modules ${moduleList .map((id, n) => { + const moduleName = idToPublicSpecifierOrEnumName(id); + const fileBase = JSON.stringify(id.replace(/\.[mc]?[tj]s$/, ".js")); + const urlString = "builtin://" + id.replace(/\.[mc]?[tj]s$/, "").replace(/[^a-zA-Z0-9]+/g, "/"); const inner = n >= nativeStartIndex ? `return generateNativeModule(globalObject, vm, generateNativeModule_${nativeModuleEnums[id]});` - : `INTERNAL_MODULE_REGISTRY_GENERATE(globalObject, vm, "${idToPublicSpecifierOrEnumName(id)}"_s, ${JSON.stringify( - id.replace(/\.[mc]?[tj]s$/, ".js"), - )}_s, InternalModuleRegistryConstants::${idToEnumName(id)}Code, "builtin://${id - .replace(/\.[mc]?[tj]s$/, "") - .replace(/[^a-zA-Z0-9]+/g, "/")}"_s);`; + : `INTERNAL_MODULE_REGISTRY_GENERATE(globalObject, vm, "${moduleName}"_s, ${fileBase}_s, InternalModuleRegistryConstants::${idToEnumName(id)}Code, "${urlString}"_s);`; return `case Field::${idToEnumName(id)}: { ${inner} }`; diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index 2cb7ae9993..101992c15d 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -718,7 +718,7 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${name}::construct(JSC::JSGlobalObj structure = InternalFunction::createSubclassStructure(globalObject, newTarget, functionGlobalObject->${className(typeName)}Structure()); RETURN_IF_EXCEPTION(scope, {}); } - + ` + (!obj.constructNeedsThis ? ` diff --git a/src/defines.zig b/src/defines.zig index b86b4842aa..9de1820517 100644 --- a/src/defines.zig +++ b/src/defines.zig @@ -329,6 +329,7 @@ pub const Define = struct { .data = value_define.*, }); + define.allocator.free(gpe.value_ptr.*); gpe.value_ptr.* = try list.toOwnedSlice(); } else { var list = try std.ArrayList(DotDefine).initCapacity(allocator, 1); @@ -399,6 +400,14 @@ pub const Define = struct { return define; } + + pub fn deinit(this: *Define) void { + var diter = this.dots.valueIterator(); + while (diter.next()) |key| this.allocator.free(key.*); + this.dots.clearAndFree(); + this.identifiers.clearAndFree(); + this.allocator.destroy(this); + } }; const string = []const u8; diff --git a/src/fs.zig b/src/fs.zig index 538f8db01b..6f6542b874 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -108,6 +108,11 @@ pub const FileSystem = struct { return &instance; } + pub fn deinit(this: *const FileSystem) void { + this.dirname_store.deinit(); + this.filename_store.deinit(); + } + pub const DirEntry = struct { pub const EntryMap = bun.StringHashMapUnmanaged(*Entry); pub const EntryStore = allocators.BSSList(Entry, Preallocate.Counts.files); diff --git a/src/http/websocket_client.zig b/src/http/websocket_client.zig index ce5321a24a..8db05a0b6c 100644 --- a/src/http/websocket_client.zig +++ b/src/http/websocket_client.zig @@ -260,7 +260,7 @@ pub fn NewWebSocketClient(comptime ssl: bool) type { var outstring = jsc.ZigString.Empty; if (utf16_bytes_) |utf16| { outstring = jsc.ZigString.from16Slice(utf16); - outstring.mark(); + outstring.markGlobal(); jsc.markBinding(@src()); out.didReceiveText(false, &outstring); } else { diff --git a/src/options.zig b/src/options.zig index fff5c21501..b7639e2d84 100644 --- a/src/options.zig +++ b/src/options.zig @@ -1899,6 +1899,10 @@ pub const BundleOptions = struct { this.defines_loaded = true; } + pub fn deinit(this: *const BundleOptions) void { + this.define.deinit(); + } + pub fn loader(this: *const BundleOptions, ext: string) Loader { return this.loaders.get(ext) orelse .file; } diff --git a/src/ptr/CowSlice.zig b/src/ptr/CowSlice.zig index c0ee935ee5..ce7627eed4 100644 --- a/src/ptr/CowSlice.zig +++ b/src/ptr/CowSlice.zig @@ -143,6 +143,7 @@ pub fn CowSliceZ(T: type, comptime sentinel: ?T) type { try str.intoOwned(allocator); } defer str.* = Self.empty; + defer if (cow_str_assertions and str.isOwned()) if (str.debug) |d| bun.destroy(d); return str.ptr[0..str.flags.len]; } diff --git a/src/resolver/dir_info.zig b/src/resolver/dir_info.zig index d59b2251bd..8c5e15ab2c 100644 --- a/src/resolver/dir_info.zig +++ b/src/resolver/dir_info.zig @@ -92,10 +92,22 @@ pub fn getEntriesConst(dirinfo: *const DirInfo) ?*const Fs.FileSystem.DirEntry { pub fn getParent(i: *const DirInfo) ?*DirInfo { return HashMap.instance.atIndex(i.parent); } + pub fn getEnclosingBrowserScope(i: *const DirInfo) ?*DirInfo { return HashMap.instance.atIndex(i.enclosing_browser_scope); } +pub fn deinit(i: *DirInfo) void { + if (i.package_json) |p| { + p.deinit(); + i.package_json = null; + } + if (i.tsconfig_json) |t| { + t.deinit(); + i.tsconfig_json = null; + } +} + // Goal: Really fast, low allocation directory map exploiting cache locality where we don't worry about lifetimes much. // 1. Don't store the keys or values of directories that don't exist // 2. Don't expect a provided key to exist after it's queried diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index d5510ad09b..e118f86f89 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -26,6 +26,7 @@ pub const PackageJSON = struct { }; pub const new = bun.TrivialNew(@This()); + pub const deinit = bun.TrivialDeinit(@This()); const node_modules_path = std.fs.path.sep_str ++ "node_modules" ++ std.fs.path.sep_str; diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 57c7474927..f202467625 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -586,6 +586,11 @@ pub const Resolver = struct { }; } + pub fn deinit(r: *ThisResolver) void { + for (r.dir_cache.values()) |*di| di.deinit(); + r.dir_cache.deinit(); + } + pub fn isExternalPattern(r: *ThisResolver, import_path: string) bool { if (r.opts.packages == .external and isPackagePath(import_path)) { return true; diff --git a/src/resolver/tsconfig_json.zig b/src/resolver/tsconfig_json.zig index 39ab047c78..596ace4211 100644 --- a/src/resolver/tsconfig_json.zig +++ b/src/resolver/tsconfig_json.zig @@ -11,7 +11,6 @@ const JSXFieldSet = FlagSet(options.JSX.Pragma); pub const TSConfigJSON = struct { pub const new = bun.TrivialNew(@This()); - pub const deinit = bun.TrivialDeinit(@This()); abs_path: string, @@ -492,6 +491,11 @@ pub const TSConfigJSON = struct { log.addRangeWarningFmt(source, r, allocator, "Non-relative path \"{s}\" is not allowed when \"baseUrl\" is not set (did you forget a leading \"./\"?)", .{text}) catch {}; return false; } + + pub fn deinit(this: *TSConfigJSON) void { + this.paths.deinit(); + bun.destroy(this); + } }; const string = []const u8; diff --git a/src/transpiler.zig b/src/transpiler.zig index cdc105969b..668ee1a978 100644 --- a/src/transpiler.zig +++ b/src/transpiler.zig @@ -437,6 +437,13 @@ pub const Transpiler = struct { }; } + pub fn deinit(this: *Transpiler) void { + this.options.deinit(); + this.log.deinit(); + this.resolver.deinit(); + this.fs.deinit(); + } + pub fn configureLinkerWithAutoJSX(transpiler: *Transpiler, auto_jsx: bool) void { transpiler.linker = Linker.init( transpiler.allocator, diff --git a/test/cli/install/bun-install-registry.test.ts b/test/cli/install/bun-install-registry.test.ts index 05b9823d86..b84b8c7260 100644 --- a/test/cli/install/bun-install-registry.test.ts +++ b/test/cli/install/bun-install-registry.test.ts @@ -26,8 +26,6 @@ import { } from "harness"; import { join, resolve } from "path"; const { parseLockfile } = install_test_helpers; -const { iniInternals } = require("bun:internal-for-testing"); -const { loadNpmrc } = iniInternals; expect.extend({ toBeValidBin, diff --git a/test/js/web/websocket/autobahn.test.ts b/test/js/web/websocket/autobahn.test.ts index bff979bdef..f5fb32b2c3 100644 --- a/test/js/web/websocket/autobahn.test.ts +++ b/test/js/web/websocket/autobahn.test.ts @@ -175,3 +175,4 @@ if (isDockerEnabled() && (await load())) { } else { it.todo("Autobahn WebSocket not detected"); } +// last test is 13.7.18 diff --git a/test/leaksan.supp b/test/leaksan.supp new file mode 100644 index 0000000000..d277476bfc --- /dev/null +++ b/test/leaksan.supp @@ -0,0 +1,110 @@ +leak:bunfig.Bunfig.parse__anon +leak:resolver.package_json.PackageJSON.parse__anon +leak:resolver.resolver.Resolver.parseTSConfig +leak:JSC::Identifier::fromString +leak:Zig__GlobalObject__create +leak:_objc_msgSend_uncached +leak:WTF::fastMalloc +leak:WTF::AutomaticThread::start +leak:Bun__transpileFile +leak:WTF::SymbolRegistry::symbolForKey +leak:js_printer.printAst__anon +leak:Bun__resolveSync +leak:JSC::moduleLoaderParseModule +leak:JSC::ScriptExecutable::newCodeBlockFor +leak:JSC::Parser>::parseFunctionExpression +leak:JSC::Parser>::parsePrimaryExpression +leak:JSC::Parser>::parseStatement +leak:JSCInitialize +leak:getaddrinfo_send_reply +leak:start_wqthread +leak:CRYPTO_set_thread_local +leak:BIO_new +leak:_tlv_get_addr +leak:Bun::generateModule +leak:Zig::ImportMetaObject::createFromSpecifier +leak:Zig::GlobalObject::moduleLoaderResolve +leak:JSModuleLoader__import +leak:dyld::ThreadLocalVariables +leak:JSC__JSModuleLoader__loadAndEvaluateModule +leak:uws_create_app +leak:lshpack_wrapper_decode +leak:lshpack_wrapper_init +leak:bun.js.ipc.onData2 +leak:bun.js.node.fs_events.InitLibrary +leak:bun.js.node.fs_events.FSEventsLoop._schedule +leak:Bun__Path__join +leak:Bun__Path__resolve +leak:Zig::GlobalObject::moduleLoaderImportModule +leak:bake.FrameworkRouter.JSFrameworkRouter.getFileIdForRouter +leak:ast.Macro.MacroContext.call +leak:bun.js.webcore.Blob.findOrCreateFileFromPath__anon +leak:BunString::toWTFString(BunString::ZeroCopyTag) +leak:bun.js.node.node_fs_binding.Bindings(.mkdtemp).runSync +leak:bun.js.ModuleLoader.fetchBuiltinModule +leak:boringssl.checkX509ServerIdentity +leak:cli.pack_command.bindings.jsReadTarball +leak:ZigString__toErrorInstance +leak:JSC::moduleLoaderModuleDeclarationInstantiation +leak:JSC::arrayProtoFuncSort +leak:bindgen_Fmt_jsFmtString +leak:bun.js.api.bun.dns.GetAddrInfoRequest.run +leak:deps.tcc.State.init__anon +leak:dynamic_library.DlDynLib.open +leak:Zig::ImportMetaObject::finishCreation +leak:uws_add_server_name_with_options +leak:bun.js.webcore.Body.Value.fromJS +leak:sys.Error.toSystemError +leak:bun.js.webcore.Blob.getNameString +leak:JSC::callIntlDateTimeFormat +leak:functionRunProfiler +leak:JSC::JSModuleLoader::evaluateNonVirtual +leak:patch.PatchFile.apply +leak:bun.js.ModuleLoader.RuntimeTranspilerStore.TranspilerJob.runFromJSThread +leak:bun.js.webcore.blob.Store.initS3WithReferencedCredentials +leak:s3.list_objects.S3ListObjectsV2Result.toJS +leak:bun.js.webcore.S3Client.S3Client.write +leak:s3.list_objects.getListObjectsOptionsFromJS +leak:bun.js.node.node_fs.NodeFS.realpathInner +leak:sys.Error.toShellSystemError +leak:lazyLoadSQLite +leak:JSC::intlAvailableLocales +leak:getaddrinfo +leak:bun.js.api.filesystem_router.FileSystemRouter.constructor +leak:JSC::intlSegmenterAvailableLocales +leak:URL__getHref +leak:bun.js.api.bun.dns.Resolver.globalLookupService +leak:jsHTTPParser_execute +leak:Resolver__nodeModulePathsJSValue +leak:URL__host +leak:bun.js.node.node_os.version +leak:bun.js.node.node_os.release +leak:JSC::stringProtoFuncReplaceUsingRegExp +leak:WebCore::parseTypeAndSubtype +leak:bun.js.node.util.parse_args.parseArgs +leak:JSC::IntlDateTimeFormat::initializeDateTimeFormat +leak:WebCore__DOMURL__fileSystemPath +leak:bun.js.node.node_fs_watcher.FSWatcher.Arguments.fromJS +leak:WebWorker__updatePtr +leak:bun.js.node.zlib.NativeZlib.Context.init +leak:sql.postgres.PostgresSQLStatement.structure +leak:sql.postgres.DataCell.parseArray__anon +leak:sql.postgres.protocol.FieldMessage.FieldMessage.init +leak:JSC::intlCollatorAvailableLocales +leak:Bun__canonicalizeIP +leak:dlopen +leak:Bun::evaluateCommonJSModuleOnce +leak:fse_run_loop +leak:Zig::NapiClass_ConstructorFunction +leak:bun.js.webcore.fetch.FetchTasklet.toResponse +leak:JSC::jsonProtoFuncStringify +leak:deps.lol-html.HTMLString.toString +leak:libarchive.libarchive-bindings.Archive.readNew +leak:Zig::SourceProvider::create + +leak:fromErrorInstance + +# JSC_TO_STRING_TAG_WITHOUT_TRANSITION +leak:TLSSocket__create +leak:WebCore::JSReadableStreamDefaultReaderPrototype::finishCreation +leak:WebCore::JSReadableStreamDefaultControllerPrototype::finishCreation diff --git a/test/no-validate-leaksan.txt b/test/no-validate-leaksan.txt new file mode 100644 index 0000000000..438c30d418 --- /dev/null +++ b/test/no-validate-leaksan.txt @@ -0,0 +1,388 @@ +# List of tests for which we do NOT enable LeakSanitizer when running in ASAN CI + +test/js/node/test/parallel/test-worker-abort-on-uncaught-exception.js +test/js/node/test/parallel/test-worker-arraybuffer-zerofill.js +test/js/node/test/parallel/test-worker-cjs-workerdata.js +test/js/node/test/parallel/test-worker-cleanexit-with-js.js +test/js/node/test/parallel/test-worker-cleanexit-with-moduleload.js +test/js/node/test/parallel/test-worker-console-listeners.js +test/js/node/test/parallel/test-worker-dns-terminate-during-query.js +test/js/node/test/parallel/test-worker-environmentdata.js +test/js/node/test/parallel/test-worker-esm-exit.js +test/js/node/test/parallel/test-worker-esm-missing-main.js +test/js/node/test/parallel/test-worker-esmodule.js +test/js/node/test/parallel/test-worker-event.js +test/js/node/test/parallel/test-worker-exit-event-error.js +test/js/node/test/parallel/test-worker-exit-from-uncaught-exception.js +test/js/node/test/parallel/test-worker-exit-heapsnapshot.js +test/js/node/test/parallel/test-worker-fs-stat-watcher.js +test/js/node/test/parallel/test-worker-heap-snapshot.js +test/js/node/test/parallel/test-worker-http2-generic-streams-terminate.js +test/js/node/test/parallel/test-worker-invalid-workerdata.js +test/js/node/test/parallel/test-worker-load-file-with-extension-other-than-js.js +test/js/node/test/parallel/test-worker-memory.js +test/js/node/test/parallel/test-worker-message-channel-sharedarraybuffer.js +test/js/node/test/parallel/test-worker-message-event.js +test/js/node/test/parallel/test-worker-message-port-constructor.js +test/js/node/test/parallel/test-worker-message-port-infinite-message-loop.js +test/js/node/test/parallel/test-worker-message-port-receive-message.js +test/js/node/test/parallel/test-worker-message-port-terminate-transfer-list.js +test/js/node/test/parallel/test-worker-message-port-transfer-duplicate.js +test/js/node/test/parallel/test-worker-message-port-transfer-terminate.js +test/js/node/test/parallel/test-worker-message-port-wasm-module.js +test/js/node/test/parallel/test-worker-message-port-wasm-threads.js +test/js/node/test/parallel/test-worker-mjs-workerdata.js +test/js/node/test/parallel/test-worker-nested-on-process-exit.js +test/js/node/test/parallel/test-worker-nested-uncaught.js +test/js/node/test/parallel/test-worker-no-sab.js +test/js/node/test/parallel/test-worker-non-fatal-uncaught-exception.js +test/js/node/test/parallel/test-worker-on-process-exit.js +test/js/node/test/parallel/test-worker-onmessage-not-a-function.js +test/js/node/test/parallel/test-worker-onmessage.js +test/js/node/test/parallel/test-worker-parent-port-ref.js +test/js/node/test/parallel/test-worker-process-argv.js +test/js/node/test/parallel/test-worker-ref-onexit.js +test/js/node/test/parallel/test-worker-ref.js +test/js/node/test/parallel/test-worker-relative-path-double-dot.js +test/js/node/test/parallel/test-worker-relative-path.js +test/js/node/test/parallel/test-worker-safe-getters.js +test/js/node/test/parallel/test-worker-sharedarraybuffer-from-worker-thread.js +test/js/node/test/parallel/test-worker-terminate-http2-respond-with-file.js +test/js/node/test/parallel/test-worker-terminate-nested.js +test/js/node/test/parallel/test-worker-terminate-null-handler.js +test/js/node/test/parallel/test-worker-terminate-timers.js +test/js/node/test/parallel/test-worker-type-check.js +test/js/node/test/parallel/test-worker-unref-from-message-during-exit.js +test/js/node/test/parallel/test-worker-workerdata-sharedarraybuffer.js +test/js/node/test/parallel/test-worker.js +test/js/node/test/parallel/test-worker.mjs +test/js/node/worker_threads/worker_destruction.test.ts +test/js/web/broadcastchannel/broadcast-channel.test.ts + + +# error exit root cause unclear +test/js/node/test/parallel/test-util-callbackify.js +test/js/node/test/sequential/test-child-process-execsync.js +test/js/node/test/parallel/test-child-process-exec-maxbuf.js +test/js/node/test/parallel/test-fs-readfile-eof.js +test/js/node/test/parallel/test-child-process-promisified.js +test/js/node/test/parallel/test-child-process-exec-encoding.js +test/js/node/test/parallel/test-child-process-execfile.js +test/bake/dev-and-prod.test.ts +test/bake/dev/bundle.test.ts +test/bake/dev/css.test.ts +test/bake/dev/esm.test.ts +test/bake/dev/hot.test.ts +test/bake/dev/react-spa.test.ts +test/bake/dev/sourcemap.test.ts +test/bake/dev/ssg-pages-router.test.ts +test/bundler/bundler_compile.test.ts +test/bundler/bundler_plugin.test.ts +test/bundler/transpiler/bun-pragma.test.ts +test/bundler/transpiler/runtime-transpiler.test.ts +test/cli/hot/hot.test.ts +test/cli/install/bun-add.test.ts +test/cli/install/bun-create.test.ts +test/cli/install/bun-install-lifecycle-scripts.test.ts +test/cli/install/bun-install-patch.test.ts +test/cli/install/bun-install-proxy.test.ts +test/cli/install/bun-install-registry.test.ts +test/cli/install/bun-install-retry.test.ts +test/cli/install/bun-install.test.ts +test/cli/install/bun-lock.test.ts +test/cli/install/bun-lockb.test.ts +test/cli/install/bun-patch.test.ts +test/cli/install/bun-pm.test.ts +test/cli/install/bun-repl.test.ts +test/cli/install/bun-update.test.ts +test/cli/install/bun-workspaces.test.ts +test/cli/install/bunx.test.ts +test/cli/install/isolated-install.test.ts +test/cli/install/migration/complex-workspace.test.ts +test/cli/install/npmrc.test.ts +test/cli/install/overrides.test.ts +test/cli/install/test-dev-peer-dependency-priority.test.ts +test/cli/run/commonjs-invalid.test.ts +test/cli/run/preload-test.test.js +test/cli/run/require-cache.test.ts +test/cli/update_interactive_formatting.test.ts +test/integration/esbuild/esbuild.test.ts +test/integration/expo-app/expo.test.ts +test/integration/next-pages/test/dev-server-ssr-100.test.ts +test/integration/next-pages/test/dev-server.test.ts +test/integration/next-pages/test/next-build.test.ts +test/integration/vite-build/vite-build.test.ts +test/js/bun/css/css-fuzz.test.ts +test/js/bun/ffi/cc.test.ts +test/js/bun/http/bun-serve-html-manifest.test.ts +test/js/bun/http/bun-server.test.ts +test/js/bun/import-attributes/import-attributes.test.ts +test/js/bun/resolve/import-custom-condition.test.ts +test/js/bun/s3/s3.leak.test.ts +test/js/bun/shell/bunshell.test.ts +test/js/bun/shell/commands/ls.test.ts +test/js/bun/shell/leak.test.ts +test/js/bun/shell/lex.test.ts +test/js/bun/spawn/spawn-stdin-destroy.test.ts +test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts +test/js/bun/test/test-only.test.ts +test/js/node/http/node-http-maxHeaderSize.test.ts +test/js/node/http/node-http.test.ts +test/js/node/http2/node-http2.test.js +test/js/node/no-addons.test.ts +test/js/node/readline/readline_never_unrefs.test.ts +test/js/third_party/@napi-rs/canvas/napi-rs-canvas.test.ts +test/js/third_party/next-auth/next-auth.test.ts +test/js/third_party/pnpm/pnpm.test.ts +test/js/web/console/console-log.test.ts +test/js/web/fetch/fetch-leak.test.ts +test/js/web/fetch/fetch.tls.test.ts +test/regression/issue/09559.test.ts +test/regression/issue/14477/14477.test.ts +test/js/node/process/stdin/stdin-fixtures.test.ts +test/cli/install/bun-run.test.ts +test/bake/dev/import-meta-inline.test.ts +test/integration/sharp/sharp.test.ts +test/cli/test/bun-test.test.ts + + +# crash for reasons not related to LSAN +test/js/node/test/parallel/test-fs-watch-recursive-watch-file.js +test/js/node/test/parallel/test-dgram-send-address-types.js +test/js/node/test/parallel/test-fs-watch.js +test/js/node/test/parallel/test-dgram-unref.js +test/js/node/test/parallel/test-fs-promises-watch.js +test/bake/dev/ecosystem.test.ts +test/bake/dev/html.test.ts +test/bake/dev/plugins.test.ts +test/bake/dev/stress.test.ts +test/bake/dev/vfile.test.ts +test/js/bun/http/serve.test.ts +test/js/bun/resolve/import-meta.test.js +test/js/node/worker_threads/worker_threads.test.ts +test/js/third_party/@duckdb/node-api/duckdb.test.ts +test/js/third_party/body-parser/express-bun-build-compile.test.ts +test/js/third_party/duckdb/duckdb-basic-usage.test.ts + + +# ASSERTION FAILED: m_normalWorld->hasOneRef() +test/js/node/test/parallel/test-unhandled-exception-with-worker-inuse.js +test/js/node/test/parallel/test-process-beforeexit-throw-exit.js +test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-1.js +test/js/node/test/parallel/test-crypto-prime.js +test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-4.js +test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-2.js +test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-3.js +test/js/third_party/@fastify/websocket/fastity-test-websocket.test.js +test/js/third_party/esbuild/esbuild-child_process.test.ts +test/js/third_party/pino/pino.test.js +test/js/third_party/socket.io/socket.io-close.test.ts +test/js/web/websocket/websocket-permessage-deflate-edge-cases.test.ts +test/js/web/websocket/websocket-permessage-deflate-simple.test.ts +test/js/web/websocket/websocket-upgrade.test.ts +test/js/web/workers/message-channel.test.ts +test/js/web/workers/worker_blob.test.ts +test/regression/issue/012040.test.ts +test/js/web/websocket/websocket-blob.test.ts +test/regression/issue/14338.test.ts +test/js/bun/util/heap-snapshot.test.ts +test/regression/issue/02499/02499.test.ts +test/js/node/test/parallel/test-http-server-stale-close.js + + +# Bun::JSNodeHTTPServerSocket::clearSocketData +test/js/node/test/parallel/test-http-server-keep-alive-max-requests-null.js +test/js/node/test/parallel/test-http-keep-alive-pipeline-max-requests.js +test/js/node/test/parallel/test-https-connecting-to-http.js +test/js/node/test/parallel/test-http-header-overflow.js +test/js/node/test/parallel/test-http-request-smuggling-content-length.js +test/js/node/test/parallel/test-http-server-keep-alive-defaults.js +test/js/node/test/parallel/test-http-socket-error-listeners.js +test/js/node/test/parallel/test-http-server-destroy-socket-on-client-error.js +test/js/node/test/parallel/test-http-dummy-characters-smuggling.js +test/js/node/test/parallel/test-http-missing-header-separator-lf.js +test/js/node/test/parallel/test-http-invalid-te.js +test/js/node/test/parallel/test-http-missing-header-separator-cr.js +test/js/node/test/parallel/test-http-server-reject-chunked-with-content-length.js +test/js/node/test/parallel/test-http-chunked-smuggling.js +test/js/node/test/parallel/test-http-double-content-length.js +test/js/node/test/parallel/test-http-blank-header.js +test/js/node/test/parallel/test-http-server-keepalive-req-gc.js + +# bun.assert(!this.hasPendingActivity() or jsc.VirtualMachine.get().isShuttingDown()); +# @call(bun.callmod_inline, Subprocess.finalize, .{thisValue}); +test/js/node/test/parallel/test-set-http-max-http-headers.js +test/js/node/test/parallel/test-child-process-windows-hide.js +test/cli/inspect/BunFrontendDevServer.test.ts +test/cli/inspect/HTTPServerAgent.test.ts +test/cli/inspect/inspect.test.ts +test/cli/install/bun-publish.test.ts +test/cli/install/catalogs.test.ts +test/cli/run/self-reference.test.ts +test/cli/watch/watch.test.ts +test/js/bun/console/console-iterator.test.ts +test/js/bun/http/async-iterator-stream.test.ts +test/js/bun/http/bun-serve-body-json-async.test.ts +test/js/bun/http/bun-serve-html.test.ts +test/js/bun/shell/env.positionals.test.ts +test/js/bun/spawn/bun-ipc-inherit.test.ts +test/js/bun/spawn/spawn-stdin-readable-stream-integration.test.ts +test/js/bun/spawn/spawn.ipc.node-bun.test.ts +test/js/bun/spawn/spawn.ipc.test.ts +test/js/bun/udp/dgram.test.ts +test/js/bun/websocket/websocket-server.test.ts +test/js/first_party/ws/ws.test.ts +test/js/node/child_process/child_process-node.test.js +test/js/node/child_process/child_process.test.ts +test/js/node/crypto/crypto.test.ts +test/js/node/dgram/node-dgram.test.js +test/js/node/process/process-args.test.js +test/js/node/tls/renegotiation.test.ts +test/js/third_party/astro/astro-post.test.js +test/js/third_party/grpc-js/test-tonic.test.ts +test/js/web/fetch/fetch.test.ts +test/js/web/timers/setImmediate.test.js +test/js/web/websocket/autobahn.test.ts +test/js/web/websocket/websocket-client.test.ts +test/regression/issue/04298/04298.test.ts +test/regression/issue/08095.test.ts +test/regression/issue/20144/20144.test.ts +test/regression/issue/update-interactive-formatting.test.ts +test/regression/issue/246-child_process_object_assign_compatibility.test.ts +test/cli/install/bun-pm-scan.test.ts +test/bake/dev/incremental-graph-edge-deletion.test.ts +test/cli/update_interactive_snapshots.test.ts +test/js/web/websocket/websocket-custom-headers.test.ts +test/js/third_party/body-parser/express-memory-leak.test.ts +test/js/bun/http/serve-body-leak.test.ts + +# Zig::SourceProvider::~SourceProvider() +test/bundler/bundler_bun.test.ts +test/bundler/bundler_cjs2esm.test.ts +test/bundler/bundler_edgecase.test.ts +test/bundler/bundler_jsx.test.ts +test/bundler/bundler_loader.test.ts +test/bundler/bundler_minify.test.ts +test/bundler/esbuild/dce.test.ts +test/bundler/esbuild/default.test.ts +test/bundler/esbuild/extra.test.ts +test/bundler/esbuild/loader.test.ts +test/bundler/esbuild/splitting.test.ts +test/bundler/html-import-manifest.test.ts +test/js/node/process/process-on.test.ts +test/js/node/v8/capture-stack-trace.test.js +vendor/elysia/test/aot/analysis.test.ts +vendor/elysia/test/aot/generation.test.ts +vendor/elysia/test/aot/has-transform.test.ts +vendor/elysia/test/aot/has-type.test.ts +vendor/elysia/test/aot/response.test.ts +vendor/elysia/test/cookie/response.test.ts +vendor/elysia/test/core/as.test.ts +vendor/elysia/test/core/config.test.ts +vendor/elysia/test/core/dynamic.test.ts +vendor/elysia/test/core/elysia.test.ts +vendor/elysia/test/core/handle-error.test.ts +vendor/elysia/test/core/modules.test.ts +vendor/elysia/test/core/mount.test.ts +vendor/elysia/test/core/native-static.test.ts +vendor/elysia/test/core/normalize.test.ts +vendor/elysia/test/core/redirect.test.ts +vendor/elysia/test/core/response.test.ts +vendor/elysia/test/core/scoped.test.ts +vendor/elysia/test/core/stop.test.ts +vendor/elysia/test/extends/decorators.test.ts +vendor/elysia/test/extends/error.test.ts +vendor/elysia/test/extends/models.test.ts +vendor/elysia/test/extends/store.test.ts +vendor/elysia/test/hoc/index.test.ts +vendor/elysia/test/lifecycle/after-handle.test.ts +vendor/elysia/test/lifecycle/before-handle.test.ts +vendor/elysia/test/lifecycle/derive.test.ts +vendor/elysia/test/lifecycle/error.test.ts +vendor/elysia/test/lifecycle/hook-types.test.ts +vendor/elysia/test/lifecycle/map-derive.test.ts +vendor/elysia/test/lifecycle/map-resolve.test.ts +vendor/elysia/test/lifecycle/map-response.test.ts +vendor/elysia/test/lifecycle/parser.test.ts +vendor/elysia/test/lifecycle/request.test.ts +vendor/elysia/test/lifecycle/resolve.test.ts +vendor/elysia/test/lifecycle/response.test.ts +vendor/elysia/test/lifecycle/transform.test.ts +vendor/elysia/test/macro/macro.test.ts +vendor/elysia/test/path/group.test.ts +vendor/elysia/test/path/guard.test.ts +vendor/elysia/test/path/path.test.ts +vendor/elysia/test/path/plugin.test.ts +vendor/elysia/test/plugins/affix.test.ts +vendor/elysia/test/plugins/checksum.test.ts +vendor/elysia/test/plugins/error-propagation.test.ts +vendor/elysia/test/production/index.test.ts +vendor/elysia/test/response/custom-response.test.ts +vendor/elysia/test/response/headers.test.ts +vendor/elysia/test/response/redirect.test.ts +vendor/elysia/test/response/static.test.ts +vendor/elysia/test/response/stream.test.ts +vendor/elysia/test/sucrose/query.test.ts +vendor/elysia/test/sucrose/sucrose.test.ts +vendor/elysia/test/tracer/aot.test.ts +vendor/elysia/test/tracer/detail.test.ts +vendor/elysia/test/tracer/timing.test.ts +vendor/elysia/test/tracer/trace.test.ts +vendor/elysia/test/type-system/array-string.test.ts +vendor/elysia/test/type-system/boolean-string.test.ts +vendor/elysia/test/type-system/coercion-number.test.ts +vendor/elysia/test/type-system/date.test.ts +vendor/elysia/test/type-system/object-string.test.ts +vendor/elysia/test/type-system/string-format.test.ts +vendor/elysia/test/type-system/union-enum.test.ts +vendor/elysia/test/units/deduplicate-checksum.test.ts +vendor/elysia/test/units/map-compact-response.test.ts +vendor/elysia/test/units/map-early-response.test.ts +vendor/elysia/test/units/map-response.test.ts +vendor/elysia/test/units/merge-deep.test.ts +vendor/elysia/test/units/replace-schema-type.test.ts +vendor/elysia/test/validator/body.test.ts +vendor/elysia/test/validator/header.test.ts +vendor/elysia/test/validator/params.test.ts +vendor/elysia/test/validator/query.test.ts +vendor/elysia/test/validator/response.test.ts +vendor/elysia/test/validator/validator.test.ts +vendor/elysia/test/ws/destructuring.test.ts +vendor/elysia/test/ws/message.test.ts + +# JSC::HandleSet::~HandleSet +# bun.js.rare_data.deinit +test/js/bun/resolve/resolve.test.ts +test/js/bun/s3/s3-storage-class.test.ts +test/js/bun/s3/s3.test.ts +test/js/bun/util/BunObject.test.ts +test/js/bun/util/fuzzy-wuzzy.test.ts +test/js/bun/util/inspect.test.js +test/js/node/util/node-inspect-tests/parallel/util-inspect.test.js +test/js/node/vm/vm.test.ts + +# JSC::BuiltinNames::~BuiltinNames +test/js/bun/shell/shell-hang.test.ts +test/js/bun/util/reportError.test.ts +test/js/node/fs/abort-signal-leak-read-write-file.test.ts +test/js/node/process/process.test.js +test/js/web/websocket/websocket.test.js +test/js/web/workers/worker.test.ts +test/regression/issue/11664.test.ts + +# ASSERTION FAILED: m_cellState == CellState::DefinitelyWhite +test/js/node/tls/node-tls-upgrade.test.ts + +# Bun::NapiExternal::~NapiExternal +test/v8/v8.test.ts +test/napi/node-napi-tests/test/js-native-api/test_general/do.test.ts +test/napi/node-napi-tests/test/js-native-api/6_object_wrap/do.test.ts + +test/bake/dev/production.test.ts +test/js/third_party/pg-gateway/pglite.test.ts + +test/js/web/websocket/websocket-subprotocol-strict.test.ts +test/js/node/net/node-net-server.test.ts +test/js/third_party/grpc-js/test-channel-credentials.test.ts +test/js/bun/http/bun-connect-x509.test.ts +test/js/third_party/rollup-v4/rollup-v4.test.ts