@atlaspack/core 2.12.1-canary.3354

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/LICENSE +201 -0
  2. package/index.d.ts +22 -0
  3. package/lib/AssetGraph.js +518 -0
  4. package/lib/Atlaspack.js +587 -0
  5. package/lib/AtlaspackConfig.js +298 -0
  6. package/lib/AtlaspackConfig.schema.js +125 -0
  7. package/lib/BundleGraph.js +1445 -0
  8. package/lib/CommittedAsset.js +133 -0
  9. package/lib/Dependency.js +88 -0
  10. package/lib/Environment.js +128 -0
  11. package/lib/InternalConfig.js +48 -0
  12. package/lib/PackagerRunner.js +519 -0
  13. package/lib/ReporterRunner.js +151 -0
  14. package/lib/RequestTracker.js +1089 -0
  15. package/lib/SymbolPropagation.js +625 -0
  16. package/lib/TargetDescriptor.schema.js +115 -0
  17. package/lib/Transformation.js +536 -0
  18. package/lib/UncommittedAsset.js +342 -0
  19. package/lib/Validation.js +215 -0
  20. package/lib/applyRuntimes.js +279 -0
  21. package/lib/assetUtils.js +189 -0
  22. package/lib/atlaspack-v3/AtlaspackV3.js +74 -0
  23. package/lib/atlaspack-v3/fs.js +30 -0
  24. package/lib/atlaspack-v3/index.js +19 -0
  25. package/lib/atlaspack-v3/jsCallable.js +15 -0
  26. package/lib/atlaspack-v3/plugins/Resolver.js +12 -0
  27. package/lib/atlaspack-v3/plugins/index.js +16 -0
  28. package/lib/atlaspack-v3/worker/index.js +3 -0
  29. package/lib/atlaspack-v3/worker/worker.js +30 -0
  30. package/lib/buildCache.js +18 -0
  31. package/lib/constants.js +21 -0
  32. package/lib/dumpGraphToGraphViz.js +206 -0
  33. package/lib/index.js +106 -0
  34. package/lib/loadAtlaspackPlugin.js +148 -0
  35. package/lib/loadDotEnv.js +54 -0
  36. package/lib/projectPath.js +86 -0
  37. package/lib/public/Asset.js +259 -0
  38. package/lib/public/Bundle.js +231 -0
  39. package/lib/public/BundleGraph.js +193 -0
  40. package/lib/public/BundleGroup.js +44 -0
  41. package/lib/public/Config.js +202 -0
  42. package/lib/public/Dependency.js +131 -0
  43. package/lib/public/Environment.js +244 -0
  44. package/lib/public/MutableBundleGraph.js +184 -0
  45. package/lib/public/PluginOptions.js +71 -0
  46. package/lib/public/Symbols.js +247 -0
  47. package/lib/public/Target.js +64 -0
  48. package/lib/registerCoreWithSerializer.js +45 -0
  49. package/lib/requests/AssetGraphRequest.js +427 -0
  50. package/lib/requests/AssetGraphRequestRust.js +187 -0
  51. package/lib/requests/AssetRequest.js +137 -0
  52. package/lib/requests/AtlaspackBuildRequest.js +78 -0
  53. package/lib/requests/AtlaspackConfigRequest.js +473 -0
  54. package/lib/requests/BundleGraphRequest.js +419 -0
  55. package/lib/requests/ConfigRequest.js +198 -0
  56. package/lib/requests/DevDepRequest.js +166 -0
  57. package/lib/requests/EntryRequest.js +295 -0
  58. package/lib/requests/PackageRequest.js +88 -0
  59. package/lib/requests/PathRequest.js +349 -0
  60. package/lib/requests/TargetRequest.js +1177 -0
  61. package/lib/requests/ValidationRequest.js +66 -0
  62. package/lib/requests/WriteBundleRequest.js +252 -0
  63. package/lib/requests/WriteBundlesRequest.js +153 -0
  64. package/lib/resolveOptions.js +234 -0
  65. package/lib/serializer.js +216 -0
  66. package/lib/serializerCore.browser.js +29 -0
  67. package/lib/serializerCore.js +16 -0
  68. package/lib/summarizeRequest.js +55 -0
  69. package/lib/types.js +35 -0
  70. package/lib/utils.js +160 -0
  71. package/lib/worker.js +170 -0
  72. package/package.json +59 -0
  73. package/src/AssetGraph.js +646 -0
  74. package/src/Atlaspack.js +632 -0
  75. package/src/AtlaspackConfig.js +490 -0
  76. package/src/AtlaspackConfig.schema.js +141 -0
  77. package/src/BundleGraph.js +2193 -0
  78. package/src/CommittedAsset.js +143 -0
  79. package/src/Dependency.js +142 -0
  80. package/src/Environment.js +151 -0
  81. package/src/InternalConfig.js +72 -0
  82. package/src/PackagerRunner.js +790 -0
  83. package/src/ReporterRunner.js +158 -0
  84. package/src/RequestTracker.js +1697 -0
  85. package/src/SymbolPropagation.js +794 -0
  86. package/src/TargetDescriptor.schema.js +136 -0
  87. package/src/Transformation.js +752 -0
  88. package/src/UncommittedAsset.js +426 -0
  89. package/src/Validation.js +223 -0
  90. package/src/applyRuntimes.js +341 -0
  91. package/src/assetUtils.js +254 -0
  92. package/src/atlaspack-v3/AtlaspackV3.js +73 -0
  93. package/src/atlaspack-v3/fs.js +36 -0
  94. package/src/atlaspack-v3/index.js +5 -0
  95. package/src/atlaspack-v3/jsCallable.js +13 -0
  96. package/src/atlaspack-v3/plugins/Resolver.js +9 -0
  97. package/src/atlaspack-v3/plugins/index.js +3 -0
  98. package/src/atlaspack-v3/worker/index.js +8 -0
  99. package/src/atlaspack-v3/worker/worker.js +14 -0
  100. package/src/buildCache.js +15 -0
  101. package/src/constants.js +22 -0
  102. package/src/dumpGraphToGraphViz.js +244 -0
  103. package/src/index.js +22 -0
  104. package/src/loadAtlaspackPlugin.js +239 -0
  105. package/src/loadDotEnv.js +56 -0
  106. package/src/projectPath.js +87 -0
  107. package/src/public/Asset.js +359 -0
  108. package/src/public/Bundle.js +337 -0
  109. package/src/public/BundleGraph.js +335 -0
  110. package/src/public/BundleGroup.js +55 -0
  111. package/src/public/Config.js +261 -0
  112. package/src/public/Dependency.js +176 -0
  113. package/src/public/Environment.js +316 -0
  114. package/src/public/MutableBundleGraph.js +320 -0
  115. package/src/public/PluginOptions.js +99 -0
  116. package/src/public/Symbols.js +315 -0
  117. package/src/public/Target.js +71 -0
  118. package/src/registerCoreWithSerializer.js +34 -0
  119. package/src/requests/AssetGraphRequest.js +577 -0
  120. package/src/requests/AssetGraphRequestRust.js +222 -0
  121. package/src/requests/AssetRequest.js +179 -0
  122. package/src/requests/AtlaspackBuildRequest.js +109 -0
  123. package/src/requests/AtlaspackConfigRequest.js +709 -0
  124. package/src/requests/BundleGraphRequest.js +547 -0
  125. package/src/requests/ConfigRequest.js +287 -0
  126. package/src/requests/DevDepRequest.js +246 -0
  127. package/src/requests/EntryRequest.js +385 -0
  128. package/src/requests/PackageRequest.js +105 -0
  129. package/src/requests/PathRequest.js +454 -0
  130. package/src/requests/TargetRequest.js +1632 -0
  131. package/src/requests/ValidationRequest.js +79 -0
  132. package/src/requests/WriteBundleRequest.js +362 -0
  133. package/src/requests/WriteBundlesRequest.js +209 -0
  134. package/src/resolveOptions.js +278 -0
  135. package/src/serializer.js +255 -0
  136. package/src/serializerCore.browser.js +8 -0
  137. package/src/serializerCore.js +5 -0
  138. package/src/summarizeRequest.js +47 -0
  139. package/src/types.js +581 -0
  140. package/src/utils.js +211 -0
  141. package/src/worker.js +189 -0
  142. package/test/AssetGraph.test.js +679 -0
  143. package/test/Atlaspack.test.js +142 -0
  144. package/test/AtlaspackConfig.test.js +405 -0
  145. package/test/AtlaspackConfigRequest.test.js +993 -0
  146. package/test/BundleGraph.test.js +121 -0
  147. package/test/EntryRequest.test.js +215 -0
  148. package/test/Environment.test.js +99 -0
  149. package/test/InternalAsset.test.js +76 -0
  150. package/test/PackagerRunner.test.js +27 -0
  151. package/test/PublicAsset.test.js +40 -0
  152. package/test/PublicBundle.test.js +68 -0
  153. package/test/PublicDependency.test.js +22 -0
  154. package/test/PublicEnvironment.test.js +27 -0
  155. package/test/PublicMutableBundleGraph.test.js +192 -0
  156. package/test/RequestTracker.test.js +448 -0
  157. package/test/SymbolPropagation.test.js +716 -0
  158. package/test/TargetRequest.test.js +1715 -0
  159. package/test/fixtures/application-targets/package.json +3 -0
  160. package/test/fixtures/atlaspack/index.js +1 -0
  161. package/test/fixtures/atlaspack/other.js +3 -0
  162. package/test/fixtures/atlaspack/package.json +1 -0
  163. package/test/fixtures/atlaspack/yarn.lock +0 -0
  164. package/test/fixtures/bundle.js +10 -0
  165. package/test/fixtures/common-targets/package.json +24 -0
  166. package/test/fixtures/common-targets-ignore/package.json +13 -0
  167. package/test/fixtures/config/.atlaspackrc +6 -0
  168. package/test/fixtures/config/subfolder/.atlaspackrc +6 -0
  169. package/test/fixtures/config-extends-not-found/.atlaspackrc +3 -0
  170. package/test/fixtures/config-extends-not-found/.atlaspackrc-json5 +3 -0
  171. package/test/fixtures/config-extends-not-found/.atlaspackrc-multiple +3 -0
  172. package/test/fixtures/config-extends-not-found/.atlaspackrc-node-modules +3 -0
  173. package/test/fixtures/config-malformed/.atlaspackrc +3 -0
  174. package/test/fixtures/config-node-pipeline/.atlaspackrc +6 -0
  175. package/test/fixtures/config-plugin-not-found/.atlaspackrc +6 -0
  176. package/test/fixtures/context/package.json +8 -0
  177. package/test/fixtures/custom-format-infer-ext/package.json +6 -0
  178. package/test/fixtures/custom-format-infer-type/package.json +7 -0
  179. package/test/fixtures/custom-format-mismatch/package.json +8 -0
  180. package/test/fixtures/custom-targets/package.json +20 -0
  181. package/test/fixtures/custom-targets-distdir/package.json +11 -0
  182. package/test/fixtures/duplicate-targets/package.json +4 -0
  183. package/test/fixtures/glob-like/[entry].js +0 -0
  184. package/test/fixtures/invalid-distpath/package.json +11 -0
  185. package/test/fixtures/invalid-engines/package.json +12 -0
  186. package/test/fixtures/invalid-source-missing/package.json +5 -0
  187. package/test/fixtures/invalid-source-not-file/package.json +5 -0
  188. package/test/fixtures/invalid-source-not-file/src/index.js +1 -0
  189. package/test/fixtures/invalid-target-source-missing/package.json +9 -0
  190. package/test/fixtures/invalid-target-source-not-file/package.json +9 -0
  191. package/test/fixtures/invalid-target-source-not-file/src/index.js +1 -0
  192. package/test/fixtures/invalid-targets/package.json +19 -0
  193. package/test/fixtures/library-custom-scopehoist/package.json +9 -0
  194. package/test/fixtures/library-scopehoist/package.json +8 -0
  195. package/test/fixtures/local-plugin-config-pkg/.atlaspackrc +3 -0
  196. package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/index.json +8 -0
  197. package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/local-plugin.js +7 -0
  198. package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/package.json +7 -0
  199. package/test/fixtures/main-format-mismatch/package.json +8 -0
  200. package/test/fixtures/main-global/package.json +8 -0
  201. package/test/fixtures/main-mjs/package.json +8 -0
  202. package/test/fixtures/module-a.js +1 -0
  203. package/test/fixtures/module-b.js +1 -0
  204. package/test/fixtures/plugins/local-plugin.js +7 -0
  205. package/test/fixtures/plugins/node_modules/atlaspack-transformer-bad-engines/index.js +7 -0
  206. package/test/fixtures/plugins/node_modules/atlaspack-transformer-bad-engines/package.json +7 -0
  207. package/test/fixtures/plugins/node_modules/atlaspack-transformer-no-engines/index.js +7 -0
  208. package/test/fixtures/plugins/node_modules/atlaspack-transformer-no-engines/package.json +4 -0
  209. package/test/fixtures/targets-default-distdir-none/package.json +5 -0
  210. package/test/fixtures/targets-default-distdir-one/package.json +8 -0
  211. package/test/fixtures/targets-default-distdir-two/package.json +18 -0
  212. package/test/requests/ConfigRequest.test.js +254 -0
  213. package/test/serializer.test.js +302 -0
  214. package/test/test-utils.js +80 -0
  215. package/test/utils.test.js +43 -0
