Skip to content

Commit

Permalink
fs: fix bufferSize option for opendir recursive
Browse files Browse the repository at this point in the history
  • Loading branch information
cu8code committed Nov 11, 2024
1 parent 57f23b4 commit d30518b
Showing 1 changed file with 79 additions and 23 deletions.
102 changes: 79 additions & 23 deletions lib/internal/fs/dir.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class Dir {
// Either `null` or an Array of pending operations (= functions to be called
// once the current operation is done).
#operationQueue = null;
#handlerQueue = [];
#isProcessing = false;



Check failure on line 50 in lib/internal/fs/dir.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

More than 2 blank lines not allowed
constructor(handle, path, options) {
if (handle == null) throw new ERR_MISSING_ARGS('handle');
Expand Down Expand Up @@ -82,63 +86,115 @@ class Dir {

validateFunction(callback, 'callback');

if (this.#operationQueue !== null) {
ArrayPrototypePush(this.#operationQueue, () => {
if (this.#isProcessing) {
this.#handlerQueue.push(() => {
this.#readImpl(maybeSync, callback);
});
return;
}

this.#isProcessing = true;

if (this.#bufferedEntries.length > 0) {
try {
const dirent = ArrayPrototypeShift(this.#bufferedEntries);

if (this.#options.recursive && dirent.isDirectory()) {
this.readSyncRecursive(dirent);
this.#queueDirectoryRead(dirent);
}

if (maybeSync)
process.nextTick(callback, null, dirent);
else
if (maybeSync) {
process.nextTick(() => {
this.#isProcessing = false;
this.#processNextHandler();
callback(null, dirent);
});
} else {
this.#isProcessing = false;
this.#processNextHandler();
callback(null, dirent);
}
return;
} catch (error) {
this.#isProcessing = false;
this.#processNextHandler();
return callback(error);
}
}

const req = new FSReqCallback();
req.oncomplete = (err, result) => {
process.nextTick(() => {
const queue = this.#operationQueue;
this.#operationQueue = null;
for (const op of queue) op();
});
this.#isProcessing = false;

if (err || result === null) {
return callback(err, result);
}
if (err || result === null) {
this.#processNextHandler();
return callback(err, result);
}

try {
this.processReadResult(this.#path, result);
const dirent = ArrayPrototypeShift(this.#bufferedEntries);
if (this.#options.recursive && dirent.isDirectory()) {
this.readSyncRecursive(dirent);
try {
this.processReadResult(this.#path, result);
const dirent = ArrayPrototypeShift(this.#bufferedEntries);
if (this.#options.recursive && dirent.isDirectory()) {
this.#queueDirectoryRead(dirent);
}
this.#processNextHandler();
callback(null, dirent);
} catch (error) {
this.#processNextHandler();
callback(error);
}
callback(null, dirent);
} catch (error) {
callback(error);
}
});
};

this.#operationQueue = [];
this.#handle.read(
this.#options.encoding,
this.#options.bufferSize,
req,
);
}

#queueDirectoryRead(dirent) {
const path = pathModule.join(dirent.parentPath, dirent.name);
const handle = dirBinding.opendir(
path,
this.#options.encoding,
);

if (handle === undefined) {
return;
}

const readNext = () => {
const result = handle.read(
this.#options.encoding,
this.#options.bufferSize,
);

Check failure on line 173 in lib/internal/fs/dir.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Trailing spaces not allowed
if (result) {
this.processReadResult(path, result);
this.#handlerQueue.push(readNext);
} else {
handle.close();
}
};

this.#handlerQueue.push(readNext);
}

#processNextHandler() {
if (this.#handlerQueue.length > 0 && !this.#isProcessing) {
this.#isProcessing = true;
const nextHandler = this.#handlerQueue.shift();
try {
nextHandler();
} finally {
this.#isProcessing = false;
process.nextTick(() => this.#processNextHandler());
}
}
}

processReadResult(path, result) {
for (let i = 0; i < result.length; i += 2) {
ArrayPrototypePush(
Expand Down

0 comments on commit d30518b

Please sign in to comment.