Skip to content

Commit 6729a74

Browse files
authored
Merge pull request #17 from vim-denops/fix-send
💥 `Session.send` should return a promise
2 parents e15221b + 453e728 commit 6729a74

File tree

7 files changed

+101
-87
lines changed

7 files changed

+101
-87
lines changed

client.ts

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
const msgidThreshold = 2 ** 32;
1313

1414
type Session = {
15-
send: (data: Command | Message) => void;
15+
send: (data: Command | Message) => Promise<void>;
1616
recv: (msgid: number) => Promise<Message>;
1717
};
1818

@@ -21,7 +21,6 @@ type Session = {
2121
*
2222
* @example
2323
* ```ts
24-
* import { assertNumber } from "https://deno.land/x/unknownutil/mod.ts";
2524
* import { channel } from "https://deno.land/x/streamtools/mod.ts";
2625
* import { Session, Client } from "./mod.ts";
2726
*
@@ -50,8 +49,8 @@ export class Client {
5049
* Note that the indexer must be unique for each session to avoid message ID conflicts.
5150
* If multiple clients are created for a single session, specify a single indexer.
5251
*
53-
* @param {Session} session The session to communicate with.
54-
* @param {Indexer} indexer The indexer to generate message IDs.
52+
* @param session The session to communicate with.
53+
* @param indexer The indexer to generate message IDs.
5554
*/
5655
constructor(session: Session, indexer?: Indexer) {
5756
this.#session = session;
@@ -72,89 +71,95 @@ export class Client {
7271
/**
7372
* Sends a message to Vim.
7473
*
75-
* @param {number} msgid The message ID.
76-
* @param {unknown} value The value to send.
74+
* @param msgid The message ID.
75+
* @param value The value to send.
7776
*/
78-
reply(msgid: number, value: unknown): void {
77+
reply(msgid: number, value: unknown): Promise<void> {
7978
const message = buildMessage(msgid, value);
80-
this.#session.send(message);
79+
return this.#session.send(message);
8180
}
8281

8382
/**
8483
* Sends a redraw command to Vim.
8584
*
86-
* @param {boolean} force Whether to force redraw.
85+
* @param force Whether to force redraw.
8786
*/
88-
redraw(force = false): void {
87+
redraw(force = false): Promise<void> {
8988
const command = buildRedrawCommand(force);
90-
this.#session.send(command);
89+
return this.#session.send(command);
9190
}
9291

9392
/**
9493
* Sends an ex command to Vim.
9594
*
96-
* @param {string} expr The expression to evaluate.
95+
* @param expr The expression to evaluate.
9796
*/
98-
ex(expr: string): void {
97+
ex(expr: string): Promise<void> {
9998
const command = buildExCommand(expr);
100-
this.#session.send(command);
99+
return this.#session.send(command);
101100
}
102101

103102
/**
104103
* Sends a normal command to Vim.
105104
*
106-
* @param {string} expr The expression to evaluate.
105+
* @param expr The expression to evaluate.
107106
*/
108-
normal(expr: string): void {
107+
normal(expr: string): Promise<void> {
109108
const command = buildNormalCommand(expr);
110-
this.#session.send(command);
109+
return this.#session.send(command);
111110
}
112111

113112
/**
114113
* Sends an expr command to Vim and wait for the result.
115114
*
116-
* @param {string} expr The expression to evaluate.
117-
* @returns {Promise<unknown>} The result of the expression.
115+
* @param expr The expression to evaluate.
116+
* @returns The result of the expression.
118117
*/
119-
expr(expr: string): Promise<unknown> {
118+
async expr(expr: string): Promise<unknown> {
120119
const msgid = this.#nextMsgid();
121120
const command = buildExprCommand(expr, msgid);
122-
this.#session.send(command);
123-
return this.#recv(msgid);
121+
const [ret, _] = await Promise.all([
122+
this.#recv(msgid),
123+
this.#session.send(command),
124+
]);
125+
return ret;
124126
}
125127

126128
/**
127129
* Sends an expr command to Vim.
128130
*
129-
* @param {string} expr The expression to evaluate.
131+
* @param expr The expression to evaluate.
130132
*/
131-
exprNoReply(expr: string): void {
133+
exprNoReply(expr: string): Promise<void> {
132134
const command = buildExprCommand(expr);
133-
this.#session.send(command);
135+
return this.#session.send(command);
134136
}
135137

136138
/**
137139
* Sends a call command to Vim and wait for the result.
138140
*
139-
* @param {string} fn The function name to call.
140-
* @param {unknown[]} args The arguments to pass to the function.
141-
* @returns {Promise<unknown>} The result of the function.
141+
* @param fn The function name to call.
142+
* @param args The arguments to pass to the function.
143+
* @returns The result of the function.
142144
*/
143-
call(fn: string, ...args: unknown[]): Promise<unknown> {
145+
async call(fn: string, ...args: unknown[]): Promise<unknown> {
144146
const msgid = this.#nextMsgid();
145147
const command = buildCallCommand(fn, args, msgid);
146-
this.#session.send(command);
147-
return this.#recv(msgid);
148+
const [ret, _] = await Promise.all([
149+
this.#recv(msgid),
150+
this.#session.send(command),
151+
]);
152+
return ret;
148153
}
149154

150155
/**
151156
* Sends a call command to Vim.
152157
*
153-
* @param {string} fn The function name to call.
154-
* @param {unknown[]} args The arguments to pass to the function.
158+
* @param fn The function name to call.
159+
* @param args The arguments to pass to the function.
155160
*/
156-
callNoReply(fn: string, ...args: unknown[]): void {
161+
callNoReply(fn: string, ...args: unknown[]): Promise<void> {
157162
const command = buildCallCommand(fn, args);
158-
this.#session.send(command);
163+
return this.#session.send(command);
159164
}
160165
}

client_test.ts

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@ import {
22
assertEquals,
33
assertRejects,
44
assertThrows,
5-
} from "https://deno.land/std@0.186.0/testing/asserts.ts";
5+
} from "https://deno.land/std@0.210.0/assert/mod.ts";
66
import { buildMessage } from "./message.ts";
77
import { Client } from "./client.ts";
88

99
Deno.test("Client.reply", async (t) => {
10-
await t.step("sends a message", () => {
10+
await t.step("sends a message", async () => {
1111
const receives: unknown[] = [];
1212
const session = {
1313
send: (message: unknown) => {
1414
receives.push(message);
15+
return Promise.resolve();
1516
},
1617
recv: () => {
1718
throw new Error("should not be called");
1819
},
1920
};
2021
const client = new Client(session);
21-
client.reply(1, "Hello");
22-
client.reply(2, "World");
22+
await client.reply(1, "Hello");
23+
await client.reply(2, "World");
2324
assertEquals(receives, [
2425
[1, "Hello"],
2526
[2, "World"],
@@ -41,19 +42,20 @@ Deno.test("Client.reply", async (t) => {
4142
});
4243

4344
Deno.test("Client.redraw", async (t) => {
44-
await t.step("sends a redraw command", () => {
45+
await t.step("sends a redraw command", async () => {
4546
const receives: unknown[] = [];
4647
const session = {
4748
send: (message: unknown) => {
4849
receives.push(message);
50+
return Promise.resolve();
4951
},
5052
recv: () => {
5153
throw new Error("should not be called");
5254
},
5355
};
5456
const client = new Client(session);
55-
client.redraw();
56-
client.redraw(true);
57+
await client.redraw();
58+
await client.redraw(true);
5759
assertEquals(receives, [
5860
["redraw", ""],
5961
["redraw", "force"],
@@ -75,18 +77,19 @@ Deno.test("Client.redraw", async (t) => {
7577
});
7678

7779
Deno.test("Client.ex", async (t) => {
78-
await t.step("sends a ex command", () => {
80+
await t.step("sends a ex command", async () => {
7981
const receives: unknown[] = [];
8082
const session = {
8183
send: (message: unknown) => {
8284
receives.push(message);
85+
return Promise.resolve();
8386
},
8487
recv: () => {
8588
throw new Error("should not be called");
8689
},
8790
};
8891
const client = new Client(session);
89-
client.ex("echo 'Hello'");
92+
await client.ex("echo 'Hello'");
9093
assertEquals(receives, [
9194
["ex", "echo 'Hello'"],
9295
]);
@@ -107,18 +110,19 @@ Deno.test("Client.ex", async (t) => {
107110
});
108111

109112
Deno.test("Client.normal", async (t) => {
110-
await t.step("sends a normal command", () => {
113+
await t.step("sends a normal command", async () => {
111114
const receives: unknown[] = [];
112115
const session = {
113116
send: (message: unknown) => {
114117
receives.push(message);
118+
return Promise.resolve();
115119
},
116120
recv: () => {
117121
throw new Error("should not be called");
118122
},
119123
};
120124
const client = new Client(session);
121-
client.normal("zO");
125+
await client.normal("zO");
122126
assertEquals(receives, [
123127
["normal", "zO"],
124128
]);
@@ -144,6 +148,7 @@ Deno.test("Client.expr", async (t) => {
144148
const session = {
145149
send: (message: unknown) => {
146150
receives.push(message);
151+
return Promise.resolve();
147152
},
148153
recv: (msgid: number) =>
149154
Promise.resolve(buildMessage(msgid, `response:${msgid}`)),
@@ -163,7 +168,7 @@ Deno.test("Client.expr", async (t) => {
163168
]);
164169
});
165170

166-
await t.step("throws an error when send fails", () => {
171+
await t.step("rejects with an error when send fails", async () => {
167172
const session = {
168173
send: () => {
169174
throw new Error("send error");
@@ -172,7 +177,7 @@ Deno.test("Client.expr", async (t) => {
172177
Promise.resolve(buildMessage(msgid, `response:${msgid}`)),
173178
};
174179
const client = new Client(session);
175-
assertThrows(
180+
await assertRejects(
176181
() => client.expr("g:vim_deno_channel_command"),
177182
Error,
178183
"send error",
@@ -183,6 +188,7 @@ Deno.test("Client.expr", async (t) => {
183188
const session = {
184189
send: () => {
185190
// Do NOTHING
191+
return Promise.resolve();
186192
},
187193
recv: () => {
188194
throw new Error("recv error");
@@ -198,18 +204,19 @@ Deno.test("Client.expr", async (t) => {
198204
});
199205

200206
Deno.test("Client.exprNoReply", async (t) => {
201-
await t.step("sends a expr command", () => {
207+
await t.step("sends a expr command", async () => {
202208
const receives: unknown[] = [];
203209
const session = {
204210
send: (message: unknown) => {
205211
receives.push(message);
212+
return Promise.resolve();
206213
},
207214
recv: () => {
208215
throw new Error("should not be called");
209216
},
210217
};
211218
const client = new Client(session);
212-
client.exprNoReply("g:vim_deno_channel_command");
219+
await client.exprNoReply("g:vim_deno_channel_command");
213220
assertEquals(receives, [
214221
["expr", "g:vim_deno_channel_command"],
215222
]);
@@ -239,6 +246,7 @@ Deno.test("Client.call", async (t) => {
239246
const session = {
240247
send: (message: unknown) => {
241248
receives.push(message);
249+
return Promise.resolve();
242250
},
243251
recv: (msgid: number) =>
244252
Promise.resolve(buildMessage(msgid, `response:${msgid}`)),
@@ -252,7 +260,7 @@ Deno.test("Client.call", async (t) => {
252260
]);
253261
});
254262

255-
await t.step("throws an error when send fails", () => {
263+
await t.step("rejects with an error when send fails", async () => {
256264
const session = {
257265
send: () => {
258266
throw new Error("send error");
@@ -261,7 +269,7 @@ Deno.test("Client.call", async (t) => {
261269
Promise.resolve(buildMessage(msgid, `response:${msgid}`)),
262270
};
263271
const client = new Client(session);
264-
assertThrows(
272+
await assertRejects(
265273
() => client.call("foo", "bar"),
266274
Error,
267275
"send error",
@@ -272,6 +280,7 @@ Deno.test("Client.call", async (t) => {
272280
const session = {
273281
send: () => {
274282
// Do NOTHING
283+
return Promise.resolve();
275284
},
276285
recv: () => {
277286
throw new Error("recv error");
@@ -287,18 +296,19 @@ Deno.test("Client.call", async (t) => {
287296
});
288297

289298
Deno.test("Client.callNoReply", async (t) => {
290-
await t.step("sends a call command", () => {
299+
await t.step("sends a call command", async () => {
291300
const receives: unknown[] = [];
292301
const session = {
293302
send: (message: unknown) => {
294303
receives.push(message);
304+
return Promise.resolve();
295305
},
296306
recv: () => {
297307
throw new Error("should not be called");
298308
},
299309
};
300310
const client = new Client(session);
301-
client.callNoReply("foo", "bar");
311+
await client.callNoReply("foo", "bar");
302312
assertEquals(receives, [
303313
["call", "foo", ["bar"]],
304314
]);

command_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
assertEquals,
33
assertThrows,
4-
} from "https://deno.land/std@0.186.0/testing/asserts.ts";
4+
} from "https://deno.land/std@0.210.0/assert/mod.ts";
55
import {
66
buildCallCommand,
77
buildExCommand,

json_streams_test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { assertEquals } from "https://deno.land/std@0.186.0/testing/asserts.ts";
1+
import { assertEquals } from "https://deno.land/std@0.210.0/assert/mod.ts";
22
import {
33
channel,
44
collect,
5-
} from "https://deno.land/x/streamtools@v0.4.0/mod.ts";
5+
} from "https://deno.land/x/streamtools@v0.5.0/mod.ts";
66
import { DecodeStream, EncodeStream } from "./json_streams.ts";
77

88
const encoder = new TextEncoder();

message_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { assertEquals } from "https://deno.land/std@0.186.0/testing/asserts.ts";
1+
import { assertEquals } from "https://deno.land/std@0.210.0/assert/mod.ts";
22
import { buildMessage, isMessage } from "./message.ts";
33

44
const isMessageTestCases = [

0 commit comments

Comments
 (0)