Skip to content

Commit 1f4af69

Browse files
committed
👍 Disable denops instance passed to gather block outside of the block
1 parent 0d7da4f commit 1f4af69

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

denops_std/batch/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ export async function main(denops: Denops): Promise<void> {
8888

8989
Not like `batch`, the function can NOT be nested.
9090

91-
Note that `denops.call()`, `denops.batch()`, or `denops.eval()` always return
92-
falsy value in `gather()`, indicating that you **cannot** write code like below:
91+
Note that `denops.call()` or `denops.eval()` always return falsy value in
92+
`gather()`, indicating that you **cannot** write code like below:
9393

9494
```typescript
9595
import { Denops } from "https://deno.land/x/denops_std/mod.ts";
@@ -106,3 +106,7 @@ export async function main(denops: Denops): Promise<void> {
106106
});
107107
}
108108
```
109+
110+
The `denops` instance passed to the `gather` block is NOT available outside of
111+
the block. An error is thrown when `denops.call()`, `denops.cmd()`, or
112+
`denops.eval()` is called.

denops_std/batch/gather.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ import { Context, Denops, Dispatcher, Meta } from "../deps.ts";
33
class GatherHelper implements Denops {
44
#denops: Denops;
55
#calls: [string, ...unknown[]][];
6+
#closed: boolean;
67

78
constructor(denops: Denops) {
89
this.#denops = denops;
910
this.#calls = [];
11+
this.#closed = false;
1012
}
1113

1214
static getCalls(helper: GatherHelper): [string, ...unknown[]][] {
1315
return helper.#calls;
1416
}
1517

18+
static close(helper: GatherHelper): void {
19+
helper.#closed = true;
20+
}
21+
1622
get name(): string {
1723
return this.#denops.name;
1824
}
@@ -30,6 +36,11 @@ class GatherHelper implements Denops {
3036
}
3137

3238
call(fn: string, ...args: unknown[]): Promise<unknown> {
39+
if (this.#closed) {
40+
throw new Error(
41+
"GatherHelper instance is not available outside of 'gather' block",
42+
);
43+
}
3344
this.#calls.push([fn, ...args]);
3445
return Promise.resolve();
3546
}
@@ -39,11 +50,21 @@ class GatherHelper implements Denops {
3950
}
4051

4152
cmd(cmd: string, ctx: Context = {}): Promise<void> {
53+
if (this.#closed) {
54+
throw new Error(
55+
"GatherHelper instance is not available outside of 'gather' block",
56+
);
57+
}
4258
this.call("denops#api#cmd", cmd, ctx);
4359
return Promise.resolve();
4460
}
4561

4662
eval(expr: string, ctx: Context = {}): Promise<unknown> {
63+
if (this.#closed) {
64+
throw new Error(
65+
"GatherHelper instance is not available outside of 'gather' block",
66+
);
67+
}
4768
this.call("denops#api#eval", expr, ctx);
4869
return Promise.resolve();
4970
}
@@ -61,7 +82,11 @@ export async function gather(
6182
main: (helper: GatherHelper) => Promise<void>,
6283
): Promise<unknown[]> {
6384
const helper = new GatherHelper(denops);
64-
await main(helper);
85+
try {
86+
await main(helper);
87+
} finally {
88+
GatherHelper.close(helper);
89+
}
6590
const calls = GatherHelper.getCalls(helper);
6691
return await denops.batch(...calls);
6792
}

denops_std/batch/gather_test.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { assertEquals, assertThrowsAsync, test } from "../deps_test.ts";
2-
import { gather } from "./gather.ts";
2+
import { gather, GatherHelper } from "./gather.ts";
33

44
test({
55
mode: "any",
@@ -57,3 +57,39 @@ test({
5757
},
5858
prelude: ["let g:denops#enable_workaround_vim_before_8_2_3081 = 1"],
5959
});
60+
test({
61+
mode: "any",
62+
name:
63+
"The 'helper' instance passed in gather block is NOT available outside of the block",
64+
fn: async (denops) => {
65+
await denops.cmd("let g:denops_gather_test = 0");
66+
await denops.cmd("command! DenopsGatherTest let g:denops_gather_test += 1");
67+
68+
let helper: GatherHelper;
69+
await gather(denops, (denops) => {
70+
helper = denops;
71+
return Promise.resolve();
72+
});
73+
await assertThrowsAsync(
74+
async () => {
75+
await helper!.call("execute", "DenopsGatherTest");
76+
},
77+
undefined,
78+
"not available outside",
79+
);
80+
await assertThrowsAsync(
81+
async () => {
82+
await helper.cmd("DenopsGatherTest");
83+
},
84+
undefined,
85+
"not available outside",
86+
);
87+
await assertThrowsAsync(
88+
async () => {
89+
const _ = await helper.eval("v:version");
90+
},
91+
undefined,
92+
"not available outside",
93+
);
94+
},
95+
});

0 commit comments

Comments
 (0)