Compare commits

...

2 Commits

Author SHA1 Message Date
Jarred Sumner
7b85856ba5 Create test-timers-immediate-unref.js 2025-04-16 19:57:31 -07:00
Jarred Sumner
3f4c8d5739 setImmediate 2025-04-16 19:51:15 -07:00
3 changed files with 53 additions and 14 deletions

View File

@@ -161,16 +161,12 @@ pub const All = struct {
// prevent libuv from polling forever
}
}.cb);
} else {
vm.uwsLoop().ref();
}
} else if (old > 0 and new <= 0) {
if (comptime Environment.isWindows) {
if (this.uv_idle.data != null) {
this.uv_idle.stop();
}
} else {
vm.uwsLoop().unref();
}
}
}
@@ -209,6 +205,10 @@ pub const All = struct {
pub fn getTimeout(this: *All, spec: *timespec, vm: *VirtualMachine) bool {
if (this.active_timer_count == 0) {
if (vm.eventLoop().immediate_tasks.items.len > 0) {
spec.* = .{ .nsec = 0, .sec = 0 };
return true;
}
return false;
}
@@ -234,11 +234,19 @@ pub const All = struct {
},
.lt => {
spec.* = min.next.duration(&now);
if (vm.eventLoop().immediate_tasks.items.len > 0) {
spec.* = .{ .nsec = 0, .sec = 0 };
}
return true;
},
}
}
if (vm.eventLoop().immediate_tasks.items.len > 0) {
spec.* = .{ .nsec = 0, .sec = 0 };
return true;
}
return false;
}

View File

@@ -1526,11 +1526,6 @@ pub const EventLoop = struct {
var ctx = this.virtual_machine;
this.tickImmediateTasks(ctx);
if (comptime Environment.isPosix) {
if (this.immediate_tasks.items.len > 0) {
this.wakeup();
}
}
if (comptime Environment.isPosix) {
// Some tasks need to keep the event loop alive for one more tick.
@@ -1553,6 +1548,7 @@ pub const EventLoop = struct {
var event_loop_sleep_timer = if (comptime Environment.isDebug) std.time.Timer.start() catch unreachable;
// for the printer, this is defined:
var timespec: bun.timespec = if (Environment.isDebug) .{ .sec = 0, .nsec = 0 } else undefined;
loop.tickWithTimeout(if (ctx.timer.getTimeout(&timespec, ctx)) &timespec else null);
if (comptime Environment.isDebug) {
@@ -1611,11 +1607,6 @@ pub const EventLoop = struct {
var ctx = this.virtual_machine;
this.tickImmediateTasks(ctx);
if (comptime Environment.isPosix) {
if (this.immediate_tasks.items.len > 0) {
this.wakeup();
}
}
if (comptime Environment.isPosix) {
const pending_unref = ctx.pending_unref_counter;

View File

@@ -0,0 +1,40 @@
const common = require('../common');
const assert = require('assert');
const immediate = setImmediate(() => {});
assert.strictEqual(immediate.hasRef(), true);
immediate.unref();
assert.strictEqual(immediate.hasRef(), false);
clearImmediate(immediate);
// This immediate should execute as it was unrefed and refed again.
// It also confirms that unref/ref are chainable.
setImmediate(common.mustCall(firstStep)).ref().unref().unref().ref();
function firstStep() {
// Unrefed setImmediate executes if it was unrefed but something else keeps
// the loop open
setImmediate(common.mustCall()).unref();
setTimeout(common.mustCall(() => { setImmediate(secondStep); }), 0);
}
function secondStep() {
// clearImmediate works just fine with unref'd immediates
const immA = setImmediate(() => {
clearImmediate(immA);
clearImmediate(immB);
// This should not keep the event loop open indefinitely
// or do anything else weird
immA.ref();
immB.ref();
}).unref();
const immB = setImmediate(common.mustNotCall()).unref();
setImmediate(common.mustCall(finalStep));
}
function finalStep() {
// This immediate should not execute as it was unrefed
// and nothing else is keeping the event loop alive
setImmediate(common.mustNotCall()).unref();
}