Skip to content

Commit

Permalink
fs: use private fields instead of symbols for Dir
Browse files Browse the repository at this point in the history
PR-URL: #51037
Refs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
  • Loading branch information
pluris committed Dec 28, 2023
1 parent 5e64483 commit c141335
Showing 1 changed file with 68 additions and 75 deletions.
143 changes: 68 additions & 75 deletions lib/internal/fs/dir.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const {
FunctionPrototypeBind,
ObjectDefineProperty,
PromiseReject,
Symbol,
SymbolAsyncIterator,
} = primordials;

Expand Down Expand Up @@ -34,74 +33,68 @@ const {
validateUint32,
} = require('internal/validators');

const kDirHandle = Symbol('kDirHandle');
const kDirPath = Symbol('kDirPath');
const kDirBufferedEntries = Symbol('kDirBufferedEntries');
const kDirClosed = Symbol('kDirClosed');
const kDirOptions = Symbol('kDirOptions');
const kDirReadImpl = Symbol('kDirReadImpl');
const kDirReadPromisified = Symbol('kDirReadPromisified');
const kDirClosePromisified = Symbol('kDirClosePromisified');
const kDirOperationQueue = Symbol('kDirOperationQueue');

class Dir {
#handle;
#path;
#bufferedEntries = [];
#closed = false;
#options;
#readPromisified;
#closePromisified;
// Either `null` or an Array of pending operations (= functions to be called
// once the current operation is done).
#operationQueue = null;

constructor(handle, path, options) {
if (handle == null) throw new ERR_MISSING_ARGS('handle');
this[kDirHandle] = handle;
this[kDirBufferedEntries] = [];
this[kDirPath] = path;
this[kDirClosed] = false;

// Either `null` or an Array of pending operations (= functions to be called
// once the current operation is done).
this[kDirOperationQueue] = null;

this[kDirOptions] = {
this.#handle = handle;
this.#path = path;
this.#options = {
bufferSize: 32,
...getOptions(options, {
encoding: 'utf8',
}),
};

validateUint32(this[kDirOptions].bufferSize, 'options.bufferSize', true);
validateUint32(this.#options.bufferSize, 'options.bufferSize', true);

this[kDirReadPromisified] = FunctionPrototypeBind(
internalUtil.promisify(this[kDirReadImpl]), this, false);
this[kDirClosePromisified] = FunctionPrototypeBind(
this.#readPromisified = FunctionPrototypeBind(
internalUtil.promisify(this.#readImpl), this, false);
this.#closePromisified = FunctionPrototypeBind(
internalUtil.promisify(this.close), this);
}

get path() {
return this[kDirPath];
return this.#path;
}

read(callback) {
return this[kDirReadImpl](true, callback);
return this.#readImpl(true, callback);
}

[kDirReadImpl](maybeSync, callback) {
if (this[kDirClosed] === true) {
#readImpl(maybeSync, callback) {
if (this.#closed === true) {
throw new ERR_DIR_CLOSED();
}

if (callback === undefined) {
return this[kDirReadPromisified]();
return this.#readPromisified();
}

validateFunction(callback, 'callback');

if (this[kDirOperationQueue] !== null) {
ArrayPrototypePush(this[kDirOperationQueue], () => {
this[kDirReadImpl](maybeSync, callback);
if (this.#operationQueue !== null) {
ArrayPrototypePush(this.#operationQueue, () => {
this.#readImpl(maybeSync, callback);
});
return;
}

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

if (this[kDirOptions].recursive && dirent.isDirectory()) {
if (this.#options.recursive && dirent.isDirectory()) {
this.readSyncRecursive(dirent);
}

Expand All @@ -118,8 +111,8 @@ class Dir {
const req = new FSReqCallback();
req.oncomplete = (err, result) => {
process.nextTick(() => {
const queue = this[kDirOperationQueue];
this[kDirOperationQueue] = null;
const queue = this.#operationQueue;
this.#operationQueue = null;
for (const op of queue) op();
});

Expand All @@ -128,9 +121,9 @@ class Dir {
}

try {
this.processReadResult(this[kDirPath], result);
const dirent = ArrayPrototypeShift(this[kDirBufferedEntries]);
if (this[kDirOptions].recursive && dirent.isDirectory()) {
this.processReadResult(this.#path, result);
const dirent = ArrayPrototypeShift(this.#bufferedEntries);
if (this.#options.recursive && dirent.isDirectory()) {
this.readSyncRecursive(dirent);
}
callback(null, dirent);
Expand All @@ -139,18 +132,18 @@ class Dir {
}
};

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

processReadResult(path, result) {
for (let i = 0; i < result.length; i += 2) {
ArrayPrototypePush(
this[kDirBufferedEntries],
this.#bufferedEntries,
getDirent(
path,
result[i],
Expand All @@ -165,14 +158,14 @@ class Dir {
const ctx = { path };
const handle = dirBinding.opendir(
pathModule.toNamespacedPath(path),
this[kDirOptions].encoding,
this.#options.encoding,
undefined,
ctx,
);
handleErrorFromBinding(ctx);
const result = handle.read(
this[kDirOptions].encoding,
this[kDirOptions].bufferSize,
this.#options.encoding,
this.#options.bufferSize,
undefined,
ctx,
);
Expand All @@ -186,26 +179,26 @@ class Dir {
}

readSync() {
if (this[kDirClosed] === true) {
if (this.#closed === true) {
throw new ERR_DIR_CLOSED();
}

if (this[kDirOperationQueue] !== null) {
if (this.#operationQueue !== null) {
throw new ERR_DIR_CONCURRENT_OPERATION();
}

if (this[kDirBufferedEntries].length > 0) {
const dirent = ArrayPrototypeShift(this[kDirBufferedEntries]);
if (this[kDirOptions].recursive && dirent.isDirectory()) {
if (this.#bufferedEntries.length > 0) {
const dirent = ArrayPrototypeShift(this.#bufferedEntries);
if (this.#options.recursive && dirent.isDirectory()) {
this.readSyncRecursive(dirent);
}
return dirent;
}

const ctx = { path: this[kDirPath] };
const result = this[kDirHandle].read(
this[kDirOptions].encoding,
this[kDirOptions].bufferSize,
const ctx = { path: this.#path };
const result = this.#handle.read(
this.#options.encoding,
this.#options.bufferSize,
undefined,
ctx,
);
Expand All @@ -215,10 +208,10 @@ class Dir {
return result;
}

this.processReadResult(this[kDirPath], result);
this.processReadResult(this.#path, result);

const dirent = ArrayPrototypeShift(this[kDirBufferedEntries]);
if (this[kDirOptions].recursive && dirent.isDirectory()) {
const dirent = ArrayPrototypeShift(this.#bufferedEntries);
if (this.#options.recursive && dirent.isDirectory()) {
this.readSyncRecursive(dirent);
}
return dirent;
Expand All @@ -227,60 +220,60 @@ class Dir {
close(callback) {
// Promise
if (callback === undefined) {
if (this[kDirClosed] === true) {
if (this.#closed === true) {
return PromiseReject(new ERR_DIR_CLOSED());
}
return this[kDirClosePromisified]();
return this.#closePromisified();
}

// callback
validateFunction(callback, 'callback');

if (this[kDirClosed] === true) {
if (this.#closed === true) {
process.nextTick(callback, new ERR_DIR_CLOSED());
return;
}

if (this[kDirOperationQueue] !== null) {
ArrayPrototypePush(this[kDirOperationQueue], () => {
if (this.#operationQueue !== null) {
ArrayPrototypePush(this.#operationQueue, () => {
this.close(callback);
});
return;
}

this[kDirClosed] = true;
this.#closed = true;
const req = new FSReqCallback();
req.oncomplete = callback;
this[kDirHandle].close(req);
this.#handle.close(req);
}

closeSync() {
if (this[kDirClosed] === true) {
if (this.#closed === true) {
throw new ERR_DIR_CLOSED();
}

if (this[kDirOperationQueue] !== null) {
if (this.#operationQueue !== null) {
throw new ERR_DIR_CONCURRENT_OPERATION();
}

this[kDirClosed] = true;
const ctx = { path: this[kDirPath] };
const result = this[kDirHandle].close(undefined, ctx);
this.#closed = true;
const ctx = { path: this.#path };
const result = this.#handle.close(undefined, ctx);
handleErrorFromBinding(ctx);
return result;
}

async* entries() {
try {
while (true) {
const result = await this[kDirReadPromisified]();
const result = await this.#readPromisified();
if (result === null) {
break;
}
yield result;
}
} finally {
await this[kDirClosePromisified]();
await this.#closePromisified();
}
}
}
Expand Down

0 comments on commit c141335

Please sign in to comment.