Skip to content

Commit 2f6145e

Browse files
authored
fix: ensure callback is called only once (#144)
1 parent 03bc815 commit 2f6145e

File tree

5 files changed

+27
-11
lines changed

5 files changed

+27
-11
lines changed

__tests__/fdir.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ for (const type of apiTypes) {
5454
const files = await api[type]();
5555
t.expect(files.every((file) => file.split("/").length <= 2)).toBe(true);
5656
});
57-
-test(`[${type}] crawl multi depth directory with options`, async (t) => {
57+
58+
test(`[${type}] crawl multi depth directory with options`, async (t) => {
5859
const api = new fdir({
5960
maxDepth: 1,
6061
}).crawl("node_modules");

src/api/functions/walk-directory.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ const walkAsync: WalkDirectoryFunction = (
1818
currentDepth,
1919
callback
2020
) => {
21-
if (currentDepth < 0) return state.queue.dequeue(null, state);
21+
state.queue.enqueue();
22+
23+
if (currentDepth <= 0) return state.queue.dequeue(null, state);
2224

2325
state.visited.push(crawlPath);
2426
state.counts.directories++;
25-
state.queue.enqueue();
2627

2728
// Perf: Node >= 10 introduced withFileTypes that helps us
2829
// skip an extra fs.stat call.
@@ -40,7 +41,7 @@ const walkSync: WalkDirectoryFunction = (
4041
currentDepth,
4142
callback
4243
) => {
43-
if (currentDepth < 0) return;
44+
if (currentDepth <= 0) return;
4445
state.visited.push(crawlPath);
4546
state.counts.directories++;
4647

src/api/queue.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@ type OnQueueEmptyCallback = (error: Error | null, output: WalkerState) => void;
77
* as soon as it completes. When the counter hits 0, it calls onQueueEmpty.
88
*/
99
export class Queue {
10-
private count: number = 0;
11-
constructor(private readonly onQueueEmpty: OnQueueEmptyCallback) {}
10+
count: number = 0;
11+
constructor(private onQueueEmpty?: OnQueueEmptyCallback) {}
1212

1313
enqueue() {
1414
this.count++;
15+
return this.count;
1516
}
1617

1718
dequeue(error: Error | null, output: WalkerState) {
18-
if (--this.count <= 0 || error) this.onQueueEmpty(error, output);
19+
if (this.onQueueEmpty && (--this.count <= 0 || error)) {
20+
this.onQueueEmpty(error, output);
21+
if (error) {
22+
output.controller.abort();
23+
this.onQueueEmpty = undefined;
24+
}
25+
}
1926
}
2027
}

src/api/walker.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export class Walker<TOutput extends Output> {
4848
),
4949
symlinks: new Map(),
5050
visited: [""].slice(0, 0),
51+
controller: new AbortController(),
5152
};
5253

5354
/*
@@ -65,6 +66,7 @@ export class Walker<TOutput extends Output> {
6566
}
6667

6768
start(): TOutput | null {
69+
this.pushDirectory(this.root, this.state.paths, this.state.options.filters);
6870
this.walkDirectory(
6971
this.state,
7072
this.root,
@@ -88,13 +90,16 @@ export class Walker<TOutput extends Output> {
8890
useRealPaths,
8991
pathSeparator,
9092
},
93+
controller,
9194
} = this.state;
9295

93-
if ((signal && signal.aborted) || (maxFiles && paths.length > maxFiles))
96+
if (
97+
controller.signal.aborted ||
98+
(signal && signal.aborted) ||
99+
(maxFiles && paths.length > maxFiles)
100+
)
94101
return;
95102

96-
this.pushDirectory(directoryPath, paths, filters);
97-
98103
const files = this.getArray(this.state.paths);
99104
for (let i = 0; i < entries.length; ++i) {
100105
const entry = entries[i];
@@ -112,8 +117,9 @@ export class Walker<TOutput extends Output> {
112117
this.state.options.pathSeparator
113118
);
114119
if (exclude && exclude(entry.name, path)) continue;
120+
this.pushDirectory(path, paths, filters);
115121
this.walkDirectory(this.state, path, path, depth - 1, this.walk);
116-
} else if (entry.isSymbolicLink() && this.resolveSymlink) {
122+
} else if (this.resolveSymlink && entry.isSymbolicLink()) {
117123
let path = joinPath.joinPathWithBasePath(entry.name, directoryPath);
118124
this.resolveSymlink(path, this.state, (stat, resolvedPath) => {
119125
if (stat.isDirectory()) {

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export type WalkerState = {
3232
counts: Counts;
3333
options: Options;
3434
queue: Queue;
35+
controller: AbortController;
3536

3637
symlinks: Map<string, string>;
3738
visited: string[];

0 commit comments

Comments
 (0)