180 lines
5.3 KiB
JavaScript
180 lines
5.3 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Dir = void 0;
|
|
const util_1 = require("./util");
|
|
const Dirent_1 = require("./Dirent");
|
|
const errors = require("../internal/errors");
|
|
/**
|
|
* A directory stream, like `fs.Dir`.
|
|
*/
|
|
class Dir {
|
|
constructor(link, options) {
|
|
this.link = link;
|
|
this.options = options;
|
|
this.iteratorInfo = [];
|
|
this.closed = false;
|
|
this.operationQueue = null;
|
|
this.path = link.getPath();
|
|
this.iteratorInfo.push(link.children[Symbol.iterator]());
|
|
}
|
|
closeBase() {
|
|
// In a real filesystem implementation, this would close file descriptors
|
|
// For memfs, we just need to mark as closed
|
|
}
|
|
readBase(iteratorInfo) {
|
|
let done;
|
|
let value;
|
|
let name;
|
|
let link;
|
|
do {
|
|
do {
|
|
({ done, value } = iteratorInfo[iteratorInfo.length - 1].next());
|
|
if (!done) {
|
|
[name, link] = value;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
} while (name === '.' || name === '..');
|
|
if (done) {
|
|
iteratorInfo.pop();
|
|
if (iteratorInfo.length === 0) {
|
|
break;
|
|
}
|
|
else {
|
|
done = false;
|
|
}
|
|
}
|
|
else {
|
|
if (this.options.recursive && link.children.size) {
|
|
iteratorInfo.push(link.children[Symbol.iterator]());
|
|
}
|
|
return Dirent_1.default.build(link, this.options.encoding);
|
|
}
|
|
} while (!done);
|
|
return null;
|
|
}
|
|
close(callback) {
|
|
// Promise-based close
|
|
if (callback === undefined) {
|
|
if (this.closed) {
|
|
return Promise.reject(new errors.Error('ERR_DIR_CLOSED'));
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
this.close(err => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
// Callback-based close
|
|
(0, util_1.validateCallback)(callback);
|
|
if (this.closed) {
|
|
process.nextTick(callback, new errors.Error('ERR_DIR_CLOSED'));
|
|
return;
|
|
}
|
|
if (this.operationQueue !== null) {
|
|
this.operationQueue.push(() => {
|
|
this.close(callback);
|
|
});
|
|
return;
|
|
}
|
|
this.closed = true;
|
|
try {
|
|
this.closeBase();
|
|
process.nextTick(callback);
|
|
}
|
|
catch (err) {
|
|
process.nextTick(callback, err);
|
|
}
|
|
}
|
|
closeSync() {
|
|
if (this.closed) {
|
|
throw new errors.Error('ERR_DIR_CLOSED');
|
|
}
|
|
if (this.operationQueue !== null) {
|
|
throw new errors.Error('ERR_DIR_CONCURRENT_OPERATION');
|
|
}
|
|
this.closed = true;
|
|
this.closeBase();
|
|
}
|
|
read(callback) {
|
|
// Promise-based read
|
|
if (callback === undefined) {
|
|
return new Promise((resolve, reject) => {
|
|
this.read((err, result) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve(result !== null && result !== void 0 ? result : null);
|
|
});
|
|
});
|
|
}
|
|
// Callback-based read
|
|
(0, util_1.validateCallback)(callback);
|
|
if (this.closed) {
|
|
process.nextTick(callback, new errors.Error('ERR_DIR_CLOSED'));
|
|
return;
|
|
}
|
|
if (this.operationQueue !== null) {
|
|
this.operationQueue.push(() => {
|
|
this.read(callback);
|
|
});
|
|
return;
|
|
}
|
|
this.operationQueue = [];
|
|
try {
|
|
const result = this.readBase(this.iteratorInfo);
|
|
process.nextTick(() => {
|
|
const queue = this.operationQueue;
|
|
this.operationQueue = null;
|
|
for (const op of queue)
|
|
op();
|
|
callback(null, result);
|
|
});
|
|
}
|
|
catch (err) {
|
|
process.nextTick(() => {
|
|
const queue = this.operationQueue;
|
|
this.operationQueue = null;
|
|
for (const op of queue)
|
|
op();
|
|
callback(err);
|
|
});
|
|
}
|
|
}
|
|
readSync() {
|
|
if (this.closed) {
|
|
throw new errors.Error('ERR_DIR_CLOSED');
|
|
}
|
|
if (this.operationQueue !== null) {
|
|
throw new errors.Error('ERR_DIR_CONCURRENT_OPERATION');
|
|
}
|
|
return this.readBase(this.iteratorInfo);
|
|
}
|
|
[Symbol.asyncIterator]() {
|
|
return {
|
|
next: async () => {
|
|
try {
|
|
const dirEnt = await this.read();
|
|
if (dirEnt !== null) {
|
|
return { done: false, value: dirEnt };
|
|
}
|
|
else {
|
|
return { done: true, value: undefined };
|
|
}
|
|
}
|
|
catch (err) {
|
|
throw err;
|
|
}
|
|
},
|
|
[Symbol.asyncIterator]() {
|
|
return this;
|
|
},
|
|
};
|
|
}
|
|
}
|
|
exports.Dir = Dir;
|
|
//# sourceMappingURL=Dir.js.map
|