dop251 / goja_nodejs

Nodejs compatibility library for Goja
MIT License
336 stars 81 forks source link

Event loop gets stuck unexpectedly #70

Closed gbl08ma closed 8 months ago

gbl08ma commented 8 months ago

Consider the following case, which I temporarily added to eventloop_test.go to ensure it could be reproduced outside of my project:

func TestEventLoop_BadCase(t *testing.T) {
    t.Parallel()
    const SCRIPT = `
    let aTimer;
    function a() {
        if(aTimer) {
            clearTimeout(aTimer);
        }
        console.log("ok");
        aTimer = setTimeout(a, 1000);
    }
    a();`

    prg, err := goja.Compile("main.js", SCRIPT, false)
    if err != nil {
        t.Fatal(err)
    }

    loop := NewEventLoop()
    loop.Start()

    loop.RunOnLoop(func(vm *goja.Runtime) {
        vm.RunProgram(prg)
    })

    time.Sleep(20 * time.Second)
    loop.Stop()
}

What I expected to see: "ok" being printed to the console roughly 20 times. What actually happens: "ok" only gets printed three times and the event loop gets unexpectedly stuck after that.

If the call to clearTimeout is removed, the code works as expected.

gbl08ma commented 8 months ago

I've already established that the reason why the loop gets stuck is that it actually exits, as loop.jobCount reaches 0 (and then, because it is running in the background, it is decremented further, with the loop exiting with a jobCount of -1). It seems there may be some sort of race where jobCount gets decremented more than it should.