From 80c2181ce934f32ae10732725dad1a9e96319e07 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 4 Sep 2026 17:08:14 +0100 Subject: refactor(pack): use vim.async Problem: vim.pack uses a private async implementation even though vim.async is now available. Solution: Remove the private implementation and run plugin operations in structured task scopes. Bound parallel work with semaphores and use protected awaits so cancellation still propagates. AI-assisted --- runtime/lua/vim/_async.lua | 110 --------------------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 runtime/lua/vim/_async.lua (limited to 'runtime/lua/vim/_async.lua') diff --git a/runtime/lua/vim/_async.lua b/runtime/lua/vim/_async.lua deleted file mode 100644 index f99ec97fb9..0000000000 --- a/runtime/lua/vim/_async.lua +++ /dev/null @@ -1,110 +0,0 @@ -local M = {} - -local max_timeout = 120000 -local copcall = package.loaded.jit and pcall or require('coxpcall').pcall - ---- @param thread thread ---- @param on_finish fun(err: string?, ...:any) ---- @param ... any -local function resume(thread, on_finish, ...) - --- @type {n: integer, [1]:boolean, [2]:string|function} - local ret = vim.F.pack_len(coroutine.resume(thread, ...)) - local stat = ret[1] - - if not stat then - -- Coroutine had error - on_finish(ret[2] --[[@as string]]) - elseif coroutine.status(thread) == 'dead' then - -- Coroutine finished - on_finish(nil, unpack(ret, 2, ret.n)) - else - local fn = ret[2] - --- @cast fn -string - - --- @type boolean, string? - local ok, err = copcall(fn, function(...) - resume(thread, on_finish, ...) - end) - - if not ok then - on_finish(err) - end - end -end - ---- @param func async fun(): ...:any ---- @param on_finish? fun(err: string?, ...:any) -function M.run(func, on_finish) - local res --- @type {n:integer, [integer]:any}? - resume(coroutine.create(func), function(err, ...) - res = vim.F.pack_len(err, ...) - if on_finish then - on_finish(err, ...) - end - end) - - return { - --- @param timeout? integer - --- @return any ... return values of `func` - wait = function(_self, timeout) - vim.wait(timeout or max_timeout, function() - return res ~= nil - end) - assert(res, 'timeout') - if res[1] then - error(res[1]) - end - return unpack(res, 2, res.n) - end, - } -end - ---- Asynchronous blocking wait ---- @async ---- @param argc integer ---- @param fun function ---- @param ... any func arguments ---- @return any ... -function M.await(argc, fun, ...) - assert(coroutine.running(), 'Async.await() must be called from an async function') - local args = vim.F.pack_len(...) --- @type {n:integer, [integer]:any} - - --- @param callback fun(...:any) - return coroutine.yield(function(callback) - args[argc] = assert(callback) - fun(unpack(args, 1, math.max(argc, args.n))) - end) -end - ---- @async ---- @param max_jobs integer ---- @param funs (async fun())[] -function M.join(max_jobs, funs) - if #funs == 0 then - return - end - - max_jobs = math.min(max_jobs, #funs) - - --- @type (async fun())[] - local remaining = { select(max_jobs + 1, unpack(funs)) } - local to_go = #funs - - M.await(1, function(on_finish) - local function run_next() - to_go = to_go - 1 - if to_go == 0 then - on_finish() - elseif #remaining > 0 then - local next_fun = table.remove(remaining) - M.run(next_fun, run_next) - end - end - - for i = 1, max_jobs do - M.run(funs[i], run_next) - end - end) -end - -return M -- cgit