Commit Graph

10361 Commits

Author SHA1 Message Date
Justin M. Keyes
25b522a75d backport: docs: misc, window (#39722)
- formalize `window-number` similar to `tabpage-number`.
- reference it from docs.
2026-05-11 21:06:59 +00:00
luukvbaal
5b8268356a fix(api): don't update 'title' when renaming non-curbuf #39743
Problem:  'title' is updated when changing the name of a non-current
          buffer with nvim_buf_set_name().
Solution: Set RedrawingDisabled when renaming the buffer.
(cherry picked from commit 96fc7c150f)
2026-05-11 20:24:27 +00:00
luukvbaal
d725ead5ec fix(messages): reset redirection message column after :echon #39472
Problem:  Message redirection column for captured output is not reset
          after :echon since (4260f73, e63346df).

Solution: Ensure msg_ext_append is set before the kind with :echon.
(cherry picked from commit ce9f4f0369)
2026-05-11 20:15:09 +00:00
zeertzjq
fa69cac7e3 fix(terminal): memory leak when pasting '=' register (#39738)
Problem:  Memory leak when pasting '=' register in terminal.
Solution: Free the register.
(cherry picked from commit 41e8201c6c)
2026-05-11 13:44:51 +00:00
zeertzjq
647b6be489 vim-patch:9.2.0461: Corrupted undofile causes use-after-free (#39707)
Problem:  The four pointer-resolution loops in u_read_undo() lack
          an i != j guard, so a header whose uh_next.seq equals
          its own uh_seq resolves uh_next.ptr to itself.  On
          buffer close, u_freeheader() sees uhp->uh_next.ptr !=
          NULL and skips updating b_u_oldhead, so u_blockfree()
          dereferences the freed header on the next iteration.
          The same pattern applies to uh_prev, uh_alt_next and
          uh_alt_prev.  A crafted .un~ file in the same directory
          as a text file can trigger the use-after-free and
          subsequent double-free when the buffer is closed.
          (Daniel Cervera)
Solution: Add an i != j guard to each of the four resolution
          loops, matching the guard already present in the
          duplicate-detection loop above.

closes: vim/vim#20168

Supported by AI

4f610f07b7

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 2d5f56c0aa)
2026-05-10 00:41:58 +00:00
zeertzjq
2902ec0541 vim-patch:9.2.0458: Crash with invalid shellredir/shellpipe value (#39691)
Problem:  Crash with invalid shellredir/shellpipe value
          (bfredl)
Solution: Validate the option and allow only a single "%s".

fixes:  vim/vim#20157
closes: vim/vim#20159

84ae09dd79

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit ffe87d91f7)
2026-05-09 01:38:36 +00:00
Luis Calle
79fd0b6655 fix(vim.range): empty ranges semantics vs regular ranges #39474
Problem:
- Empty ranges have different `<`, `<=`, `has` and `intersect` semantics compared to regular ranges.
- `to_inclusive_pos` assumes that the end position of a range is exclusive, which is not true for empty ranges

Solution:
Special case empty ranges in these operations.

(cherry picked from commit 416f3482e7)
2026-05-08 10:17:30 +00:00
Alexej Kowalew
2389cf2e39 fix(shell): preserve CR when :! outputs to binary-mode buffer #39558
Problem:
When `:!` writes shell output to a buffer, write_output() splits on `\r`, `\n`,
and `\r\n`, replacing the terminator byte with NUL. For a binary-mode buffer
this is wrong: `\r` should be preserved verbatim, not treated as a line
terminator. This wrong behavior causes a file like `\r\n` round-trips through
`:%!cat` to `\n`.

This was masked when 'shelltemp' was enabled, because output went through a temp
file and the regular file I/O path handled binary-mode correctly. Switching the
default to 'noshelltemp' exposed the bug, since output is now piped directly
into write_output().

Solution:
In `write_output()`, skip the `\r` and `\r\n` splits for a binary-mode buffer;
only split on `\n`.

(cherry picked from commit 832a68835b)
2026-05-08 08:11:25 +00:00
Nathan Zeng
d8a94658f5 refactor(test): use public enum in select_spec #39665
Problem: select_spec tests a public function, but uses private enums.

Solution: Replace private enums with public enums.
(cherry picked from commit a61c8f3580)
2026-05-08 08:00:12 +00:00
Justin M. Keyes
b3cd33d029 backport feat(tui): restore 'ttyfast' to control tty requests (#39667)
feat(tui): restore 'ttyfast' to control tty requests

Problem:
When running nvim on a remote machine over SSH, if there is high ping,
then bg detection may not complete in time. This results in a warning
every time nvim is started. #38648

Solution:
Restore 'ttyfast' option and allow it to control whether or not bg
detection is performed. Because this is during startup and before any
user config or commands, we use the environment variable
`NVIM_NOTTYFAST` to allow disabling `ttyfast` during initialization.

Co-authored-by: Kyle <50718101+kylesower@users.noreply.github.com>
2026-05-08 06:49:34 +00:00
zeertzjq
03af1ec931 vim-patch:9.2.0450: [security]: heap buffer overflow in spellfile.c read_compound() (#39660)
Problem:  read_compound() in spellfile.c computes the size of the regex
          pattern buffer using signed-int arithmetic on the attacker
          controlled SN_COMPOUND sectionlen.  With sectionlen=0x40000008
          and UTF-8 encoding active the multiplication wraps to 27 while
          the per-byte loop writes up to ~1B bytes, overflowing the heap.
          Reachable when loading a crafted .spl file (e.g. via 'set spell'
          after a modeline sets 'spelllang').  The cp/ap/crp allocations
          have the same int + 1 overflow class (Daniel Cervera)
Solution: Use type size_t as buffer size and reject values larger than
          COMPOUND_MAX_LEN (100000).  Apply the same size_t treatment to
          the cp/ap/crp allocations.

Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-q4jv-r9gj-6cwv

9299332917

Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit 0976ce255b)
2026-05-08 00:16:08 +00:00
Szymon Wilczek
dcf9e8a98e fix(treesitter): crash in ts_parser_delete after gc #39497
Problem:
parser_gc() calls ts_parser_delete() but leaves the userdata pointer
pointing to freed memory. If the GC finalizer runs at an unexpected time
(e.g. inside nvim_buf_get_lines #39411), a stale pointer could cause a crash.

Solution:
- NULL out `*ud` after ts_parser_delete() in parser_gc()
- Update parser_check() to handle NULL with a clear error message,
guarding all parser methods against UAF

Co-authored-by: Lewis Russell <lewis6991@gmail.com>
Signed-off-by: Szymon Wilczek <swilczek.lx@gmail.com>
(cherry picked from commit 0c3e6e1b0e)
2026-05-07 13:22:38 +00:00
Justin M. Keyes
6e44bd3c71 backport fix(treesitter): drop select() kwargs (#39647)
fix(treesitter): drop select() kwargs

Problem:
Unnecessary kwargs.

Solution:
Use param instead of kwargs.
2026-05-07 11:21:05 +00:00
Yi Ming
f54f566bf8 feat(diagnostic)!: deprecate format as a table 2026-05-07 12:03:02 +02:00
Justin M. Keyes
b982adfe10 docs: misc, rename "tabpage" 2026-05-07 12:03:02 +02:00
Nathan Zeng
a0dcdcd8a0 feat(treesitter): provide select()
Problem: No public method for treesitter incremental selection.

Solution: Add `vim.treesitter.select()`.
2026-05-07 12:03:02 +02:00
Justin M. Keyes
ad27075c8d feat(pos): pos:to_offset(), pos.offset() (#39639)
Problem:
For a given position, it is not easy to compare which of several other positions is closest to it.

Solution:
Add support for converting `vim.Pos` to a buffer byte offset.

This allows for sorting, e.g:
```lua
table.sort(positions, function(pos1, pos2)
  return pos1:to_offset() < pos2:to_offset()
end
```

Or a binary search, e.g:
```lua
vim.list.bisect(positions, pos, { key = function(pos) return pos:to_offset() end })
```

Co-authored-by: Yi Ming <ofseed@foxmail.com>
2026-05-07 05:16:53 -04:00
Tomasz N
70f22713a1 fix(ui2): entering the pager fails if <ESC> is remapped to :fclose (#39462)
Problem:  Entering the pager fails if <ESC> is remapped to :fclose by user.
Solution: Avoid executing mappings with nvim_feedkeys() that closes expanded cmdline.
(cherry picked from commit 2b7a00746d)
2026-05-06 13:58:25 +00:00
zeertzjq
0aa77cb78c vim-patch:9.2.0443: GUI: cancelling save dialog overwrites or discards unnamed buffer (#39617)
Problem:  When closing gvim with an unsaved unnamed buffer, choosing
          "Yes" in the "Save changes?" dialog and then "Cancel" in the
          file selection dialog either silently writes the buffer to a
          file named "Untitled" (overwriting any existing file with
          that name) or discards the buffer altogether
          (vibs29, after v9.1.0265).
Solution: In dialog_changed(), if browse_save_fname() leaves the buffer
          without a file name, treat it as a cancel and return without
          saving.  Also stop clearing the modified flag in the restore
          path on write failure, so the unsaved changes are kept and
          the caller (e.g. gui_shell_closed()) can also cancel the
          close.  Pre-fill the file dialog with "Untitled" to match
          the preceding "Save changes to ..." prompt.  Add a test for
          the write-failure path (Hirohito Higashi).

fixes:  vim/vim#20132
closes: vim/vim#20143

cf947e7ef0

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
(cherry picked from commit 2bb426ce4a)
2026-05-06 01:47:06 +00:00
zeertzjq
15a58bb02a vim-patch:9.2.0444: Cannot set 'path' option via modeline
Problem:  Cannot set 'path' option via modeline (zeertzjq, after v9.2.0435)
Solution: Revert the part that disallows setting 'path' via modeline.

closes: vim/vim#20137

88fb739918

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit d1c3d6fbaa)
2026-05-06 00:54:27 +00:00
zeertzjq
b013940391 vim-patch:9.2.0435: [security]: backticks in 'path' may cause shell execution on completion
Problem:  [security]: Backticks enclosed shell commands in the 'path'
          option value are executed during completion (q1uf3ng).
Solution: Skip path entries containing backticks, add P_SECURE to 'path'
          option, so that it cannot be set from a modeline (for symmetry with
          the 'cdpath' option)

Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-hwg5-3cxw-wvvg

Supported by AI.

190cb3c2b9

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit b06f8b174f)
2026-05-06 00:54:27 +00:00
David Balatero
a5482eeb9f test: flaky terminal channel exitcode check #39580
Problem:
The `nvim_get_chan_info()` terminal channel test used `shell-test INTERACT` to verify that `jobstop()` reports an unhandled `SIGHUP` as exit code `129`.

`INTERACT` reads from stdin with `fgets()`, so closing the PTY could race with `SIGHUP` delivery. If `fgets()` observed EOF first, `shell-test` exited normally with code `0`, causing intermittent failures on slower sanitizer builds.

Solution:
Add a `shell-test HOLD` mode that prints a readiness prompt and then waits without reading stdin. Use it for the `SIGHUP` assertion so PTY EOF cannot make the helper exit normally before the signal path is observed.

(cherry picked from commit 78111e5371)
2026-05-05 23:21:25 +00:00
Yi Ming
e67f9c5853 fix(lua): avoid __index when deciding if a table is a list #39556
Problem:
When a table has `__index`, `vim.islist` is unreliable.

Solution:
Index using `rawget`.

(cherry picked from commit 264fbc0ace)
2026-05-05 20:54:41 +00:00
David Balatero
c9cb49358b test: unreliable pack_spec.after_each: "EBUSY: resource busy or locked" #39606
Problem:
`EBUSY` during cleanup:
Windows CI can intermittently fail `pack_spec.lua` with `EBUSY` while removing
`site/pack/core/opt/plugindirs`.

This can happen because:
- the test Nvim session may still be alive when `after_each()` removes the pack
  directory
- Windows does not allow removing a directory while another process still has an
  open handle below it
- startup-time `vim.pack.add()` performs a real `git clone`, so process and file
  handle release timing can vary on slower runners

Startup timeout:
The startup tests can also fail before cleanup because they wait for `_G.done`
with a fixed timeout. That timeout includes the time needed for startup to run
`vim.pack.add()` and finish the local clone.

Solution:
Close before cleanup:
Capture the pack, lockfile, and log paths while the test Nvim session is still
available, then call `n.check_close()` before removing the pack directory.

Extend Windows startup wait:
Increase the `_G.done` retry budget only on Windows so startup-time
`vim.pack.add()` has more time to finish on slower CI runners.

(cherry picked from commit 19a2ef5afa)
2026-05-05 18:33:31 +00:00
David Balatero
d9baaf7da1 fix(ci): generate more data to stress output throttling test #39577
Problem:
This test would sometimes fail to match lines starting with `.` (indicating throttling) due to a race condition, likely because throttling completed before the test could properly assert.

Solution:
I 6x'd the amount of test data we were pushing into `nvim` in an attempt to trigger throttling consistently.

I don't _love_ this solution as it is still non-deterministic and might not hold up over time.

A good solution would be: create a deterministic way to pause neovim in a functional test, assert on the temporarily throttle state, then unpause neovim. However, it's likely this is not possible today and will take too much effort.

Before test time (30000 lines): ~0.40sec/run
After test time (150000 lines): ~1.7sec/run

This increases test runtime, but if it removes flakes I think it's worth it.

(cherry picked from commit cbedd537ac)
2026-05-04 16:53:44 +00:00
zeertzjq
f9f2596288 vim-patch:9.2.0436: Buffer overflow when parsing overlong errorformat lines (#39578)
Problem:  When an error line in a file passed to :cfile / :cgetfile is
          longer than IOSIZE, qf_parse_file_pfx() copies the tail
          into the fixed-size IObuff with STRMOVE(), overflowing the heap buffer.
          The same code path can also loop indefinitely because
          qf_parse_file_pfx() always returns QF_MULTISCAN when a
          tail is present, and qf_init_ext() unconditionally goes
          to "restofline" without bounding the tail length (Nabih).
Solution: Remove the STRMOVE() into IObuff.  In the QF_MULTISCAN
          branch, alias linebuf into the tail directly and update
          linelen, requiring strict progress (new length less than
          the previous length) before retrying; otherwise ignore
          the line.

closes: vim/vim#20126

Supported by AI

77677c33de

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 0e69a38026)
2026-05-03 23:34:55 +00:00
David Balatero
4f22640b86 fix(treesitter): get_node_text() inconsistent trailing newline #39409
Problem:
`get_node_text()` returned inconsistent results between buffer and
string sources when a node's range ends at `end_col == 0` (i.e. the node
ends with a newline). The buffer path dropped the trailing newline; the
string path included it correctly.

Solution:
Append `'\n'` in `buf_range_get_text()` when `end_col == 0` and
`start_row ~= end_row`. The `start_row ~= end_row` guard excludes
zero-width nodes at column 0, which should return `""`.

Remove the workaround in the `#trim!` directive that manually
compensated for the missing newline.

Strip whitespace in `resolve_lang()` so injection language nodes ending
at `end_col == 0` (e.g. `">lua\n"`) still resolve correctly.

(cherry picked from commit 7ed5609439)
2026-05-03 13:53:04 +00:00
Tristan Knight
8919b02eba fix(lsp): dynamic registration for off-spec method #39544
Problem:
LSP clients previously did not handle dynamic registration for off-spec methods

Solution:
Update the client logic to assume support for dynamic registration when
the method is unknown. Adjust the registration provider fallback and
enhance tests to verify correct behaviour for unknown methods and their
registration options. This improves compatibility with servers using
custom dynamic registrations.

AI-assisted: OpenCode
(cherry picked from commit 344d984ed2)
2026-05-02 10:54:42 +08:00
Yochem van Rosmalen
e069022215 fix(help): fix CTRL character issue for :help {subject} #39537
Problem:
The argument to `:help` is normalized to fit the general tag format.
I.e. i^U-default, iCTRL-U-default and i_CTRL_U-default should all point
to the i_CTRL_U-default tag. Our normalization adds an underscore around
the CTRL keycode, e.g. iCTRL-GCTRL-J becomes i_CTRL-G_CTRL-J. That's not
necessary if the following part starts with a dash, like the case of
iCTRL-U-default.

Solution:
Do not insert an underscore if the following character is a dash/minus
(-).

(cherry picked from commit 84ae70c172)
2026-05-01 10:50:35 +00:00
Justin M. Keyes
4b424a06c5 backport fix(lsp): send didClose, didOpen when languageId changes (#39519)
fix(lsp): send didClose, didOpen when languageId changes

Problem:
If a buffer's filetype changes after the LSP client has already
attached (e.g. from json to jsonc via a modeline), but the client
supports both filetypes, it stays attached. It does not notify the
server of the new languageId, causing the server to incorrectly process
the file using the old languageId.

Solution:
Save the languageId used during textDocument/didOpen, and send
textDocument/didClose + textDocument/didOpen when buffer's languageId
changed.

Lsp spec:
0003fb53f1/_specifications/lsp/3.18/textDocument/didOpen.md (L5)
> If the language id of a document changes, the client
> needs to send a textDocument/didClose to the server followed by a
> textDocument/didOpen with the new language id if the server handles
> the new language id as well.

AI-assisted: Gemini 3.1 Pro

Co-authored-by: phanium <91544758+phanen@users.noreply.github.com>
2026-04-30 13:09:55 +00:00
Olivia Kinnear
c9ca59ad28 backport: fix(lsp): util.lua attempt to concatenate userdata #39510
Problem:
Error when querying document symbols using python-lsp-server:

    lsp/util.lua:1955: attempt to concatenate field 'containerName' (a userdata value)

Solution:
Check for `vim.NIL`.

(cherry picked from commit 1799aaebda)
2026-04-29 16:13:47 -04:00
neovim-backports[bot]
378f5f49b3 backport: fix(lsp): show meaningful error on invalid completion response (#39476)
Problem: vim.NIL is truthy in Lua, so `#(result.items or result)`
crashes on `#vim.NIL` when servers return null.

Solution: skip spec-allowed result=null silently, raise an error
on items=null with the server name.

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion
(cherry picked from commit b9431b340f)

Co-authored-by: glepnir <glephunter@gmail.com>
2026-04-28 11:27:50 -04:00
zeertzjq
34bf0472ab fix(marks): don't use spell decorations from other lines (#39441)
Spell decorations from other lines aren't relevant to the current line.
Also, decor_redraw_col() can only go forward, while spell navigation
needs to go both forward and backward.

(cherry picked from commit 46c83ce321)
2026-04-27 23:36:36 +00:00
Justin M. Keyes
fb56d50032 fix(eval): writestring() handling of null #39328
Problem:
- write_blob, write_string dereference args which may be NULL.
- `writefile(v:_null_blob, …)` fails.

Solution:
- Fix the annotation.
- Handle null blob.

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
(cherry picked from commit 6d0cdcd605)
2026-04-26 14:27:11 +00:00
Luis Calle
49efe692f3 feat(vim.pos): accept buf=0 for current buf #39414 2026-04-26 12:41:06 +02:00
Yi Ming
828a35b14f feat(docs): render class dot members as module functions
AI-assisted: Codex
2026-04-26 12:39:45 +02:00
Justin M. Keyes
26678ebbd8 backport: docs: misc (#39395) 2026-04-25 13:51:22 -04:00
zeertzjq
f0baa18043 fix(channel): stack-buffer-overflow with exit during connection (#39387)
Problem:  When Nvim exits while connecting to a socket it leads to
          stack-buffer-overflow.
Solution: Associate the handle with the Stream and use the Stream's
          internal_close_cb to update the "closed" status.
(cherry picked from commit 4ed2e66d2e)
2026-04-25 12:38:20 +00:00
zeertzjq
e5114d03b5 test: add finally() to meta file (#39388)
(cherry picked from commit df8cf0ed25)
2026-04-25 10:10:25 +00:00
Tristan Knight
aedbae4ab6 fix(lsp): handle self-mapped methods in supports_method #39383
Problem:
The LSP client incorrectly checks for server capabilities when determining
support for self-mapped methods (e.g., 'shutdown'), which do not have
corresponding capabilities in the server's response. This leads to false
negatives when checking if such methods are supported.
This was handled correctly for dynamic registrations, but not for static.

Methods such as 'shutdown', do not have a related server capability and should
be assumed to be supported.

Solution:
Update the `supports_method` logic to always return true for self-mapped
methods.

(cherry picked from commit f83d0b9653)
2026-04-24 23:19:16 +00:00
neovim-backports[bot]
e5d6d2e769 backport: fix(api): leak preview callback LuaRef in nvim_create_user_command (#39377)
Problem:
Invalid `nvim_create_user_command` calls can leak the
`preview` callback reference after Neovim has taken ownership of it.

1. build with {a,l}san
2. run:
    ```sh
    <path/to/nvim> --headless -u NONE --clean +'lua
    for i = 1, 100 do
      pcall(vim.api.nvim_create_user_command,
        "some very epic stuff" .. i,
        {}, -- NOTE: this is INVALID (not a function or string)
        { preview = function() end })
    end
    vim.cmd("qa!")
    ' +qa
    ```
3. see:
    ```
    100 lua references were leaked!
    ```

Solution:
Clear `preview_luaref` in `err:`.

(cherry picked from commit 393f687503)

Co-authored-by: Barrett Ruth <62671086+barrettruth@users.noreply.github.com>
2026-04-24 17:27:46 -04:00
neovim-backports[bot]
4df16ecdb9 backport: fix(api): LuaRef leak in nvim_set_keymap on LHS too long (>=66 bytes) (#39376)
Problem: `nvim_set_keymap` leaks the `callback` `LuaRef` when the
LHS is too long.

Solution: Make `set_maparg_lhs_rhs` transfer `rhs_lua` to
`MapArguments` up front so the caller always owns the ref.

(cherry picked from commit 58aad59e1c)

Co-authored-by: Barrett Ruth <62671086+barrettruth@users.noreply.github.com>
2026-04-24 17:27:14 -04:00
Justin M. Keyes
3b69e3d0cf test: fix merge conflict 2026-04-24 20:18:19 +02:00
glepnir
3d923bfa50 test: curbuf initialized in describe-block
Problem: curbuf was initialized at describe-block load time
before any Nvim session existed.

Solution: Replace with 0 directly at call sites.
2026-04-24 15:33:31 +02:00
Barrett Ruth
654c964d1a fix(trust): hash unchanged empty buffers as empty files #39027
Problem:
`vim.secure.trust()` hashes an unchanged empty buffer as
a newline, so trusting an empty file by buffer never works.

Solution:
Hash unchanged empty-buffers `''` so buffer-based
trust matches the on-disk empty file.

(cherry picked from commit 0a8218a2b4)
2026-04-23 23:38:56 +00:00
Barrett Ruth
c4d3a3d363 fix(lsp): filter code_action diagnostics to the cursor #38988
Problem:
Cursor-position `vim.lsp.buf.code_action()` requests include all diagnostics on the current line, so unrelated same-line diagnostics affect the returned actions.

Solution:
Filter same-line diagnostics to the cursor position for cursor-position requests.

(cherry picked from commit ecb8402197)
2026-04-23 23:07:26 +00:00
Ashley Hauck
93dc301781 fix(lsp): callHierarchy/outgoingCalls ranges are relative to caller, not callee #39336
Problem:
The fromRanges field of the result of callHierarchy/outgoingCalls is
documented as being relative to the caller. Using
vim.lsp.buf.outgoing_calls() opened the qflist with an entry with the
callee's filename, but the caller's line number.

Solution:
Open the qflist with the callers file (the bufnr from the request),
rather than the callees (the uri from the resulting CallHierarchyItem)

(cherry picked from commit 7e006b06c4)
2026-04-23 23:07:07 +00:00
Barrett Ruth
39e8c584d5 fix(terminal): memory leak in pending TermRequest StringBuilder #39333
Problem: Destroying a terminal with pending `TermRequest` events leaks
memory.

Solution: Make `emit_termrequest` the sole owner of its `pending_send`
allocation.

(cherry picked from commit 19ef632dec)
2026-04-23 23:05:20 +00:00
Justin M. Keyes
f945aa451b refactor(test): deduplicate trust tests 2026-04-23 23:01:15 +02:00
atusy
27d01f2dbb fix(lsp): handle null id in JSON-RPC responses
Problem:
LSP spec allows response message to have a null request-id.
This may happen when for example client sends unparseable request.
https://github.com/microsoft/language-server-protocol/issues/196

Solution:
Guard the server response branches against id=vim.NIL (json null),
and handle error responses with null id by logging a warning
and dispatching on error.

Problem:
CI (ubuntu asan, ubuntu tsan, windows) reports `uv_loop_close()
hang?` from the two new null-id response tests. The leaked
handle is the server-side accepted TCP socket created inside
`server:listen` callback. The tests closed only the listener
but not the accepted socket, so libuv could not finish shutting
down the loop and each test session took ~2s extra to exit.

Solution:
Hoist the accepted socket to the outer `exec_lua` scope and
close it at teardown before closing the listener. The close
runs synchronously inside `exec_lua`, so the loop has time to
dispose the handle before the session exits.

* test(lsp): close accepted socket on read-loop exit/error

Match the precedent in the handler test ("handler can return
false as response") and the shared `_create_tcp_server` helper
in `test/functional/plugin/lsp/testutil.lua`: close the
accepted socket from inside the `create_read_loop` exit/error
callbacks. The teardown close added in the previous commit
remains as belt-and-suspenders, so the socket is disposed
whether the server goes away first or the client does.
2026-04-23 23:00:25 +02:00