neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit b2d471ab337e56f660eb7c89ae24f447f7b7a165
parent 4a34da82c18e6da1e46d6bf3d21082a6b6c8b947
Author: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date:   Thu,  7 Dec 2023 08:01:27 -0800

fix(lua): allow nil values in serialized Lua arrays (#26329)

When we convert a Lua table to an Object, we consider the table a
"dictionary" if it contains only string keys, and an array if it
contains all numeric indices with no gaps. While rare, Lua tables can
have both strictly numeric indices and gaps (e.g. { [2] = 2 }). These
currently cannot be serialized because it is not considered an array.

However, we know the maximum index of the table and as long as all of
the keys in the table are numeric, it is still possible to serialize
this table as an array. The missing indices will have nil values.
Diffstat:
Msrc/nvim/lua/converter.c | 6+-----
Mtest/functional/lua/api_spec.lua | 4++++
2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c @@ -148,7 +148,7 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate) } } else { if (tsize == 0 - || (tsize == ret.maxidx + || (tsize <= ret.maxidx && other_keys_num == 0 && ret.string_keys_num == 0)) { ret.type = kObjectTypeArray; @@ -1129,10 +1129,6 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err) } const size_t idx = cur.obj->data.array.size++; lua_rawgeti(lstate, -1, (int)idx + 1); - if (lua_isnil(lstate, -1)) { - lua_pop(lstate, 2); - continue; - } kvi_push(stack, cur); cur = (ObjPopStackItem) { .obj = &cur.obj->data.array.items[idx], diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua @@ -245,4 +245,8 @@ describe('luaeval(vim.api.…)', function() eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", 0, 1.5, "test")')) eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", true, {}, {[vim.type_idx]=vim.types.array})')) end) + + it('serializes sparse arrays in Lua', function() + eq({ [1] = vim.NIL, [2] = 2 }, exec_lua [[ return { [2] = 2 } ]]) + end) end)