wasmoon icon indicating copy to clipboard operation
wasmoon copied to clipboard

Cannot await inside callback

Open timstableford opened this issue 4 years ago • 2 comments

local res = sleep(1):next(function ()
    sleep(10):await()
    return 15
end)
print("res", res:await())

Returns

Error: Lua Error(ErrorRun/2): cannot resume dead coroutine
    at Thread.assertOk (/home/tstableford/projects/wasmoon/dist/index.js:409:23)
    at Thread.<anonymous> (/home/tstableford/projects/wasmoon/dist/index.js:142:22)
    at Generator.throw (<anonymous>)
    at rejected (/home/tstableford/projects/wasmoon/dist/index.js:26:69)

This makes sense because aren't async and aren't threads. That means they attempt to run within the parent thread. If they did run in a child thread then it would be possible to make jsFunc's async but then it would get a bit mad with async everywhere.

Maybe there's a good solution and maybe not, if there's not though it should be documented.

timstableford avatar Apr 06 '21 17:04 timstableford

A quickly workaround for that:

function async(callback)
    return function(...)
        local co = coroutine.create(callback)
        local safe, result = coroutine.resume(co, ...)

        return Promise.create(function(resolve, reject)
            local function step()
                if coroutine.status(co) == "dead" then
                    local send = safe and resolve or reject
                    return send(result)
                end

                safe, result = coroutine.resume(co)

                if safe and result == Promise.resolve(result) then
                    result:finally(step)
                else
                    step()
                end
            end

            result:finally(step)
        end)
    end
end

ceifa avatar Apr 07 '21 14:04 ceifa

Packages cannot use top-await too, since required files run on the main thread

local file = io.open("test.lua", "w+")
file:write([[
    coroutine.yield("potato")
]])
file:flush()

local co = coroutine.create(function()
    coroutine.yield("hello")
    require("test")
    coroutine.yield("world")
end)

print(coroutine.resume(co)) -- hello
print(coroutine.resume(co)) -- attempt to yield across a C-call boundary
print(coroutine.resume(co)) -- dead coroutine

ceifa avatar Jul 22 '21 17:07 ceifa