2626
2727const {
2828 ArrayPrototypePush,
29+ ArrayPrototypeShift,
2930 BigIntPrototypeToString,
3031 MathMax,
3132 Number,
@@ -140,7 +141,6 @@ const {
140141 validateObject,
141142 validateString,
142143} = require ( 'internal/validators' ) ;
143-
144144let truncateWarn = true ;
145145let fs ;
146146
@@ -1404,34 +1404,64 @@ function mkdirSync(path, options) {
14041404 }
14051405}
14061406
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- } ) ;
1407+ /**
1408+ * An iterative algorithm for reading the entire contents of the `basePath` directory.
1409+ * This function does not validate `basePath` as a directory. It is passed directly to
1410+ * `binding.readdir` after a `nullCheck`.
1411+ * @param {string } basePath
1412+ * @param {{ encoding: string, withFileTypes: boolean } } options
1413+ * @returns {Array<string> | Array<Dirent> }
1414+ */
1415+ function readdirSyncRecursive ( basePath , options ) {
1416+ nullCheck ( basePath , 'path' , true ) ;
1417+
1418+ const results = [ ] ;
1419+ const opsQueue = [ ] ;
1420+
1421+ function _read ( _path ) {
1422+ const ctx = { _path } ;
1423+ const result = binding . readdir (
1424+ pathModule . toNamespacedPath ( _path ) ,
1425+ options . encoding ,
1426+ ! ! options . withFileTypes ,
1427+ undefined ,
1428+ ctx ,
1429+ ) ;
1430+ handleErrorFromBinding ( ctx ) ;
1431+
1432+ if ( options . withFileTypes ) {
1433+ const dirents = getDirents ( _path , result ) ;
1434+ for ( let i = 0 ; i < dirents . length ; i ++ ) {
1435+ const dirent = dirents [ i ] ;
1436+ ArrayPrototypePush ( results , dirent ) ;
1437+ if ( dirent . isDirectory ( ) ) {
1438+ ArrayPrototypePush ( opsQueue , curryRead ( pathModule . join ( dirent . path , dirent . name ) ) ) ;
1439+ }
1440+ }
1441+ } else {
1442+ for ( let i = 0 ; i < result . length ; i ++ ) {
1443+ const ent = result [ i ] ;
1444+ const innerPath = pathModule . join ( _path , ent ) ;
1445+ const relativePath = pathModule . relative ( basePath , innerPath ) ;
1446+ const stat = binding . internalModuleStat ( innerPath ) ;
1447+ ArrayPrototypePush ( results , relativePath ) ;
1448+ if ( stat === 1 ) {
1449+ ArrayPrototypePush ( opsQueue , curryRead ( innerPath ) ) ;
1450+ }
1451+ }
1452+ }
1453+ }
1454+
1455+ const curryRead = ( p ) => ( ) => _read ( p ) ;
1456+
1457+ ArrayPrototypePush ( opsQueue , curryRead ( basePath ) ) ;
1458+
1459+ while ( opsQueue . length !== 0 ) {
1460+ const op = ArrayPrototypeShift ( opsQueue ) ;
1461+ op ( ) ;
1462+ }
1463+
1464+ return results ;
14351465}
14361466
14371467/**
@@ -1456,7 +1486,7 @@ function readdir(path, options, callback) {
14561486 }
14571487
14581488 if ( options . recursive ) {
1459- callback ( null , readdirSyncRecursive ( path , path , options ) ) ;
1489+ callback ( null , readdirSyncRecursive ( path , options ) ) ;
14601490 return ;
14611491 }
14621492
@@ -1494,7 +1524,7 @@ function readdirSync(path, options) {
14941524 }
14951525
14961526 if ( options . recursive ) {
1497- return readdirSyncRecursive ( path , path , options ) ;
1527+ return readdirSyncRecursive ( path , options ) ;
14981528 }
14991529
15001530 const ctx = { path } ;
0 commit comments