aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bun.js/api/bun/socket.zig8
-rw-r--r--src/bun.js/api/transpiler.zig2
-rw-r--r--src/bun.js/bindings/bindings.zig68
-rw-r--r--src/bun.js/bindings/exports.zig2
-rw-r--r--src/bun.js/node/types.zig4
-rw-r--r--src/bun.js/test/jest.zig10
-rw-r--r--src/bun.js/webcore/encoding.zig2
-rw-r--r--src/bun.js/webcore/response.zig44
-rw-r--r--src/nullable_allocator.zig31
9 files changed, 96 insertions, 75 deletions
diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig
index 38b6837b3..8851ff47b 100644
--- a/src/bun.js/api/bun/socket.zig
+++ b/src/bun.js/api/bun/socket.zig
@@ -379,9 +379,9 @@ pub const Listener = struct {
var socket = Listener{
.handlers = handlers,
.connection = if (port) |port_| .{
- .host = .{ .host = (hostname_or_unix.cloneIfNeeded() catch unreachable).slice(), .port = port_ },
+ .host = .{ .host = (hostname_or_unix.cloneIfNeeded(bun.default_allocator) catch unreachable).slice(), .port = port_ },
} else .{
- .unix = (hostname_or_unix.cloneIfNeeded() catch unreachable).slice(),
+ .unix = (hostname_or_unix.cloneIfNeeded(bun.default_allocator) catch unreachable).slice(),
},
.ssl = ssl_enabled,
};
@@ -660,9 +660,9 @@ pub const Listener = struct {
var socket_context = uws.us_create_socket_context(@boolToInt(ssl_enabled), uws.Loop.get().?, @sizeOf(usize), ctx_opts).?;
var connection: Listener.UnixOrHost = if (port) |port_| .{
- .host = .{ .host = (hostname_or_unix.cloneIfNeeded() catch unreachable).slice(), .port = port_ },
+ .host = .{ .host = (hostname_or_unix.cloneIfNeeded(bun.default_allocator) catch unreachable).slice(), .port = port_ },
} else .{
- .unix = (hostname_or_unix.cloneIfNeeded() catch unreachable).slice(),
+ .unix = (hostname_or_unix.cloneIfNeeded(bun.default_allocator) catch unreachable).slice(),
};
if (ssl_enabled) {
diff --git a/src/bun.js/api/transpiler.zig b/src/bun.js/api/transpiler.zig
index 6ce7c70de..c48f1f093 100644
--- a/src/bun.js/api/transpiler.zig
+++ b/src/bun.js/api/transpiler.zig
@@ -683,7 +683,7 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo
const replacementValue = JSC.JSObject.getIndex(value, globalThis, 1);
if (exportReplacementValue(replacementValue, globalThis)) |to_replace| {
const replacementKey = JSC.JSObject.getIndex(value, globalThis, 0);
- var slice = (try replacementKey.toSlice(globalThis, bun.default_allocator).cloneIfNeeded());
+ var slice = (try replacementKey.toSlice(globalThis, bun.default_allocator).cloneIfNeeded(bun.default_allocator));
var replacement_name = slice.slice();
if (!JSLexer.isIdentifier(replacement_name)) {
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index 6d5f87662..7aa148c4d 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -16,6 +16,8 @@ const ArrayBuffer = @import("../base.zig").ArrayBuffer;
const JSC = @import("../../jsc.zig");
const Shimmer = JSC.Shimmer;
const FFI = @import("./FFI.zig");
+const NullableAllocator = @import("../../nullable_allocator.zig").NullableAllocator;
+
pub const JSObject = extern struct {
pub const shim = Shimmer("JSC", "JSObject", @This());
bytes: shim.Bytes,
@@ -91,7 +93,7 @@ pub const ZigString = extern struct {
pub fn clone(this: ZigString, allocator: std.mem.Allocator) !ZigString {
var sliced = this.toSlice(allocator);
- if (!sliced.allocated) {
+ if (!sliced.isAllocated()) {
var str = ZigString.init(try allocator.dupe(u8, sliced.slice()));
str.mark();
str.markUTF8();
@@ -197,47 +199,49 @@ pub const ZigString = extern struct {
pub const shim = Shimmer("", "ZigString", @This());
pub const Slice = struct {
- allocator: std.mem.Allocator,
+ allocator: NullableAllocator = .{},
ptr: [*]const u8,
len: u32,
- allocated: bool = false,
pub fn fromUTF8(input: []const u8) Slice {
return .{
.ptr = input.ptr,
.len = @truncate(u32, input.len),
- .allocated = false,
- .allocator = bun.default_allocator,
+ .allocator = NullableAllocator.init(bun.default_allocator),
};
}
- pub const empty = Slice{ .allocator = bun.default_allocator, .ptr = undefined, .len = 0, .allocated = false };
+ pub const empty = Slice{ .ptr = undefined, .len = 0 };
+
+ pub inline fn isAllocated(this: Slice) bool {
+ return !this.allocator.isNull();
+ }
pub fn clone(this: Slice, allocator: std.mem.Allocator) !Slice {
- if (!this.allocated) {
- return Slice{ .allocator = allocator, .ptr = this.ptr, .len = this.len, .allocated = false };
+ if (this.isAllocated()) {
+ return Slice{ .allocator = this.allocator, .ptr = this.ptr, .len = this.len };
}
var duped = try allocator.dupe(u8, this.ptr[0..this.len]);
- return Slice{ .allocator = allocator, .ptr = duped.ptr, .len = this.len, .allocated = true };
+ return Slice{ .allocator = NullableAllocator.init(allocator), .ptr = duped.ptr, .len = this.len };
}
- pub fn cloneIfNeeded(this: Slice) !Slice {
- if (this.allocated) {
+ pub fn cloneIfNeeded(this: Slice, allocator: std.mem.Allocator) !Slice {
+ if (this.isAllocated()) {
return this;
}
- var duped = try this.allocator.dupe(u8, this.ptr[0..this.len]);
- return Slice{ .allocator = this.allocator, .ptr = duped.ptr, .len = this.len, .allocated = true };
+ var duped = try allocator.dupe(u8, this.ptr[0..this.len]);
+ return Slice{ .allocator = NullableAllocator.init(allocator), .ptr = duped.ptr, .len = this.len };
}
pub fn cloneZ(this: Slice, allocator: std.mem.Allocator) !Slice {
- if (this.allocated or this.len == 0) {
+ if (this.isAllocated() or this.len == 0) {
return this;
}
var duped = try allocator.dupeZ(u8, this.ptr[0..this.len]);
- return Slice{ .allocator = allocator, .ptr = duped.ptr, .len = this.len, .allocated = true };
+ return Slice{ .allocator = NullableAllocator.init(allocator), .ptr = duped.ptr, .len = this.len };
}
pub fn slice(this: Slice) []const u8 {
@@ -272,11 +276,9 @@ pub const ZigString = extern struct {
/// Does nothing if the slice is not allocated
pub fn deinit(this: *const Slice) void {
- if (!this.allocated) {
- return;
+ if (this.allocator.get()) |allocator| {
+ allocator.free(this.slice());
}
-
- this.allocator.free(this.slice());
}
};
@@ -445,22 +447,19 @@ pub const ZigString = extern struct {
pub fn toSliceFast(this: ZigString, allocator: std.mem.Allocator) Slice {
if (this.len == 0)
- return Slice{ .ptr = "", .len = 0, .allocator = allocator, .allocated = false };
+ return Slice.empty;
if (is16Bit(&this)) {
var buffer = this.toOwnedSlice(allocator) catch unreachable;
return Slice{
.ptr = buffer.ptr,
.len = @truncate(u32, buffer.len),
- .allocated = true,
- .allocator = allocator,
+ .allocator = NullableAllocator.init(allocator),
};
}
return Slice{
.ptr = untagged(this.ptr),
.len = @truncate(u32, this.len),
- .allocated = false,
- .allocator = allocator,
};
}
@@ -468,54 +467,43 @@ pub const ZigString = extern struct {
/// It is slow but safer when the input is from JavaScript
pub fn toSlice(this: ZigString, allocator: std.mem.Allocator) Slice {
if (this.len == 0)
- return Slice{ .ptr = "", .len = 0, .allocator = allocator, .allocated = false };
+ return Slice.empty;
if (is16Bit(&this)) {
var buffer = this.toOwnedSlice(allocator) catch unreachable;
return Slice{
+ .allocator = NullableAllocator.init(allocator),
.ptr = buffer.ptr,
.len = @truncate(u32, buffer.len),
- .allocated = true,
- .allocator = allocator,
};
}
if (!this.isUTF8() and !strings.isAllASCII(untagged(this.ptr)[0..this.len])) {
var buffer = this.toOwnedSlice(allocator) catch unreachable;
- return Slice{
- .ptr = buffer.ptr,
- .len = @truncate(u32, buffer.len),
- .allocated = true,
- .allocator = allocator,
- };
+ return Slice.fromUTF8(buffer);
}
return Slice{
.ptr = untagged(this.ptr),
.len = @truncate(u32, this.len),
- .allocated = false,
- .allocator = allocator,
};
}
pub fn toSliceZ(this: ZigString, allocator: std.mem.Allocator) Slice {
if (this.len == 0)
- return Slice{ .ptr = "", .len = 0, .allocator = allocator, .allocated = false };
+ return Slice.empty;
if (is16Bit(&this)) {
var buffer = this.toOwnedSliceZ(allocator) catch unreachable;
return Slice{
.ptr = buffer.ptr,
.len = @truncate(u32, buffer.len),
- .allocated = true,
- .allocator = allocator,
+ .allocator = NullableAllocator.init(allocator),
};
}
return Slice{
.ptr = untagged(this.ptr),
.len = @truncate(u32, this.len),
- .allocated = false,
- .allocator = allocator,
};
}
diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig
index fb2d45c45..eb4f33001 100644
--- a/src/bun.js/bindings/exports.zig
+++ b/src/bun.js/bindings/exports.zig
@@ -1999,7 +1999,7 @@ pub const ZigConsoleClient = struct {
var tag_name_slice: ZigString.Slice = ZigString.Slice.empty;
var is_tag_kind_primitive = false;
- defer if (tag_name_slice.allocated) tag_name_slice.deinit();
+ defer if (tag_name_slice.isAllocated()) tag_name_slice.deinit();
if (value.get(this.globalThis, "type")) |type_value| {
const _tag = Tag.get(type_value, this.globalThis);
diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig
index 526e33f29..144274b9b 100644
--- a/src/bun.js/node/types.zig
+++ b/src/bun.js/node/types.zig
@@ -1675,7 +1675,7 @@ pub const Path = struct {
PathHandler.normalizeStringNode(str, &buf, .windows);
var out_str = JSC.ZigString.init(out);
- if (str_slice.allocated) out_str.setOutputEncoding();
+ if (str_slice.isAllocated()) out_str.setOutputEncoding();
return out_str.toValueGC(globalThis);
}
pub fn parse(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue {
@@ -1743,7 +1743,7 @@ pub const Path = struct {
PathHandler.relativePlatform(from, to, .windows, true);
var out_str = JSC.ZigString.init(out);
- if (from_slice.allocated or to_slice.allocated) out_str.setOutputEncoding();
+ if (from_slice.isAllocated() or to_slice.isAllocated()) out_str.setOutputEncoding();
return out_str.toValueGC(globalThis);
}
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig
index cab53c1e6..3e962c047 100644
--- a/src/bun.js/test/jest.zig
+++ b/src/bun.js/test/jest.zig
@@ -707,7 +707,8 @@ pub const TestScope = struct {
}
if (js.JSValueIsString(ctx, args[0])) {
- label = (JSC.JSValue.fromRef(arguments[0]).toSlice(ctx, getAllocator(ctx)).cloneIfNeeded() catch unreachable).slice();
+ const allocator = getAllocator(ctx);
+ label = (JSC.JSValue.fromRef(arguments[0]).toSlice(ctx, allocator).cloneIfNeeded(allocator) catch unreachable).slice();
args = args[1..];
}
@@ -972,6 +973,7 @@ pub const DescribeScope = struct {
var label = ZigString.init("");
var args = arguments;
+ const allocator = getAllocator(ctx);
if (js.JSValueIsString(ctx, arguments[0])) {
JSC.JSValue.fromRef(arguments[0]).toZigString(&label, ctx.ptr());
@@ -979,15 +981,15 @@ pub const DescribeScope = struct {
}
if (args.len == 0 or !js.JSObjectIsFunction(ctx, args[0])) {
- JSError(getAllocator(ctx), "describe() requires a callback function", .{}, ctx, exception);
+ JSError(allocator, "describe() requires a callback function", .{}, ctx, exception);
return js.JSValueMakeUndefined(ctx);
}
var callback = args[0];
- var scope = getAllocator(ctx).create(DescribeScope) catch unreachable;
+ var scope = allocator.create(DescribeScope) catch unreachable;
scope.* = .{
- .label = (label.toSlice(getAllocator(ctx)).cloneIfNeeded() catch unreachable).slice(),
+ .label = (label.toSlice(allocator).cloneIfNeeded(allocator) catch unreachable).slice(),
.parent = this,
.file_id = this.file_id,
};
diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig
index f70071ae3..bf1e8c992 100644
--- a/src/bun.js/webcore/encoding.zig
+++ b/src/bun.js/webcore/encoding.zig
@@ -666,7 +666,7 @@ pub const TextDecoder = struct {
}
var str = arguments[0].toSlice(globalThis, default_allocator);
- defer if (str.allocated) str.deinit();
+ defer if (str.isAllocated()) str.deinit();
encoding = EncodingLabel.which(str.slice()) orelse {
globalThis.throwInvalidArguments("Unsupported encoding label \"{s}\"", .{str.slice()});
return null;
diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig
index c47648a5d..43b40b3b6 100644
--- a/src/bun.js/webcore/response.zig
+++ b/src/bun.js/webcore/response.zig
@@ -36,6 +36,7 @@ const JSPromise = JSC.JSPromise;
const JSValue = JSC.JSValue;
const JSError = JSC.JSError;
const JSGlobalObject = JSC.JSGlobalObject;
+const NullableAllocator = @import("../../nullable_allocator.zig").NullableAllocator;
const VirtualMachine = @import("../javascript.zig").VirtualMachine;
const Task = JSC.Task;
@@ -333,15 +334,16 @@ pub const Response = struct {
json_value.jsonStringify(globalThis.ptr(), 0, &zig_str);
if (zig_str.len > 0) {
- var zig_str_slice = zig_str.toSlice(getAllocator(globalThis));
+ const allocator = getAllocator(globalThis);
+ var zig_str_slice = zig_str.toSlice(allocator);
- if (zig_str_slice.allocated) {
+ if (zig_str_slice.isAllocated()) {
response.body.value = .{
- .Blob = Blob.initWithAllASCII(zig_str_slice.mut(), zig_str_slice.allocator, globalThis.ptr(), false),
+ .Blob = Blob.initWithAllASCII(zig_str_slice.mut(), allocator, globalThis.ptr(), false),
};
} else {
response.body.value = .{
- .Blob = Blob.initWithAllASCII(getAllocator(globalThis).dupe(u8, zig_str_slice.slice()) catch unreachable, zig_str_slice.allocator, globalThis.ptr(), true),
+ .Blob = Blob.initWithAllASCII(allocator.dupe(u8, zig_str_slice.slice()) catch unreachable, allocator, globalThis.ptr(), true),
};
}
}
@@ -3101,12 +3103,7 @@ pub const Blob = struct {
input_path = .{ .fd = store.data.file.pathlike.fd };
} else {
input_path = .{
- .path = ZigString.Slice{
- .ptr = store.data.file.pathlike.path.slice().ptr,
- .len = @truncate(u32, store.data.file.pathlike.path.slice().len),
- .allocated = false,
- .allocator = bun.default_allocator,
- },
+ .path = ZigString.Slice.fromUTF8(store.data.file.pathlike.path.slice()),
};
}
@@ -3800,10 +3797,10 @@ pub const Blob = struct {
JSC.JSValue.JSType.DerivedStringObject,
=> {
var sliced = top_value.toSlice(global, bun.default_allocator);
- const is_all_ascii = !sliced.allocated;
- if (!sliced.allocated and sliced.len > 0) {
+ const is_all_ascii = !sliced.isAllocated();
+ if (!sliced.isAllocated() and sliced.len > 0) {
sliced.ptr = @ptrCast([*]const u8, (try bun.default_allocator.dupe(u8, sliced.slice())).ptr);
- sliced.allocated = true;
+ sliced.allocator = NullableAllocator.init(bun.default_allocator);
}
return Blob.initWithAllASCII(bun.constStrToU8(sliced.slice()), bun.default_allocator, global, is_all_ascii);
@@ -3861,11 +3858,12 @@ pub const Blob = struct {
JSC.JSValue.JSType.DerivedStringObject,
=> {
var sliced = current.toSlice(global, bun.default_allocator);
- could_have_non_ascii = could_have_non_ascii or sliced.allocated;
+ const allocator = sliced.allocator.get();
+ could_have_non_ascii = could_have_non_ascii or allocator != null;
joiner.append(
sliced.slice(),
0,
- if (sliced.allocated) sliced.allocator else null,
+ allocator,
);
},
@@ -3890,11 +3888,12 @@ pub const Blob = struct {
JSC.JSValue.JSType.DerivedStringObject,
=> {
var sliced = item.toSlice(global, bun.default_allocator);
- could_have_non_ascii = could_have_non_ascii or sliced.allocated;
+ const allocator = sliced.allocator.get();
+ could_have_non_ascii = could_have_non_ascii or allocator != null;
joiner.append(
sliced.slice(),
0,
- if (sliced.allocated) sliced.allocator else null,
+ allocator,
);
continue;
},
@@ -3966,11 +3965,12 @@ pub const Blob = struct {
else => {
var sliced = current.toSlice(global, bun.default_allocator);
- could_have_non_ascii = could_have_non_ascii or sliced.allocated;
+ const allocator = sliced.allocator.get();
+ could_have_non_ascii = could_have_non_ascii or allocator != null;
joiner.append(
sliced.slice(),
0,
- if (sliced.allocated) sliced.allocator else null,
+ allocator,
);
},
}
@@ -5399,7 +5399,7 @@ pub const Request = struct {
const urlOrObject = arguments[0];
const url_or_object_type = urlOrObject.jsType();
if (url_or_object_type.isStringLike()) {
- request.url = (arguments[0].toSlice(globalThis, bun.default_allocator).cloneIfNeeded() catch {
+ request.url = (arguments[0].toSlice(globalThis, bun.default_allocator).cloneIfNeeded(bun.default_allocator) catch {
return null;
}).slice();
request.url_was_allocated = request.url.len > 0;
@@ -5418,7 +5418,7 @@ pub const Request = struct {
}
if (urlOrObject.fastGet(globalThis, .url)) |url| {
- request.url = (url.toSlice(globalThis, bun.default_allocator).cloneIfNeeded() catch {
+ request.url = (url.toSlice(globalThis, bun.default_allocator).cloneIfNeeded(bun.default_allocator) catch {
return null;
}).slice();
request.url_was_allocated = request.url.len > 0;
@@ -5439,7 +5439,7 @@ pub const Request = struct {
request.method = req_init.method;
}
- request.url = (arguments[0].toSlice(globalThis, bun.default_allocator).cloneIfNeeded() catch {
+ request.url = (arguments[0].toSlice(globalThis, bun.default_allocator).cloneIfNeeded(bun.default_allocator) catch {
return null;
}).slice();
request.url_was_allocated = request.url.len > 0;
diff --git a/src/nullable_allocator.zig b/src/nullable_allocator.zig
new file mode 100644
index 000000000..8af65d6bb
--- /dev/null
+++ b/src/nullable_allocator.zig
@@ -0,0 +1,31 @@
+const std = @import("std");
+
+/// A nullable allocator the same size as `std.mem.Allocator`.
+pub const NullableAllocator = struct {
+ ptr: *anyopaque = undefined,
+ // Utilize the null pointer optimization on the vtable instead of
+ // the regular ptr because some allocator implementations might tag their
+ // `ptr` property.
+ vtable: ?*const std.mem.Allocator.VTable = null,
+
+ pub inline fn init(a: std.mem.Allocator) @This() {
+ return .{
+ .ptr = a.ptr,
+ .vtable = a.vtable,
+ };
+ }
+
+ pub inline fn isNull(this: @This()) bool {
+ return this.vtable == null;
+ }
+
+ pub inline fn get(this: @This()) ?std.mem.Allocator {
+ return if (this.vtable) |vt| std.mem.Allocator{ .ptr = this.ptr, .vtable = vt } else null;
+ }
+};
+
+comptime {
+ if (@sizeOf(NullableAllocator) != @sizeOf(std.mem.Allocator)) {
+ @compileError("Expected the sizes to be the same.");
+ }
+}