@@ -75,6 +75,17 @@ function isUnpackDir(path: string, pattern: Minimatch, rawPattern: string): bool
75
75
return path . startsWith ( rawPattern ) || pattern . match ( path )
76
76
}
77
77
78
+ function addValue ( map : Map < string , Array < string > > , key : string , value : string ) {
79
+ let list = map . get ( key )
80
+ if ( list == null ) {
81
+ list = [ value ]
82
+ map . set ( key , list )
83
+ }
84
+ else {
85
+ list . push ( value )
86
+ }
87
+ }
88
+
78
89
class AsarPackager {
79
90
private readonly toPack : Array < string > = [ ]
80
91
private readonly fs = new Filesystem ( this . src )
@@ -104,9 +115,10 @@ class AsarPackager {
104
115
return this . srcRealPath
105
116
}
106
117
107
- async detectUnpackedDirs ( files : Array < string > , metadata : Map < string , Stats > , autoUnpackDirs : Set < string > , createDirPromises : Array < Promise < any > > , unpackedDest : string , fileIndexToModulePackageData : Array < BluebirdPromise < string > > ) {
118
+ async detectUnpackedDirs ( files : Array < string > , metadata : Map < string , Stats > , autoUnpackDirs : Set < string > , unpackedDest : string , fileIndexToModulePackageData : Map < number , BluebirdPromise < string > > ) {
108
119
const packageJsonStringLength = "package.json" . length
109
- const readPackageJsonPromises : Array < Promise < any > > = [ ]
120
+ const dirToCreate = new Map < string , Array < string > > ( )
121
+
110
122
for ( let i = 0 , n = files . length ; i < n ; i ++ ) {
111
123
const file = files [ i ]
112
124
const index = file . lastIndexOf ( NODE_MODULES_PATTERN )
@@ -126,25 +138,14 @@ class AsarPackager {
126
138
const nodeModuleDir = file . substring ( 0 , nextSlashIndex )
127
139
128
140
if ( file . length === ( nodeModuleDir . length + 1 + packageJsonStringLength ) && file . endsWith ( "package.json" ) ) {
129
- const promise = readJson ( file )
130
-
131
- if ( readPackageJsonPromises . length > MAX_FILE_REQUESTS ) {
132
- await BluebirdPromise . all ( readPackageJsonPromises )
133
- readPackageJsonPromises . length = 0
134
- }
135
- readPackageJsonPromises . push ( promise )
136
- fileIndexToModulePackageData [ i ] = promise
141
+ fileIndexToModulePackageData . set ( i , readJson ( file ) . then ( it => cleanupPackageJson ( it ) ) )
137
142
}
138
143
139
144
if ( autoUnpackDirs . has ( nodeModuleDir ) ) {
140
145
const fileParent = path . dirname ( file )
141
146
if ( fileParent !== nodeModuleDir && ! autoUnpackDirs . has ( fileParent ) ) {
142
147
autoUnpackDirs . add ( fileParent )
143
- createDirPromises . push ( ensureDir ( path . join ( unpackedDest , path . relative ( this . src , fileParent ) ) ) )
144
- if ( createDirPromises . length > MAX_FILE_REQUESTS ) {
145
- await BluebirdPromise . all ( createDirPromises )
146
- createDirPromises . length = 0
147
- }
148
+ addValue ( dirToCreate , path . relative ( this . src , nodeModuleDir ) , path . relative ( nodeModuleDir , fileParent ) )
148
149
}
149
150
continue
150
151
}
@@ -167,11 +168,7 @@ class AsarPackager {
167
168
let fileParent = path . dirname ( file )
168
169
169
170
// create parent dir to be able to copy file later without directory existence check
170
- createDirPromises . push ( ensureDir ( path . join ( unpackedDest , path . relative ( this . src , fileParent ) ) ) )
171
- if ( createDirPromises . length > MAX_FILE_REQUESTS ) {
172
- await BluebirdPromise . all ( createDirPromises )
173
- createDirPromises . length = 0
174
- }
171
+ addValue ( dirToCreate , path . relative ( this . src , nodeModuleDir ) , path . relative ( nodeModuleDir , fileParent ) )
175
172
176
173
while ( fileParent !== nodeModuleDir ) {
177
174
autoUnpackDirs . add ( fileParent )
@@ -180,32 +177,35 @@ class AsarPackager {
180
177
autoUnpackDirs . add ( nodeModuleDir )
181
178
}
182
179
183
- if ( readPackageJsonPromises . length > 0 ) {
184
- await BluebirdPromise . all ( readPackageJsonPromises )
180
+ if ( fileIndexToModulePackageData . size > 0 ) {
181
+ await BluebirdPromise . all ( < any > fileIndexToModulePackageData . values ( ) )
185
182
}
186
- if ( createDirPromises . length > 0 ) {
187
- await BluebirdPromise . all ( createDirPromises )
188
- createDirPromises . length = 0
183
+
184
+ if ( dirToCreate . size > 0 ) {
185
+ // child directories should be not created asynchronously - parent directories should be created first
186
+ await BluebirdPromise . map ( dirToCreate . keys ( ) , async ( it ) => {
187
+ const base = path . join ( unpackedDest , it )
188
+ await ensureDir ( base )
189
+ await BluebirdPromise . each ( dirToCreate . get ( it ) ! , it => ensureDir ( path . join ( base , it ) ) )
190
+ } , concurrency )
189
191
}
190
192
}
191
193
192
194
async createPackageFromFiles ( files : Array < string > , metadata : Map < string , Stats > ) {
193
195
// search auto unpacked dir
194
196
const autoUnpackDirs = new Set < string > ( )
195
-
196
- const createDirPromises : Array < Promise < any > > = [ ensureDir ( path . dirname ( this . outFile ) ) ]
197
197
const unpackedDest = `${ this . outFile } .unpacked`
198
-
199
- const fileIndexToModulePackageData : Array < BluebirdPromise < string > > = new Array ( files . length )
198
+ const fileIndexToModulePackageData = new Map < number , BluebirdPromise < string > > ( )
200
199
if ( this . options . smartUnpack !== false ) {
201
- await this . detectUnpackedDirs ( files , metadata , autoUnpackDirs , createDirPromises , unpackedDest , fileIndexToModulePackageData )
200
+ await this . detectUnpackedDirs ( files , metadata , autoUnpackDirs , unpackedDest , fileIndexToModulePackageData )
202
201
}
203
202
204
203
const unpackDir = this . options . unpackDir == null ? null : new Minimatch ( this . options . unpackDir )
205
204
const unpack = this . options . unpack == null ? null : new Minimatch ( this . options . unpack , {
206
205
matchBase : true
207
206
} )
208
207
208
+ const createDirPromises : Array < Promise < any > > = [ ensureDir ( path . dirname ( this . outFile ) ) ]
209
209
const copyPromises : Array < Promise < any > > = [ ]
210
210
const mainPackageJson = path . join ( this . src , "package.json" )
211
211
for ( let i = 0 , n = files . length ; i < n ; i ++ ) {
@@ -220,15 +220,15 @@ class AsarPackager {
220
220
createDirPromises . length = 0
221
221
}
222
222
223
- const packageDataPromise = fileIndexToModulePackageData [ i ]
223
+ const packageDataPromise = fileIndexToModulePackageData . get ( i )
224
224
let newData : any | null = null
225
225
if ( packageDataPromise == null ) {
226
226
if ( this . options . extraMetadata != null && file === mainPackageJson ) {
227
227
newData = JSON . stringify ( deepAssign ( await readJson ( file ) , this . options . extraMetadata ) , null , 2 )
228
228
}
229
229
}
230
230
else {
231
- newData = cleanupPackageJson ( packageDataPromise . value ( ) )
231
+ newData = packageDataPromise . value ( )
232
232
}
233
233
234
234
const fileSize = newData == null ? stat . size : Buffer . byteLength ( newData )
@@ -238,9 +238,15 @@ class AsarPackager {
238
238
node . unpacked = true
239
239
240
240
if ( ! dirNode . unpacked ) {
241
- createDirPromises . push ( ensureDir ( path . join ( unpackedDest , path . relative ( this . src , fileParent ) ) ) )
242
- await BluebirdPromise . all ( createDirPromises )
243
- createDirPromises . length = 0
241
+ const promise = ensureDir ( path . join ( unpackedDest , path . relative ( this . src , fileParent ) ) )
242
+ if ( createDirPromises . length === 0 ) {
243
+ await createDirPromises
244
+ }
245
+ else {
246
+ createDirPromises . push ( promise )
247
+ await BluebirdPromise . all ( createDirPromises )
248
+ createDirPromises . length = 0
249
+ }
244
250
}
245
251
246
252
const unpackedFile = path . join ( unpackedDest , path . relative ( this . src , file ) )
@@ -298,7 +304,9 @@ class AsarPackager {
298
304
}
299
305
}
300
306
301
- await BluebirdPromise . all ( copyPromises )
307
+ if ( copyPromises . length > 0 ) {
308
+ await BluebirdPromise . all ( copyPromises )
309
+ }
302
310
}
303
311
304
312
private async addLink ( file : string ) {
0 commit comments