aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/Strong.zig
blob: d2ed3afbd3b379035e45d3a1ee0dbd3545a47198 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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();
    }
};