@@ -24,6 +24,8 @@ const nextTick = (functionToCall: Function, args: any[] = []) => {
24
24
process . nextTick ( ( ) => functionToCall ( ...args ) ) ;
25
25
} ;
26
26
27
+ const binding = internalBinding ( 'fs' ) ;
28
+
27
29
// Cache asar archive objects.
28
30
const cachedArchives = new Map < string , NodeJS . AsarArchive > ( ) ;
29
31
@@ -705,7 +707,87 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
705
707
} ;
706
708
707
709
type ReaddirOptions = { encoding : BufferEncoding | null ; withFileTypes ?: false , recursive ?: false } | undefined | null ;
708
- type ReaddirCallback = ( err : NodeJS . ErrnoException | null , files : string [ ] ) => void ;
710
+ type ReaddirCallback = ( err : NodeJS . ErrnoException | null , files ?: string [ ] ) => void ;
711
+
712
+ const processReaddirResult = ( args : any ) => ( args . context . withFileTypes ? handleDirents ( args ) : handleFilePaths ( args ) ) ;
713
+
714
+ function handleDirents ( { result, currentPath, context } : { result : string [ ] , currentPath : string , context : any } ) {
715
+ const { 0 : names , 1 : types } = result ;
716
+ const { length } = names ;
717
+
718
+ for ( let i = 0 ; i < length ; i ++ ) {
719
+ // Avoid excluding symlinks, as they are not directories.
720
+ // Refs: https://github.com/nodejs/node/issues/52663
721
+ const fullPath = path . join ( currentPath , names [ i ] ) ;
722
+ const dirent = getDirent ( currentPath , names [ i ] , types [ i ] ) ;
723
+ context . readdirResults . push ( dirent ) ;
724
+
725
+ if ( dirent . isDirectory ( ) || binding . internalModuleStat ( binding , fullPath ) === 1 ) {
726
+ context . pathsQueue . push ( fullPath ) ;
727
+ }
728
+ }
729
+ }
730
+
731
+ function handleFilePaths ( { result, currentPath, context } : { result : string [ ] , currentPath : string , context : any } ) {
732
+ for ( let i = 0 ; i < result . length ; i ++ ) {
733
+ const resultPath = path . join ( currentPath , result [ i ] ) ;
734
+ const relativeResultPath = path . relative ( context . basePath , resultPath ) ;
735
+ const stat = binding . internalModuleStat ( binding , resultPath ) ;
736
+ context . readdirResults . push ( relativeResultPath ) ;
737
+
738
+ if ( stat === 1 ) {
739
+ context . pathsQueue . push ( resultPath ) ;
740
+ }
741
+ }
742
+ }
743
+
744
+ function readdirRecursive ( basePath : string , options : ReaddirOptions , callback : ReaddirCallback ) {
745
+ const context = {
746
+ withFileTypes : Boolean ( options ! . withFileTypes ) ,
747
+ encoding : options ! . encoding ,
748
+ basePath,
749
+ readdirResults : [ ] ,
750
+ pathsQueue : [ basePath ]
751
+ } ;
752
+
753
+ let i = 0 ;
754
+
755
+ function read ( pathArg : string ) {
756
+ const req = new binding . FSReqCallback ( ) ;
757
+ req . oncomplete = ( err : any , result : any ) => {
758
+ if ( err ) {
759
+ callback ( err ) ;
760
+ return ;
761
+ }
762
+
763
+ if ( result === undefined ) {
764
+ callback ( null , context . readdirResults ) ;
765
+ return ;
766
+ }
767
+
768
+ processReaddirResult ( {
769
+ result,
770
+ currentPath : pathArg ,
771
+ context
772
+ } ) ;
773
+
774
+ if ( i < context . pathsQueue . length ) {
775
+ read ( context . pathsQueue [ i ++ ] ) ;
776
+ } else {
777
+ callback ( null , context . readdirResults ) ;
778
+ }
779
+ } ;
780
+
781
+ binding . readdir (
782
+ pathArg ,
783
+ context . encoding ,
784
+ context . withFileTypes ,
785
+ req
786
+ ) ;
787
+ }
788
+
789
+ read ( context . pathsQueue [ i ++ ] ) ;
790
+ }
709
791
710
792
const { readdir } = fs ;
711
793
fs . readdir = function ( pathArgument : string , options : ReaddirOptions , callback : ReaddirCallback ) {
@@ -720,7 +802,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
720
802
}
721
803
722
804
if ( options ?. recursive ) {
723
- nextTick ( callback ! , [ null , readdirSyncRecursive ( pathArgument , options ) ] ) ;
805
+ readdirRecursive ( pathArgument , options , callback ) ;
724
806
return ;
725
807
}
726
808
@@ -771,7 +853,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
771
853
}
772
854
773
855
if ( options ?. recursive ) {
774
- return readdirRecursive ( pathArgument , options ) ;
856
+ return readdirRecursivePromises ( pathArgument , options ) ;
775
857
}
776
858
777
859
const pathInfo = splitPath ( pathArgument ) ;
@@ -868,8 +950,6 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
868
950
return readPackageJSON ( realPath , isESM , base , specifier ) ;
869
951
} ;
870
952
871
- const binding = internalBinding ( 'fs' ) ;
872
-
873
953
const { internalModuleStat } = binding ;
874
954
internalBinding ( 'fs' ) . internalModuleStat = ( receiver : unknown , pathArgument : string ) => {
875
955
const pathInfo = splitPath ( pathArgument ) ;
@@ -888,7 +968,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
888
968
} ;
889
969
890
970
const { kUsePromises } = binding ;
891
- async function readdirRecursive ( originalPath : string , options : ReaddirOptions ) {
971
+ async function readdirRecursivePromises ( originalPath : string , options : ReaddirOptions ) {
892
972
const result : any [ ] = [ ] ;
893
973
894
974
const pathInfo = splitPath ( originalPath ) ;
@@ -992,11 +1072,13 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
992
1072
}
993
1073
994
1074
function readdirSyncRecursive ( basePath : string , options : ReaddirOptions ) {
995
- const withFileTypes = Boolean ( options ! . withFileTypes ) ;
996
- const encoding = options ! . encoding ;
997
-
998
- const readdirResults : string [ ] = [ ] ;
999
- const pathsQueue = [ basePath ] ;
1075
+ const context = {
1076
+ withFileTypes : Boolean ( options ! . withFileTypes ) ,
1077
+ encoding : options ! . encoding ,
1078
+ basePath,
1079
+ readdirResults : [ ] as any ,
1080
+ pathsQueue : [ basePath ]
1081
+ } ;
1000
1082
1001
1083
function read ( pathArg : string ) {
1002
1084
let readdirResult ;
@@ -1011,7 +1093,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
1011
1093
if ( ! readdirResult ) return ;
1012
1094
// If we're in an asar dir, we need to ensure the result is in the same format as the
1013
1095
// native call to readdir withFileTypes i.e. an array of arrays.
1014
- if ( withFileTypes ) {
1096
+ if ( context . withFileTypes ) {
1015
1097
readdirResult = [
1016
1098
[ ...readdirResult ] , readdirResult . map ( ( p : string ) => {
1017
1099
return internalBinding ( 'fs' ) . internalModuleStat ( binding , path . join ( pathArg , p ) ) ;
@@ -1021,14 +1103,14 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
1021
1103
} else {
1022
1104
readdirResult = binding . readdir (
1023
1105
path . toNamespacedPath ( pathArg ) ,
1024
- encoding ,
1025
- withFileTypes
1106
+ context . encoding ,
1107
+ context . withFileTypes
1026
1108
) ;
1027
1109
}
1028
1110
1029
1111
if ( readdirResult === undefined ) return ;
1030
1112
1031
- if ( withFileTypes ) {
1113
+ if ( context . withFileTypes ) {
1032
1114
const length = readdirResult [ 0 ] . length ;
1033
1115
for ( let i = 0 ; i < length ; i ++ ) {
1034
1116
const resultPath = path . join ( pathArg , readdirResult [ 0 ] [ i ] ) ;
@@ -1045,9 +1127,9 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
1045
1127
1046
1128
const dirent = getDirent ( pathArg , readdirResult [ 0 ] [ i ] , type ) ;
1047
1129
1048
- readdirResults . push ( dirent ) ;
1130
+ context . readdirResults . push ( dirent ) ;
1049
1131
if ( dirent . isDirectory ( ) ) {
1050
- pathsQueue . push ( path . join ( dirent . path , dirent . name ) ) ;
1132
+ context . pathsQueue . push ( path . join ( dirent . path , dirent . name ) ) ;
1051
1133
}
1052
1134
}
1053
1135
} else {
@@ -1056,17 +1138,17 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
1056
1138
const relativeResultPath = path . relative ( basePath , resultPath ) ;
1057
1139
const stat = internalBinding ( 'fs' ) . internalModuleStat ( binding , resultPath ) ;
1058
1140
1059
- readdirResults . push ( relativeResultPath ) ;
1060
- if ( stat === 1 ) pathsQueue . push ( resultPath ) ;
1141
+ context . readdirResults . push ( relativeResultPath ) ;
1142
+ if ( stat === 1 ) context . pathsQueue . push ( resultPath ) ;
1061
1143
}
1062
1144
}
1063
1145
}
1064
1146
1065
- for ( let i = 0 ; i < pathsQueue . length ; i ++ ) {
1066
- read ( pathsQueue [ i ] ) ;
1147
+ for ( let i = 0 ; i < context . pathsQueue . length ; i ++ ) {
1148
+ read ( context . pathsQueue [ i ] ) ;
1067
1149
}
1068
1150
1069
- return readdirResults ;
1151
+ return context . readdirResults ;
1070
1152
}
1071
1153
1072
1154
// Calling mkdir for directory inside asar archive should throw ENOTDIR
0 commit comments