| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent cc7e5dd commit 7273ef5
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1214,6 +1214,9 @@ a colon, Node.js will open a file system stream, as described by | |||
| 1214 | 1214 | <!-- YAML | |
| 1215 | 1215 | added: v12.12.0 | |
| 1216 | 1216 | changes: | |
| 1217 | + - version: REPLACEME | ||
| 1218 | + pr-url: https://github.com/nodejs/node/pull/41439 | ||
| 1219 | + description: Added `recursive` option. | ||
| 1217 | 1220 | - version: | |
| 1218 | 1221 | - v13.1.0 | |
| 1219 | 1222 | - v12.16.0 | |
@@ -1227,6 +1230,8 @@ changes: | |||
| 1227 | 1230 | * `bufferSize` {number} Number of directory entries that are buffered | |
| 1228 | 1231 | internally when reading from the directory. Higher values lead to better | |
| 1229 | 1232 | performance but higher memory usage. **Default:** `32` | |
| 1233 | + * `recursive` {boolean} Resolved `Dir` will be an {AsyncIterable} | ||
| 1234 | + containing all sub files and directories. **Default:** `false` | ||
| 1230 | 1235 | * Returns: {Promise} Fulfills with an {fs.Dir}. | |
| 1231 | 1236 | ||
| 1232 | 1237 | Asynchronously open a directory for iterative scanning. See the POSIX | |
@@ -1260,6 +1265,9 @@ closed after the iterator exits. | |||
| 1260 | 1265 | <!-- YAML | |
| 1261 | 1266 | added: v10.0.0 | |
| 1262 | 1267 | changes: | |
| 1268 | + - version: REPLACEME | ||
| 1269 | + pr-url: https://github.com/nodejs/node/pull/41439 | ||
| 1270 | + description: Added `recursive` option. | ||
| 1263 | 1271 | - version: v10.11.0 | |
| 1264 | 1272 | pr-url: https://github.com/nodejs/node/pull/22020 | |
| 1265 | 1273 | description: New option `withFileTypes` was added. | |
@@ -1269,6 +1277,7 @@ changes: | |||
| 1269 | 1277 | * `options` {string|Object} | |
| 1270 | 1278 | * `encoding` {string} **Default:** `'utf8'` | |
| 1271 | 1279 | * `withFileTypes` {boolean} **Default:** `false` | |
| 1280 | + * `recursive` {boolean} **Default:** `false` | ||
| 1272 | 1281 | * Returns: {Promise} Fulfills with an array of the names of the files in | |
| 1273 | 1282 | the directory excluding `'.'` and `'..'`. | |
| 1274 | 1283 | ||
@@ -3344,6 +3353,9 @@ Functions based on `fs.open()` exhibit this behavior as well: | |||
| 3344 | 3353 | <!-- YAML | |
| 3345 | 3354 | added: v12.12.0 | |
| 3346 | 3355 | changes: | |
| 3356 | + - version: REPLACEME | ||
| 3357 | + pr-url: https://github.com/nodejs/node/pull/41439 | ||
| 3358 | + description: Added `recursive` option. | ||
| 3347 | 3359 | - version: v18.0.0 | |
| 3348 | 3360 | pr-url: https://github.com/nodejs/node/pull/41678 | |
| 3349 | 3361 | description: Passing an invalid callback to the `callback` argument | |
@@ -3362,6 +3374,7 @@ changes: | |||
| 3362 | 3374 | * `bufferSize` {number} Number of directory entries that are buffered | |
| 3363 | 3375 | internally when reading from the directory. Higher values lead to better | |
| 3364 | 3376 | performance but higher memory usage. **Default:** `32` | |
| 3377 | + * `recursive` {boolean} **Default:** `false` | ||
| 3365 | 3378 | * `callback` {Function} | |
| 3366 | 3379 | * `err` {Error} | |
| 3367 | 3380 | * `dir` {fs.Dir} | |
@@ -3478,6 +3491,9 @@ above values. | |||
| 3478 | 3491 | <!-- YAML | |
| 3479 | 3492 | added: v0.1.8 | |
| 3480 | 3493 | changes: | |
| 3494 | + - version: REPLACEME | ||
| 3495 | + pr-url: https://github.com/nodejs/node/pull/41439 | ||
| 3496 | + description: Added `recursive` option. | ||
| 3481 | 3497 | - version: v18.0.0 | |
| 3482 | 3498 | pr-url: https://github.com/nodejs/node/pull/41678 | |
| 3483 | 3499 | description: Passing an invalid callback to the `callback` argument | |
@@ -3507,6 +3523,7 @@ changes: | |||
| 3507 | 3523 | * `options` {string|Object} | |
| 3508 | 3524 | * `encoding` {string} **Default:** `'utf8'` | |
| 3509 | 3525 | * `withFileTypes` {boolean} **Default:** `false` | |
| 3526 | + * `recursive` {boolean} **Default:** `false` | ||
| 3510 | 3527 | * `callback` {Function} | |
| 3511 | 3528 | * `err` {Error} | |
| 3512 | 3529 | * `files` {string\[]|Buffer\[]|fs.Dirent\[]} | |
@@ -5470,6 +5487,9 @@ object with an `encoding` property specifying the character encoding to use. | |||
| 5470 | 5487 | <!-- YAML | |
| 5471 | 5488 | added: v12.12.0 | |
| 5472 | 5489 | changes: | |
| 5490 | + - version: REPLACEME | ||
| 5491 | + pr-url: https://github.com/nodejs/node/pull/41439 | ||
| 5492 | + description: Added `recursive` option. | ||
| 5473 | 5493 | - version: | |
| 5474 | 5494 | - v13.1.0 | |
| 5475 | 5495 | - v12.16.0 | |
@@ -5483,6 +5503,7 @@ changes: | |||
| 5483 | 5503 | * `bufferSize` {number} Number of directory entries that are buffered | |
| 5484 | 5504 | internally when reading from the directory. Higher values lead to better | |
| 5485 | 5505 | performance but higher memory usage. **Default:** `32` | |
| 5506 | + * `recursive` {boolean} **Default:** `false` | ||
| 5486 | 5507 | * Returns: {fs.Dir} | |
| 5487 | 5508 | ||
| 5488 | 5509 | Synchronously open a directory. See opendir(3). | |
@@ -5526,6 +5547,9 @@ this API: [`fs.open()`][]. | |||
| 5526 | 5547 | <!-- YAML | |
| 5527 | 5548 | added: v0.1.21 | |
| 5528 | 5549 | changes: | |
| 5550 | + - version: REPLACEME | ||
| 5551 | + pr-url: https://github.com/nodejs/node/pull/41439 | ||
| 5552 | + description: Added `recursive` option. | ||
| 5529 | 5553 | - version: v10.10.0 | |
| 5530 | 5554 | pr-url: https://github.com/nodejs/node/pull/22020 | |
| 5531 | 5555 | description: New option `withFileTypes` was added. | |
@@ -5539,6 +5563,7 @@ changes: | |||
| 5539 | 5563 | * `options` {string|Object} | |
| 5540 | 5564 | * `encoding` {string} **Default:** `'utf8'` | |
| 5541 | 5565 | * `withFileTypes` {boolean} **Default:** `false` | |
| 5566 | + * `recursive` {boolean} **Default:** `false` | ||
| 5542 | 5567 | * Returns: {string\[]|Buffer\[]|fs.Dirent\[]} | |
| 5543 | 5568 | ||
| 5544 | 5569 | Reads the contents of the directory. | |
@@ -6384,6 +6409,16 @@ The file name that this {fs.Dirent} object refers to. The type of this | |||
| 6384 | 6409 | value is determined by the `options.encoding` passed to [`fs.readdir()`][] or | |
| 6385 | 6410 | [`fs.readdirSync()`][]. | |
| 6386 | 6411 | ||
| 6412 | + #### `dirent.path` | ||
| 6413 | + | ||
| 6414 | + <!-- YAML | ||
| 6415 | + added: REPLACEME | ||
| 6416 | + --> | ||
| 6417 | + | ||
| 6418 | + * {string} | ||
| 6419 | + | ||
| 6420 | + The base path that this {fs.Dirent} object refers to. | ||
| 6421 | + | ||
| 6387 | 6422 | ### Class: `fs.FSWatcher` | |
| 6388 | 6423 | ||
| 6389 | 6424 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1399,6 +1399,36 @@ function mkdirSync(path, options) { | |||
| 1399 | 1399 | } | |
| 1400 | 1400 | } | |
| 1401 | 1401 | ||
| 1402 | + // TODO(Ethan-Arrowood): Make this iterative too | ||
| 1403 | + function readdirSyncRecursive(path, origPath, options) { | ||
| 1404 | + nullCheck(path, 'path', true); | ||
| 1405 | + const ctx = { path }; | ||
| 1406 | + const result = binding.readdir(pathModule.toNamespacedPath(path), | ||
| 1407 | + options.encoding, !!options.withFileTypes, undefined, ctx); | ||
| 1408 | + handleErrorFromBinding(ctx); | ||
| 1409 | + return options.withFileTypes ? | ||
| 1410 | + getDirents(path, result).flatMap((dirent) => { | ||
| 1411 | + return [ | ||
| 1412 | + dirent, | ||
| 1413 | + ...(dirent.isDirectory() ? | ||
| 1414 | + readdirSyncRecursive( | ||
| 1415 | + pathModule.join(path, dirent.name), | ||
| 1416 | + origPath, | ||
| 1417 | + options, | ||
| 1418 | + ) : []), | ||
| 1419 | + ]; | ||
| 1420 | + }) : | ||
| 1421 | + result.flatMap((ent) => { | ||
| 1422 | + const innerPath = pathModule.join(path, ent); | ||
| 1423 | + const relativePath = pathModule.relative(origPath, innerPath); | ||
| 1424 | + const stat = binding.internalModuleStat(innerPath); | ||
| 1425 | + return [ | ||
| 1426 | + relativePath, | ||
| 1427 | + ...(stat === 1 ? readdirSyncRecursive(innerPath, origPath, options) : []), | ||
| 1428 | + ]; | ||
| 1429 | + }); | ||
| 1430 | + } | ||
| 1431 | + | ||
| 1402 | 1432 | /** | |
| 1403 | 1433 | * Reads the contents of a directory. | |
| 1404 | 1434 | * @param {string | Buffer | URL} path | |
@@ -1416,6 +1446,14 @@ function readdir(path, options, callback) { | |||
| 1416 | 1446 | callback = makeCallback(typeof options === 'function' ? options : callback); | |
| 1417 | 1447 | options = getOptions(options); | |
| 1418 | 1448 | path = getValidatedPath(path); | |
| 1449 | + if (options.recursive != null) { | ||
| 1450 | + validateBoolean(options.recursive, 'options.recursive'); | ||
| 1451 | + } | ||
| 1452 | + | ||
| 1453 | + if (options.recursive) { | ||
| 1454 | + callback(null, readdirSyncRecursive(path, path, options)); | ||
| 1455 | + return; | ||
| 1456 | + } | ||
| 1419 | 1457 | ||
| 1420 | 1458 | const req = new FSReqCallback(); | |
| 1421 | 1459 | if (!options.withFileTypes) { | |
@@ -1439,12 +1477,21 @@ function readdir(path, options, callback) { | |||
| 1439 | 1477 | * @param {string | { | |
| 1440 | 1478 | * encoding?: string; | |
| 1441 | 1479 | * withFileTypes?: boolean; | |
| 1480 | + * recursive?: boolean; | ||
| 1442 | 1481 | * }} [options] | |
| 1443 | 1482 | * @returns {string | Buffer[] | Dirent[]} | |
| 1444 | 1483 | */ | |
| 1445 | 1484 | function readdirSync(path, options) { | |
| 1446 | 1485 | options = getOptions(options); | |
| 1447 | 1486 | path = getValidatedPath(path); | |
| 1487 | + if (options.recursive != null) { | ||
| 1488 | + validateBoolean(options.recursive, 'options.recursive'); | ||
| 1489 | + } | ||
| 1490 | + | ||
| 1491 | + if (options.recursive) { | ||
| 1492 | + return readdirSyncRecursive(path, path, options); | ||
| 1493 | + } | ||
| 1494 | + | ||
| 1448 | 1495 | const ctx = { path }; | |
| 1449 | 1496 | const result = binding.readdir(pathModule.toNamespacedPath(path), | |
| 1450 | 1497 | options.encoding, !!options.withFileTypes, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,8 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | 4 | ArrayPrototypePush, | |
| 5 | - ArrayPrototypeSlice, | ||
| 6 | - ArrayPrototypeSplice, | ||
| 5 | + ArrayPrototypeShift, | ||
| 7 | 6 | FunctionPrototypeBind, | |
| 8 | 7 | ObjectDefineProperty, | |
| 9 | 8 | PromiseReject, | |
@@ -99,13 +98,21 @@ class Dir { | |||
| 99 | 98 | } | |
| 100 | 99 | ||
| 101 | 100 | if (this[kDirBufferedEntries].length > 0) { | |
| 102 | - const { 0: name, 1: type } = | ||
| 103 | - ArrayPrototypeSplice(this[kDirBufferedEntries], 0, 2); | ||
| 104 | - if (maybeSync) | ||
| 105 | - process.nextTick(getDirent, this[kDirPath], name, type, callback); | ||
| 106 | - else | ||
| 107 | - getDirent(this[kDirPath], name, type, callback); | ||
| 108 | - return; | ||
| 101 | + try { | ||
| 102 | + const dirent = ArrayPrototypeShift(this[kDirBufferedEntries]); | ||
| 103 | + | ||
| 104 | + if (this[kDirOptions].recursive && dirent.isDirectory()) { | ||
| 105 | + this.readSyncRecursive(dirent); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + if (maybeSync) | ||
| 109 | + process.nextTick(callback, null, dirent); | ||
| 110 | + else | ||
| 111 | + callback(null, dirent); | ||
| 112 | + return; | ||
| 113 | + } catch (error) { | ||
| 114 | + return callback(error); | ||
| 115 | + } | ||
| 109 | 116 | } | |
| 110 | 117 | ||
| 111 | 118 | const req = new FSReqCallback(); | |
@@ -120,8 +127,16 @@ class Dir { | |||
| 120 | 127 | return callback(err, result); | |
| 121 | 128 | } | |
| 122 | 129 | ||
| 123 | - this[kDirBufferedEntries] = ArrayPrototypeSlice(result, 2); | ||
| 124 | - getDirent(this[kDirPath], result[0], result[1], callback); | ||
| 130 | + try { | ||
| 131 | + this.processReadResult(this[kDirPath], result); | ||
| 132 | + const dirent = ArrayPrototypeShift(this[kDirBufferedEntries]); | ||
| 133 | + if (this[kDirOptions].recursive && dirent.isDirectory()) { | ||
| 134 | + this.readSyncRecursive(dirent); | ||
| 135 | + } | ||
| 136 | + callback(null, dirent); | ||
| 137 | + } catch (error) { | ||
| 138 | + callback(error); | ||
| 139 | + } | ||
| 125 | 140 | }; | |
| 126 | 141 | ||
| 127 | 142 | this[kDirOperationQueue] = []; | |
@@ -132,6 +147,45 @@ class Dir { | |||
| 132 | 147 | ); | |
| 133 | 148 | } | |
| 134 | 149 | ||
| 150 | + processReadResult(path, result) { | ||
| 151 | + for (let i = 0; i < result.length; i += 2) { | ||
| 152 | + ArrayPrototypePush( | ||
| 153 | + this[kDirBufferedEntries], | ||
| 154 | + getDirent( | ||
| 155 | + pathModule.join(path, result[i]), | ||
| 156 | + result[i], | ||
| 157 | + result[i + 1], | ||
| 158 | + ), | ||
| 159 | + ); | ||
| 160 | + } | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + // TODO(Ethan-Arrowood): Review this implementation. Make it iterative. | ||
| 164 | + // Can we better leverage the `kDirOperationQueue`? | ||
| 165 | + readSyncRecursive(dirent) { | ||
| 166 | + const ctx = { path: dirent.path }; | ||
| 167 | + const handle = dirBinding.opendir( | ||
| 168 | + pathModule.toNamespacedPath(dirent.path), | ||
| 169 | + this[kDirOptions].encoding, | ||
| 170 | + undefined, | ||
| 171 | + ctx, | ||
| 172 | + ); | ||
| 173 | + handleErrorFromBinding(ctx); | ||
| 174 | + const result = handle.read( | ||
| 175 | + this[kDirOptions].encoding, | ||
| 176 | + this[kDirOptions].bufferSize, | ||
| 177 | + undefined, | ||
| 178 | + ctx, | ||
| 179 | + ); | ||
| 180 | + | ||
| 181 | + if (result) { | ||
| 182 | + this.processReadResult(dirent.path, result); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + handle.close(undefined, ctx); | ||
| 186 | + handleErrorFromBinding(ctx); | ||
| 187 | + } | ||
| 188 | + | ||
| 135 | 189 | readSync() { | |
| 136 | 190 | if (this[kDirClosed] === true) { | |
| 137 | 191 | throw new ERR_DIR_CLOSED(); | |
@@ -142,9 +196,11 @@ class Dir { | |||
| 142 | 196 | } | |
| 143 | 197 | ||
| 144 | 198 | if (this[kDirBufferedEntries].length > 0) { | |
| 145 | - const { 0: name, 1: type } = | ||
| 146 | - ArrayPrototypeSplice(this[kDirBufferedEntries], 0, 2); | ||
| 147 | - return getDirent(this[kDirPath], name, type); | ||
| 199 | + const dirent = ArrayPrototypeShift(this[kDirBufferedEntries]); | ||
| 200 | + if (this[kDirOptions].recursive && dirent.isDirectory()) { | ||
| 201 | + this.readSyncRecursive(dirent); | ||
| 202 | + } | ||
| 203 | + return dirent; | ||
| 148 | 204 | } | |
| 149 | 205 | ||
| 150 | 206 | const ctx = { path: this[kDirPath] }; | |
@@ -160,8 +216,13 @@ class Dir { | |||
| 160 | 216 | return result; | |
| 161 | 217 | } | |
| 162 | 218 | ||
| 163 | - this[kDirBufferedEntries] = ArrayPrototypeSlice(result, 2); | ||
| 164 | - return getDirent(this[kDirPath], result[0], result[1]); | ||
| 219 | + this.processReadResult(this[kDirPath], result); | ||
| 220 | + | ||
| 221 | + const dirent = ArrayPrototypeShift(this[kDirBufferedEntries]); | ||
| 222 | + if (this[kDirOptions].recursive && dirent.isDirectory()) { | ||
| 223 | + this.readSyncRecursive(dirent); | ||
| 224 | + } | ||
| 225 | + return dirent; | ||
| 165 | 226 | } | |
| 166 | 227 | ||
| 167 | 228 | close(callback) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments