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