Skip to content

Commit a09c7a5

Browse files
authored
Merge #30384 test: spawn_wait()
2 parents b52531a + 700a25e commit a09c7a5

File tree

9 files changed

+224
-83
lines changed

9 files changed

+224
-83
lines changed

Diff for: MAINTAIN.md

+2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ These dependencies are "vendored" (inlined), we must update the sources manually
143143

144144
* `src/mpack/`: [libmpack](https://github.com/libmpack/libmpack)
145145
* send improvements upstream!
146+
* `src/mpack/lmpack.c`: [libmpack-lua](https://github.com/libmpack/libmpack-lua)
147+
* send improvements upstream!
146148
* `src/xdiff/`: [xdiff](https://github.com/git/git/tree/master/xdiff)
147149
* `src/cjson/`: [lua-cjson](https://github.com/openresty/lua-cjson)
148150
* `src/klib/`: [Klib](https://github.com/attractivechaos/klib)

Diff for: runtime/lua/coxpcall.lua

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
-------------------------------------------------------------------------------
2+
-- (Not needed for LuaJIT or Lua 5.2+)
3+
--
24
-- Coroutine safe xpcall and pcall versions
35
--
6+
-- https://keplerproject.github.io/coxpcall/
7+
--
48
-- Encapsulates the protected calls with a coroutine based loop, so errors can
59
-- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines
610
-- yielding inside the call to pcall or xpcall.

Diff for: src/nvim/grid.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,8 @@ void grid_line_start(ScreenGrid *grid, int row)
383383

384384
assert((size_t)grid_line_maxcol <= linebuf_size);
385385

386-
if (rdb_flags & kOptRdbFlagInvalid) {
386+
if (full_screen && (rdb_flags & kOptRdbFlagInvalid)) {
387+
assert(linebuf_char);
387388
// Current batch must not depend on previous contents of linebuf_char.
388389
// Set invalid values which will cause assertion failures later if they are used.
389390
memset(linebuf_char, 0xFF, sizeof(schar_T) * linebuf_size);

Diff for: src/nvim/main.c

+1
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ int main(int argc, char **argv)
634634
if (params.luaf != NULL) {
635635
// Like "--cmd", "+", "-c" and "-S", don't truncate messages.
636636
msg_scroll = true;
637+
DLOG("executing Lua -l script");
637638
bool lua_ok = nlua_exec_file(params.luaf);
638639
TIME_MSG("executing Lua -l script");
639640
if (msg_didout) {

Diff for: test/client/msgpack_rpc_stream.lua renamed to test/client/rpc_stream.lua

+28-21
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,41 @@
1+
---
2+
--- Reading/writing of msgpack over any of the stream types from `uv_stream.lua`.
3+
--- Does not implement the RPC protocol, see `session.lua` for that.
4+
---
5+
16
local mpack = vim.mpack
27

38
local Response = {}
49
Response.__index = Response
510

6-
function Response.new(msgpack_rpc_stream, request_id)
11+
function Response.new(rpc_stream, request_id)
712
return setmetatable({
8-
_msgpack_rpc_stream = msgpack_rpc_stream,
13+
_rpc_stream = rpc_stream,
914
_request_id = request_id,
1015
}, Response)
1116
end
1217

1318
function Response:send(value, is_error)
14-
local data = self._msgpack_rpc_stream._session:reply(self._request_id)
19+
local data = self._rpc_stream._session:reply(self._request_id)
1520
if is_error then
16-
data = data .. self._msgpack_rpc_stream._pack(value)
17-
data = data .. self._msgpack_rpc_stream._pack(mpack.NIL)
21+
data = data .. self._rpc_stream._pack(value)
22+
data = data .. self._rpc_stream._pack(mpack.NIL)
1823
else
19-
data = data .. self._msgpack_rpc_stream._pack(mpack.NIL)
20-
data = data .. self._msgpack_rpc_stream._pack(value)
24+
data = data .. self._rpc_stream._pack(mpack.NIL)
25+
data = data .. self._rpc_stream._pack(value)
2126
end
22-
self._msgpack_rpc_stream._stream:write(data)
27+
self._rpc_stream._stream:write(data)
2328
end
2429

25-
--- @class test.MsgpackRpcStream
30+
--- Nvim msgpack RPC stream.
31+
---
32+
--- @class test.RpcStream
2633
--- @field private _stream test.Stream
2734
--- @field private __pack table
28-
local MsgpackRpcStream = {}
29-
MsgpackRpcStream.__index = MsgpackRpcStream
35+
local RpcStream = {}
36+
RpcStream.__index = RpcStream
3037

31-
function MsgpackRpcStream.new(stream)
38+
function RpcStream.new(stream)
3239
return setmetatable({
3340
_stream = stream,
3441
_pack = mpack.Packer(),
@@ -50,10 +57,10 @@ function MsgpackRpcStream.new(stream)
5057
},
5158
}),
5259
}),
53-
}, MsgpackRpcStream)
60+
}, RpcStream)
5461
end
5562

56-
function MsgpackRpcStream:write(method, args, response_cb)
63+
function RpcStream:write(method, args, response_cb)
5764
local data
5865
if response_cb then
5966
assert(type(response_cb) == 'function')
@@ -66,10 +73,10 @@ function MsgpackRpcStream:write(method, args, response_cb)
6673
self._stream:write(data)
6774
end
6875

69-
function MsgpackRpcStream:read_start(request_cb, notification_cb, eof_cb)
76+
function RpcStream:read_start(on_request, on_notification, on_eof)
7077
self._stream:read_start(function(data)
7178
if not data then
72-
return eof_cb()
79+
return on_eof()
7380
end
7481
local type, id_or_cb, method_or_error, args_or_result
7582
local pos = 1
@@ -78,9 +85,9 @@ function MsgpackRpcStream:read_start(request_cb, notification_cb, eof_cb)
7885
type, id_or_cb, method_or_error, args_or_result, pos = self._session:receive(data, pos)
7986
if type == 'request' or type == 'notification' then
8087
if type == 'request' then
81-
request_cb(method_or_error, args_or_result, Response.new(self, id_or_cb))
88+
on_request(method_or_error, args_or_result, Response.new(self, id_or_cb))
8289
else
83-
notification_cb(method_or_error, args_or_result)
90+
on_notification(method_or_error, args_or_result)
8491
end
8592
elseif type == 'response' then
8693
if method_or_error == mpack.NIL then
@@ -94,12 +101,12 @@ function MsgpackRpcStream:read_start(request_cb, notification_cb, eof_cb)
94101
end)
95102
end
96103

97-
function MsgpackRpcStream:read_stop()
104+
function RpcStream:read_stop()
98105
self._stream:read_stop()
99106
end
100107

101-
function MsgpackRpcStream:close(signal)
108+
function RpcStream:close(signal)
102109
self._stream:close(signal)
103110
end
104111

105-
return MsgpackRpcStream
112+
return RpcStream

Diff for: test/client/session.lua

+45-13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1+
---
2+
--- Nvim msgpack-RPC protocol session. Manages requests/notifications/responses.
3+
---
4+
15
local uv = vim.uv
2-
local MsgpackRpcStream = require('test.client.msgpack_rpc_stream')
6+
local RpcStream = require('test.client.rpc_stream')
37

8+
--- Nvim msgpack-RPC protocol session. Manages requests/notifications/responses.
9+
---
410
--- @class test.Session
5-
--- @field private _pending_messages string[]
6-
--- @field private _msgpack_rpc_stream test.MsgpackRpcStream
11+
--- @field private _pending_messages string[] Requests/notifications received from the remote end.
12+
--- @field private _rpc_stream test.RpcStream
713
--- @field private _prepare uv.uv_prepare_t
814
--- @field private _timer uv.uv_timer_t
9-
--- @field private _is_running boolean
15+
--- @field private _is_running boolean true during `Session:run()` scope.
1016
--- @field exec_lua_setup boolean
1117
local Session = {}
1218
Session.__index = Session
@@ -51,9 +57,10 @@ local function coroutine_exec(func, ...)
5157
end))
5258
end
5359

