Dir.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Dir = void 0;
  4. const util_1 = require("./util");
  5. const Dirent_1 = require("./Dirent");
  6. const errors = require("../internal/errors");
  7. /**
  8. * A directory stream, like `fs.Dir`.
  9. */
  10. class Dir {
  11. constructor(link, options) {
  12. this.link = link;
  13. this.options = options;
  14. this.iteratorInfo = [];
  15. this.closed = false;
  16. this.operationQueue = null;
  17. this.path = link.getPath();
  18. this.iteratorInfo.push(link.children[Symbol.iterator]());
  19. }
  20. closeBase() {
  21. // In a real filesystem implementation, this would close file descriptors
  22. // For memfs, we just need to mark as closed
  23. }
  24. readBase(iteratorInfo) {
  25. let done;
  26. let value;
  27. let name;
  28. let link;
  29. do {
  30. do {
  31. ({ done, value } = iteratorInfo[iteratorInfo.length - 1].next());
  32. if (!done) {
  33. [name, link] = value;
  34. }
  35. else {
  36. break;
  37. }
  38. } while (name === '.' || name === '..');
  39. if (done) {
  40. iteratorInfo.pop();
  41. if (iteratorInfo.length === 0) {
  42. break;
  43. }
  44. else {
  45. done = false;
  46. }
  47. }
  48. else {
  49. if (this.options.recursive && link.children.size) {
  50. iteratorInfo.push(link.children[Symbol.iterator]());
  51. }
  52. return Dirent_1.default.build(link, this.options.encoding);
  53. }
  54. } while (!done);
  55. return null;
  56. }
  57. close(callback) {
  58. // Promise-based close
  59. if (callback === undefined) {
  60. if (this.closed) {
  61. return Promise.reject(new errors.Error('ERR_DIR_CLOSED'));
  62. }
  63. return new Promise((resolve, reject) => {
  64. this.close(err => {
  65. if (err)
  66. reject(err);
  67. else
  68. resolve();
  69. });
  70. });
  71. }
  72. // Callback-based close
  73. (0, util_1.validateCallback)(callback);
  74. if (this.closed) {
  75. process.nextTick(callback, new errors.Error('ERR_DIR_CLOSED'));
  76. return;
  77. }
  78. if (this.operationQueue !== null) {
  79. this.operationQueue.push(() => {
  80. this.close(callback);
  81. });
  82. return;
  83. }
  84. this.closed = true;
  85. try {
  86. this.closeBase();
  87. process.nextTick(callback);
  88. }
  89. catch (err) {
  90. process.nextTick(callback, err);
  91. }
  92. }
  93. closeSync() {
  94. if (this.closed) {
  95. throw new errors.Error('ERR_DIR_CLOSED');
  96. }
  97. if (this.operationQueue !== null) {
  98. throw new errors.Error('ERR_DIR_CONCURRENT_OPERATION');
  99. }
  100. this.closed = true;
  101. this.closeBase();
  102. }
  103. read(callback) {
  104. // Promise-based read
  105. if (callback === undefined) {
  106. return new Promise((resolve, reject) => {
  107. this.read((err, result) => {
  108. if (err)
  109. reject(err);
  110. else
  111. resolve(result !== null && result !== void 0 ? result : null);
  112. });
  113. });
  114. }
  115. // Callback-based read
  116. (0, util_1.validateCallback)(callback);
  117. if (this.closed) {
  118. process.nextTick(callback, new errors.Error('ERR_DIR_CLOSED'));
  119. return;
  120. }
  121. if (this.operationQueue !== null) {
  122. this.operationQueue.push(() => {
  123. this.read(callback);
  124. });
  125. return;
  126. }
  127. this.operationQueue = [];
  128. try {
  129. const result = this.readBase(this.iteratorInfo);
  130. process.nextTick(() => {
  131. const queue = this.operationQueue;
  132. this.operationQueue = null;
  133. for (const op of queue)
  134. op();
  135. callback(null, result);
  136. });
  137. }
  138. catch (err) {
  139. process.nextTick(() => {
  140. const queue = this.operationQueue;
  141. this.operationQueue = null;
  142. for (const op of queue)
  143. op();
  144. callback(err);
  145. });
  146. }
  147. }
  148. readSync() {
  149. if (this.closed) {
  150. throw new errors.Error('ERR_DIR_CLOSED');
  151. }
  152. if (this.operationQueue !== null) {
  153. throw new errors.Error('ERR_DIR_CONCURRENT_OPERATION');
  154. }
  155. return this.readBase(this.iteratorInfo);
  156. }
  157. [Symbol.asyncIterator]() {
  158. return {
  159. next: async () => {
  160. try {
  161. const dirEnt = await this.read();
  162. if (dirEnt !== null) {
  163. return { done: false, value: dirEnt };
  164. }
  165. else {
  166. return { done: true, value: undefined };
  167. }
  168. }
  169. catch (err) {
  170. throw err;
  171. }
  172. },
  173. [Symbol.asyncIterator]() {
  174. return this;
  175. },
  176. };
  177. }
  178. }
  179. exports.Dir = Dir;
  180. //# sourceMappingURL=Dir.js.map