@@ -1370,6 +1370,102 @@ function mkdirSync(path, options) {
1370
1370
}
1371
1371
}
1372
1372
1373
+ /*
1374
+ * An recursive algorithm for reading the entire contents of the `basePath` directory.
1375
+ * This function does not validate `basePath` as a directory. It is passed directly to
1376
+ * `binding.readdir`.
1377
+ * @param {string } basePath
1378
+ * @param {{ encoding: string, withFileTypes: boolean } } options
1379
+ * @param {(
1380
+ * err?: Error,
1381
+ * files?: string[] | Buffer[] | Dirent[]
1382
+ * ) => any} callback
1383
+ * @returns {void }
1384
+ */
1385
+ function readdirRecursive ( basePath , options , callback ) {
1386
+ const context = {
1387
+ withFileTypes : Boolean ( options . withFileTypes ) ,
1388
+ encoding : options . encoding ,
1389
+ basePath,
1390
+ readdirResults : [ ] ,
1391
+ pathsQueue : [ basePath ] ,
1392
+ } ;
1393
+
1394
+ let i = 0 ;
1395
+
1396
+ function read ( path ) {
1397
+ const req = new FSReqCallback ( ) ;
1398
+ req . oncomplete = ( err , result ) => {
1399
+ if ( err ) {
1400
+ callback ( err ) ;
1401
+ return ;
1402
+ }
1403
+
1404
+ if ( result === undefined ) {
1405
+ callback ( null , context . readdirResults ) ;
1406
+ return ;
1407
+ }
1408
+
1409
+ processReaddirResult ( {
1410
+ result,
1411
+ currentPath : path ,
1412
+ context,
1413
+ } ) ;
1414
+
1415
+ if ( i < context . pathsQueue . length ) {
1416
+ read ( context . pathsQueue [ i ++ ] ) ;
1417
+ } else {
1418
+ callback ( null , context . readdirResults ) ;
1419
+ }
1420
+ } ;
1421
+
1422
+ binding . readdir (
1423
+ path ,
1424
+ context . encoding ,
1425
+ context . withFileTypes ,
1426
+ req ,
1427
+ ) ;
1428
+ }
1429
+
1430
+ read ( context . pathsQueue [ i ++ ] ) ;
1431
+ }
1432
+
1433
+ // Calling `readdir` with `withFileTypes=true`, the result is an array of arrays.
1434
+ // The first array is the names, and the second array is the types.
1435
+ // They are guaranteed to be the same length; hence, setting `length` to the length
1436
+ // of the first array within the result.
1437
+ const processReaddirResult = ( args ) => ( args . context . withFileTypes ? handleDirents ( args ) : handleFilePaths ( args ) ) ;
1438
+
1439
+ function handleDirents ( { result, currentPath, context } ) {
1440
+ const { 0 : names , 1 : types } = result ;
1441
+ const { length } = names ;
1442
+
1443
+ for ( let i = 0 ; i < length ; i ++ ) {
1444
+ // Avoid excluding symlinks, as they are not directories.
1445
+ // Refs: https://github.com/nodejs/node/issues/52663
1446
+ const fullPath = pathModule . join ( currentPath , names [ i ] ) ;
1447
+ const dirent = getDirent ( currentPath , names [ i ] , types [ i ] ) ;
1448
+ ArrayPrototypePush ( context . readdirResults , dirent ) ;
1449
+
1450
+ if ( dirent . isDirectory ( ) || binding . internalModuleStat ( binding , fullPath ) === 1 ) {
1451
+ ArrayPrototypePush ( context . pathsQueue , fullPath ) ;
1452
+ }
1453
+ }
1454
+ }
1455
+
1456
+ function handleFilePaths ( { result, currentPath, context } ) {
1457
+ for ( let i = 0 ; i < result . length ; i ++ ) {
1458
+ const resultPath = pathModule . join ( currentPath , result [ i ] ) ;
1459
+ const relativeResultPath = pathModule . relative ( context . basePath , resultPath ) ;
1460
+ const stat = binding . internalModuleStat ( binding , resultPath ) ;
1461
+ ArrayPrototypePush ( context . readdirResults , relativeResultPath ) ;
1462
+
1463
+ if ( stat === 1 ) {
1464
+ ArrayPrototypePush ( context . pathsQueue , resultPath ) ;
1465
+ }
1466
+ }
1467
+ }
1468
+
1373
1469
/**
1374
1470
* An iterative algorithm for reading the entire contents of the `basePath` directory.
1375
1471
* This function does not validate `basePath` as a directory. It is passed directly to
@@ -1379,58 +1475,37 @@ function mkdirSync(path, options) {
1379
1475
* @returns {string[] | Dirent[] }
1380
1476
*/
1381
1477
function readdirSyncRecursive ( basePath , options ) {
1382
- const withFileTypes = Boolean ( options . withFileTypes ) ;
1383
- const encoding = options . encoding ;
1384
-
1385
- const readdirResults = [ ] ;
1386
- const pathsQueue = [ basePath ] ;
1478
+ const context = {
1479
+ withFileTypes : Boolean ( options . withFileTypes ) ,
1480
+ encoding : options . encoding ,
1481
+ basePath,
1482
+ readdirResults : [ ] ,
1483
+ pathsQueue : [ basePath ] ,
1484
+ } ;
1387
1485
1388
1486
function read ( path ) {
1389
1487
const readdirResult = binding . readdir (
1390
1488
path ,
1391
- encoding ,
1392
- withFileTypes ,
1489
+ context . encoding ,
1490
+ context . withFileTypes ,
1393
1491
) ;
1394
1492
1395
1493
if ( readdirResult === undefined ) {
1396
1494
return ;
1397
1495
}
1398
1496
1399
- if ( withFileTypes ) {
1400
- // Calling `readdir` with `withFileTypes=true`, the result is an array of arrays.
1401
- // The first array is the names, and the second array is the types.
1402
- // They are guaranteed to be the same length; hence, setting `length` to the length
1403
- // of the first array within the result.
1404
- const length = readdirResult [ 0 ] . length ;
1405
- for ( let i = 0 ; i < length ; i ++ ) {
1406
- // Avoid excluding symlinks, as they are not directories.
1407
- // Refs: https://github.com/nodejs/node/issues/52663
1408
- const stat = binding . internalModuleStat ( binding , pathModule . join ( path , readdirResult [ 0 ] [ i ] ) ) ;
1409
- const dirent = getDirent ( path , readdirResult [ 0 ] [ i ] , readdirResult [ 1 ] [ i ] ) ;
1410
- ArrayPrototypePush ( readdirResults , dirent ) ;
1411
- if ( dirent . isDirectory ( ) || stat === 1 ) {
1412
- ArrayPrototypePush ( pathsQueue , pathModule . join ( dirent . parentPath , dirent . name ) ) ;
1413
- }
1414
- }
1415
- } else {
1416
- for ( let i = 0 ; i < readdirResult . length ; i ++ ) {
1417
- const resultPath = pathModule . join ( path , readdirResult [ i ] ) ;
1418
- const relativeResultPath = pathModule . relative ( basePath , resultPath ) ;
1419
- const stat = binding . internalModuleStat ( binding , resultPath ) ;
1420
- ArrayPrototypePush ( readdirResults , relativeResultPath ) ;
1421
- // 1 indicates directory
1422
- if ( stat === 1 ) {
1423
- ArrayPrototypePush ( pathsQueue , resultPath ) ;
1424
- }
1425
- }
1426
- }
1497
+ processReaddirResult ( {
1498
+ result : readdirResult ,
1499
+ currentPath : path ,
1500
+ context,
1501
+ } ) ;
1427
1502
}
1428
1503
1429
- for ( let i = 0 ; i < pathsQueue . length ; i ++ ) {
1430
- read ( pathsQueue [ i ] ) ;
1504
+ for ( let i = 0 ; i < context . pathsQueue . length ; i ++ ) {
1505
+ read ( context . pathsQueue [ i ] ) ;
1431
1506
}
1432
1507
1433
- return readdirResults ;
1508
+ return context . readdirResults ;
1434
1509
}
1435
1510
1436
1511
/**
@@ -1456,7 +1531,7 @@ function readdir(path, options, callback) {
1456
1531
}
1457
1532
1458
1533
if ( options . recursive ) {
1459
- callback ( null , readdirSyncRecursive ( path , options ) ) ;
1534
+ readdirRecursive ( path , options , callback ) ;
1460
1535
return ;
1461
1536
}
1462
1537
0 commit comments