tiny-readdir 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +46 -28
- package/dist/types.d.ts +3 -3
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +22 -0
- package/package.json +11 -9
- package/src/index.ts +58 -31
- package/src/types.ts +3 -3
- package/src/utils.ts +43 -0
- package/test/{native.js → index.js} +34 -0
- package/test/yielding.js +0 -35
package/dist/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/* IMPORT */
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { isFunction, makeCounterPromise } from './utils.js';
|
|
4
5
|
/* MAIN */
|
|
5
6
|
const readdir = (rootPath, options) => {
|
|
6
7
|
const followSymlinks = options?.followSymlinks ?? false;
|
|
7
8
|
const maxDepth = options?.depth ?? Infinity;
|
|
8
9
|
const maxPaths = options?.limit ?? Infinity;
|
|
9
|
-
const
|
|
10
|
+
const ignore = options?.ignore ?? (() => false);
|
|
11
|
+
const isIgnored = isFunction(ignore) ? ignore : (targetPath) => ignore.test(targetPath);
|
|
10
12
|
const signal = options?.signal ?? { aborted: false };
|
|
11
13
|
const directories = [];
|
|
12
14
|
const files = [];
|
|
@@ -15,6 +17,7 @@ const readdir = (rootPath, options) => {
|
|
|
15
17
|
const visited = new Set();
|
|
16
18
|
const resultEmpty = { directories: [], files: [], symlinks: [], map: {} };
|
|
17
19
|
const result = { directories, files, symlinks, map };
|
|
20
|
+
const { promise, increment, decrement } = makeCounterPromise();
|
|
18
21
|
let foundPaths = 0;
|
|
19
22
|
const handleDirectory = (dirmap, subPath, depth) => {
|
|
20
23
|
if (visited.has(subPath))
|
|
@@ -29,7 +32,7 @@ const readdir = (rootPath, options) => {
|
|
|
29
32
|
return;
|
|
30
33
|
if (foundPaths >= maxPaths)
|
|
31
34
|
return;
|
|
32
|
-
|
|
35
|
+
populateResultFromPath(subPath, depth + 1);
|
|
33
36
|
};
|
|
34
37
|
const handleFile = (dirmap, subPath) => {
|
|
35
38
|
if (visited.has(subPath))
|
|
@@ -56,7 +59,7 @@ const readdir = (rootPath, options) => {
|
|
|
56
59
|
return;
|
|
57
60
|
if (foundPaths >= maxPaths)
|
|
58
61
|
return;
|
|
59
|
-
|
|
62
|
+
populateResultFromSymlink(subPath, depth + 1);
|
|
60
63
|
};
|
|
61
64
|
const handleStat = (dirmap, rootPath, stat, depth) => {
|
|
62
65
|
if (signal.aborted)
|
|
@@ -64,13 +67,13 @@ const readdir = (rootPath, options) => {
|
|
|
64
67
|
if (isIgnored(rootPath))
|
|
65
68
|
return;
|
|
66
69
|
if (stat.isDirectory()) {
|
|
67
|
-
|
|
70
|
+
handleDirectory(dirmap, rootPath, depth);
|
|
68
71
|
}
|
|
69
72
|
else if (stat.isFile()) {
|
|
70
|
-
|
|
73
|
+
handleFile(dirmap, rootPath);
|
|
71
74
|
}
|
|
72
75
|
else if (stat.isSymbolicLink()) {
|
|
73
|
-
|
|
76
|
+
handleSymlink(dirmap, rootPath, depth);
|
|
74
77
|
}
|
|
75
78
|
};
|
|
76
79
|
const handleDirent = (dirmap, rootPath, dirent, depth) => {
|
|
@@ -81,48 +84,63 @@ const readdir = (rootPath, options) => {
|
|
|
81
84
|
if (isIgnored(subPath))
|
|
82
85
|
return;
|
|
83
86
|
if (dirent.isDirectory()) {
|
|
84
|
-
|
|
87
|
+
handleDirectory(dirmap, subPath, depth);
|
|
85
88
|
}
|
|
86
89
|
else if (dirent.isFile()) {
|
|
87
|
-
|
|
90
|
+
handleFile(dirmap, subPath);
|
|
88
91
|
}
|
|
89
92
|
else if (dirent.isSymbolicLink()) {
|
|
90
|
-
|
|
93
|
+
handleSymlink(dirmap, subPath, depth);
|
|
91
94
|
}
|
|
92
95
|
};
|
|
93
96
|
const handleDirents = (dirmap, rootPath, dirents, depth) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
+
for (let i = 0, l = dirents.length; i < l; i++) {
|
|
98
|
+
handleDirent(dirmap, rootPath, dirents[i], depth);
|
|
99
|
+
}
|
|
97
100
|
};
|
|
98
|
-
const populateResultFromPath =
|
|
101
|
+
const populateResultFromPath = (rootPath, depth) => {
|
|
99
102
|
if (signal.aborted)
|
|
100
103
|
return;
|
|
101
104
|
if (depth > maxDepth)
|
|
102
105
|
return;
|
|
103
106
|
if (foundPaths >= maxPaths)
|
|
104
107
|
return;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
108
|
+
increment();
|
|
109
|
+
fs.readdir(rootPath, { withFileTypes: true }, (error, dirents) => {
|
|
110
|
+
if (error)
|
|
111
|
+
return decrement();
|
|
112
|
+
if (signal.aborted)
|
|
113
|
+
return decrement();
|
|
114
|
+
if (!dirents.length)
|
|
115
|
+
return decrement();
|
|
116
|
+
const dirmap = map[rootPath] = { directories: [], files: [], symlinks: [] };
|
|
117
|
+
handleDirents(dirmap, rootPath, dirents, depth);
|
|
118
|
+
decrement();
|
|
119
|
+
});
|
|
112
120
|
};
|
|
113
121
|
const populateResultFromSymlink = async (rootPath, depth) => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
increment();
|
|
123
|
+
fs.realpath(rootPath, (error, realPath) => {
|
|
124
|
+
if (error)
|
|
125
|
+
return decrement();
|
|
126
|
+
if (signal.aborted)
|
|
127
|
+
return decrement();
|
|
128
|
+
fs.stat(realPath, async (error, stat) => {
|
|
129
|
+
if (error)
|
|
130
|
+
return decrement();
|
|
131
|
+
if (signal.aborted)
|
|
132
|
+
return decrement();
|
|
133
|
+
const dirmap = map[rootPath] = { directories: [], files: [], symlinks: [] };
|
|
134
|
+
handleStat(dirmap, realPath, stat, depth);
|
|
135
|
+
decrement();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
121
138
|
};
|
|
122
139
|
const getResult = async (rootPath, depth = 1) => {
|
|
123
140
|
rootPath = path.normalize(rootPath);
|
|
124
141
|
visited.add(rootPath);
|
|
125
|
-
|
|
142
|
+
populateResultFromPath(rootPath, depth);
|
|
143
|
+
await promise;
|
|
126
144
|
if (signal.aborted)
|
|
127
145
|
return resultEmpty;
|
|
128
146
|
return result;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
type
|
|
1
|
+
type Callback = () => void;
|
|
2
2
|
type Options = {
|
|
3
3
|
depth?: number;
|
|
4
4
|
limit?: number;
|
|
5
5
|
followSymlinks?: boolean;
|
|
6
|
-
ignore?: (targetPath: string) => boolean;
|
|
6
|
+
ignore?: ((targetPath: string) => boolean) | RegExp;
|
|
7
7
|
signal?: {
|
|
8
8
|
aborted: boolean;
|
|
9
9
|
};
|
|
@@ -19,4 +19,4 @@ type ResultDirectories = {
|
|
|
19
19
|
type Result = ResultDirectory & {
|
|
20
20
|
map: ResultDirectories;
|
|
21
21
|
};
|
|
22
|
-
export type {
|
|
22
|
+
export type { Callback, Options, ResultDirectory, ResultDirectories, Result };
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Callback } from './types';
|
|
2
|
+
declare const isFunction: (value: unknown) => value is Function;
|
|
3
|
+
declare const makeCounterPromise: () => {
|
|
4
|
+
promise: Promise<void>;
|
|
5
|
+
increment: Callback;
|
|
6
|
+
decrement: Callback;
|
|
7
|
+
};
|
|
8
|
+
export { isFunction, makeCounterPromise };
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* IMPORT */
|
|
2
|
+
import makeNakedPromise from 'promise-make-naked';
|
|
3
|
+
/* MAIN */
|
|
4
|
+
const isFunction = (value) => {
|
|
5
|
+
return (typeof value === 'function');
|
|
6
|
+
};
|
|
7
|
+
const makeCounterPromise = () => {
|
|
8
|
+
const { promise, resolve } = makeNakedPromise();
|
|
9
|
+
let counter = 0;
|
|
10
|
+
const increment = () => {
|
|
11
|
+
counter += 1;
|
|
12
|
+
};
|
|
13
|
+
const decrement = () => {
|
|
14
|
+
counter -= 1;
|
|
15
|
+
if (counter)
|
|
16
|
+
return;
|
|
17
|
+
resolve();
|
|
18
|
+
};
|
|
19
|
+
return { promise, increment, decrement };
|
|
20
|
+
};
|
|
21
|
+
/* EXPORT */
|
|
22
|
+
export { isFunction, makeCounterPromise };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "tiny-readdir",
|
|
3
3
|
"repository": "github:fabiospampinato/tiny-readdir",
|
|
4
4
|
"description": "A simple promisified recursive readdir function.",
|
|
5
|
-
"version": "2.1
|
|
5
|
+
"version": "2.2.1",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"exports": "./dist/index.js",
|
|
@@ -11,10 +11,9 @@
|
|
|
11
11
|
"clean": "tsex clean",
|
|
12
12
|
"compile": "tsex compile",
|
|
13
13
|
"compile:watch": "tsex compile --watch",
|
|
14
|
-
"test": "
|
|
15
|
-
"test:
|
|
16
|
-
"
|
|
17
|
-
"prepublishOnly": "npm run clean && npm run compile && npm run test"
|
|
14
|
+
"test": "tsex test",
|
|
15
|
+
"test:watch": "tsex test --watch",
|
|
16
|
+
"prepublishOnly": "tsex prepare"
|
|
18
17
|
},
|
|
19
18
|
"keywords": [
|
|
20
19
|
"readdir",
|
|
@@ -23,10 +22,13 @@
|
|
|
23
22
|
"simple",
|
|
24
23
|
"tiny"
|
|
25
24
|
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"promise-make-naked": "^2.1.1"
|
|
27
|
+
},
|
|
26
28
|
"devDependencies": {
|
|
27
|
-
"@types/node": "^
|
|
28
|
-
"fava": "^0.
|
|
29
|
-
"tsex": "^
|
|
30
|
-
"typescript": "^
|
|
29
|
+
"@types/node": "^20.4.8",
|
|
30
|
+
"fava": "^0.2.1",
|
|
31
|
+
"tsex": "^3.0.1",
|
|
32
|
+
"typescript": "^5.1.6"
|
|
31
33
|
}
|
|
32
34
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
-
import
|
|
6
|
+
import {isFunction, makeCounterPromise} from './utils';
|
|
7
|
+
import type {Options, ResultDirectory, ResultDirectories, Result} from './types';
|
|
7
8
|
|
|
8
9
|
/* MAIN */
|
|
9
10
|
|
|
@@ -12,7 +13,8 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
12
13
|
const followSymlinks = options?.followSymlinks ?? false;
|
|
13
14
|
const maxDepth = options?.depth ?? Infinity;
|
|
14
15
|
const maxPaths = options?.limit ?? Infinity;
|
|
15
|
-
const
|
|
16
|
+
const ignore = options?.ignore ?? (() => false);
|
|
17
|
+
const isIgnored = isFunction ( ignore ) ? ignore : ( targetPath: string ) => ignore.test ( targetPath );
|
|
16
18
|
const signal = options?.signal ?? { aborted: false };
|
|
17
19
|
const directories: string[] = [];
|
|
18
20
|
const files: string[] = [];
|
|
@@ -21,10 +23,11 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
21
23
|
const visited = new Set<string> ();
|
|
22
24
|
const resultEmpty: Result = { directories: [], files: [], symlinks: [], map: {} };
|
|
23
25
|
const result: Result = { directories, files, symlinks, map };
|
|
26
|
+
const {promise, increment, decrement} = makeCounterPromise ();
|
|
24
27
|
|
|
25
28
|
let foundPaths = 0;
|
|
26
29
|
|
|
27
|
-
const handleDirectory = ( dirmap: ResultDirectory, subPath: string, depth: number ):
|
|
30
|
+
const handleDirectory = ( dirmap: ResultDirectory, subPath: string, depth: number ): void => {
|
|
28
31
|
|
|
29
32
|
if ( visited.has ( subPath ) ) return;
|
|
30
33
|
|
|
@@ -39,7 +42,7 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
39
42
|
|
|
40
43
|
if ( foundPaths >= maxPaths ) return;
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
populateResultFromPath ( subPath, depth + 1 );
|
|
43
46
|
|
|
44
47
|
};
|
|
45
48
|
|
|
@@ -56,7 +59,7 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
56
59
|
|
|
57
60
|
};
|
|
58
61
|
|
|
59
|
-
const handleSymlink = ( dirmap: ResultDirectory, subPath: string, depth: number ):
|
|
62
|
+
const handleSymlink = ( dirmap: ResultDirectory, subPath: string, depth: number ): void => {
|
|
60
63
|
|
|
61
64
|
if ( visited.has ( subPath ) ) return;
|
|
62
65
|
|
|
@@ -73,11 +76,11 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
73
76
|
|
|
74
77
|
if ( foundPaths >= maxPaths ) return;
|
|
75
78
|
|
|
76
|
-
|
|
79
|
+
populateResultFromSymlink ( subPath, depth + 1 );
|
|
77
80
|
|
|
78
81
|
};
|
|
79
82
|
|
|
80
|
-
const handleStat = ( dirmap: ResultDirectory, rootPath: string, stat: fs.Stats, depth: number ):
|
|
83
|
+
const handleStat = ( dirmap: ResultDirectory, rootPath: string, stat: fs.Stats, depth: number ): void => {
|
|
81
84
|
|
|
82
85
|
if ( signal.aborted ) return;
|
|
83
86
|
|
|
@@ -85,21 +88,21 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
85
88
|
|
|
86
89
|
if ( stat.isDirectory () ) {
|
|
87
90
|
|
|
88
|
-
|
|
91
|
+
handleDirectory ( dirmap, rootPath, depth );
|
|
89
92
|
|
|
90
93
|
} else if ( stat.isFile () ) {
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
handleFile ( dirmap, rootPath );
|
|
93
96
|
|
|
94
97
|
} else if ( stat.isSymbolicLink () ) {
|
|
95
98
|
|
|
96
|
-
|
|
99
|
+
handleSymlink ( dirmap, rootPath, depth );
|
|
97
100
|
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
};
|
|
101
104
|
|
|
102
|
-
const handleDirent = ( dirmap: ResultDirectory, rootPath: string, dirent: fs.Dirent, depth: number ):
|
|
105
|
+
const handleDirent = ( dirmap: ResultDirectory, rootPath: string, dirent: fs.Dirent, depth: number ): void => {
|
|
103
106
|
|
|
104
107
|
if ( signal.aborted ) return;
|
|
105
108
|
|
|
@@ -110,31 +113,31 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
110
113
|
|
|
111
114
|
if ( dirent.isDirectory () ) {
|
|
112
115
|
|
|
113
|
-
|
|
116
|
+
handleDirectory ( dirmap, subPath, depth );
|
|
114
117
|
|
|
115
118
|
} else if ( dirent.isFile () ) {
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
handleFile ( dirmap, subPath );
|
|
118
121
|
|
|
119
122
|
} else if ( dirent.isSymbolicLink () ) {
|
|
120
123
|
|
|
121
|
-
|
|
124
|
+
handleSymlink ( dirmap, subPath, depth );
|
|
122
125
|
|
|
123
126
|
}
|
|
124
127
|
|
|
125
128
|
};
|
|
126
129
|
|
|
127
|
-
const handleDirents = ( dirmap: ResultDirectory, rootPath: string, dirents: fs.Dirent[], depth: number ):
|
|
130
|
+
const handleDirents = ( dirmap: ResultDirectory, rootPath: string, dirents: fs.Dirent[], depth: number ): void => {
|
|
128
131
|
|
|
129
|
-
|
|
132
|
+
for ( let i = 0, l = dirents.length; i < l; i++ ) {
|
|
130
133
|
|
|
131
|
-
|
|
134
|
+
handleDirent ( dirmap, rootPath, dirents[i], depth );
|
|
132
135
|
|
|
133
|
-
}
|
|
136
|
+
}
|
|
134
137
|
|
|
135
138
|
};
|
|
136
139
|
|
|
137
|
-
const populateResultFromPath =
|
|
140
|
+
const populateResultFromPath = ( rootPath: string, depth: number ): void => {
|
|
138
141
|
|
|
139
142
|
if ( signal.aborted ) return;
|
|
140
143
|
|
|
@@ -142,29 +145,51 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
142
145
|
|
|
143
146
|
if ( foundPaths >= maxPaths ) return;
|
|
144
147
|
|
|
145
|
-
|
|
148
|
+
increment ();
|
|
146
149
|
|
|
147
|
-
|
|
150
|
+
fs.readdir ( rootPath, { withFileTypes: true }, ( error, dirents ) => {
|
|
151
|
+
|
|
152
|
+
if ( error ) return decrement ();
|
|
148
153
|
|
|
149
|
-
|
|
154
|
+
if ( signal.aborted ) return decrement ();
|
|
150
155
|
|
|
151
|
-
|
|
156
|
+
if ( !dirents.length ) return decrement ();
|
|
157
|
+
|
|
158
|
+
const dirmap = map[rootPath] = { directories: [], files: [], symlinks: [] };
|
|
152
159
|
|
|
153
|
-
|
|
160
|
+
handleDirents ( dirmap, rootPath, dirents, depth );
|
|
161
|
+
|
|
162
|
+
decrement ();
|
|
163
|
+
|
|
164
|
+
});
|
|
154
165
|
|
|
155
166
|
};
|
|
156
167
|
|
|
157
168
|
const populateResultFromSymlink = async ( rootPath: string, depth: number ): Promise<void> => {
|
|
158
169
|
|
|
159
|
-
|
|
170
|
+
increment ();
|
|
160
171
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
172
|
+
fs.realpath ( rootPath, ( error, realPath ) => {
|
|
173
|
+
|
|
174
|
+
if ( error ) return decrement ();
|
|
164
175
|
|
|
165
|
-
|
|
176
|
+
if ( signal.aborted ) return decrement ();
|
|
166
177
|
|
|
167
|
-
|
|
178
|
+
fs.stat ( realPath, async ( error, stat ) => {
|
|
179
|
+
|
|
180
|
+
if ( error ) return decrement ();
|
|
181
|
+
|
|
182
|
+
if ( signal.aborted ) return decrement ();
|
|
183
|
+
|
|
184
|
+
const dirmap = map[rootPath] = { directories: [], files: [], symlinks: [] };
|
|
185
|
+
|
|
186
|
+
handleStat ( dirmap, realPath, stat, depth );
|
|
187
|
+
|
|
188
|
+
decrement ();
|
|
189
|
+
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
});
|
|
168
193
|
|
|
169
194
|
};
|
|
170
195
|
|
|
@@ -174,7 +199,9 @@ const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
|
|
174
199
|
|
|
175
200
|
visited.add ( rootPath );
|
|
176
201
|
|
|
177
|
-
|
|
202
|
+
populateResultFromPath ( rootPath, depth );
|
|
203
|
+
|
|
204
|
+
await promise;
|
|
178
205
|
|
|
179
206
|
if ( signal.aborted ) return resultEmpty;
|
|
180
207
|
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/* HELPERS */
|
|
3
3
|
|
|
4
|
-
type
|
|
4
|
+
type Callback = () => void;
|
|
5
5
|
|
|
6
6
|
/* MAIN */
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ type Options = {
|
|
|
9
9
|
depth?: number,
|
|
10
10
|
limit?: number,
|
|
11
11
|
followSymlinks?: boolean,
|
|
12
|
-
ignore?: ( targetPath: string ) => boolean,
|
|
12
|
+
ignore?: (( targetPath: string ) => boolean) | RegExp,
|
|
13
13
|
signal?: { aborted: boolean }
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -29,4 +29,4 @@ type Result = ResultDirectory & {
|
|
|
29
29
|
|
|
30
30
|
/* EXPORT */
|
|
31
31
|
|
|
32
|
-
export type {
|
|
32
|
+
export type {Callback, Options, ResultDirectory, ResultDirectories, Result};
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
/* IMPORT */
|
|
3
|
+
|
|
4
|
+
import makeNakedPromise from 'promise-make-naked';
|
|
5
|
+
import type {Callback} from './types';
|
|
6
|
+
|
|
7
|
+
/* MAIN */
|
|
8
|
+
|
|
9
|
+
const isFunction = ( value: unknown ): value is Function => {
|
|
10
|
+
|
|
11
|
+
return ( typeof value === 'function' );
|
|
12
|
+
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const makeCounterPromise = (): { promise: Promise<void>, increment: Callback, decrement: Callback } => {
|
|
16
|
+
|
|
17
|
+
const {promise, resolve} = makeNakedPromise<void> ();
|
|
18
|
+
|
|
19
|
+
let counter = 0;
|
|
20
|
+
|
|
21
|
+
const increment = (): void => {
|
|
22
|
+
|
|
23
|
+
counter += 1;
|
|
24
|
+
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const decrement = (): void => {
|
|
28
|
+
|
|
29
|
+
counter -= 1;
|
|
30
|
+
|
|
31
|
+
if ( counter ) return;
|
|
32
|
+
|
|
33
|
+
resolve ();
|
|
34
|
+
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return { promise, increment, decrement };
|
|
38
|
+
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/* EXPORT */
|
|
42
|
+
|
|
43
|
+
export {isFunction, makeCounterPromise};
|
|
@@ -164,4 +164,38 @@ describe ( 'Tiny Readdir', it => {
|
|
|
164
164
|
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
+
it ( 'does not freeze the main thread', async t => {
|
|
168
|
+
|
|
169
|
+
return new Promise ( resolve => {
|
|
170
|
+
|
|
171
|
+
let count = 0;
|
|
172
|
+
let start = Date.now ();
|
|
173
|
+
|
|
174
|
+
const aborter = new AbortController ();
|
|
175
|
+
const signal = aborter.signal;
|
|
176
|
+
|
|
177
|
+
const intervalId = setInterval ( () => {
|
|
178
|
+
count += 1;
|
|
179
|
+
console.log ( 'tick', count );
|
|
180
|
+
if ( count !== 100 ) return;
|
|
181
|
+
clearInterval ( intervalId );
|
|
182
|
+
const end = Date.now ();
|
|
183
|
+
const elapsed = end - start;
|
|
184
|
+
console.log ( 'elapsed', elapsed );
|
|
185
|
+
console.log ( elapsed );
|
|
186
|
+
if ( elapsed > 1500 ) {
|
|
187
|
+
t.fail ();
|
|
188
|
+
} else {
|
|
189
|
+
t.pass ();
|
|
190
|
+
}
|
|
191
|
+
aborter.abort ();
|
|
192
|
+
resolve ();
|
|
193
|
+
}, 10 );
|
|
194
|
+
|
|
195
|
+
readdir ( '/', { signal } );
|
|
196
|
+
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
});
|
|
200
|
+
|
|
167
201
|
});
|
package/test/yielding.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/* IMPORT */
|
|
3
|
-
|
|
4
|
-
import readdir from '../dist/index.js';
|
|
5
|
-
|
|
6
|
-
/* MAIN */
|
|
7
|
-
|
|
8
|
-
const main = async () => {
|
|
9
|
-
|
|
10
|
-
let count = 0;
|
|
11
|
-
let start = Date.now ();
|
|
12
|
-
|
|
13
|
-
setInterval ( () => {
|
|
14
|
-
count += 1;
|
|
15
|
-
console.log ( 'tick', count );
|
|
16
|
-
if ( count < 100 ) return;
|
|
17
|
-
const end = Date.now ();
|
|
18
|
-
const elapsed = end - start;
|
|
19
|
-
console.log ( 'elapsed', elapsed );
|
|
20
|
-
if ( elapsed > 1500 ) {
|
|
21
|
-
process.exit ( 1 ); // Fail
|
|
22
|
-
} else {
|
|
23
|
-
process.exit ( 0 ); // Success
|
|
24
|
-
}
|
|
25
|
-
}, 10 );
|
|
26
|
-
|
|
27
|
-
await readdir ( '/' );
|
|
28
|
-
|
|
29
|
-
process.exit ( 1 ); // Fail
|
|
30
|
-
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/* RUNNING */
|
|
34
|
-
|
|
35
|
-
await main ();
|