Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/bake/production.zig
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ pub fn buildWithVm(ctx: bun.cli.Command.Context, cwd: []const u8, vm: *VirtualMa
allocator,
.{ .js = vm.event_loop },
);
const bundled_outputs = bundled_outputs_list.items;
const bundled_outputs = bundled_outputs_list.items();
if (bundled_outputs.len == 0) {
Output.prettyln("done", .{});
Output.flush();
Expand Down
4 changes: 2 additions & 2 deletions src/bundler/bundle_v2.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,7 @@ pub const BundleV2 = struct {
bake_options: BakeOptions,
alloc: std.mem.Allocator,
event_loop: EventLoop,
) !std.ArrayList(options.OutputFile) {
) !bun.collections.ArrayListDefault(options.OutputFile) {
var this = try BundleV2.init(
server_transpiler,
bake_options,
Expand Down Expand Up @@ -1596,7 +1596,7 @@ pub const BundleV2 = struct {
);

if (chunks.len == 0) {
return std.ArrayList(options.OutputFile).init(bun.default_allocator);
return bun.collections.ArrayListDefault(options.OutputFile).init();
}

return try this.linker.generateChunksInParallel(chunks, false);
Expand Down
2 changes: 1 addition & 1 deletion src/bundler/linker_context/generateChunksInParallel.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub fn generateChunksInParallel(
c: *LinkerContext,
chunks: []Chunk,
comptime is_dev_server: bool,
) !if (is_dev_server) void else std.ArrayList(options.OutputFile) {
) !if (is_dev_server) void else bun.collections.ArrayListDefault(options.OutputFile) {
const trace = bun.perf.trace("Bundler.generateChunksInParallel");
defer trace.end();

Expand Down
8 changes: 4 additions & 4 deletions src/install/lockfile.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1257,17 +1257,17 @@ pub fn saveToDisk(this: *Lockfile, load_result: *const LoadResult, options: *con
break :bytes writer_buf.list.items;
}

var bytes = std.ArrayList(u8).init(bun.default_allocator);
var bytes = bun.collections.ArrayListDefault(u8).init();

var total_size: usize = 0;
var end_pos: usize = 0;
Lockfile.Serializer.save(this, options, &bytes, &total_size, &end_pos) catch |err| {
Output.err(err, "failed to serialize lockfile", .{});
Global.crash();
};
if (bytes.items.len >= end_pos)
bytes.items[end_pos..][0..@sizeOf(usize)].* = @bitCast(total_size);
break :bytes bytes.items;
if (bytes.items().len >= end_pos)
bytes.items()[end_pos..][0..@sizeOf(usize)].* = @bitCast(total_size);
break :bytes bytes.toOwnedSlice() catch bun.outOfMemory();
};
defer bun.default_allocator.free(bytes);

Expand Down
36 changes: 18 additions & 18 deletions src/io/PipeWriter.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ pub fn WindowsBufferedWriter(Parent: type, function_table: anytype) type {

/// Basic std.ArrayList(u8) + usize cursor wrapper
pub const StreamBuffer = struct {
list: std.ArrayList(u8) = std.ArrayList(u8).init(bun.default_allocator),
list: bun.collections.ArrayListDefault(u8) = bun.collections.ArrayListDefault(u8).init(),
cursor: usize = 0,

pub fn reset(this: *StreamBuffer) void {
Expand All @@ -1107,19 +1107,19 @@ pub const StreamBuffer = struct {
}

pub fn maybeShrink(this: *StreamBuffer) void {
if (this.list.capacity > std.heap.pageSize()) {
if (this.list.capacity() > std.heap.pageSize()) {
// workaround insane zig decision to make it undefined behavior to resize .len < .capacity
this.list.expandToCapacity();
this.list.expandToCapacity(undefined);
this.list.shrinkAndFree(std.heap.pageSize());
}
}

pub fn memoryCost(this: *const StreamBuffer) usize {
return this.list.capacity;
return this.list.capacity();
}

pub fn size(this: *const StreamBuffer) usize {
return this.list.items.len - this.cursor;
return this.list.items().len - this.cursor;
}

pub fn isEmpty(this: *const StreamBuffer) bool {
Expand Down Expand Up @@ -1152,7 +1152,7 @@ pub const StreamBuffer = struct {

pub fn writeTypeAsBytesAssumeCapacity(this: *StreamBuffer, comptime T: type, data: T) void {
var byte_list = bun.ByteList.moveFromList(&this.list);
defer this.list = byte_list.moveToListManaged(this.list.allocator);
defer this.list = byte_list.moveToListManaged(this.list.allocator());
byte_list.writeTypeAsBytesAssumeCapacity(T, data);
}

Expand All @@ -1164,20 +1164,20 @@ pub const StreamBuffer = struct {

{
var byte_list = bun.ByteList.moveFromList(&this.list);
defer this.list = byte_list.moveToListManaged(this.list.allocator);
_ = try byte_list.writeLatin1(this.list.allocator, buffer);
defer this.list = byte_list.moveToListManaged(this.list.allocator());
_ = try byte_list.writeLatin1(this.list.allocator(), buffer);
}

return this.list.items[this.cursor..];
return this.list.items()[this.cursor..];
} else if (comptime @TypeOf(writeFn) == @TypeOf(&writeUTF16) and writeFn == &writeUTF16) {
{
var byte_list = bun.ByteList.moveFromList(&this.list);
defer this.list = byte_list.moveToListManaged(this.list.allocator);
defer this.list = byte_list.moveToListManaged(this.list.allocator());

_ = try byte_list.writeUTF16(this.list.allocator, buffer);
_ = try byte_list.writeUTF16(this.list.allocator(), buffer);
}

return this.list.items[this.cursor..];
return this.list.items()[this.cursor..];
} else if (comptime @TypeOf(writeFn) == @TypeOf(&write) and writeFn == &write) {
return buffer;
} else {
Expand All @@ -1193,25 +1193,25 @@ pub const StreamBuffer = struct {
}

var byte_list = bun.ByteList.moveFromList(&this.list);
defer this.list = byte_list.moveToListManaged(this.list.allocator);
defer this.list = byte_list.moveToListManaged(this.list.allocator());

_ = try byte_list.writeLatin1(this.list.allocator, buffer);
_ = try byte_list.writeLatin1(this.list.allocator(), buffer);
}

pub fn writeUTF16(this: *StreamBuffer, buffer: []const u16) OOM!void {
var byte_list = bun.ByteList.moveFromList(&this.list);
defer this.list = byte_list.moveToListManaged(this.list.allocator);
defer this.list = byte_list.moveToListManaged(this.list.allocator());

_ = try byte_list.writeUTF16(this.list.allocator, buffer);
_ = try byte_list.writeUTF16(this.list.allocator(), buffer);
}

pub fn slice(this: *const StreamBuffer) []const u8 {
return this.list.items[this.cursor..];
return this.list.items()[this.cursor..];
}

pub fn deinit(this: *StreamBuffer) void {
this.cursor = 0;
if (this.list.capacity > 0) {
if (this.list.capacity() > 0) {
this.list.clearAndFree();
}
}
Expand Down
28 changes: 14 additions & 14 deletions src/s3/list_objects.zig
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ pub const S3ListObjectsV2Result = struct {
continuation_token: ?[]const u8,
next_continuation_token: ?[]const u8,
start_after: ?[]const u8,
common_prefixes: ?std.ArrayList([]const u8),
contents: ?std.ArrayList(S3ListObjectsContents),
common_prefixes: ?bun.collections.ArrayListDefault([]const u8),
contents: ?bun.collections.ArrayListDefault(S3ListObjectsContents),

pub fn deinit(this: *const @This()) void {
if (this.contents) |contents| {
for (contents.items) |*item| item.deinit();
for (contents.items()) |*item| item.deinit();
contents.deinit();
}
Comment on lines 66 to 69
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Avoid double-deinit on contents elements

With bun.collections.ArrayListDefault, deinit() already walks the list and runs each element's deinit. Manually looping the elements before calling contents.deinit() now triggers S3ListObjectsContents.deinit() twice, so the etag OwnedIn (and any other owned fields) will be freed twice. Please drop the manual loop and rely on contents.deinit() (or use deinitShallow() only if you truly want to skip element finalizers).

🤖 Prompt for AI Agents
In src/s3/list_objects.zig around lines 66 to 69, remove the manual loop that
iterates over contents.items() and calls each item.deinit() because
bun.collections.ArrayListDefault::deinit() already finalizes each element;
leaving the loop causes double-deinit and double-free of owned fields like etag
— simply call contents.deinit() (or replace with contents.deinitShallow() only
if you intentionally want to skip element finalizers) and delete the explicit
for-loop.

if (this.common_prefixes) |common_prefixes| {
common_prefixes.deinit();
common_prefixes.deinitShallow();
}
}

Expand Down Expand Up @@ -115,9 +115,9 @@ pub const S3ListObjectsV2Result = struct {
}

if (this.contents) |contents| {
const jsContents = try JSValue.createEmptyArray(globalObject, contents.items.len);
const jsContents = try JSValue.createEmptyArray(globalObject, contents.items().len);

for (contents.items, 0..) |item, i| {
for (contents.items(), 0..) |item, i| {
const objectInfo = JSValue.createEmptyObject(globalObject, 1);
objectInfo.put(globalObject, jsc.ZigString.static("key"), try bun.String.createUTF8ForJS(globalObject, item.key));

Expand Down Expand Up @@ -165,9 +165,9 @@ pub const S3ListObjectsV2Result = struct {
}

if (this.common_prefixes) |common_prefixes| {
const jsCommonPrefixes = try JSValue.createEmptyArray(globalObject, common_prefixes.items.len);
const jsCommonPrefixes = try JSValue.createEmptyArray(globalObject, common_prefixes.items().len);

for (common_prefixes.items, 0..) |prefix, i| {
for (common_prefixes.items(), 0..) |prefix, i| {
const jsPrefix = JSValue.createEmptyObject(globalObject, 1);
jsPrefix.put(globalObject, jsc.ZigString.static("prefix"), try bun.String.createUTF8ForJS(globalObject, prefix));
try jsCommonPrefixes.putIndex(globalObject, @intCast(i), jsPrefix);
Expand Down Expand Up @@ -196,8 +196,8 @@ pub fn parseS3ListObjectsResult(xml: []const u8) !S3ListObjectsV2Result {
.start_after = null,
};

var contents = std.ArrayList(S3ListObjectsContents).init(bun.default_allocator);
var common_prefixes = std.ArrayList([]const u8).init(bun.default_allocator);
var contents = bun.collections.ArrayListDefault(S3ListObjectsContents).init();
var common_prefixes = bun.collections.ArrayListDefault([]const u8).init();

// we dont use trailing ">" as it may finish with xmlns=...
if (strings.indexOf(xml, "<ListBucketResult")) |delete_result_pos| {
Expand Down Expand Up @@ -482,17 +482,17 @@ pub fn parseS3ListObjectsResult(xml: []const u8) !S3ListObjectsV2Result {
}
}

if (contents.items.len != 0) {
if (contents.items().len != 0) {
result.contents = contents;
} else {
for (contents.items) |*item| item.deinit();
for (contents.items()) |*item| item.deinit();
contents.deinit();
}

if (common_prefixes.items.len != 0) {
if (common_prefixes.items().len != 0) {
result.common_prefixes = common_prefixes;
} else {
common_prefixes.deinit();
common_prefixes.deinitShallow();
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/string.zig
Original file line number Diff line number Diff line change
Expand Up @@ -857,10 +857,10 @@ pub const String = extern struct {

pub fn createFormatForJS(globalObject: *jsc.JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) bun.JSError!jsc.JSValue {
jsc.markBinding(@src());
var builder = std.ArrayList(u8).init(bun.default_allocator);
var builder = bun.collections.ArrayListDefault(u8).init();
defer builder.deinit();
bun.handleOom(builder.writer().print(fmt, args));
return bun.cpp.BunString__createUTF8ForJS(globalObject, builder.items.ptr, builder.items.len);
return bun.cpp.BunString__createUTF8ForJS(globalObject, builder.items().ptr, builder.items().len);
}

pub fn parseDate(this: *String, globalObject: *jsc.JSGlobalObject) bun.JSError!f64 {
Expand Down