aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-01 19:54:02 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-01 19:54:02 -0700
commit5c989c957a6b6464e9faacde6d820830a7e70aaf (patch)
tree572605a71082cfcb857d7a7ebb4c149650d2112f /src
parent8af0764b3b9da137a15b7881c1b08376c5ab0bcc (diff)
downloadbun-5c989c957a6b6464e9faacde6d820830a7e70aaf.tar.gz
bun-5c989c957a6b6464e9faacde6d820830a7e70aaf.tar.zst
bun-5c989c957a6b6464e9faacde6d820830a7e70aaf.zip
Add abstraction for protecting values we're iterating on
Diffstat (limited to 'src')
-rw-r--r--src/javascript/jsc/base.zig11
-rw-r--r--src/javascript/jsc/bindings/bindings.zig8
-rw-r--r--src/javascript/jsc/node/node_fs_binding.zig9
-rw-r--r--src/javascript/jsc/node/types.zig43
4 files changed, 47 insertions, 24 deletions
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig
index aa9e9abd2..c6a861e17 100644
--- a/src/javascript/jsc/base.zig
+++ b/src/javascript/jsc/base.zig
@@ -2690,7 +2690,7 @@ pub fn wrap(
args[i] = ctx.ptr();
},
ZigString => {
- var string_value = iter.nextEat() orelse {
+ var string_value = iter.protectEatNext() orelse {
JSC.throwInvalidArguments("Missing argument", .{}, ctx, exception);
return null;
};
@@ -2712,7 +2712,7 @@ pub fn wrap(
}
},
*Response => {
- args[i] = (iter.nextEat() orelse {
+ args[i] = (iter.protectEatNext() orelse {
JSC.throwInvalidArguments("Missing Response object", .{}, ctx, exception);
return null;
}).as(Response) orelse {
@@ -2721,7 +2721,7 @@ pub fn wrap(
};
},
*Request => {
- args[i] = (iter.nextEat() orelse {
+ args[i] = (iter.protectEatNext() orelse {
JSC.throwInvalidArguments("Missing Request object", .{}, ctx, exception);
return null;
}).as(Request) orelse {
@@ -2740,7 +2740,7 @@ pub fn wrap(
args[i] = exception;
},
JSValue => {
- const val = iter.nextEat() orelse {
+ const val = iter.protectEatNext() orelse {
JSC.throwInvalidArguments("Missing argument", .{}, ctx, exception);
return null;
};
@@ -2753,6 +2753,7 @@ pub fn wrap(
var result: JSValue = @call(.{}, @field(Container, name), args);
if (result.isError()) {
exception.* = result.asObjectRef();
+ iter.deinit();
return null;
}
@@ -2778,6 +2779,8 @@ pub fn wrap(
}
}
+ iter.deinit();
+
return result.asObjectRef();
}
}.callback;
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index 8d916af11..ef4b3edfe 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -2402,13 +2402,13 @@ pub const JSValue = enum(u64) {
return cppFn("toInt64", .{this});
}
- pub fn isUndefined(this: JSValue) bool {
+ pub inline fn isUndefined(this: JSValue) bool {
return @enumToInt(this) == 0xa;
}
- pub fn isNull(this: JSValue) bool {
+ pub inline fn isNull(this: JSValue) bool {
return @enumToInt(this) == 0x2;
}
- pub fn isEmptyOrUndefinedOrNull(this: JSValue) bool {
+ pub inline fn isEmptyOrUndefinedOrNull(this: JSValue) bool {
return switch (@enumToInt(this)) {
0, 0xa, 0x2 => true,
else => false,
@@ -2421,7 +2421,7 @@ pub const JSValue = enum(u64) {
};
}
/// Empty as in "JSValue {}" rather than an empty string
- pub fn isEmpty(this: JSValue) bool {
+ pub inline fn isEmpty(this: JSValue) bool {
return switch (@enumToInt(this)) {
0 => true,
else => false,
diff --git a/src/javascript/jsc/node/node_fs_binding.zig b/src/javascript/jsc/node/node_fs_binding.zig
index ea3376ffb..59b58778a 100644
--- a/src/javascript/jsc/node/node_fs_binding.zig
+++ b/src/javascript/jsc/node/node_fs_binding.zig
@@ -42,14 +42,7 @@ fn callSync(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction {
exception: JSC.C.ExceptionRef,
) JSC.C.JSValueRef {
var slice = ArgumentsSlice.init(@ptrCast([*]const JSC.JSValue, arguments.ptr)[0..arguments.len]);
-
- defer {
- // TODO: fix this
- for (arguments) |arg| {
- JSC.C.JSValueUnprotect(ctx, arg);
- }
- slice.arena.deinit();
- }
+ defer slice.deinit();
const args = if (comptime Arguments != void)
(Arguments.fromJS(ctx, &slice, exception) orelse return null)
diff --git a/src/javascript/jsc/node/types.zig b/src/javascript/jsc/node/types.zig
index 9ad49e756..f7c8ac967 100644
--- a/src/javascript/jsc/node/types.zig
+++ b/src/javascript/jsc/node/types.zig
@@ -301,8 +301,7 @@ pub const PathLike = union(Tag) {
if (exception.* != null) return null;
if (!Valid.pathBuffer(buffer, ctx, exception)) return null;
- JSC.C.JSValueProtect(ctx, arg.asObjectRef());
- arguments.eat();
+ arguments.protectEat();
return PathLike{ .buffer = buffer };
},
@@ -311,8 +310,7 @@ pub const PathLike = union(Tag) {
if (exception.* != null) return null;
if (!Valid.pathBuffer(buffer, ctx, exception)) return null;
- JSC.C.JSValueProtect(ctx, arg.asObjectRef());
- arguments.eat();
+ arguments.protectEat();
return PathLike{ .buffer = buffer };
},
@@ -326,8 +324,7 @@ pub const PathLike = union(Tag) {
if (!Valid.pathString(zig_str, ctx, exception)) return null;
- JSC.C.JSValueProtect(ctx, arg.asObjectRef());
- arguments.eat();
+ arguments.protectEat();
if (zig_str.is16Bit()) {
var printed = std.mem.span(std.fmt.allocPrintZ(arguments.arena.allocator(), "{}", .{zig_str}) catch unreachable);
@@ -341,8 +338,7 @@ pub const PathLike = union(Tag) {
var zig_str = domurl.pathname();
if (!Valid.pathString(zig_str, ctx, exception)) return null;
- JSC.C.JSValueProtect(ctx, arg.asObjectRef());
- arguments.eat();
+ arguments.protectEat();
if (zig_str.is16Bit()) {
var printed = std.mem.span(std.fmt.allocPrintZ(arguments.arena.allocator(), "{}", .{zig_str}) catch unreachable);
@@ -421,6 +417,37 @@ pub const ArgumentsSlice = struct {
arena: std.heap.ArenaAllocator = std.heap.ArenaAllocator.init(bun.default_allocator),
all: []const JSC.JSValue,
threw: bool = false,
+ protected: std.bit_set.IntegerBitSet(32) = std.bit_set.IntegerBitSet(32).initEmpty(),
+
+ pub fn unprotect(this: *ArgumentsSlice) void {
+ var iter = this.protected.iterator(.{});
+ var ctx = JSC.VirtualMachine.vm.global.ref();
+ while (iter.next()) |i| {
+ JSC.C.JSValueUnprotect(ctx, this.all[i].asObjectRef());
+ }
+ this.protected = std.bit_set.IntegerBitSet(32).initEmpty();
+ }
+
+ pub fn deinit(this: *ArgumentsSlice) void {
+ this.unprotect();
+ this.arena.deinit();
+ }
+
+ pub fn protectEat(this: *ArgumentsSlice) void {
+ if (this.remaining.len == 0) return;
+ const index = this.all.len - this.remaining.len;
+ this.protected.set(index);
+ JSC.C.JSValueProtect(JSC.VirtualMachine.vm.global.ref(), this.all[index].asObjectRef());
+ this.eat();
+ }
+
+ pub fn protectEatNext(this: *ArgumentsSlice) ?JSC.JSValue {
+ if (this.remaining.len == 0) return null;
+ const index = this.all.len - this.remaining.len;
+ this.protected.set(index);
+ JSC.C.JSValueProtect(JSC.VirtualMachine.vm.global.ref(), this.all[index].asObjectRef());
+ return this.nextEat();
+ }
pub fn from(arguments: []const JSC.JSValueRef) ArgumentsSlice {
return init(@ptrCast([*]const JSC.JSValue, arguments.ptr)[0..arguments.len]);