From 89135cff030b06f60cd596a9ae81cd9583987517 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 12 Feb 2024 21:38:37 -0500 Subject: [PATCH] fix(loader): remove cyclic dependency on vim.fs (when --luamod-dev) Problem: Loading `vim.fs` via the `vim.loader` Lua package loader will result in a stack overflow due to a cyclic dependency. This may happen when the `vim.fs` module isn't byte-compiled, i.e. when `--luamod-dev` is used (#27413). Solution: `vim.loader` depends on `vim.fs`. Therefore `vim.fs` should be loaded in advance. --- runtime/lua/vim/loader.lua | 5 +++-- test/functional/lua/loader_spec.lua | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index b77251cf7e..ec99e417c2 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -1,3 +1,4 @@ +local fs = vim.fs -- "vim.fs" is a dependency, so must be loaded early. local uv = vim.uv local uri_encode = vim.uri_encode --- @type function @@ -63,7 +64,7 @@ function Loader.get_hash(path) end local function normalize(path) - return vim.fs.normalize(path, { expand_env = false }) + return fs.normalize(path, { expand_env = false }) end --- Gets the rtp excluding after directories. @@ -432,7 +433,7 @@ end function Loader.lsmod(path) if not Loader._indexed[path] then Loader._indexed[path] = {} - for name, t in vim.fs.dir(path .. '/lua') do + for name, t in fs.dir(path .. '/lua') do local modpath = path .. '/lua/' .. name -- HACK: type is not always returned due to a bug in luv t = t or Loader.get_hash(modpath).type diff --git a/test/functional/lua/loader_spec.lua b/test/functional/lua/loader_spec.lua index cdb561330a..4e42a18405 100644 --- a/test/functional/lua/loader_spec.lua +++ b/test/functional/lua/loader_spec.lua @@ -3,10 +3,32 @@ local helpers = require('test.functional.helpers')(after_each) local exec_lua = helpers.exec_lua local command = helpers.command +local clear = helpers.clear local eq = helpers.eq describe('vim.loader', function() - before_each(helpers.clear) + before_each(clear) + + it('can work in compatibility with --luamod-dev #27413', function() + clear({ args = { '--luamod-dev' } }) + exec_lua [[ + vim.loader.enable() + + require("vim.fs") + + -- try to load other vim submodules as well (Nvim Lua stdlib) + for key, _ in pairs(vim._submodules) do + local modname = 'vim.' .. key -- e.g. "vim.fs" + + local lhs = vim[key] + local rhs = require(modname) + assert( + lhs == rhs, + ('%s != require("%s"), %s != %s'):format(modname, modname, tostring(lhs), tostring(rhs)) + ) + end + ]] + end) it('handles changing files (#23027)', function() exec_lua [[