2727const {
2828 ArrayPrototypePush,
2929 BigIntPrototypeToString,
30+ Boolean,
3031 MathMax,
3132 Number,
3233 ObjectDefineProperties,
@@ -95,6 +96,7 @@ const {
9596 copyObject,
9697 Dirent,
9798 emitRecursiveRmdirWarning,
99+ getDirent,
98100 getDirents,
99101 getOptions,
100102 getValidatedFd,
@@ -1399,34 +1401,60 @@ function mkdirSync(path, options) {
13991401 }
14001402}
14011403
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- } ) ;
1404+ /**
1405+ * An iterative algorithm for reading the entire contents of the `basePath` directory.
1406+ * This function does not validate `basePath` as a directory. It is passed directly to
1407+ * `binding.readdir` after a `nullCheck`.
1408+ * @param {string } basePath
1409+ * @param {{ encoding: string, withFileTypes: boolean } } options
1410+ * @returns {string[] | Dirent[] }
1411+ */
1412+ function readdirSyncRecursive ( basePath , options ) {
1413+ nullCheck ( basePath , 'path' , true ) ;
1414+
1415+ const withFileTypes = Boolean ( options . withFileTypes ) ;
1416+ const encoding = options . encoding ;
1417+
1418+ const readdirResults = [ ] ;
1419+ const pathsQueue = [ basePath ] ;
1420+
1421+ const ctx = { path : basePath } ;
1422+ function read ( path ) {
1423+ ctx . path = path ;
1424+ const readdirResult = binding . readdir (
1425+ pathModule . toNamespacedPath ( path ) ,
1426+ encoding ,
1427+ withFileTypes ,
1428+ undefined ,
1429+ ctx ,
1430+ ) ;
1431+ handleErrorFromBinding ( ctx ) ;
1432+
1433+ for ( let i = 0 ; i < readdirResult . length ; i ++ ) {
1434+ if ( withFileTypes ) {
1435+ const dirent = getDirent ( path , readdirResult [ 0 ] [ i ] , readdirResult [ 1 ] [ i ] ) ;
1436+ ArrayPrototypePush ( readdirResults , dirent ) ;
1437+ if ( dirent . isDirectory ( ) ) {
1438+ ArrayPrototypePush ( pathsQueue , pathModule . join ( dirent . path , dirent . name ) ) ;
1439+ }
1440+ } else {
1441+ const resultPath = pathModule . join ( path , readdirResult [ i ] ) ;
1442+ const relativeResultPath = pathModule . relative ( basePath , resultPath ) ;
1443+ const stat = binding . internalModuleStat ( resultPath ) ;
1444+ ArrayPrototypePush ( readdirResults , relativeResultPath ) ;
1445+ // 1 indicates directory
1446+ if ( stat === 1 ) {
1447+ ArrayPrototypePush ( pathsQueue , resultPath ) ;
1448+ }
1449+ }
1450+ }
1451+ }
1452+
1453+ for ( let i = 0 ; i < pathsQueue . length ; i ++ ) {
1454+ read ( pathsQueue [ i ] ) ;
1455+ }
1456+
1457+ return readdirResults ;
14301458}
14311459
14321460/**
@@ -1451,7 +1479,7 @@ function readdir(path, options, callback) {
14511479 }
14521480
14531481 if ( options . recursive ) {
1454- callback ( null , readdirSyncRecursive ( path , path , options ) ) ;
1482+ callback ( null , readdirSyncRecursive ( path , options ) ) ;
14551483 return ;
14561484 }
14571485
@@ -1489,7 +1517,7 @@ function readdirSync(path, options) {
14891517 }
14901518
14911519 if ( options . recursive ) {
1492- return readdirSyncRecursive ( path , path , options ) ;
1520+ return readdirSyncRecursive ( path , options ) ;
14931521 }
14941522
14951523 const ctx = { path } ;
0 commit comments