@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,192 @@
1
+ // @flow strict-local
2
+
3
+ import type {Dependency} from '@atlaspack/types';
4
+
5
+ import assert from 'assert';
6
+ import invariant from 'assert';
7
+ import InternalBundleGraph from '../src/BundleGraph';
8
+ import MutableBundleGraph from '../src/public/MutableBundleGraph';
9
+ import {DEFAULT_ENV, DEFAULT_TARGETS, DEFAULT_OPTIONS} from './test-utils';
10
+ import AssetGraph, {nodeFromAssetGroup} from '../src/AssetGraph';
11
+ import {createAsset as _createAsset} from '../src/assetUtils';
12
+ import {createDependency as _createDependency} from '../src/Dependency';
13
+ import nullthrows from 'nullthrows';
14
+ import {toProjectPath} from '../src/projectPath';
15
+
16
+ function createAsset(opts) {
17
+ return _createAsset('/', opts);
18
+ }
19
+
20
+ function createDependency(opts) {
21
+ return _createDependency('/', opts);
22
+ }
23
+
24
+ const id1 = '0123456789abcdef0123456789abcdef';
25
+ const id2 = '9876543210fedcba9876543210fedcba';
26
+
27
+ describe('PublicMutableBundleGraph', () => {
28
+ it('creates publicIds for bundles', () => {
29
+ let internalBundleGraph = InternalBundleGraph.fromAssetGraph(
30
+ createMockAssetGraph(),
31
+ false,
32
+ );
33
+ let mutableBundleGraph = new MutableBundleGraph(
34
+ internalBundleGraph,
35
+ DEFAULT_OPTIONS,
36
+ );
37
+
38
+ mutableBundleGraph.traverse(node => {
39
+ if (
40
+ node.type === 'dependency' &&
41
+ mutableBundleGraph.getResolvedAsset(node.value)
42
+ ) {
43
+ let target = nullthrows(node.value.target);
44
+ let group = mutableBundleGraph.createBundleGroup(node.value, target);
45
+ let resolved = mutableBundleGraph.getResolvedAsset(node.value);
46
+ if (resolved != null) {
47
+ mutableBundleGraph.addBundleToBundleGroup(
48
+ mutableBundleGraph.createBundle({
49
+ entryAsset: resolved,
50
+ target,
51
+ }),
52
+ group,
53
+ );
54
+ }
55
+ }
56
+ });
57
+
58
+ assert.deepEqual(
59
+ internalBundleGraph.getBundles().map(b => b.publicId),
60
+ ['8LVYC', 'd7Pd5'],
61
+ );
62
+ });
63
+
64
+ it('is safe to add a bundle to a bundleGroup multiple times', () => {
65
+ let internalBundleGraph = InternalBundleGraph.fromAssetGraph(
66
+ createMockAssetGraph(),
67
+ false,
68
+ );
69
+ let mutableBundleGraph = new MutableBundleGraph(
70
+ internalBundleGraph,
71
+ DEFAULT_OPTIONS,
72
+ );
73
+
74
+ let dependency: Dependency;
75
+ mutableBundleGraph.traverse((node, _, actions) => {
76
+ if (node.type === 'dependency') {
77
+ dependency = node.value;
78
+ actions.stop();
79
+ }
80
+ });
81
+
82
+ invariant(dependency != null);
83
+
84
+ let target = nullthrows(dependency.target);
85
+ let bundleGroup = mutableBundleGraph.createBundleGroup(dependency, target);
86
+ let bundle = mutableBundleGraph.createBundle({
87
+ entryAsset: nullthrows(mutableBundleGraph.getResolvedAsset(dependency)),
88
+ target,
89
+ });
90
+
91
+ mutableBundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
92
+ mutableBundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
93
+ });
94
+ });
95
+
96
+ const stats = {size: 0, time: 0};
97
+ function createMockAssetGraph() {
98
+ let graph = new AssetGraph();
99
+ graph.setRootConnections({
100
+ entries: [toProjectPath('/', '/index'), toProjectPath('/', '/index2')],
101
+ });
102
+
103
+ graph.resolveEntry(
104
+ toProjectPath('/', '/index'),
105
+ [
106
+ {
107
+ filePath: toProjectPath('/', '/path/to/index/src/main.js'),
108
+ packagePath: toProjectPath('/', '/path/to/index'),
109
+ },
110
+ ],
111
+ '1',
112
+ );
113
+ graph.resolveEntry(
114
+ toProjectPath('/', '/index2'),
115
+ [
116
+ {
117
+ filePath: toProjectPath('/', '/path/to/index/src/main2.js'),
118
+ packagePath: toProjectPath('/', '/path/to/index'),
119
+ },
120
+ ],
121
+ '2',
122
+ );
123
+ graph.resolveTargets(
124
+ {
125
+ filePath: toProjectPath('/', '/path/to/index/src/main.js'),
126
+ packagePath: toProjectPath('/', '/path/to/index'),
127
+ },
128
+ DEFAULT_TARGETS,
129
+ '3',
130
+ );
131
+ graph.resolveTargets(
132
+ {
133
+ filePath: toProjectPath('/', '/path/to/index/src/main2.js'),
134
+ packagePath: toProjectPath('/', '/path/to/index'),
135
+ },
136
+ DEFAULT_TARGETS,
137
+ '4',
138
+ );
139
+
140
+ let dep1 = createDependency({
141
+ specifier: 'path/to/index/src/main.js',
142
+ specifierType: 'esm',
143
+ needsStableName: true,
144
+ env: DEFAULT_ENV,
145
+ target: DEFAULT_TARGETS[0],
146
+ });
147
+ let dep2 = createDependency({
148
+ specifier: 'path/to/index/src/main2.js',
149
+ specifierType: 'esm',
150
+ needsStableName: true,
151
+ env: DEFAULT_ENV,
152
+ target: DEFAULT_TARGETS[0],
153
+ });
154
+
155
+ let filePath = toProjectPath('/', '/index.js');
156
+ let req1 = {filePath, env: DEFAULT_ENV};
157
+ graph.resolveDependency(dep1, nodeFromAssetGroup(req1).value, '5');
158
+ graph.resolveAssetGroup(
159
+ req1,
160
+ [
161
+ createAsset({
162
+ id: id1,
163
+ filePath,
164
+ type: 'js',
165
+ isSource: true,
166
+ stats,
167
+ env: DEFAULT_ENV,
168
+ }),
169
+ ],
170
+ '6',
171
+ );
172
+
173
+ filePath = toProjectPath('/', '/index2.js');
174
+ let req2 = {filePath, env: DEFAULT_ENV};
175
+ graph.resolveDependency(dep2, nodeFromAssetGroup(req2).value, '7');
176
+ graph.resolveAssetGroup(
177
+ req2,
178
+ [
179
+ createAsset({
180
+ id: id2,
181
+ filePath,
182
+ type: 'js',
183
+ isSource: true,
184
+ stats,
185
+ env: DEFAULT_ENV,
186
+ }),
187
+ ],
188
+ '8',
189
+ );
190
+
191
+ return graph;
192
+ }
@@ -0,0 +1,448 @@
1
+ // @flow strict-local
2
+
3
+ import assert from 'assert';
4
+ import nullthrows from 'nullthrows';
5
+ import RequestTracker, {type RunAPI} from '../src/RequestTracker';
6
+ import WorkerFarm from '@atlaspack/workers';
7
+ import {DEFAULT_OPTIONS} from './test-utils';
8
+ import {INITIAL_BUILD} from '../src/constants';
9
+ import {makeDeferredWithPromise} from '@atlaspack/utils';
10
+
11
+ const options = DEFAULT_OPTIONS;
12
+ const farm = new WorkerFarm({workerPath: require.resolve('../src/worker.js')});
13
+
14
+ describe('RequestTracker', () => {
15
+ it('should not run requests that have not been invalidated', async () => {
16
+ let tracker = new RequestTracker({farm, options});
17
+ await tracker.runRequest({
18
+ id: 'abc',
19
+ type: 7,
20
+ run: () => {},
21
+ input: null,
22
+ });
23
+ let called = false;
24
+ await tracker.runRequest({
25
+ id: 'abc',
26
+ type: 7,
27
+ run: () => {
28
+ called = true;
29
+ },
30
+ input: null,
31
+ });
32
+ assert(called === false);
33
+ });
34
+
35
+ it('should rerun requests that have been invalidated', async () => {
36
+ let tracker = new RequestTracker({farm, options});
37
+ await tracker.runRequest({
38
+ id: 'abc',
39
+ type: 7,
40
+ run: () => {},
41
+ input: null,
42
+ });
43
+ tracker.graph.invalidateNode(
44
+ tracker.graph.getNodeIdByContentKey('abc'),
45
+ INITIAL_BUILD,
46
+ );
47
+ let called = false;
48
+ await tracker.runRequest({
49
+ id: 'abc',
50
+ type: 7,
51
+ run: () => {
52
+ called = true;
53
+ },
54
+ input: null,
55
+ });
56
+ assert(called === true);
57
+ });
58
+
59
+ it('should invalidate requests with invalidated subrequests', async () => {
60
+ let tracker = new RequestTracker({farm, options});
61
+ await tracker.runRequest({
62
+ id: 'abc',
63
+ type: 7,
64
+ run: async ({api}) => {
65
+ await api.runRequest({
66
+ id: 'xyz',
67
+ type: 7,
68
+ run: () => {},
69
+ input: null,
70
+ });
71
+ },
72
+ input: null,
73
+ });
74
+ tracker.graph.invalidateNode(
75
+ tracker.graph.getNodeIdByContentKey('xyz'),
76
+ INITIAL_BUILD,
77
+ );
78
+ assert(
79
+ tracker
80
+ .getInvalidRequests()
81
+ .map(req => req.id)
82
+ .includes('abc'),
83
+ );
84
+ });
85
+
86
+ it('should invalidate requests that failed', async () => {
87
+ let tracker = new RequestTracker({farm, options});
88
+ await tracker
89
+ .runRequest({
90
+ id: 'abc',
91
+ type: 7,
92
+ run: async () => {
93
+ await Promise.resolve();
94
+ throw new Error('woops');
95
+ },
96
+ input: null,
97
+ })
98
+ .then(null, () => {
99
+ /* do nothing */
100
+ });
101
+ assert(
102
+ tracker
103
+ .getInvalidRequests()
104
+ .map(req => req.id)
105
+ .includes('abc'),
106
+ );
107
+ });
108
+
109
+ it('should remove subrequests that are no longer called within a request', async () => {
110
+ let tracker = new RequestTracker({farm, options});
111
+ await tracker.runRequest({
112
+ id: 'abc',
113
+ type: 7,
114
+ run: async ({api}) => {
115
+ await api.runRequest({
116
+ id: 'xyz',
117
+ type: 7,
118
+ run: () => {},
119
+ input: null,
120
+ });
121
+ },
122
+ input: null,
123
+ });
124
+ let nodeId = nullthrows(tracker.graph.getNodeIdByContentKey('abc'));
125
+ tracker.graph.invalidateNode(nodeId, INITIAL_BUILD);
126
+ await tracker.runRequest({
127
+ id: 'abc',
128
+ type: 7,
129
+ run: async ({api}) => {
130
+ await api.runRequest({
131
+ id: '123',
132
+ type: 7,
133
+ run: () => {},
134
+ input: null,
135
+ });
136
+ },
137
+ input: null,
138
+ });
139
+ assert(!tracker.graph.hasContentKey('xyz'));
140
+ });
141
+
142
+ it('should return a cached result if it was stored', async () => {
143
+ let tracker = new RequestTracker({farm, options});
144
+ await tracker.runRequest({
145
+ id: 'abc',
146
+ type: 7,
147
+ // $FlowFixMe string isn't a valid result
148
+ run: async ({api}: {api: RunAPI<string | void>, ...}) => {
149
+ let result = await Promise.resolve('hello');
150
+ api.storeResult(result);
151
+ },
152
+ input: null,
153
+ });
154
+ let result = await tracker.runRequest({
155
+ id: 'abc',
156
+ type: 7,
157
+ run: async () => {},
158
+ input: null,
159
+ });
160
+ assert(result === 'hello');
161
+ });
162
+
163
+ it('should reject all in progress requests when the abort controller aborts', async () => {
164
+ let tracker = new RequestTracker({farm, options});
165
+ let p = tracker
166
+ .runRequest({
167
+ id: 'abc',
168
+ type: 7,
169
+ run: async () => {
170
+ await Promise.resolve('hello');
171
+ },
172
+ input: null,
173
+ })
174
+ .then(null, () => {
175
+ /* do nothing */
176
+ });
177
+ // $FlowFixMe
178
+ tracker.setSignal({aborted: true});
179
+ await p;
180
+ assert(
181
+ tracker
182
+ .getInvalidRequests()
183
+ .map(req => req.id)
184
+ .includes('abc'),
185
+ );
186
+ });
187
+
188
+ it('should write cache to disk and store index', async () => {
189
+ let tracker = new RequestTracker({farm, options});
190
+
191
+ await tracker.runRequest({
192
+ id: 'abc',
193
+ type: 7,
194
+ // $FlowFixMe string isn't a valid result
195
+ run: async ({api}: {api: RunAPI<string | void>, ...}) => {
196
+ let result = await Promise.resolve();
197
+ api.storeResult(result);
198
+ },
199
+ input: null,
200
+ });
201
+
202
+ await tracker.writeToCache();
203
+
204
+ assert(tracker.graph.cachedRequestChunks.size > 0);
205
+ });
206
+
207
+ it('should not write to cache when the abort controller aborts', async () => {
208
+ let tracker = new RequestTracker({farm, options});
209
+
210
+ const abortController = new AbortController();
211
+ abortController.abort();
212
+
213
+ await tracker.writeToCache(abortController.signal);
214
+
215
+ assert(tracker.graph.cachedRequestChunks.size === 0);
216
+ });
217
+
218
+ it('should not requeue requests if the previous request is still running', async () => {
219
+ let tracker = new RequestTracker({farm, options});
220
+
221
+ let lockA = makeDeferredWithPromise();
222
+ let lockB = makeDeferredWithPromise();
223
+
224
+ let requestA = tracker.runRequest({
225
+ id: 'abc',
226
+ type: 7,
227
+ // $FlowFixMe string isn't a valid result
228
+ run: async ({api}: {api: RunAPI<string>, ...}) => {
229
+ await lockA.promise;
230
+ api.storeResult('a');
231
+ return 'a';
232
+ },
233
+ input: null,
234
+ });
235
+
236
+ let calledB = false;
237
+ let requestB = tracker.runRequest({
238
+ id: 'abc',
239
+ type: 7,
240
+ // $FlowFixMe string isn't a valid result
241
+ run: async ({api}: {api: RunAPI<string>, ...}) => {
242
+ calledB = true;
243
+ await lockB.promise;
244
+ api.storeResult('b');
245
+ return 'b';
246
+ },
247
+ input: null,
248
+ });
249
+
250
+ lockA.deferred.resolve();
251
+ lockB.deferred.resolve();
252
+ let resultA = await requestA;
253
+ let resultB = await requestB;
254
+ assert.strictEqual(resultA, 'a');
255
+ assert.strictEqual(resultB, 'a');
256
+ assert.strictEqual(calledB, false);
257
+
258
+ let cachedResult = await tracker.runRequest({
259
+ id: 'abc',
260
+ type: 7,
261
+ run: () => {},
262
+ input: null,
263
+ });
264
+ assert.strictEqual(cachedResult, 'a');
265
+ });
266
+
267
+ it('should requeue requests if the previous request is still running but failed', async () => {
268
+ let tracker = new RequestTracker({farm, options});
269
+
270
+ let lockA = makeDeferredWithPromise();
271
+ let lockB = makeDeferredWithPromise();
272
+
273
+ let requestA = tracker
274
+ .runRequest({
275
+ id: 'abc',
276
+ type: 7,
277
+ run: async () => {
278
+ await lockA.promise;
279
+ throw new Error('whoops');
280
+ },
281
+ input: null,
282
+ })
283
+ .catch(() => {
284
+ // ignore
285
+ });
286
+
287
+ let requestB = tracker.runRequest({
288
+ id: 'abc',
289
+ type: 7,
290
+ // $FlowFixMe string isn't a valid result
291
+ run: async ({api}: {api: RunAPI<string | void>, ...}) => {
292
+ await lockB.promise;
293
+ api.storeResult('b');
294
+ },
295
+ input: null,
296
+ });
297
+
298
+ lockA.deferred.resolve();
299
+ lockB.deferred.resolve();
300
+ await requestA;
301
+ await requestB;
302
+
303
+ let called = false;
304
+ let cachedResult = await tracker.runRequest({
305
+ id: 'abc',
306
+ type: 7,
307
+ run: () => {
308
+ called = true;
309
+ },
310
+ input: null,
311
+ });
312
+ assert.strictEqual(cachedResult, 'b');
313
+ assert.strictEqual(called, false);
314
+ });
315
+
316
+ it('should ignore stale node chunks from cache', async () => {
317
+ let tracker = new RequestTracker({farm, options});
318
+
319
+ // Set the nodes per blob low so we can ensure multiple files without
320
+ // creating 17,000 nodes
321
+ tracker.graph.nodesPerBlob = 2;
322
+
323
+ tracker.graph.addNode({type: 0, id: 'some-file-node-1'});
324
+ tracker.graph.addNode({type: 0, id: 'some-file-node-2'});
325
+ tracker.graph.addNode({type: 0, id: 'some-file-node-3'});
326
+ tracker.graph.addNode({type: 0, id: 'some-file-node-4'});
327
+ tracker.graph.addNode({type: 0, id: 'some-file-node-5'});
328
+
329
+ await tracker.writeToCache();
330
+
331
+ // Create a new request tracker that shouldn't look at the old cache files
332
+ tracker = new RequestTracker({farm, options});
333
+ assert.equal(tracker.graph.nodes.length, 0);
334
+
335
+ tracker.graph.addNode({type: 0, id: 'some-file-node-1'});
336
+ await tracker.writeToCache();
337
+
338
+ // Init a request tracker that should only read the relevant cache files
339
+ tracker = await RequestTracker.init({farm, options});
340
+ assert.equal(tracker.graph.nodes.length, 1);
341
+ });
342
+
343
+ it('should init with multiple node chunks', async () => {
344
+ let tracker = new RequestTracker({farm, options});
345
+
346
+ // Set the nodes per blob low so we can ensure multiple files without
347
+ // creating 17,000 nodes
348
+ tracker.graph.nodesPerBlob = 2;
349
+
350
+ tracker.graph.addNode({type: 0, id: 'some-file-node-1'});
351
+ tracker.graph.addNode({type: 0, id: 'some-file-node-2'});
352
+ tracker.graph.addNode({type: 0, id: 'some-file-node-3'});
353
+ tracker.graph.addNode({type: 0, id: 'some-file-node-4'});
354
+ tracker.graph.addNode({type: 0, id: 'some-file-node-5'});
355
+
356
+ await tracker.writeToCache();
357
+
358
+ tracker = await RequestTracker.init({farm, options});
359
+ assert.equal(tracker.graph.nodes.length, 5);
360
+ });
361
+
362
+ it('should write new nodes to cache', async () => {
363
+ let tracker = new RequestTracker({farm, options});
364
+
365
+ tracker.graph.addNode({
366
+ type: 0,
367
+ id: 'test-file',
368
+ });
369
+ await tracker.writeToCache();
370
+ assert.equal(tracker.graph.nodes.length, 1);
371
+
372
+ tracker.graph.addNode({
373
+ type: 0,
374
+ id: 'test-file-2',
375
+ });
376
+ await tracker.writeToCache();
377
+ assert.equal(tracker.graph.nodes.length, 2);
378
+
379
+ // Create a new tracker from cache
380
+ tracker = await RequestTracker.init({farm, options});
381
+
382
+ await tracker.writeToCache();
383
+ assert.equal(tracker.graph.nodes.length, 2);
384
+ });
385
+
386
+ it('should write updated nodes to cache', async () => {
387
+ let tracker = new RequestTracker({farm, options});
388
+
389
+ let contentKey = 'abc';
390
+ await tracker.runRequest({
391
+ id: contentKey,
392
+ type: 7,
393
+ // $FlowFixMe string isn't a valid result
394
+ run: async ({api}: {api: RunAPI<string | void>, ...}) => {
395
+ let result = await Promise.resolve('a');
396
+ api.storeResult(result);
397
+ },
398
+ input: null,
399
+ });
400
+ assert.equal(await tracker.getRequestResult(contentKey), 'a');
401
+ await tracker.writeToCache();
402
+
403
+ await tracker.runRequest(
404
+ {
405
+ id: contentKey,
406
+ type: 7,
407
+ // $FlowFixMe string isn't a valid result
408
+ run: async ({api}: {api: RunAPI<string | void>, ...}) => {
409
+ let result = await Promise.resolve('b');
410
+ api.storeResult(result);
411
+ },
412
+ input: null,
413
+ },
414
+ {force: true},
415
+ );
416
+ assert.equal(await tracker.getRequestResult(contentKey), 'b');
417
+ await tracker.writeToCache();
418
+
419
+ // Create a new tracker from cache
420
+ tracker = await RequestTracker.init({farm, options});
421
+
422
+ assert.equal(await tracker.getRequestResult(contentKey), 'b');
423
+ });
424
+
425
+ it('should write invalidated nodes to cache', async () => {
426
+ let tracker = new RequestTracker({farm, options});
427
+
428
+ let contentKey = 'abc';
429
+ await tracker.runRequest({
430
+ id: contentKey,
431
+ type: 7,
432
+ run: () => {},
433
+ input: null,
434
+ });
435
+ let nodeId = tracker.graph.getNodeIdByContentKey(contentKey);
436
+ assert.equal(tracker.graph.getNode(nodeId)?.invalidateReason, 0);
437
+ await tracker.writeToCache();
438
+
439
+ tracker.graph.invalidateNode(nodeId, 1);
440
+ assert.equal(tracker.graph.getNode(nodeId)?.invalidateReason, 1);
441
+ await tracker.writeToCache();
442
+
443
+ // Create a new tracker from cache
444
+ tracker = await RequestTracker.init({farm, options});
445
+
446
+ assert.equal(tracker.graph.getNode(nodeId)?.invalidateReason, 1);
447
+ });
448
+ });