@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,716 @@
1
+ // @flow strict-local
2
+ import assert from 'assert';
3
+ import invariant from 'assert';
4
+ import nullthrows from 'nullthrows';
5
+ import type {FilePath, SourceLocation, Meta, Symbol} from '@atlaspack/types';
6
+ import type {ContentKey, NodeId} from '@atlaspack/graph';
7
+ import type {Diagnostic} from '@atlaspack/diagnostic';
8
+ import ThrowableDiagnostic from '@atlaspack/diagnostic';
9
+ import {setEqual} from '@atlaspack/utils';
10
+ import AssetGraph, {
11
+ nodeFromAssetGroup,
12
+ nodeFromDep,
13
+ nodeFromEntryFile,
14
+ nodeFromAsset,
15
+ } from '../src/AssetGraph';
16
+ import {createDependency as _createDependency} from '../src/Dependency';
17
+ import {createAsset as _createAsset} from '../src/assetUtils';
18
+ import {
19
+ toProjectPath as _toProjectPath,
20
+ type ProjectPath,
21
+ } from '../src/projectPath';
22
+ import {propagateSymbols} from '../src/SymbolPropagation';
23
+ import dumpGraphToGraphViz from '../src/dumpGraphToGraphViz';
24
+ import {DEFAULT_ENV, DEFAULT_OPTIONS, DEFAULT_TARGETS} from './test-utils';
25
+ import type {
26
+ Asset,
27
+ AssetNode,
28
+ AssetGraphNode,
29
+ Dependency,
30
+ DependencyNode,
31
+ } from '../src/types';
32
+
33
+ const stats = {size: 0, time: 0};
34
+
35
+ function createAsset(opts) {
36
+ return _createAsset('/', opts);
37
+ }
38
+
39
+ function createDependency(opts) {
40
+ return _createDependency('/', opts);
41
+ }
42
+
43
+ function toProjectPath(p) {
44
+ return _toProjectPath('/', p);
45
+ }
46
+
47
+ function fromProjectPathUnix(p: ProjectPath) {
48
+ // $FlowFixMe
49
+ return '/' + p;
50
+ }
51
+
52
+ function nullthrowsAssetNode(v: ?AssetGraphNode): AssetNode {
53
+ invariant(v?.type === 'asset');
54
+ return v;
55
+ }
56
+ function nullthrowsDependencyNode(v: ?AssetGraphNode): DependencyNode {
57
+ invariant(v?.type === 'dependency');
58
+ return v;
59
+ }
60
+
61
+ function createAssetGraph(
62
+ assets: Array<
63
+ [
64
+ FilePath,
65
+ /* symbols (or cleared) */ ?Array<
66
+ [Symbol, {|local: Symbol, loc?: ?SourceLocation, meta?: ?Meta|}],
67
+ >,
68
+ /* sideEffects */ boolean,
69
+ ],
70
+ >,
71
+ dependencies: Array<
72
+ [
73
+ /* from */ FilePath,
74
+ /* to */ FilePath,
75
+ /* symbols (or cleared) */ ?Array<
76
+ [
77
+ Symbol,
78
+ {|
79
+ local: Symbol,
80
+ loc?: ?SourceLocation,
81
+ isWeak: boolean,
82
+ meta?: ?Meta,
83
+ |},
84
+ ],
85
+ >,
86
+ ],
87
+ >,
88
+ isLibrary?: boolean,
89
+ ) {
90
+ let graph = new AssetGraph();
91
+ let entryFilePath = '/index.js';
92
+ graph.setRootConnections({
93
+ entries: [toProjectPath(entryFilePath)],
94
+ });
95
+ let entry = {
96
+ filePath: toProjectPath(entryFilePath),
97
+ packagePath: toProjectPath('/'),
98
+ };
99
+ let entryNodeContentKey = nodeFromEntryFile(entry).id;
100
+ graph.resolveEntry(toProjectPath(entryFilePath), [entry], '1');
101
+ graph.resolveTargets(entry, DEFAULT_TARGETS, '2');
102
+ let entryDependencyId = graph.getNodeIdsConnectedFrom(
103
+ graph.getNodeIdByContentKey(entryNodeContentKey),
104
+ )[0];
105
+ if (isLibrary) {
106
+ let entryDependencyNode = nullthrows(graph.getNode(entryDependencyId));
107
+ invariant(entryDependencyNode.type === 'dependency');
108
+ entryDependencyNode.value.symbols = new Map([
109
+ ['*', {local: '*', isWeak: true, loc: null}],
110
+ ]);
111
+ entryDependencyNode.usedSymbolsDown.add('*');
112
+ entryDependencyNode.usedSymbolsUp.set('*', undefined);
113
+ }
114
+
115
+ let assetId = 1;
116
+ let changedAssets = new Map();
117
+ let assetGroupNodes = new Map<FilePath, NodeId>();
118
+ let assetNodes = new Map<FilePath, NodeId>();
119
+ for (let [filePath, symbols, sideEffects] of assets) {
120
+ let assetGroup = nodeFromAssetGroup({
121
+ filePath: toProjectPath(filePath),
122
+ env: DEFAULT_ENV,
123
+ sideEffects,
124
+ });
125
+ let assetGroupNodeId = graph.addNodeByContentKey(assetGroup.id, assetGroup);
126
+ assetGroupNodes.set(filePath, assetGroupNodeId);
127
+
128
+ let asset = nodeFromAsset(
129
+ createAsset({
130
+ id: String(assetId),
131
+ filePath: toProjectPath(filePath),
132
+ type: 'js',
133
+ isSource: true,
134
+ sideEffects,
135
+ stats,
136
+ symbols: symbols ? new Map(symbols) : symbols,
137
+ env: DEFAULT_ENV,
138
+ }),
139
+ );
140
+ let assetNodeId = graph.addNodeByContentKey(asset.id, asset);
141
+ assetNodes.set(filePath, assetNodeId);
142
+ changedAssets.set(String(assetId), asset.value);
143
+
144
+ graph.addEdge(assetGroupNodeId, assetNodeId);
145
+
146
+ assetId++;
147
+ }
148
+
149
+ for (let [from, to, symbols] of dependencies) {
150
+ let dependencyNode = nodeFromDep(
151
+ createDependency({
152
+ specifier: to,
153
+ specifierType: 'esm',
154
+ env: DEFAULT_ENV,
155
+ symbols: symbols ? new Map(symbols) : symbols,
156
+ sourcePath: from,
157
+ sourceAssetId: from,
158
+ }),
159
+ );
160
+ let dependencyNodeId = graph.addNodeByContentKey(
161
+ dependencyNode.id,
162
+ dependencyNode,
163
+ );
164
+ graph.addEdge(nullthrows(assetNodes.get(from)), dependencyNodeId);
165
+ graph.addEdge(dependencyNodeId, nullthrows(assetGroupNodes.get(to)));
166
+ }
167
+
168
+ let entryAssetGroup = nullthrows(assetGroupNodes.get(entryFilePath));
169
+ graph.addEdge(entryDependencyId, entryAssetGroup);
170
+
171
+ return {graph, changedAssets};
172
+ }
173
+
174
+ function assertUsedSymbols(
175
+ graph: AssetGraph,
176
+ _expectedAsset: Array<[FilePath, /* usedSymbols */ Array<Symbol>]>,
177
+ _expectedDependency: Array<
178
+ [
179
+ FilePath,
180
+ FilePath,
181
+ /* usedSymbols */ Array<[Symbol, ?[FilePath, ?Symbol]] | [Symbol]> | null,
182
+ ],
183
+ >,
184
+ isLibrary?: boolean,
185
+ ) {
186
+ let expectedAsset = new Map(
187
+ _expectedAsset.map(([f, symbols]) => [f, symbols]),
188
+ );
189
+ let expectedDependency = new Map(
190
+ _expectedDependency.map(([from, to, sym]) => [
191
+ from + ':' + to,
192
+ // $FlowFixMe[invalid-tuple-index]
193
+ sym ? sym.map(v => [v[0], v[1] ?? [to, v[0]]]) : sym,
194
+ ]),
195
+ );
196
+
197
+ if (isLibrary) {
198
+ let entryDep = nullthrows(
199
+ [...graph.nodes.values()].find(
200
+ n => n?.type === 'dependency' && n.value.sourceAssetId == null,
201
+ ),
202
+ );
203
+ invariant(entryDep.type === 'dependency');
204
+ assertDependencyUsedSymbols(
205
+ entryDep.usedSymbolsUp,
206
+ new Map([['*', undefined]]),
207
+ 'entryDep',
208
+ );
209
+ }
210
+
211
+ function assertDependencyUsedSymbols(usedSymbolsUp, expectedMap, id) {
212
+ assertSetEqual(
213
+ new Set(usedSymbolsUp.keys()),
214
+ new Set(expectedMap.keys()),
215
+ id,
216
+ );
217
+
218
+ for (let [s, resolved] of usedSymbolsUp) {
219
+ let exp = expectedMap.get(s);
220
+ if (resolved && exp) {
221
+ let asset = nullthrows(graph.getNodeByContentKey(resolved.asset));
222
+ invariant(asset.type === 'asset');
223
+ assert.strictEqual(
224
+ fromProjectPathUnix(asset.value.filePath),
225
+ exp[0],
226
+ `dep ${id}@${s} resolved asset: ${fromProjectPathUnix(
227
+ asset.value.filePath,
228
+ )} !== ${exp[0]}`,
229
+ );
230
+ assert.strictEqual(
231
+ resolved.symbol,
232
+ exp[1],
233
+ `dep ${id}@${s} resolved symbol: ${String(
234
+ resolved.symbol,
235
+ )} !== ${String(exp[1])}`,
236
+ );
237
+ } else {
238
+ assert.equal(resolved, exp);
239
+ }
240
+ }
241
+ }
242
+
243
+ for (let [nodeId, node] of graph.nodes.entries()) {
244
+ if (node?.type === 'asset') {
245
+ let filePath = fromProjectPathUnix(node.value.filePath);
246
+ let expected = new Set(nullthrows(expectedAsset.get(filePath)));
247
+ assertSetEqual(node.usedSymbols, expected, filePath);
248
+ } else if (node?.type === 'dependency' && node.value.sourcePath != null) {
249
+ let resolutionId = graph.getNodeIdsConnectedFrom(nodeId)[0];
250
+ let resolution = nullthrows(graph.getNode(resolutionId));
251
+ invariant(resolution.type === 'asset_group');
252
+ let to = resolution.value.filePath;
253
+
254
+ let id =
255
+ fromProjectPathUnix(nullthrows(node.value.sourcePath)) +
256
+ ':' +
257
+ fromProjectPathUnix(nullthrows(to));
258
+ let expected = expectedDependency.get(id);
259
+ if (!expected) {
260
+ assert(expected === null);
261
+ assertSetEqual(new Set(node.usedSymbolsUp.keys()), new Set(), id);
262
+ assert(node.excluded, `${id} should be excluded`);
263
+ } else {
264
+ assert(!node.excluded, `${id} should not be excluded`);
265
+ let expectedMap = new Map(expected);
266
+
267
+ assertDependencyUsedSymbols(node.usedSymbolsUp, expectedMap, id);
268
+ }
269
+ }
270
+ }
271
+ }
272
+
273
+ function assertSetEqual<T>(
274
+ actual: $ReadOnlySet<T>,
275
+ expected: $ReadOnlySet<T>,
276
+ prefix?: string = '',
277
+ ) {
278
+ assert(
279
+ setEqual(actual, expected),
280
+ `${prefix} [${[...actual].join(',')}] wasn't [${[...expected].join(',')}]`,
281
+ );
282
+ }
283
+
284
+ async function testPropagation(
285
+ assets: Array<
286
+ [
287
+ FilePath,
288
+ /* symbols (or cleared) */ ?Array<
289
+ [Symbol, {|local: Symbol, loc?: ?SourceLocation, meta?: ?Meta|}],
290
+ >,
291
+ /* sideEffects */ boolean,
292
+ /* usedSymbols */ Array<Symbol>,
293
+ ],
294
+ >,
295
+ dependencies: Array<
296
+ [
297
+ /* from */ FilePath,
298
+ /* to */ FilePath,
299
+ /* symbols (or cleared) */ ?Array<
300
+ [
301
+ Symbol,
302
+ {|
303
+ local: Symbol,
304
+ loc?: ?SourceLocation,
305
+ isWeak: boolean,
306
+ meta?: ?Meta,
307
+ |},
308
+ ],
309
+ >,
310
+ /* usedSymbols */ Array<
311
+ [Symbol, ?[FilePath, ?Symbol]] | [Symbol],
312
+ > | /* excluded */ null,
313
+ ],
314
+ >,
315
+ isLibrary?: boolean,
316
+ ): Promise<AssetGraph> {
317
+ let {graph, changedAssets} = createAssetGraph(
318
+ assets.map(([f, symbols, sideEffects]) => [f, symbols, sideEffects]),
319
+ dependencies.map(([from, to, symbols]) => [from, to, symbols]),
320
+ isLibrary,
321
+ );
322
+ await dumpGraphToGraphViz(graph, 'test_before');
323
+
324
+ handlePropagationErrors(
325
+ propagateSymbols({
326
+ options: DEFAULT_OPTIONS,
327
+ assetGraph: graph,
328
+ changedAssetsPropagation: new Set(changedAssets.keys()),
329
+ assetGroupsWithRemovedParents: new Set(),
330
+ previousErrors: undefined,
331
+ }),
332
+ );
333
+
334
+ await dumpGraphToGraphViz(graph, 'test_after');
335
+
336
+ assertUsedSymbols(
337
+ graph,
338
+ assets.map(([f, , , usedSymbols]) => [f, usedSymbols]),
339
+ dependencies.map(([from, to, , usedSymbols]) => [from, to, usedSymbols]),
340
+ isLibrary,
341
+ );
342
+
343
+ return graph;
344
+ }
345
+
346
+ function handlePropagationErrors(errors: Map<NodeId, Array<Diagnostic>>) {
347
+ if (errors.size > 0) {
348
+ throw new ThrowableDiagnostic({
349
+ diagnostic: [...errors.values()][0],
350
+ });
351
+ }
352
+ }
353
+
354
+ function assertPropagationErrors(
355
+ graph: AssetGraph,
356
+ actual: Map<NodeId, Array<Diagnostic>>,
357
+ expected: Iterable<[FilePath, Array<Diagnostic>]>,
358
+ ) {
359
+ assert.deepEqual(
360
+ [...actual].map(([k, v]) => [
361
+ nullthrowsAssetNode(graph.getNode(k)).value.filePath,
362
+ v,
363
+ ]),
364
+ [...expected],
365
+ );
366
+ }
367
+
368
+ function changeDependency(
369
+ graph: AssetGraph,
370
+ from: FilePath,
371
+ to: FilePath,
372
+ cb: ($NonMaybeType<Dependency['symbols']>) => void,
373
+ ): Iterable<[ContentKey, Asset]> {
374
+ let sourceAssetNode = nullthrowsAssetNode(
375
+ [...graph.nodes.values()].find(
376
+ n => n?.type === 'asset' && n.value.filePath === from,
377
+ ),
378
+ );
379
+ sourceAssetNode.usedSymbolsDownDirty = true;
380
+ let depNode = nullthrowsDependencyNode(
381
+ [...graph.nodes.values()].find(
382
+ n =>
383
+ n?.type === 'dependency' &&
384
+ n.value.sourcePath === from &&
385
+ n.value.specifier === to,
386
+ ),
387
+ );
388
+ cb(nullthrows(depNode.value.symbols));
389
+ return [[sourceAssetNode.id, sourceAssetNode.value]];
390
+ }
391
+
392
+ function changeAsset(
393
+ graph: AssetGraph,
394
+ asset: FilePath,
395
+ cb: ($NonMaybeType<Asset['symbols']>) => void,
396
+ ): Iterable<[ContentKey, Asset]> {
397
+ let node = nullthrowsAssetNode(
398
+ [...graph.nodes.values()].find(
399
+ n => n?.type === 'asset' && n.value.filePath === asset,
400
+ ),
401
+ );
402
+ node.usedSymbolsUpDirty = true;
403
+ node.usedSymbolsDownDirty = true;
404
+ cb(nullthrows(node.value.symbols));
405
+ return [[node.id, node.value]];
406
+ }
407
+
408
+ // process.env.ATLASPACK_DUMP_GRAPHVIZ = '';
409
+ // process.env.ATLASPACK_DUMP_GRAPHVIZ = 'symbols';
410
+
411
+ describe('SymbolPropagation', () => {
412
+ it('basic tree', async () => {
413
+ // prettier-ignore
414
+ await testPropagation(
415
+ [
416
+ ['/index.js', [], true, []],
417
+ ['/lib.js', [['f', {local: 'lib1$foo'}], ['b', {local: 'lib2$bar'}]], false, []],
418
+ ['/lib1.js', [['foo', {local: 'v'}]], false, ['foo']],
419
+ ['/lib2.js', [['bar', {local: 'v'}]], false, []],
420
+ ],
421
+ [
422
+ ['/index.js', '/lib.js', [['f', {local: 'f', isWeak: false}]], [['f', ['/lib1.js', 'foo']]]],
423
+ ['/lib.js', '/lib1.js', [['foo', {local: 'lib1$foo', isWeak: true}]], [['foo']]],
424
+ ['/lib.js', '/lib2.js', [['bar', {local: 'lib2$bar', isWeak: true}]], null],
425
+ ],
426
+ );
427
+ });
428
+
429
+ it('basic tree - dependency symbol change export', async () => {
430
+ // prettier-ignore
431
+ let graph = await testPropagation(
432
+ [
433
+ ['/index.js', [], true, []],
434
+ ['/lib.js', [['f', {local: 'f'}], ['b', {local: 'b'}]], true, ['f']],
435
+ ],
436
+ [
437
+ ['/index.js', '/lib.js', [['f', {local: 'f', isWeak: false}]], [['f']]],
438
+ ],
439
+ );
440
+
441
+ let changedAssets = [
442
+ ...changeDependency(graph, 'index.js', '/lib.js', symbols => {
443
+ symbols.set('b', {
444
+ local: 'b',
445
+ isWeak: false,
446
+ loc: undefined,
447
+ });
448
+ }),
449
+ ];
450
+ propagateSymbols({
451
+ options: DEFAULT_OPTIONS,
452
+ assetGraph: graph,
453
+ changedAssetsPropagation: new Set(new Map(changedAssets).keys()),
454
+ assetGroupsWithRemovedParents: new Set(),
455
+ });
456
+
457
+ // prettier-ignore
458
+ assertUsedSymbols(graph,
459
+ [
460
+ ['/index.js', []],
461
+ ['/lib.js', ['f', 'b']],
462
+ ],
463
+ [
464
+ ['/index.js', '/lib.js', [['f'], ['b']]],
465
+ ],
466
+ );
467
+ });
468
+
469
+ it('basic tree - dependency symbol change import and error', async () => {
470
+ // prettier-ignore
471
+ let graph = await testPropagation(
472
+ [
473
+ ['/index.js', [], true, []],
474
+ ['/lib.js', [['f', {local: 'f'}]], true, ['f']],
475
+ ],
476
+ [
477
+ ['/index.js', '/lib.js', [['f', {local: 'f', isWeak: false}]], [['f']]],
478
+ ],
479
+ );
480
+
481
+ let changedAssets = [
482
+ ...changeDependency(graph, 'index.js', '/lib.js', symbols => {
483
+ symbols.delete('f');
484
+ symbols.set('f2', {
485
+ local: 'f2',
486
+ isWeak: false,
487
+ loc: undefined,
488
+ });
489
+ }),
490
+ ];
491
+ let errors = propagateSymbols({
492
+ options: DEFAULT_OPTIONS,
493
+ assetGraph: graph,
494
+ changedAssetsPropagation: new Set(new Map(changedAssets).keys()),
495
+ assetGroupsWithRemovedParents: new Set(),
496
+ });
497
+
498
+ assertPropagationErrors(graph, errors, [
499
+ [
500
+ 'lib.js',
501
+ [
502
+ {
503
+ message: "lib.js does not export 'f2'",
504
+ origin: '@atlaspack/core',
505
+ codeFrames: undefined,
506
+ },
507
+ ],
508
+ ],
509
+ ]);
510
+ });
511
+
512
+ it('basic tree - asset symbol change export and error', async () => {
513
+ // prettier-ignore
514
+ let graph = await testPropagation(
515
+ [
516
+ ['/index.js', [], true, []],
517
+ ['/lib.js', [['f', {local: 'f'}]], true, ['f']],
518
+ ],
519
+ [
520
+ ['/index.js', '/lib.js', [['f', {local: 'f', isWeak: false}]], [['f']]],
521
+ ],
522
+ );
523
+
524
+ let changedAssets = [
525
+ ...changeAsset(graph, 'lib.js', symbols => {
526
+ symbols.delete('f');
527
+ symbols.set('f2', {
528
+ local: 'f2',
529
+ loc: undefined,
530
+ });
531
+ }),
532
+ ];
533
+
534
+ let errors = propagateSymbols({
535
+ options: DEFAULT_OPTIONS,
536
+ assetGraph: graph,
537
+ changedAssetsPropagation: new Set(new Map(changedAssets).keys()),
538
+ assetGroupsWithRemovedParents: new Set(),
539
+ });
540
+
541
+ assertPropagationErrors(graph, errors, [
542
+ [
543
+ 'lib.js',
544
+ [
545
+ {
546
+ message: "lib.js does not export 'f'",
547
+ origin: '@atlaspack/core',
548
+ codeFrames: undefined,
549
+ },
550
+ ],
551
+ ],
552
+ ]);
553
+ });
554
+
555
+ it('basic tree - dependency symbol change reexport', async () => {
556
+ // prettier-ignore
557
+ let graph = await testPropagation(
558
+ [
559
+ ['/index.js', [], true, []],
560
+ ['/lib.js', [['f', {local: 'lib1$foo'}], ['b', {local: 'lib2$bar'}]], true, []],
561
+ ['/lib1.js', [['foo', {local: 'v'}]], true, ['foo']],
562
+ ['/lib2.js', [['bar', {local: 'v'}]], true, []],
563
+ ],
564
+ [
565
+ ['/index.js', '/lib.js', [['f', {local: 'f', isWeak: false}]], [['f']]],
566
+ ['/lib.js', '/lib1.js', [['foo', {local: 'lib1$foo', isWeak: true}]], [['foo']]],
567
+ ['/lib.js', '/lib2.js', [['bar', {local: 'lib2$bar', isWeak: true}]], []],
568
+ ],
569
+ );
570
+
571
+ let changedAssets = [
572
+ ...changeDependency(graph, 'index.js', '/lib.js', symbols => {
573
+ symbols.set('b', {
574
+ local: 'b',
575
+ isWeak: false,
576
+ loc: undefined,
577
+ });
578
+ }),
579
+ ];
580
+ propagateSymbols({
581
+ options: DEFAULT_OPTIONS,
582
+ assetGraph: graph,
583
+ changedAssetsPropagation: new Set(new Map(changedAssets).keys()),
584
+ assetGroupsWithRemovedParents: new Set(),
585
+ });
586
+
587
+ // prettier-ignore
588
+ assertUsedSymbols(graph,
589
+ [
590
+ ['/index.js', []],
591
+ ['/lib.js', []],
592
+ ['/lib1.js', ['foo']],
593
+ ['/lib2.js', ['bar']],
594
+ ],
595
+ [
596
+ ['/index.js', '/lib.js', [['f'],['b']]],
597
+ ['/lib.js', '/lib1.js', [['foo']]],
598
+ ['/lib.js', '/lib2.js', [['bar']]],
599
+ ],
600
+ );
601
+ });
602
+
603
+ it('basic tree with reexport-all', async () => {
604
+ // prettier-ignore
605
+ await testPropagation(
606
+ [
607
+ ['/index.js', [], true, []],
608
+ ['/lib.js', [], false, []],
609
+ ['/lib1.js', [['foo', {local: 'v'}]], false, ['foo']],
610
+ ['/lib2.js', [['bar', {local: 'v'}]], false, []],
611
+ ],
612
+ [
613
+ ['/index.js', '/lib.js', [['foo', {local: 'foo', isWeak: false}]], [['foo', ['/lib1.js', 'foo']]]],
614
+ ['/lib.js', '/lib1.js', [['*', {local: '*', isWeak: true}]], [['foo']]],
615
+ ['/lib.js', '/lib2.js', [['*', {local: '*', isWeak: true}]], null],
616
+ ],
617
+ );
618
+ });
619
+
620
+ it('dependency with * imports everything', async () => {
621
+ // prettier-ignore
622
+ await testPropagation(
623
+ [
624
+ ['/index.js', [], true, []],
625
+ ['/lib.js', [['a', {local: 'lib1$foo'}], ['b', {local: 'lib1$b'}]], true, ['*']],
626
+ ['/lib1.js', [['b', {local: 'v'}]], true, ['b']],
627
+ ['/lib2.js', [['c', {local: 'v'}]], true, ['*']],
628
+ ],
629
+ [
630
+ ['/index.js', '/lib.js', [['*', {local: 'lib', isWeak: false}]], [['*']]],
631
+ ['/lib.js', '/lib1.js', [['b', {local: 'lib1$foo', isWeak: true}]], [['b']]],
632
+ // TODO should usedSymbolsUp actually list the individual symbols instead of '*'?
633
+ ['/lib.js', '/lib2.js', [['*', {local: '*', isWeak: true}]], [['*']]],
634
+ ],
635
+ );
636
+ });
637
+
638
+ it('dependency with cleared symbols imports side-effect-full parts', async () => {
639
+ // prettier-ignore
640
+ await testPropagation(
641
+ [
642
+ ['/index.js', [], true, []],
643
+ ['/lib.js', [['a', {local: 'lib1$foo'}], ['b', {local: 'lib$b'}]], true, ['b']],
644
+ ['/lib1.js', [['b', {local: 'v'}]], true, ['b']],
645
+ ['/lib2.js', [['c', {local: 'v'}]], false, ['*']],
646
+ ],
647
+ [
648
+ ['/index.js', '/lib.js', null, []],
649
+ ['/lib.js', '/lib1.js', [['b', {local: 'lib1$foo', isWeak: true}]], [['b']]],
650
+ ['/lib.js', '/lib2.js', [['*', {local: '*', isWeak: true}]], [['*']]],
651
+ ],
652
+ );
653
+ });
654
+
655
+ it('dependency with cleared symbols imports side-effect-free package', async () => {
656
+ // prettier-ignore
657
+ await testPropagation(
658
+ [
659
+ ['/index.js', [], true, []],
660
+ ['/lib.js', [['a', {local: 'lib$a'}], ['b', {local: 'lib1$b'}], ['c', {local: 'lib2$c'}]], false, ['a']],
661
+ ['/lib1.js', [['b', {local: 'v'}]], false, ['b']],
662
+ ['/lib2.js', [['c', {local: 'v'}]], false, ['c']],
663
+ ['/lib3.js', [['d', {local: 'v'}]], false, ['*']],
664
+ ],
665
+ [
666
+ ['/index.js', '/lib.js', null, []],
667
+ ['/lib.js', '/lib1.js', [['b', {local: 'lib1$b', isWeak: true}]], [['b']]],
668
+ ['/lib.js', '/lib2.js', [['c', {local: 'lib2$c', isWeak: true}]], [['c']]],
669
+ ['/lib.js', '/lib3.js', [['*', {local: '*', isWeak: true}]], [['*']]],
670
+ ],
671
+ );
672
+ });
673
+
674
+ it('library build with entry dependency', async () => {
675
+ // prettier-ignore
676
+ await testPropagation(
677
+ [
678
+ ['/index.js', [["foo", {local: "foo"}], ['b', {local: 'b$b'}]], true, ['*']],
679
+ ],
680
+ [],
681
+ true
682
+ );
683
+ });
684
+
685
+ it('library build with entry dependency and reexport', async () => {
686
+ // prettier-ignore
687
+ await testPropagation(
688
+ [
689
+ ['/index.js', [["foo", {local: "foo"}], ['b', {local: 'b$b'}]], true, ['*']],
690
+ ['/b.js', [['b', {local: 'b'}]], true, ['b']],
691
+ ],
692
+ [
693
+ ['/index.js', '/b.js', [['b', {local: 'b$b', isWeak: false}]], [['b']]],
694
+ ],
695
+ true
696
+ );
697
+ });
698
+
699
+ it('cyclic dependency', async () => {
700
+ // prettier-ignore
701
+ await testPropagation(
702
+ [
703
+ ['/index.js', [], true, []],
704
+ ['/a.js', [['a', {local: 'b$b'}], ['real', {local: 'real'}]], true, ['real']],
705
+ ['/b.js', [['b', {local: 'c$c'}]], true, []],
706
+ ['/c.js', [['c', {local: 'a$real'}]], true, []],
707
+ ],
708
+ [
709
+ ['/index.js', '/a.js', [['a', {local: 'a', isWeak: false}]], [['a']]],
710
+ ['/a.js', '/b.js', [['b', {local: 'b$b', isWeak: true}]], [['b']]],
711
+ ['/b.js', '/c.js', [['c', {local: 'c$c', isWeak: true}]], [['c']]],
712
+ ['/c.js', '/a.js', [['real', {local: 'a$real', isWeak: true}]], [['real']]],
713
+ ],
714
+ );
715
+ });
716
+ });