60+
--- Creates a new msgpack-RPC session.
5461
function Session.new(stream)
5562
return setmetatable({
56-
_msgpack_rpc_stream = MsgpackRpcStream.new(stream),
63+
_rpc_stream = RpcStream.new(stream),
5764
_pending_messages = {},
5865
_prepare = uv.new_prepare(),
5966
_timer = uv.new_timer(),
@@ -91,10 +98,13 @@ function Session:next_message(timeout)
9198
return table.remove(self._pending_messages, 1)
9299
end
93100

101+
--- Sends a notification to the RPC endpoint.
94102
function Session:notify(method, ...)
95-
self._msgpack_rpc_stream:write(method, { ... })
103+
self._rpc_stream:write(method, { ... })
96104
end
97105

106+
--- Sends a request to the RPC endpoint.
107+
---
98108
--- @param method string
99109
--- @param ... any
100110
--- @return boolean, table
@@ -114,8 +124,16 @@ function Session:request(method, ...)
114124
return true, result
115125
end
116126

117-
--- Runs the event loop.
127+
--- Processes incoming RPC requests/notifications until exhausted.
128+
---
129+
--- TODO(justinmk): luaclient2 avoids this via uvutil.cb_wait() + uvutil.add_idle_call()?
130+
---
131+
--- @param request_cb function Handles requests from the sever to the local end.
132+
--- @param notification_cb function Handles notifications from the sever to the local end.
133+
--- @param setup_cb function
134+
--- @param timeout number
118135
function Session:run(request_cb, notification_cb, setup_cb, timeout)
136+
--- Handles an incoming request.
119137
local function on_request(method, args, response)
120138
coroutine_exec(request_cb, method, args, function(status, result, flag)
121139
if status then
@@ -126,6 +144,7 @@ function Session:run(request_cb, notification_cb, setup_cb, timeout)
126144
end)
127145
end
128146

147+
--- Handles an incoming notification.
129148
local function on_notification(method, args)
130149
coroutine_exec(notification_cb, method, args)
131150
end
@@ -160,39 +179,45 @@ function Session:close(signal)
160179
if not self._prepare:is_closing() then
161180
self._prepare:close()
162181
end
163-
self._msgpack_rpc_stream:close(signal)
182+
self._rpc_stream:close(signal)
164183
self.closed = true
165184
end
166185

186+
--- Sends a request to the RPC endpoint, without blocking (schedules a coroutine).
167187
function Session:_yielding_request(method, args)
168188
return coroutine.yield(function(co)
169-
self._msgpack_rpc_stream:write(method, args, function(err, result)
189+
self._rpc_stream:write(method, args, function(err, result)
170190
resume(co, err, result)
171191
end)
172192
end)
173193
end
174194

195+
--- Sends a request to the RPC endpoint, and blocks (polls event loop) until a response is received.
175196
function Session:_blocking_request(method, args)
176197
local err, result
177198

199+
-- Invoked when a request is received from the remote end.
178200
local function on_request(method_, args_, response)
179201
table.insert(self._pending_messages, { 'request', method_, args_, response })
180202
end
181203

204+
-- Invoked when a notification is received from the remote end.
182205
local function on_notification(method_, args_)
183206
table.insert(self._pending_messages, { 'notification', method_, args_ })
184207
end
185208

186-
self._msgpack_rpc_stream:write(method, args, function(e, r)
209+
self._rpc_stream:write(method, args, function(e, r)
187210
err = e
188211
result = r
189212
uv.stop()
190213
end)
191214

215+
-- Poll for incoming requests/notifications received from the remote end.
192216
self:_run(on_request, on_notification)
193217
return (err or self.eof_err), result
194218
end
195219

220+
--- Polls for incoming requests/notifications received from the remote end.
196221
function Session:_run(request_cb, notification_cb, timeout)
197222
if type(timeout) == 'number' then
198223
self._prepare:start(function()
@@ -202,14 +227,21 @@ function Session:_run(request_cb, notification_cb, timeout)
202227
self._prepare:stop()
203228
end)
204229
end
205-
self._msgpack_rpc_stream:read_start(request_cb, notification_cb, function()
230+
self._rpc_stream:read_start(request_cb, notification_cb, function()
206231
uv.stop()
207-
self.eof_err = { 1, 'EOF was received from Nvim. Likely the Nvim process crashed.' }
232+
233+
--- @diagnostic disable-next-line: invisible
234+
local stderr = self._rpc_stream._stream.stderr --[[@as string?]]
235+
-- See if `ProcStream.stderr` has anything useful.
236+
stderr = '' ~= ((stderr or ''):match('^%s*(.*%S)') or '') and ' stderr:\n' .. stderr or ''
237+
238+
self.eof_err = { 1, 'EOF was received from Nvim. Likely the Nvim process crashed.' .. stderr }
208239
end)
209240
uv.run()
210241
self._prepare:stop()
211242
self._timer:stop()
212-
self._msgpack_rpc_stream:read_stop()
243+
self._rpc_stream:read_stop()
213244
end
214245

246+
--- Nvim msgpack-RPC session.
215247
return Session

0 commit comments

Comments
 (0)