build(lua): vendor coxpcall

Do not require luarocks on PUC lua CI just because of this single lua file
This commit is contained in:
bfredl 2023-09-09 23:45:06 +02:00
parent 87db6d894a
commit 25e51d393a
5 changed files with 114 additions and 6 deletions

View File

@ -3,3 +3,4 @@
/test
/runtime/lua/vim/re.lua
/runtime/lua/vim/_meta/options.lua
/runtime/lua/coxpcall.lua

View File

@ -224,7 +224,9 @@ add_glob_target(
FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr luacheck -q
GLOB_DIRS runtime/ scripts/ src/ test/
GLOB_PAT *.lua
EXCLUDE runtime/lua/vim/_meta/.*
EXCLUDE
runtime/lua/vim/_meta/.*
runtime/lua/coxpcall.lua
TOUCH_STRATEGY SINGLE)
add_dependencies(lintlua-luacheck lua-dev-deps)
@ -237,6 +239,7 @@ add_glob_target(
EXCLUDE
/runtime/lua/vim/re.lua
/runtime/lua/vim/_meta/.*
/runtime/lua/coxpcall.lua
TOUCH_STRATEGY SINGLE)
add_custom_target(lintlua)

View File

@ -143,6 +143,7 @@ These dependencies are "vendored" (inlined), we must update the sources manually
* Run `scripts/gen_lsp.lua` to update.
* `src/bit.c`: only for PUC lua: port of `require'bit'` from luajit https://bitop.luajit.org/
* [treesitter parsers](https://github.com/neovim/neovim/blob/fcc24e43e0b5f9d801a01ff2b8f78ce8c16dd551/cmake.deps/CMakeLists.txt#L197-L210)
* `runtime/lua/coxpcall.lua`: coxpcall (only needed for PUC lua, builtin to luajit)
### Forks

View File

@ -97,8 +97,3 @@ endif()
add_custom_target(test_deps)
Download(luacheck 1.1.0-1 ${LUACHECK_EXE})
if(PREFER_LUA)
Download(coxpcall 1.17.0-1)
add_dependencies(test_deps coxpcall)
endif()

108
runtime/lua/coxpcall.lua Normal file
View File

@ -0,0 +1,108 @@
-------------------------------------------------------------------------------
-- Coroutine safe xpcall and pcall versions
--
-- Encapsulates the protected calls with a coroutine based loop, so errors can
-- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines
-- yielding inside the call to pcall or xpcall.
--
-- Authors: Roberto Ierusalimschy and Andre Carregal
-- Contributors: Thomas Harning Jr., Ignacio Burgueño, Fabio Mascarenhas
--
-- Copyright 2005 - Kepler Project
--
-- $Id: coxpcall.lua,v 1.13 2008/05/19 19:20:02 mascarenhas Exp $
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Checks if (x)pcall function is coroutine safe
-------------------------------------------------------------------------------
local function isCoroutineSafe(func)
local co = coroutine.create(function()
return func(coroutine.yield, function() end)
end)
coroutine.resume(co)
return coroutine.resume(co)
end
-- No need to do anything if pcall and xpcall are already safe.
if isCoroutineSafe(pcall) and isCoroutineSafe(xpcall) then
copcall = pcall
coxpcall = xpcall
return { pcall = pcall, xpcall = xpcall, running = coroutine.running }
end
-------------------------------------------------------------------------------
-- Implements xpcall with coroutines
-------------------------------------------------------------------------------
local performResume, handleReturnValue
local oldpcall, oldxpcall = pcall, xpcall
local pack = table.pack or function(...) return {n = select("#", ...), ...} end
local unpack = table.unpack or unpack
local running = coroutine.running
local coromap = setmetatable({}, { __mode = "k" })
function handleReturnValue(err, co, status, ...)
if not status then
return false, err(debug.traceback(co, (...)), ...)
end
if coroutine.status(co) == 'suspended' then
return performResume(err, co, coroutine.yield(...))
else
return true, ...
end
end
function performResume(err, co, ...)
return handleReturnValue(err, co, coroutine.resume(co, ...))
end
local function id(trace, ...)
return trace
end
function coxpcall(f, err, ...)
local current = running()
if not current then
if err == id then
return oldpcall(f, ...)
else
if select("#", ...) > 0 then
local oldf, params = f, pack(...)
f = function() return oldf(unpack(params, 1, params.n)) end
end
return oldxpcall(f, err)
end
else
local res, co = oldpcall(coroutine.create, f)
if not res then
local newf = function(...) return f(...) end
co = coroutine.create(newf)
end
coromap[co] = current
return performResume(err, co, ...)
end
end
local function corunning(coro)
if coro ~= nil then
assert(type(coro)=="thread", "Bad argument; expected thread, got: "..type(coro))
else
coro = running()
end
while coromap[coro] do
coro = coromap[coro]
end
if coro == "mainthread" then return nil end
return coro
end
-------------------------------------------------------------------------------
-- Implements pcall with coroutines
-------------------------------------------------------------------------------
function copcall(f, ...)
return coxpcall(f, id, ...)
end
return { pcall = copcall, xpcall = coxpcall, running = corunning }