27
27
const {
28
28
ArrayPrototypePush,
29
29
BigIntPrototypeToString,
30
+ Boolean,
30
31
MathMax,
31
32
Number,
32
33
ObjectDefineProperties,
@@ -97,6 +98,7 @@ const {
97
98
copyObject,
98
99
Dirent,
99
100
emitRecursiveRmdirWarning,
101
+ getDirent,
100
102
getDirents,
101
103
getOptions,
102
104
getValidatedFd,
@@ -1404,34 +1406,60 @@ function mkdirSync(path, options) {
1404
1406
}
1405
1407
}
1406
1408
1407
- // TODO(Ethan-Arrowood): Make this iterative too
1408
- function readdirSyncRecursive ( path , origPath , options ) {
1409
- nullCheck ( path , 'path' , true ) ;
1410
- const ctx = { path } ;
1411
- const result = binding . readdir ( pathModule . toNamespacedPath ( path ) ,
1412
- options . encoding , ! ! options . withFileTypes , undefined , ctx ) ;
1413
- handleErrorFromBinding ( ctx ) ;
1414
- return options . withFileTypes ?
1415
- getDirents ( path , result ) . flatMap ( ( dirent ) => {
1416
- return [
1417
- dirent ,
1418
- ...( dirent . isDirectory ( ) ?
1419
- readdirSyncRecursive (
1420
- pathModule . join ( path , dirent . name ) ,
1421
- origPath ,
1422
- options ,
1423
- ) : [ ] ) ,
1424
- ] ;
1425
- } ) :
1426
- result . flatMap ( ( ent ) => {
1427
- const innerPath = pathModule . join ( path , ent ) ;
1428
- const relativePath = pathModule . relative ( origPath , innerPath ) ;
1429
- const stat = binding . internalModuleStat ( innerPath ) ;
1430
- return [
1431
- relativePath ,
1432
- ...( stat === 1 ? readdirSyncRecursive ( innerPath , origPath , options ) : [ ] ) ,
1433
- ] ;
1434
- } ) ;
1409
+ /**
1410
+ * An iterative algorithm for reading the entire contents of the `basePath` directory.
1411
+ * This function does not validate `basePath` as a directory. It is passed directly to
1412
+ * `binding.readdir` after a `nullCheck`.
1413
+ * @param {string } basePath
1414
+ * @param {{ encoding: string, withFileTypes: boolean } } options
1415
+ * @returns {string[] | Dirent[] }
1416
+ */
1417
+ function readdirSyncRecursive ( basePath , options ) {
1418
+ nullCheck ( basePath , 'path' , true ) ;
1419
+
1420
+ const withFileTypes = Boolean ( options . withFileTypes ) ;
1421
+ const encoding = options . encoding ;
1422
+
1423
+ const readdirResults = [ ] ;
1424
+ const pathsQueue = [ basePath ] ;
1425
+
1426
+ const ctx = { path : basePath } ;
1427
+ function read ( path ) {
1428
+ ctx . path = path ;
1429
+ const readdirResult = binding . readdir (
1430
+ pathModule . toNamespacedPath ( path ) ,
1431
+ encoding ,
1432
+ withFileTypes ,
1433
+ undefined ,
1434
+ ctx ,
1435
+ ) ;
1436
+ handleErrorFromBinding ( ctx ) ;
1437
+
1438
+ for ( let i = 0 ; i < readdirResult . length ; i ++ ) {
1439
+ if ( withFileTypes ) {
1440
+ const dirent = getDirent ( path , readdirResult [ 0 ] [ i ] , readdirResult [ 1 ] [ i ] ) ;
1441
+ ArrayPrototypePush ( readdirResults , dirent ) ;
1442
+ if ( dirent . isDirectory ( ) ) {
1443
+ ArrayPrototypePush ( pathsQueue , pathModule . join ( dirent . path , dirent . name ) ) ;
1444
+ }
1445
+ } else {
1446
+ const resultPath = pathModule . join ( path , readdirResult [ i ] ) ;
1447
+ const relativeResultPath = pathModule . relative ( basePath , resultPath ) ;
1448
+ const stat = binding . internalModuleStat ( resultPath ) ;
1449
+ ArrayPrototypePush ( readdirResults , relativeResultPath ) ;
1450
+ // 1 indicates directory
1451
+ if ( stat === 1 ) {
1452
+ ArrayPrototypePush ( pathsQueue , resultPath ) ;
1453
+ }
1454
+ }
1455
+ }
1456
+ }
1457
+
1458
+ for ( let i = 0 ; i < pathsQueue . length ; i ++ ) {
1459
+ read ( pathsQueue [ i ] ) ;
1460
+ }
1461
+
1462
+ return readdirResults ;
1435
1463
}
1436
1464
1437
1465
/**
@@ -1456,7 +1484,7 @@ function readdir(path, options, callback) {
1456
1484
}
1457
1485
1458
1486
if ( options . recursive ) {
1459
- callback ( null , readdirSyncRecursive ( path , path , options ) ) ;
1487
+ callback ( null , readdirSyncRecursive ( path , options ) ) ;
1460
1488
return ;
1461
1489
}
1462
1490
@@ -1494,7 +1522,7 @@ function readdirSync(path, options) {
1494
1522
}
1495
1523
1496
1524
if ( options . recursive ) {
1497
- return readdirSyncRecursive ( path , path , options ) ;
1525
+ return readdirSyncRecursive ( path , options ) ;
1498
1526
}
1499
1527
1500
1528
const ctx = { path } ;
0 commit comments