aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/api/bun.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/api/bun.zig')
-rw-r--r--src/bun.js/api/bun.zig63
1 files changed, 60 insertions, 3 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 7d7c0ec7a..eb235da2f 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -2340,6 +2340,7 @@ pub const Timer = struct {
ref: JSC.Ref = JSC.Ref.init(),
globalThis: *JSC.JSGlobalObject,
callback: JSC.Strong = .{},
+ arguments: JSC.Strong = .{},
repeat: bool = false,
pub const Task = JSC.AnyTask.New(CallbackJob, perform);
@@ -2369,6 +2370,7 @@ pub const Timer = struct {
pub fn deinit(this: *CallbackJob) void {
this.callback.deinit();
+ this.arguments.deinit();
this.ref.unref(this.globalThis.bunVM());
bun.default_allocator.destroy(this);
}
@@ -2395,9 +2397,34 @@ pub const Timer = struct {
}
}
+ var args_buf: [8]JSC.JSValue = undefined;
+ var args: []JSC.JSValue = &.{};
+ var args_needs_deinit = false;
+ defer if (args_needs_deinit) bun.default_allocator.free(args);
+
const callback = this.callback.get() orelse @panic("Expected CallbackJob to have a callback function");
+ if (this.arguments.trySwap()) |arguments| {
+ const count = arguments.getLengthOfArray(globalThis);
+ if (count > 0) {
+ if (count > args_buf.len) {
+ args = bun.default_allocator.alloc(JSC.JSValue, count) catch unreachable;
+ args_needs_deinit = true;
+ } else {
+ args = args_buf[0..count];
+ }
+ var arg = args.ptr;
+ var i: u32 = 0;
+ while (i < count) : (i += 1) {
+ arg[0] = JSC.JSObject.getIndex(arguments, globalThis, @truncate(u32, i));
+ arg += 1;
+ }
+ }
+ }
- const result = callback.call(globalThis, &.{});
+ const result = callback.callWithGlobalThis(
+ globalThis,
+ args,
+ );
if (result.isEmptyOrUndefinedOrNull() or !result.isCell()) {
this.deinit();
@@ -2435,6 +2462,7 @@ pub const Timer = struct {
globalThis: *JSC.JSGlobalObject,
timer: *uws.Timer,
poll_ref: JSC.PollRef = JSC.PollRef.init(),
+ arguments: JSC.Strong = .{},
// this is sized to be the same as one pointer
pub const ID = extern struct {
@@ -2478,6 +2506,21 @@ pub const Timer = struct {
)
else
this.callback,
+ .arguments = if (repeats and this.arguments.has())
+ JSC.Strong.create(
+ this.arguments.get() orelse {
+ // if the arguments freed, that's an error
+ if (comptime Environment.allow_assert)
+ unreachable;
+
+ this.deinit();
+ _ = map.swapRemove(timer_id.id);
+ return;
+ },
+ globalThis,
+ )
+ else
+ this.arguments,
.globalThis = globalThis,
.id = timer_id.id,
.repeat = timer_id.repeat > 0,
@@ -2488,6 +2531,7 @@ pub const Timer = struct {
// - reuse the JSC.Strong
if (!repeats) {
this.callback = .{};
+ this.arguments = .{};
map.put(vm.allocator, timer_id.id, null) catch unreachable;
this.deinit();
}
@@ -2507,9 +2551,11 @@ pub const Timer = struct {
JSC.markBinding(@src());
var vm = this.globalThis.bunVM();
+
this.poll_ref.unref(vm);
this.timer.deinit();
this.callback.deinit();
+ this.arguments.deinit();
}
};
@@ -2518,6 +2564,7 @@ pub const Timer = struct {
globalThis: *JSGlobalObject,
callback: JSValue,
countdown: JSValue,
+ arguments_array_or_zero: JSValue,
repeat: bool,
) !void {
JSC.markBinding(@src());
@@ -2545,6 +2592,10 @@ pub const Timer = struct {
.repeat = false,
};
+ if (arguments_array_or_zero != .zero) {
+ cb.arguments = JSC.Strong.create(arguments_array_or_zero, globalThis);
+ }
+
var job = vm.allocator.create(CallbackJob) catch @panic(
"Out of memory while allocating Timeout",
);
@@ -2570,6 +2621,10 @@ pub const Timer = struct {
),
};
+ if (arguments_array_or_zero != .zero) {
+ timeout.arguments = JSC.Strong.create(arguments_array_or_zero, globalThis);
+ }
+
timeout.poll_ref.ref(vm);
map.put(vm.allocator, id, timeout) catch unreachable;
@@ -2588,12 +2643,13 @@ pub const Timer = struct {
globalThis: *JSGlobalObject,
callback: JSValue,
countdown: JSValue,
+ arguments: JSValue,
) callconv(.C) JSValue {
JSC.markBinding(@src());
const id = globalThis.bunVM().timer.last_id;
globalThis.bunVM().timer.last_id +%= 1;
- Timer.set(id, globalThis, callback, countdown, false) catch
+ Timer.set(id, globalThis, callback, countdown, arguments, false) catch
return JSValue.jsUndefined();
return JSValue.jsNumberWithType(i32, id);
@@ -2602,12 +2658,13 @@ pub const Timer = struct {
globalThis: *JSGlobalObject,
callback: JSValue,
countdown: JSValue,
+ arguments: JSValue,
) callconv(.C) JSValue {
JSC.markBinding(@src());
const id = globalThis.bunVM().timer.last_id;
globalThis.bunVM().timer.last_id +%= 1;
- Timer.set(id, globalThis, callback, countdown, true) catch
+ Timer.set(id, globalThis, callback, countdown, arguments, true) catch
return JSValue.jsUndefined();
return JSValue.jsNumberWithType(i32, id);