@@ -55,6 +55,7 @@ struct AssetGraphBuilder {
55
55
receiver : ResultReceiver ,
56
56
asset_request_to_asset_idx : HashMap < u64 , NodeIndex > ,
57
57
waiting_asset_requests : HashMap < u64 , HashSet < NodeIndex > > ,
58
+ entry_dependencies : Vec < ( String , NodeIndex ) > ,
58
59
}
59
60
60
61
impl AssetGraphBuilder {
@@ -71,6 +72,7 @@ impl AssetGraphBuilder {
71
72
receiver,
72
73
asset_request_to_asset_idx : HashMap :: new ( ) ,
73
74
waiting_asset_requests : HashMap :: new ( ) ,
75
+ entry_dependencies : Vec :: new ( ) ,
74
76
}
75
77
}
76
78
@@ -131,6 +133,22 @@ impl AssetGraphBuilder {
131
133
}
132
134
}
133
135
136
+ // Connect the entries to the root node in the graph. We do this in
137
+ // alphabetical order so it's consistent between builds.
138
+ //
139
+ // Ideally, we wouldn't depend on edge order being consistent between builds
140
+ // and instead rely on in-place sorting or similar to ensure deterministic
141
+ // builds. However, as the rest of the code base (bundling, runtimes,
142
+ // packaging, etc) relies on the deterministic edge order and it's very
143
+ // complicated/risky to fix all the places that would be affected we'll keep it that
144
+ // way for now.
145
+ self
146
+ . entry_dependencies
147
+ . sort_by_key ( |( entry, _) | entry. clone ( ) ) ;
148
+ for ( _, node_index) in self . entry_dependencies . iter ( ) {
149
+ self . graph . add_edge ( & self . graph . root_node ( ) , node_index) ;
150
+ }
151
+
134
152
Ok ( ResultAndInvalidations {
135
153
result : RequestResult :: AssetGraph ( AssetGraphRequestOutput { graph : self . graph } ) ,
136
154
invalidations : vec ! [ ] ,
@@ -192,10 +210,12 @@ impl AssetGraphBuilder {
192
210
. request_context
193
211
. queue_request ( asset_request, self . sender . clone ( ) ) ;
194
212
} else if let Some ( asset_node_index) = self . asset_request_to_asset_idx . get ( & id) {
195
- // We have already completed this AssetRequest so we can connect the
196
- // Dependency to the Asset immediately
197
- self . graph . add_edge ( & dependency_idx, asset_node_index) ;
198
- self . propagate_requested_symbols ( * asset_node_index, dependency_idx) ;
213
+ if !self . graph . has_edge ( & dependency_idx, asset_node_index) {
214
+ // We have already completed this AssetRequest so we can connect the
215
+ // Dependency to the Asset immediately
216
+ self . graph . add_edge ( & dependency_idx, asset_node_index) ;
217
+ self . propagate_requested_symbols ( * asset_node_index, dependency_idx) ;
218
+ }
199
219
} else {
200
220
// The AssetRequest has already been kicked off but is yet to
201
221
// complete. Register this Dependency to be connected once it
@@ -282,8 +302,10 @@ impl AssetGraphBuilder {
282
302
// for this AssetNode to be created
283
303
if let Some ( waiting) = self . waiting_asset_requests . remove ( & request_id) {
284
304
for dep in waiting {
285
- self . graph . add_edge ( & dep, & asset_idx) ;
286
- self . propagate_requested_symbols ( asset_idx, dep) ;
305
+ if !self . graph . has_edge ( & dep, & asset_idx) {
306
+ self . graph . add_edge ( & dep, & asset_idx) ;
307
+ self . propagate_requested_symbols ( asset_idx, dep) ;
308
+ }
287
309
}
288
310
}
289
311
}
@@ -405,10 +427,12 @@ impl AssetGraphBuilder {
405
427
for target in targets {
406
428
let entry =
407
429
diff_paths ( & entry, & self . request_context . project_root ) . unwrap_or_else ( || entry. clone ( ) ) ;
430
+ let entry = entry. to_str ( ) . unwrap ( ) . to_string ( ) ;
408
431
409
- let dependency = Dependency :: entry ( entry. to_str ( ) . unwrap ( ) . to_string ( ) , target) ;
432
+ let dependency = Dependency :: entry ( entry. clone ( ) , target) ;
410
433
411
434
let dep_node = self . graph . add_entry_dependency ( dependency. clone ( ) ) ;
435
+ self . entry_dependencies . push ( ( entry, dep_node) ) ;
412
436
413
437
let request = PathRequest {
414
438
dependency : Arc :: new ( dependency) ,
0 commit comments