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