This commit is contained in:
Dylan Conway
2025-05-01 13:57:41 -07:00
parent 7f768634fa
commit 85167870d0
3 changed files with 15 additions and 14 deletions

View File

@@ -750,8 +750,9 @@ pub const ImmediateObject = struct {
return globalObject.throw("Immediate is not constructible", .{});
}
pub fn runImmediateTask(this: *ImmediateObject, vm: *VirtualMachine, exception_thrown: bool) bool {
return this.internals.runImmediateTask(vm, exception_thrown);
// returns true if an exception was thrown
pub fn runImmediateTask(this: *ImmediateObject, vm: *VirtualMachine) bool {
return this.internals.runImmediateTask(vm);
}
pub fn toPrimitive(this: *ImmediateObject, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSValue {
@@ -853,21 +854,22 @@ pub const TimerObjectInternals = struct {
extern "c" fn Bun__JSTimeout__call(globalObject: *JSC.JSGlobalObject, timer: JSValue, callback: JSValue, arguments: JSValue) bool;
pub fn runImmediateTask(this: *TimerObjectInternals, vm: *VirtualMachine, exception_thrown: bool) bool {
// returns true if an exception was thrown
pub fn runImmediateTask(this: *TimerObjectInternals, vm: *VirtualMachine) bool {
if (this.flags.has_cleared_timer or
// unref'd setImmediate callbacks should only run if there are things keeping the event
// loop alive other than setImmediates
(!this.flags.is_keeping_event_loop_alive and !vm.isEventLoopAliveExcludingImmediates()))
{
this.deref();
return exception_thrown;
return false;
}
const timer = this.strong_this.get() orelse {
if (Environment.isDebug) {
@panic("TimerObjectInternals.runImmediateTask: this_object is null");
}
return exception_thrown;
return false;
};
const globalThis = vm.global;
this.strong_this.deinit();
@@ -878,16 +880,16 @@ pub const TimerObjectInternals = struct {
const callback = ImmediateObject.js.callbackGetCached(timer).?;
const arguments = ImmediateObject.js.argumentsGetCached(timer).?;
this.ref();
const threw_exception = this.run(globalThis, timer, callback, arguments, this.asyncID(), vm);
const exception_thrown = this.run(globalThis, timer, callback, arguments, this.asyncID(), vm);
this.deref();
if (this.eventLoopTimer().state == .FIRED) {
this.deref();
}
vm.eventLoop().exitMaybeDrainMicrotask(!exception_thrown and !threw_exception);
vm.eventLoop().exitMaybeDrainMicrotask(!exception_thrown);
return exception_thrown or threw_exception;
return exception_thrown;
}
pub fn asyncID(this: *const TimerObjectInternals) u64 {

View File

@@ -38,7 +38,7 @@ static bool call(JSGlobalObject* globalObject, JSValue timerObject, JSValue call
auto callData = JSC::getCallData(callbackValue);
if (callData.type == CallData::Type::None) {
Bun__reportUnhandledError(globalObject, JSValue::encode(createNotAFunctionError(globalObject, callbackValue)));
return false;
return true;
}
MarkedArgumentBuffer args;
@@ -73,12 +73,12 @@ static bool call(JSGlobalObject* globalObject, JSValue timerObject, JSValue call
return hadException;
}
// Returns false if an exception was thrown.
// Returns true if an exception was thrown.
extern "C" bool Bun__JSTimeout__call(JSGlobalObject* globalObject, EncodedJSValue timerObject, EncodedJSValue callbackValue, EncodedJSValue argumentsValue)
{
auto& vm = globalObject->vm();
if (UNLIKELY(vm.hasPendingTerminationException())) {
return false;
return true;
}
return call(globalObject, JSValue::decode(timerObject), JSValue::decode(callbackValue), JSValue::decode(argumentsValue));

View File

@@ -1423,11 +1423,10 @@ pub const EventLoop = struct {
var exception_thrown = false;
for (to_run_now.items) |task| {
exception_thrown = task.runImmediateTask(virtual_machine, exception_thrown);
exception_thrown = task.runImmediateTask(virtual_machine);
}
// if an exception was thrown, drain the pending microtasks from the remaining
// immediate tasks.
// make sure microtasks are drained if the last task had an exception
if (exception_thrown) {
this.maybeDrainMicrotasks();
}