Files
bun.sh/src/bun.js/Strong.zig
Jarred Sumner 1db119ec11 Fix memory leak (#3887)
* Fix memory leak

* Remove an extra copy

* Further fixes

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-07-30 02:03:32 -07:00

115 lines
3.0 KiB
Zig

const bun = @import("root").bun;
const JSC = bun.JSC;
const StrongImpl = opaque {
pub fn init(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) *StrongImpl {
JSC.markBinding(@src());
return Bun__StrongRef__new(globalThis, value);
}
pub fn get(this: *StrongImpl) JSC.JSValue {
JSC.markBinding(@src());
return Bun__StrongRef__get(this);
}
pub fn set(this: *StrongImpl, globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) void {
JSC.markBinding(@src());
Bun__StrongRef__set(this, globalThis, value);
}
pub fn clear(this: *StrongImpl) void {
JSC.markBinding(@src());
Bun__StrongRef__clear(this);
}
pub fn deinit(
this: *StrongImpl,
) void {
JSC.markBinding(@src());
Bun__StrongRef__delete(this);
}
extern fn Bun__StrongRef__delete(this: *StrongImpl) void;
extern fn Bun__StrongRef__new(*JSC.JSGlobalObject, JSC.JSValue) *StrongImpl;
extern fn Bun__StrongRef__get(this: *StrongImpl) JSC.JSValue;
extern fn Bun__StrongRef__set(this: *StrongImpl, *JSC.JSGlobalObject, JSC.JSValue) void;
extern fn Bun__StrongRef__clear(this: *StrongImpl) void;
};
pub const Strong = struct {
ref: ?*StrongImpl = null,
globalThis: ?*JSC.JSGlobalObject = null,
pub fn init() Strong {
return .{};
}
pub fn create(
value: JSC.JSValue,
globalThis: *JSC.JSGlobalObject,
) Strong {
if (value != .zero) {
return .{ .ref = StrongImpl.init(globalThis, value), .globalThis = globalThis };
}
return .{ .globalThis = globalThis };
}
pub fn get(this: *Strong) ?JSC.JSValue {
var ref = this.ref orelse return null;
const result = ref.get();
if (result == .zero) {
return null;
}
return result;
}
pub fn swap(this: *Strong) JSC.JSValue {
var ref = this.ref orelse return .zero;
const result = ref.get();
if (result == .zero) {
return .zero;
}
ref.clear();
return result;
}
pub fn has(this: *Strong) bool {
var ref = this.ref orelse return false;
return ref.get() != .zero;
}
pub fn trySwap(this: *Strong) ?JSC.JSValue {
const result = this.swap();
if (result == .zero) {
return null;
}
return result;
}
pub fn set(this: *Strong, globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) void {
var ref: *StrongImpl = this.ref orelse {
if (value == .zero) return;
this.ref = StrongImpl.init(globalThis, value);
this.globalThis = globalThis;
return;
};
this.globalThis = globalThis;
ref.set(globalThis, value);
}
pub fn clear(this: *Strong) void {
var ref: *StrongImpl = this.ref orelse return;
ref.clear();
}
pub fn deinit(this: *Strong) void {
var ref: *StrongImpl = this.ref orelse return;
this.ref = null;
ref.deinit();
}
};