-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
134 lines (125 loc) · 2.81 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* using and disposable check tests
* $ pnpm add -D @types/node core-js [email protected]
* tsconfig.json - compilerOptions: { target: "es2022", lib: ["esnext", "es2022"], ...}
* $ pnpm tsc -p . && node --expose-gc lib/index.js
*/
// need runtime polyfill (yet)
import "core-js/modules/esnext.symbol.dispose.js";
import "core-js/modules/esnext.symbol.async-dispose.js";
import "core-js/modules/esnext.disposable-stack.constructor.js";
// ref. https://zenn.dev/ventus/articles/ts5_2-using-preview
import { test } from "node:test";
import { deepEqual } from "node:assert";
function createTestDisposable(onDispose: () => any): Disposable {
return {
[Symbol.dispose]() {
onDispose();
}
}
}
function createTestAsyncDisposable(onAsyncDispose: () => any): AsyncDisposable {
return {
async [Symbol.asyncDispose]() {
return new Promise<void>(resolve => setTimeout(() => {
onAsyncDispose();
resolve();
}, 16));
}
}
}
test('disposbale', () => {
const order: string[] = [];
{
order.push('start');
using _d1 = createTestDisposable(() => order.push('d1'));
using _d2 = createTestDisposable(() => order.push('d2'));
{
using _d3 = createTestDisposable(() => order.push('d3'));
}
order.push('end')
}
deepEqual(order, [
'start',
'd3',
'end',
'd2',
'd1',
]);
});
test('DisposbaleStack', () => {
const order: string[] = [];
{
order.push('start');
using stack = new DisposableStack();
stack.use(
createTestDisposable(() => order.push('d1'))
);
stack.use(
createTestDisposable(() => order.push('d2'))
);
order.push('end')
}
deepEqual(order, [
'start',
'end',
'd2',
'd1',
]);
});
test('DisposbaleStack adopt', () => {
const order: string[] = [];
{
order.push('start');
using stack = new DisposableStack();
stack.adopt(
{
v: 1
},
() => {
order.push('adopted');
}
);
order.push('end')
}
deepEqual(order, [
'start',
'end',
'adopted',
]);
});
test('async-disposbale', async () => {
const order: string[] = [];
{
order.push('start');
await using _a1 = createTestAsyncDisposable(() => order.push('a1'));
order.push("a1-a2");
await using _a2 = createTestAsyncDisposable(() => order.push('a2'));
{
await using _a3 = createTestDisposable(() => order.push('a3'));
}
order.push('end')
}
order.push('out');
deepEqual(order, [
'start',
'a1-a2',
'a3',
'end',
'a2',
'a1',
'out'
]);
});
// Just call Symbol.dispose, no gc.
test('expose to parent closure', () => {
let buf: any = null;
{
using d1 = createTestDisposable(() => {});
// @ts-ignore
d1.v = 1;
buf = d1;
}
if (globalThis.gc) globalThis.gc();
deepEqual(buf.v, 1);
});