@@ -0,0 +1,577 @@
1
+ // @flow strict-local
2
+
3
+ import type {NodeId} from '@atlaspack/graph';
4
+ import type {Async} from '@atlaspack/types';
5
+ import type {SharedReference} from '@atlaspack/workers';
6
+ import type {
7
+ Asset,
8
+ AssetGroup,
9
+ AssetRequestInput,
10
+ Dependency,
11
+ Entry,
12
+ AtlaspackOptions,
13
+ Target,
14
+ } from '../types';
15
+ import type {StaticRunOpts, RunAPI} from '../RequestTracker';
16
+ import type {EntryRequestResult} from './EntryRequest';
17
+ import type {PathRequestInput} from './PathRequest';
18
+ import type {Diagnostic} from '@atlaspack/diagnostic';
19
+ import logger from '@atlaspack/logger';
20
+
21
+ import invariant from 'assert';
22
+ import nullthrows from 'nullthrows';
23
+ import {PromiseQueue, setEqual} from '@atlaspack/utils';
24
+ import {hashString} from '@atlaspack/rust';
25
+ import ThrowableDiagnostic from '@atlaspack/diagnostic';
26
+ import {Priority} from '../types';
27
+ import AssetGraph from '../AssetGraph';
28
+ import {ATLASPACK_VERSION} from '../constants';
29
+ import createEntryRequest from './EntryRequest';
30
+ import createTargetRequest from './TargetRequest';
31
+ import createAssetRequest from './AssetRequest';
32
+ import createPathRequest from './PathRequest';
33
+ import {type ProjectPath, fromProjectPathRelative} from '../projectPath';
34
+ import dumpGraphToGraphViz from '../dumpGraphToGraphViz';
35
+ import {propagateSymbols} from '../SymbolPropagation';
36
+ import {requestTypes} from '../RequestTracker';
37
+
38
+ export type AssetGraphRequestInput = {|
39
+ entries?: Array<ProjectPath>,
40
+ assetGroups?: Array<AssetGroup>,
41
+ optionsRef: SharedReference,
42
+ name: string,
43
+ shouldBuildLazily?: boolean,
44
+ lazyIncludes?: RegExp[],
45
+ lazyExcludes?: RegExp[],
46
+ requestedAssetIds?: Set<string>,
47
+ |};
48
+
49
+ export type AssetGraphRequestResult = {|
50
+ assetGraph: AssetGraph,
51
+ /** Assets added/modified since the last successful build. */
52
+ changedAssets: Map<string, Asset>,
53
+ /** Assets added/modified since the last symbol propagation invocation. */
54
+ changedAssetsPropagation: Set<string>,
55
+ assetGroupsWithRemovedParents: ?Set<NodeId>,
56
+ previousSymbolPropagationErrors: ?Map<NodeId, Array<Diagnostic>>,
57
+ assetRequests: Array<AssetGroup>,
58
+ |};
59
+
60
+ type RunInput = {|
61
+ input: AssetGraphRequestInput,
62
+ ...StaticRunOpts<AssetGraphRequestResult>,
63
+ |};
64
+
65
+ type AssetGraphRequest = {|
66
+ id: string,
67
+ +type: typeof requestTypes.asset_graph_request,
68
+ run: RunInput => Async<AssetGraphRequestResult>,
69
+ input: AssetGraphRequestInput,
70
+ |};
71
+
72
+ export default function createAssetGraphRequest(
73
+ requestInput: AssetGraphRequestInput,
74
+ ): AssetGraphRequest {
75
+ return {
76
+ type: requestTypes.asset_graph_request,
77
+ id: requestInput.name,
78
+ run: async input => {
79
+ let prevResult =
80
+ await input.api.getPreviousResult<AssetGraphRequestResult>();
81
+
82
+ let builder = new AssetGraphBuilder(input, prevResult);
83
+ let assetGraphRequest = await await builder.build();
84
+
85
+ // early break for incremental bundling if production or flag is off;
86
+ if (
87
+ !input.options.shouldBundleIncrementally ||
88
+ input.options.mode === 'production'
89
+ ) {
90
+ assetGraphRequest.assetGraph.safeToIncrementallyBundle = false;
91
+ }
92
+
93
+ return assetGraphRequest;
94
+ },
95
+ input: requestInput,
96
+ };
97
+ }
98
+
99
+ const typesWithRequests = new Set([
100
+ 'entry_specifier',
101
+ 'entry_file',
102
+ 'dependency',
103
+ 'asset_group',
104
+ ]);
105
+
106
+ export class AssetGraphBuilder {
107
+ assetGraph: AssetGraph;
108
+ assetRequests: Array<AssetGroup> = [];
109
+ queue: PromiseQueue<mixed>;
110
+ changedAssets: Map<string, Asset>;
111
+ changedAssetsPropagation: Set<string>;
112
+ prevChangedAssetsPropagation: ?Set<string>;
113
+ optionsRef: SharedReference;
114
+ options: AtlaspackOptions;
115
+ api: RunAPI<AssetGraphRequestResult>;
116
+ name: string;
117
+ cacheKey: string;
118
+ shouldBuildLazily: boolean;
119
+ lazyIncludes: RegExp[];
120
+ lazyExcludes: RegExp[];
121
+ requestedAssetIds: Set<string>;
122
+ isSingleChangeRebuild: boolean;
123
+ assetGroupsWithRemovedParents: Set<NodeId>;
124
+ previousSymbolPropagationErrors: Map<NodeId, Array<Diagnostic>>;
125
+
126
+ constructor(
127
+ {input, api, options}: RunInput,
128
+ prevResult: ?AssetGraphRequestResult,
129
+ ) {
130
+ let {
131
+ entries,
132
+ assetGroups,
133
+ optionsRef,
134
+ name,
135
+ requestedAssetIds,
136
+ shouldBuildLazily,
137
+ lazyIncludes,
138
+ lazyExcludes,
139
+ } = input;
140
+ let assetGraph = prevResult?.assetGraph ?? new AssetGraph();
141
+ assetGraph.safeToIncrementallyBundle = true;
142
+ assetGraph.setRootConnections({
143
+ entries,
144
+ assetGroups,
145
+ });
146
+ assetGraph.undeferredDependencies.clear();
147
+ this.assetGroupsWithRemovedParents =
148
+ prevResult?.assetGroupsWithRemovedParents ?? new Set();
149
+ this.previousSymbolPropagationErrors =
150
+ prevResult?.previousSymbolPropagationErrors ?? new Map();
151
+ this.changedAssets = prevResult?.changedAssets ?? new Map();
152
+ this.changedAssetsPropagation = new Set();
153
+ this.prevChangedAssetsPropagation = prevResult?.changedAssetsPropagation;
154
+
155
+ this.assetGraph = assetGraph;
156
+ this.optionsRef = optionsRef;
157
+ this.options = options;
158
+ this.api = api;
159
+ this.name = name;
160
+ this.requestedAssetIds = requestedAssetIds ?? new Set();
161
+ this.shouldBuildLazily = shouldBuildLazily ?? false;
162
+ this.lazyIncludes = lazyIncludes ?? [];
163
+ this.lazyExcludes = lazyExcludes ?? [];
164
+ this.cacheKey =
165
+ hashString(
166
+ `${ATLASPACK_VERSION}${name}${JSON.stringify(entries) ?? ''}${
167
+ options.mode
168
+ }${options.shouldBuildLazily ? 'lazy' : 'eager'}`,
169
+ ) + '-AssetGraph';
170
+
171
+ this.isSingleChangeRebuild =
172
+ api
173
+ .getInvalidSubRequests()
174
+ .filter(req => req.requestType === 'asset_request').length === 1;
175
+ this.queue = new PromiseQueue();
176
+
177
+ assetGraph.onNodeRemoved = nodeId => {
178
+ this.assetGroupsWithRemovedParents.delete(nodeId);
179
+
180
+ // This needs to mark all connected nodes that doesn't become orphaned
181
+ // due to replaceNodesConnectedTo to make sure that the symbols of
182
+ // nodes from which at least one parent was removed are updated.
183
+ let node = nullthrows(assetGraph.getNode(nodeId));
184
+ if (assetGraph.isOrphanedNode(nodeId) && node.type === 'dependency') {
185
+ let children = assetGraph.getNodeIdsConnectedFrom(nodeId);
186
+ for (let child of children) {
187
+ let childNode = nullthrows(assetGraph.getNode(child));
188
+ invariant(
189
+ childNode.type === 'asset_group' || childNode.type === 'asset',
190
+ );
191
+ childNode.usedSymbolsDownDirty = true;
192
+ this.assetGroupsWithRemovedParents.add(child);
193
+ }
194
+ }
195
+ };
196
+ }
197
+
198
+ async build(): Promise<AssetGraphRequestResult> {
199
+ let errors = [];
200
+ let rootNodeId = nullthrows(
201
+ this.assetGraph.rootNodeId,
202
+ 'A root node is required to traverse',
203
+ );
204
+
205
+ let visitedAssetGroups = new Set();
206
+ let visited = new Set([rootNodeId]);
207
+
208
+ const visit = (nodeId: NodeId) => {
209
+ if (errors.length > 0) {
210
+ return;
211
+ }
212
+
213
+ if (this.shouldSkipRequest(nodeId)) {
214
+ visitChildren(nodeId);
215
+ } else {
216
+ // ? do we need to visit children inside of the promise that is queued?
217
+ this.queueCorrespondingRequest(nodeId, errors).then(() =>
218
+ visitChildren(nodeId),
219
+ );
220
+ }
221
+ };
222
+
223
+ const visitChildren = (nodeId: NodeId) => {
224
+ for (let childNodeId of this.assetGraph.getNodeIdsConnectedFrom(nodeId)) {
225
+ let child = nullthrows(this.assetGraph.getNode(childNodeId));
226
+ if (
227
+ (!visited.has(childNodeId) || child.hasDeferred) &&
228
+ this.shouldVisitChild(nodeId, childNodeId)
229
+ ) {
230
+ if (child.type === 'asset_group') {
231
+ visitedAssetGroups.add(childNodeId);
232
+ }
233
+
234
+ visited.add(childNodeId);
235
+ visit(childNodeId);
236
+ }
237
+ }
238
+ };
239
+
240
+ visit(rootNodeId);
241
+ await this.queue.run();
242
+
243
+ logger.verbose({
244
+ origin: '@atlaspack/core',
245
+ message: 'Asset graph walked',
246
+ meta: {
247
+ visitedAssetGroupsCount: visitedAssetGroups.size,
248
+ },
249
+ });
250
+
251
+ if (this.prevChangedAssetsPropagation) {
252
+ // Add any previously seen Assets that have not been propagated yet to
253
+ // 'this.changedAssetsPropagation', but only if they still remain in the graph
254
+ // as they could have been removed since the last build
255
+ for (let assetId of this.prevChangedAssetsPropagation) {
256
+ if (this.assetGraph.hasContentKey(assetId)) {
257
+ this.changedAssetsPropagation.add(assetId);
258
+ }
259
+ }
260
+ }
261
+
262
+ if (errors.length) {
263
+ this.api.storeResult(
264
+ {
265
+ assetGraph: this.assetGraph,
266
+ changedAssets: this.changedAssets,
267
+ changedAssetsPropagation: this.changedAssetsPropagation,
268
+ assetGroupsWithRemovedParents: this.assetGroupsWithRemovedParents,
269
+ previousSymbolPropagationErrors: undefined,
270
+ assetRequests: [],
271
+ },
272
+ this.cacheKey,
273
+ );
274
+
275
+ // TODO: eventually support multiple errors since requests could reject in parallel
276
+ throw errors[0];
277
+ }
278
+
279
+ if (this.assetGraph.nodes.length > 1) {
280
+ await dumpGraphToGraphViz(
281
+ this.assetGraph,
282
+ 'AssetGraph_' + this.name + '_before_prop',
283
+ );
284
+ try {
285
+ let errors = propagateSymbols({
286
+ options: this.options,
287
+ assetGraph: this.assetGraph,
288
+ changedAssetsPropagation: this.changedAssetsPropagation,
289
+ assetGroupsWithRemovedParents: this.assetGroupsWithRemovedParents,
290
+ previousErrors: this.previousSymbolPropagationErrors,
291
+ });
292
+ this.changedAssetsPropagation.clear();
293
+
294
+ if (errors.size > 0) {
295
+ this.api.storeResult(
296
+ {
297
+ assetGraph: this.assetGraph,
298
+ changedAssets: this.changedAssets,
299
+ changedAssetsPropagation: this.changedAssetsPropagation,
300
+ assetGroupsWithRemovedParents: this.assetGroupsWithRemovedParents,
301
+ previousSymbolPropagationErrors: errors,
302
+ assetRequests: [],
303
+ },
304
+ this.cacheKey,
305
+ );
306
+
307
+ // Just throw the first error. Since errors can bubble (e.g. reexporting a reexported symbol also fails),
308
+ // determining which failing export is the root cause is nontrivial (because of circular dependencies).
309
+ throw new ThrowableDiagnostic({
310
+ diagnostic: [...errors.values()][0],
311
+ });
312
+ }
313
+ } catch (e) {
314
+ await dumpGraphToGraphViz(
315
+ this.assetGraph,
316
+ 'AssetGraph_' + this.name + '_failed',
317
+ );
318
+ throw e;
319
+ }
320
+ }
321
+ await dumpGraphToGraphViz(this.assetGraph, 'AssetGraph_' + this.name);
322
+
323
+ this.api.storeResult(
324
+ {
325
+ assetGraph: this.assetGraph,
326
+ changedAssets: new Map(),
327
+ changedAssetsPropagation: this.changedAssetsPropagation,
328
+ assetGroupsWithRemovedParents: undefined,
329
+ previousSymbolPropagationErrors: undefined,
330
+ assetRequests: [],
331
+ },
332
+ this.cacheKey,
333
+ );
334
+
335
+ return {
336
+ assetGraph: this.assetGraph,
337
+ changedAssets: this.changedAssets,
338
+ changedAssetsPropagation: this.changedAssetsPropagation,
339
+ assetGroupsWithRemovedParents: undefined,
340
+ previousSymbolPropagationErrors: undefined,
341
+ assetRequests: this.assetRequests,
342
+ };
343
+ }
344
+
345
+ shouldVisitChild(nodeId: NodeId, childNodeId: NodeId): boolean {
346
+ if (this.shouldBuildLazily) {
347
+ let node = nullthrows(this.assetGraph.getNode(nodeId));
348
+ let childNode = nullthrows(this.assetGraph.getNode(childNodeId));
349
+
350
+ if (node.type === 'asset' && childNode.type === 'dependency') {
351
+ // This logic will set `node.requested` to `true` if the node is in the list of requested asset ids
352
+ // (i.e. this is an entry of a (probably) placeholder bundle that wasn't previously requested)
353
+ //
354
+ // Otherwise, if this node either is explicitly not requested, or has had it's requested attribute deleted,
355
+ // it will determine whether this node is an "async child" - that is, is it a (probably)
356
+ // dynamic import(). If so, it will explicitly have it's `node.requested` set to `false`
357
+ //
358
+ // If it's not requested, but it's not an async child then it's `node.requested` is deleted (undefined)
359
+
360
+ // by default with lazy compilation all nodes are lazy
361
+ let isNodeLazy = true;
362
+
363
+ // For conditional lazy building - if this node matches the `lazyInclude` globs that means we want
364
+ // only those nodes to be treated as lazy - that means if this node does _NOT_ match that glob, then we
365
+ // also consider it not lazy (so it gets marked as requested).
366
+ const relativePath = fromProjectPathRelative(node.value.filePath);
367
+ if (this.lazyIncludes.length > 0) {
368
+ isNodeLazy = this.lazyIncludes.some(lazyIncludeRegex =>
369
+ relativePath.match(lazyIncludeRegex),
370
+ );
371
+ }
372
+ // Excludes override includes, so a node is _not_ lazy if it is included in the exclude list.
373
+ if (this.lazyExcludes.length > 0 && isNodeLazy) {
374
+ isNodeLazy = !this.lazyExcludes.some(lazyExcludeRegex =>
375
+ relativePath.match(lazyExcludeRegex),
376
+ );
377
+ }
378
+
379
+ if (this.requestedAssetIds.has(node.value.id) || !isNodeLazy) {
380
+ node.requested = true;
381
+ } else if (!node.requested) {
382
+ let isAsyncChild = this.assetGraph
383
+ .getIncomingDependencies(node.value)
384
+ .every(dep => dep.isEntry || dep.priority !== Priority.sync);
385
+ if (isAsyncChild) {
386
+ node.requested = !isNodeLazy;
387
+ } else {
388
+ delete node.requested;
389
+ }
390
+ }
391
+
392
+ let previouslyDeferred = childNode.deferred;
393
+ childNode.deferred = node.requested === false;
394
+
395
+ // The child dependency node we're now evaluating should not be deferred if it's parent
396
+ // is explicitly not requested (requested = false, but not requested = undefined)
397
+ //
398
+ // if we weren't previously deferred but we are now, then this dependency node's parents should also
399
+ // be marked as deferred
400
+ //
401
+ // if we were previously deferred but we not longer are, then then all parents should no longer be
402
+ // deferred either
403
+ if (!previouslyDeferred && childNode.deferred) {
404
+ this.assetGraph.markParentsWithHasDeferred(childNodeId);
405
+ } else if (previouslyDeferred && !childNode.deferred) {
406
+ // Mark Asset and Dependency as dirty for symbol propagation as it was
407
+ // previously deferred and it's used symbols may have changed
408
+ this.changedAssetsPropagation.add(node.id);
409
+ node.usedSymbolsDownDirty = true;
410
+ this.changedAssetsPropagation.add(childNode.id);
411
+ childNode.usedSymbolsDownDirty = true;
412
+
413
+ this.assetGraph.unmarkParentsWithHasDeferred(childNodeId);
414
+ }
415
+
416
+ // We `shouldVisitChild` if the childNode is not deferred
417
+ return !childNode.deferred;
418
+ }
419
+ }
420
+
421
+ return this.assetGraph.shouldVisitChild(nodeId, childNodeId);
422
+ }
423
+
424
+ shouldSkipRequest(nodeId: NodeId): boolean {
425
+ let node = nullthrows(this.assetGraph.getNode(nodeId));
426
+ return (
427
+ node.complete === true ||
428
+ !typesWithRequests.has(node.type) ||
429
+ (node.correspondingRequest != null &&
430
+ this.api.canSkipSubrequest(node.correspondingRequest))
431
+ );
432
+ }
433
+
434
+ queueCorrespondingRequest(
435
+ nodeId: NodeId,
436
+ errors: Array<Error>,
437
+ ): Promise<mixed> {
438
+ let promise;
439
+ let node = nullthrows(this.assetGraph.getNode(nodeId));
440
+ switch (node.type) {
441
+ case 'entry_specifier':
442
+ promise = this.runEntryRequest(node.value);
443
+ break;
444
+ case 'entry_file':
445
+ promise = this.runTargetRequest(node.value);
446
+ break;
447
+ case 'dependency':
448
+ promise = this.runPathRequest(node.value);
449
+ break;
450
+ case 'asset_group':
451
+ promise = this.runAssetRequest(node.value);
452
+ break;
453
+ default:
454
+ throw new Error(
455
+ `Can not queue corresponding request of node with type ${node.type}`,
456
+ );
457
+ }
458
+ return this.queue.add(() =>
459
+ promise.then(null, error => errors.push(error)),
460
+ );
461
+ }
462
+
463
+ async runEntryRequest(input: ProjectPath) {
464
+ let prevEntries = this.assetGraph.safeToIncrementallyBundle
465
+ ? this.assetGraph
466
+ .getEntryAssets()
467
+ .map(asset => asset.id)
468
+ .sort()
469
+ : [];
470
+
471
+ let request = createEntryRequest(input);
472
+ let result = await this.api.runRequest<ProjectPath, EntryRequestResult>(
473
+ request,
474
+ {
475
+ force: true,
476
+ },
477
+ );
478
+ this.assetGraph.resolveEntry(request.input, result.entries, request.id);
479
+
480
+ if (this.assetGraph.safeToIncrementallyBundle) {
481
+ let currentEntries = this.assetGraph
482
+ .getEntryAssets()
483
+ .map(asset => asset.id)
484
+ .sort();
485
+ let didEntriesChange =
486
+ prevEntries.length !== currentEntries.length ||
487
+ prevEntries.every(
488
+ (entryId, index) => entryId === currentEntries[index],
489
+ );
490
+
491
+ if (didEntriesChange) {
492
+ this.assetGraph.safeToIncrementallyBundle = false;
493
+ }
494
+ }
495
+ }
496
+
497
+ async runTargetRequest(input: Entry) {
498
+ let request = createTargetRequest(input);
499
+ let targets = await this.api.runRequest<Entry, Array<Target>>(request, {
500
+ force: true,
501
+ });
502
+ this.assetGraph.resolveTargets(request.input, targets, request.id);
503
+ }
504
+
505
+ async runPathRequest(input: Dependency) {
506
+ let request = createPathRequest({dependency: input, name: this.name});
507
+ let result = await this.api.runRequest<PathRequestInput, ?AssetGroup>(
508
+ request,
509
+ {force: true},
510
+ );
511
+ this.assetGraph.resolveDependency(input, result, request.id);
512
+ }
513
+
514
+ async runAssetRequest(input: AssetGroup) {
515
+ this.assetRequests.push(input);
516
+ let request = createAssetRequest({
517
+ ...input,
518
+ name: this.name,
519
+ optionsRef: this.optionsRef,
520
+ isSingleChangeRebuild: this.isSingleChangeRebuild,
521
+ });
522
+
523
+ let assets = await this.api.runRequest<AssetRequestInput, Array<Asset>>(
524
+ request,
525
+ {force: true},
526
+ );
527
+
528
+ if (assets != null) {
529
+ for (let asset of assets) {
530
+ if (this.assetGraph.safeToIncrementallyBundle) {
531
+ let otherAsset = this.assetGraph.getNodeByContentKey(asset.id);
532
+ if (otherAsset != null) {
533
+ invariant(otherAsset.type === 'asset');
534
+ if (!this._areDependenciesEqualForAssets(asset, otherAsset.value)) {
535
+ this.assetGraph.safeToIncrementallyBundle = false;
536
+ }
537
+ } else {
538
+ // adding a new entry or dependency
539
+ this.assetGraph.safeToIncrementallyBundle = false;
540
+ }
541
+ }
542
+ this.changedAssets.set(asset.id, asset);
543
+ this.changedAssetsPropagation.add(asset.id);
544
+ }
545
+ this.assetGraph.resolveAssetGroup(input, assets, request.id);
546
+ } else {
547
+ this.assetGraph.safeToIncrementallyBundle = false;
548
+ }
549
+
550
+ this.isSingleChangeRebuild = false;
551
+ }
552
+
553
+ /**
554
+ * Used for incremental bundling of modified assets
555
+ */
556
+ _areDependenciesEqualForAssets(asset: Asset, otherAsset: Asset): boolean {
557
+ let assetDependencies = Array.from(asset?.dependencies.keys()).sort();
558
+ let otherAssetDependencies = Array.from(
559
+ otherAsset?.dependencies.keys(),
560
+ ).sort();
561
+
562
+ if (assetDependencies.length !== otherAssetDependencies.length) {
563
+ return false;
564
+ }
565
+
566
+ return assetDependencies.every((key, index) => {
567
+ if (key !== otherAssetDependencies[index]) {
568
+ return false;
569
+ }
570
+
571
+ return setEqual(
572
+ new Set(asset?.dependencies.get(key)?.symbols?.keys()),
573
+ new Set(otherAsset?.dependencies.get(key)?.symbols?.keys()),
574
+ );
575
+ });
576
+ }
577
+ }