Repository: neovim/neovim
File: src/gen/gen_api_dispatch.lua (Lua)

Code before:
  str = str:gsub(' +$', '')
  output:write(str:format(...))
end

-- start building lua output
output = assert(io.open(lua_c_bindings_outputf, 'wb'))

include_headers(output, headers)
output:write('\n')

--- @type {binding: string, api:string}[]
local lua_c_functions = {}

--- Generates C code to bridge RPC API <=> Lua.
---
--- Inspect the result here:
---    build/src/nvim/auto/api/private/dispatch_wrappers.generated.h
--- @param fn gen_api_dispatch.Function
local function process_function(fn)
  local lua_c_function_name = ('nlua_api_%s'):format(fn.name)
  write_shifted_output(
    [[

  static int %s(lua_State *lstate)
  {
    ENTER_LUA_ACTIVE_STATE(lstate);
    Error err = ERROR_INIT;
    Arena arena = ARENA_EMPTY;
    char *err_param = 0;
    if (lua_gettop(lstate) != %i) {
      api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s");
      goto exit_0;
    }
  ]],
    lua_c_function_name,
    #fn.parameters,
    #fn.parameters,
    (#fn.parameters == 1) and '' or 's'
  )
  lua_c_functions[#lua_c_functions + 1] = {
    binding = lua_c_function_name,
    api = fn.name,
  }

  if not fn.fast then
    write_shifted_output(
      [[
    if (!nlua_is_deferred_safe()) {
      return luaL_error(lstate, e_fast_api_disabled, "%s");
    }
    ]],

Review comment (suggestion):
`LEAVE_LUA_ACTIVE_STATE()` is not called if the function returns here:
```c
    if (!nlua_is_deferred_safe()) {
      return luaL_error(lstate, e_fast_api_disabled, "%s");
    }
```
Additionally, is it necessary to call `ENTER_LUA_ACTIVE_STATE()` this early? I think only the actual API call may use `active_lstate`.

Also I remembered I did something else that also involves saving and restoring in <https://github.com/neovim/neovim/pull/32622/files#diff-a9e7b6d06d43f0fab9faeacbd587790177f028f8118d867082513193fbdb4fb4> (not all the changes there are related) by just adding the saving and restoring above and below the actual function call.

Code after:
  str = str:gsub(' +$', '')
  output:write(str:format(...))
end

-- start building lua output
output = assert(io.open(lua_c_bindings_outputf, 'wb'))

include_headers(output, headers)
output:write('\n')

--- @type {binding: string, api:string}[]
local lua_c_functions = {}

--- Generates C code to bridge RPC API <=> Lua.
---
--- Inspect the result here:
---    build/src/nvim/auto/api/private/dispatch_wrappers.generated.h
--- @param fn gen_api_dispatch.Function
local function process_function(fn)
  local lua_c_function_name = ('nlua_api_%s'):format(fn.name)
  write_shifted_output(
    [[

  static int %s(lua_State *lstate)
  {
    Error err = ERROR_INIT;
    Arena arena = ARENA_EMPTY;
    char *err_param = 0;
    if (lua_gettop(lstate) != %i) {
      api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s");
      goto exit_0;
    }
  ]],
    lua_c_function_name,
    #fn.parameters,
    #fn.parameters,
    (#fn.parameters == 1) and '' or 's'
  )
  lua_c_functions[#lua_c_functions + 1] = {
    binding = lua_c_function_name,
    api = fn.name,
  }

  if not fn.fast then
    write_shifted_output(
      [[
    if (!nlua_is_deferred_safe()) {
      return luaL_error(lstate, e_fast_api_disabled, "%s");
    }
    ]],
      fn.name