12
12
13
13
const invariant = require ( 'fbjs/lib/invariant' ) ;
14
14
const memoize = require ( 'async/memoize' ) ;
15
+ const nullthrows = require ( 'fbjs/lib/nullthrows' ) ;
15
16
const queue = require ( 'async/queue' ) ;
16
17
const seq = require ( 'async/seq' ) ;
17
18
18
- import type { GraphFn , LoadFn , ResolveFn , File , Module } from './types.flow' ;
19
+ import type {
20
+ Callback ,
21
+ File ,
22
+ GraphFn ,
23
+ LoadFn ,
24
+ Module ,
25
+ ResolveFn ,
26
+ } from './types.flow' ;
27
+
28
+ type Async$Queue < T , C > = {
29
+ buffer : number ,
30
+ concurrency : number ,
31
+ drain : ( ) => mixed ,
32
+ empty : ( ) => mixed ,
33
+ error : ( Error , T ) => mixed ,
34
+ idle ( ) : boolean ,
35
+ kill ( ) : void ,
36
+ length ( ) : number ,
37
+ pause ( ) : void ,
38
+ paused : boolean ,
39
+ push ( T | Array < T > , void | C ) : void ,
40
+ resume ( ) : void ,
41
+ running ( ) : number ,
42
+ saturated : ( ) => mixed ,
43
+ started : boolean ,
44
+ unsaturated : ( ) => mixed ,
45
+ unshift ( T , void | C ) : void ,
46
+ workersList ( ) : Array < T > ,
47
+ } ;
48
+
49
+ type LoadQueue =
50
+ Async$Queue < { id : string , parent : string } , Callback < File , Array < string >>> ;
19
51
20
52
const createParentModule =
21
- ( ) => ( { file : { path : '' , ast : { } } , dependencies : [ ] } ) ;
53
+ ( ) => ( { file : { code : '' , isPolyfill : false , path : '' } , dependencies : [ ] } ) ;
22
54
23
55
const noop = ( ) => { } ;
56
+ const NO_OPTIONS = { } ;
24
57
25
58
exports . create = function create ( resolve : ResolveFn , load : LoadFn ) : GraphFn {
26
- function Graph ( entryPoints , platform , options = { } , callback = noop ) {
27
- const { cwd = '' , log = ( console : any ) , optimize = false , skip} = options ;
59
+ function Graph ( entryPoints , platform , options , callback = noop ) {
60
+ const {
61
+ cwd = '' ,
62
+ log = ( console : any ) ,
63
+ optimize = false ,
64
+ skip,
65
+ } = options || NO_OPTIONS ;
28
66
29
67
if ( typeof platform !== 'string' ) {
30
68
log . error ( '`Graph`, called without a platform' ) ;
@@ -35,58 +73,76 @@ exports.create = function create(resolve: ResolveFn, load: LoadFn): GraphFn {
35
73
const modules : Map < string | null , Module > = new Map ( ) ;
36
74
modules . set ( null , createParentModule ( ) ) ;
37
75
38
- const loadQueue = queue ( seq (
39
- ( { id, parent} , cb ) => resolve ( id , parent , platform , options , cb ) ,
76
+ const loadQueue : LoadQueue = queue ( seq (
77
+ ( { id, parent} , cb ) => resolve ( id , parent , platform , options || NO_OPTIONS , cb ) ,
40
78
memoize ( ( file , cb ) => load ( file , { log, optimize} , cb ) ) ,
41
79
) , Number . MAX_SAFE_INTEGER ) ;
42
80
43
- const cleanup = ( ) => ( loadQueue . drain = noop ) ;
44
81
loadQueue . drain = ( ) => {
45
- cleanup ( ) ;
82
+ loadQueue . kill ( ) ;
46
83
callback ( null , collect ( null , modules ) ) ;
47
84
} ;
48
-
49
- function loadModule ( id : string , parent : string | null , parentDependencyIndex ) {
50
- function onFileLoaded (
51
- error : ?Error ,
52
- file : File ,
53
- dependencyIDs : Array < string > ,
54
- ) {
55
- if ( error ) {
56
- cleanup ( ) ;
57
- callback ( error ) ;
58
- return ;
59
- }
60
-
61
- const parentModule = modules . get ( parent ) ;
62
- invariant ( parentModule , 'Invalid parent module: ' + String ( parent ) ) ;
63
- parentModule . dependencies [ parentDependencyIndex ] = { id, path : file . path } ;
64
-
65
- if ( ( ! skip || ! skip . has ( file . path ) ) && ! modules . has ( file . path ) ) {
66
- const dependencies = Array ( dependencyIDs . length ) ;
67
- modules . set ( file . path , { file, dependencies} ) ;
68
- dependencyIDs . forEach (
69
- ( dependencyID , j ) => loadModule ( dependencyID , file . path , j ) ) ;
70
- }
71
- }
72
- loadQueue . push ( { id, parent : parent != null ? parent : cwd } , onFileLoaded ) ;
73
- }
85
+ loadQueue . error = error => {
86
+ loadQueue . error = noop ;
87
+ loadQueue . kill ( ) ;
88
+ callback ( error ) ;
89
+ } ;
74
90
75
91
let i = 0 ;
76
92
for ( const entryPoint of entryPoints ) {
77
- loadModule ( entryPoint , null , i ++ ) ;
93
+ loadModule ( entryPoint , null , i ++ , loadQueue , modules , skip , cwd , callback ) ;
78
94
}
79
95
80
- if ( loadQueue . idle ( ) ) {
96
+ if ( i === 0 ) {
81
97
log . error ( '`Graph` called without any entry points' ) ;
82
- cleanup ( ) ;
98
+ loadQueue . kill ( ) ;
83
99
callback ( Error ( 'At least one entry point has to be passed.' ) ) ;
84
100
}
85
101
}
86
102
87
103
return Graph ;
88
104
} ;
89
105
106
+ function loadModule (
107
+ id : string ,
108
+ parent : string | null ,
109
+ parentDependencyIndex : number ,
110
+ loadQueue : LoadQueue ,
111
+ modules : Map < string | null , Module > ,
112
+ skip ?: Set < string > ,
113
+ cwd : string ,
114
+ ) {
115
+ function onFileLoaded (
116
+ error ?: ?Error ,
117
+ file ?: File ,
118
+ dependencyIDs ?: Array < string > ,
119
+ ) {
120
+ if ( error ) {
121
+ return ;
122
+ }
123
+
124
+ const { path} = nullthrows ( file ) ;
125
+ dependencyIDs = nullthrows ( dependencyIDs ) ;
126
+
127
+ const parentModule = modules . get ( parent ) ;
128
+ invariant ( parentModule , 'Invalid parent module: ' + String ( parent ) ) ;
129
+ parentModule . dependencies [ parentDependencyIndex ] = { id, path} ;
130
+
131
+ if ( ( ! skip || ! skip . has ( path ) ) && ! modules . has ( path ) ) {
132
+ const dependencies = Array ( dependencyIDs . length ) ;
133
+ modules . set ( path , { dependencies, file : nullthrows ( file ) } ) ;
134
+ for ( let i = 0 ; i < dependencyIDs . length ; ++ i ) {
135
+ loadModule ( dependencyIDs [ i ] , path , i , loadQueue , modules , skip , cwd ) ;
136
+ }
137
+ }
138
+ }
139
+
140
+ loadQueue . push (
141
+ { id, parent : parent != null ? parent : cwd } ,
142
+ onFileLoaded ,
143
+ ) ;
144
+ }
145
+
90
146
function collect (
91
147
path ,
92
148
modules ,
@@ -100,8 +156,11 @@ function collect(
100
156
serialized . push ( module ) ;
101
157
seen . add ( path ) ;
102
158
}
103
- module . dependencies . forEach (
104
- dependency => collect ( dependency . path , modules , serialized , seen ) ) ;
159
+
160
+ const { dependencies } = module ;
161
+ for ( var i = 0 ; i < dependencies . length ; i ++ ) {
162
+ collect ( dependencies [ i ] . path , modules , serialized , seen ) ;
163
+ }
105
164
106
165
return serialized ;
107
166
}
0 commit comments