@atlaspack/core 2.16.2-canary.13 → 2.16.2-canary.130

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 (95) hide show
  1. package/CHANGELOG.md +284 -0
  2. package/index.d.ts +4 -0
  3. package/lib/AssetGraph.js +27 -7
  4. package/lib/Atlaspack.js +35 -27
  5. package/lib/AtlaspackConfig.schema.js +7 -1
  6. package/lib/BundleGraph.js +8 -5
  7. package/lib/Dependency.js +6 -2
  8. package/lib/Environment.js +5 -3
  9. package/lib/EnvironmentManager.js +137 -0
  10. package/lib/InternalConfig.js +3 -2
  11. package/lib/PackagerRunner.js +54 -16
  12. package/lib/RequestTracker.js +345 -132
  13. package/lib/SymbolPropagation.js +14 -0
  14. package/lib/Transformation.js +2 -2
  15. package/lib/UncommittedAsset.js +20 -2
  16. package/lib/applyRuntimes.js +2 -1
  17. package/lib/assetUtils.js +2 -1
  18. package/lib/atlaspack-v3/AtlaspackV3.js +16 -3
  19. package/lib/atlaspack-v3/worker/compat/environment.js +2 -2
  20. package/lib/atlaspack-v3/worker/compat/mutable-asset.js +6 -6
  21. package/lib/atlaspack-v3/worker/compat/plugin-config.js +5 -5
  22. package/lib/atlaspack-v3/worker/index.js +3 -0
  23. package/lib/atlaspack-v3/worker/worker.js +8 -0
  24. package/lib/dumpGraphToGraphViz.js +1 -1
  25. package/lib/index.js +29 -1
  26. package/lib/public/Asset.js +7 -9
  27. package/lib/public/Bundle.js +12 -13
  28. package/lib/public/BundleGraph.js +3 -2
  29. package/lib/public/BundleGroup.js +2 -3
  30. package/lib/public/Config.js +95 -8
  31. package/lib/public/Dependency.js +4 -4
  32. package/lib/public/Environment.js +2 -3
  33. package/lib/public/MutableBundleGraph.js +5 -4
  34. package/lib/public/PluginOptions.js +1 -2
  35. package/lib/public/Target.js +4 -4
  36. package/lib/requests/AssetGraphRequest.js +13 -1
  37. package/lib/requests/AssetGraphRequestRust.js +17 -2
  38. package/lib/requests/AssetRequest.js +2 -1
  39. package/lib/requests/BundleGraphRequest.js +13 -1
  40. package/lib/requests/ConfigRequest.js +27 -4
  41. package/lib/requests/DevDepRequest.js +11 -1
  42. package/lib/requests/PathRequest.js +10 -0
  43. package/lib/requests/TargetRequest.js +18 -16
  44. package/lib/requests/WriteBundleRequest.js +15 -3
  45. package/lib/requests/WriteBundlesRequest.js +22 -1
  46. package/lib/resolveOptions.js +7 -4
  47. package/lib/worker.js +18 -1
  48. package/package.json +18 -25
  49. package/src/AssetGraph.js +30 -7
  50. package/src/Atlaspack.js +40 -23
  51. package/src/BundleGraph.js +13 -8
  52. package/src/Dependency.js +13 -5
  53. package/src/Environment.js +9 -6
  54. package/src/EnvironmentManager.js +145 -0
  55. package/src/InternalConfig.js +6 -5
  56. package/src/PackagerRunner.js +72 -20
  57. package/src/RequestTracker.js +526 -157
  58. package/src/SymbolPropagation.js +13 -1
  59. package/src/UncommittedAsset.js +23 -3
  60. package/src/applyRuntimes.js +6 -1
  61. package/src/assetUtils.js +4 -3
  62. package/src/atlaspack-v3/AtlaspackV3.js +24 -3
  63. package/src/atlaspack-v3/worker/compat/plugin-config.js +9 -5
  64. package/src/atlaspack-v3/worker/index.js +2 -1
  65. package/src/atlaspack-v3/worker/worker.js +7 -0
  66. package/src/index.js +5 -1
  67. package/src/public/Asset.js +13 -6
  68. package/src/public/Bundle.js +12 -11
  69. package/src/public/BundleGraph.js +10 -2
  70. package/src/public/BundleGroup.js +2 -2
  71. package/src/public/Config.js +132 -18
  72. package/src/public/Dependency.js +4 -3
  73. package/src/public/Environment.js +2 -2
  74. package/src/public/MutableBundleGraph.js +8 -5
  75. package/src/public/PluginOptions.js +1 -1
  76. package/src/public/Target.js +4 -3
  77. package/src/requests/AssetGraphRequest.js +13 -3
  78. package/src/requests/AssetGraphRequestRust.js +14 -2
  79. package/src/requests/AssetRequest.js +2 -1
  80. package/src/requests/BundleGraphRequest.js +13 -3
  81. package/src/requests/ConfigRequest.js +33 -9
  82. package/src/requests/DevDepRequest.js +22 -9
  83. package/src/requests/PathRequest.js +4 -0
  84. package/src/requests/TargetRequest.js +19 -25
  85. package/src/requests/WriteBundleRequest.js +14 -8
  86. package/src/requests/WriteBundlesRequest.js +31 -3
  87. package/src/resolveOptions.js +4 -2
  88. package/src/types.js +10 -7
  89. package/test/Environment.test.js +43 -34
  90. package/test/EnvironmentManager.test.js +192 -0
  91. package/test/PublicEnvironment.test.js +10 -7
  92. package/test/RequestTracker.test.js +124 -29
  93. package/test/public/Config.test.js +108 -0
  94. package/test/requests/ConfigRequest.test.js +199 -7
  95. package/test/test-utils.js +4 -9
package/src/types.js CHANGED
@@ -34,6 +34,7 @@ import type {ProjectPath} from './projectPath';
34
34
  import type {Event} from '@parcel/watcher';
35
35
  import type {FeatureFlags} from '@atlaspack/feature-flags';
36
36
  import type {BackendType} from '@parcel/watcher';
37
+ import type {EnvironmentRef} from './EnvironmentManager';
37
38
 
38
39
  export type AtlaspackPluginNode = {|
39
40
  packageName: PackageName,
@@ -97,7 +98,7 @@ export type InternalSourceLocation = {|
97
98
  export type Target = {|
98
99
  distEntry?: ?FilePath,
99
100
  distDir: ProjectPath,
100
- env: Environment,
101
+ env: EnvironmentRef,
101
102
  name: string,
102
103
  publicUrl: string,
103
104
  loc?: ?InternalSourceLocation,
@@ -139,11 +140,12 @@ export type Dependency = {|
139
140
  isEntry: boolean,
140
141
  isOptional: boolean,
141
142
  loc: ?InternalSourceLocation,
142
- env: Environment,
143
+ env: EnvironmentRef,
143
144
  packageConditions?: number,
144
145
  customPackageConditions?: Array<string>,
145
146
  meta: Meta,
146
147
  resolverMeta?: ?Meta,
148
+ resolverPriority?: $Values<typeof Priority>,
147
149
  target: ?Target,
148
150
  sourceAssetId: ?string,
149
151
  sourcePath: ?ProjectPath,
@@ -180,7 +182,7 @@ export type Asset = {|
180
182
  bundleBehavior: ?$Values<typeof BundleBehavior>,
181
183
  isBundleSplittable: boolean,
182
184
  isSource: boolean,
183
- env: Environment,
185
+ env: EnvironmentRef,
184
186
  meta: Meta,
185
187
  stats: Stats,
186
188
  contentKey: ?string,
@@ -388,7 +390,7 @@ export type RootNode = {|id: ContentKey, +type: 'root', value: string | null|};
388
390
  export type AssetRequestInput = {|
389
391
  name?: string, // AssetGraph name, needed so that different graphs can isolated requests since the results are not stored
390
392
  filePath: ProjectPath,
391
- env: Environment,
393
+ env: EnvironmentRef,
392
394
  isSource?: boolean,
393
395
  canDefer?: boolean,
394
396
  sideEffects?: boolean,
@@ -492,13 +494,13 @@ export type Config = {|
492
494
  id: string,
493
495
  isSource: boolean,
494
496
  searchPath: ProjectPath,
495
- env: Environment,
497
+ env: EnvironmentRef,
496
498
  cacheKey: ?string,
497
499
  result: ConfigResult,
498
500
  invalidateOnFileChange: Set<ProjectPath>,
499
501
  invalidateOnConfigKeyChange: Array<{|
500
502
  filePath: ProjectPath,
501
- configKey: string,
503
+ configKey: string[],
502
504
  |}>,
503
505
  invalidateOnFileCreate: Array<InternalFileCreateInvalidation>,
504
506
  invalidateOnEnvChange: Set<string>,
@@ -539,7 +541,7 @@ export type Bundle = {|
539
541
  publicId: ?string,
540
542
  hashReference: string,
541
543
  type: string,
542
- env: Environment,
544
+ env: EnvironmentRef,
543
545
  entryAssetIds: Array<ContentKey>,
544
546
  mainEntryId: ?ContentKey,
545
547
  needsStableName: ?boolean,
@@ -573,6 +575,7 @@ export type BundleGroupNode = {|
573
575
 
574
576
  export type PackagedBundleInfo = {|
575
577
  filePath: ProjectPath,
578
+ bundleId: ContentKey,
576
579
  type: string,
577
580
  stats: Stats,
578
581
  |};
@@ -5,10 +5,11 @@ import assert from 'assert';
5
5
  import expect from 'expect';
6
6
  import {createEnvironment} from '../src/Environment';
7
7
  import {initializeMonitoring} from '../../rust';
8
+ import {fromEnvironmentId} from '../src/EnvironmentManager';
8
9
 
9
10
  describe('Environment', () => {
10
11
  it('assigns a default environment with nothing passed', () => {
11
- assert.deepEqual(createEnvironment(), {
12
+ assert.deepEqual(fromEnvironmentId(createEnvironment()), {
12
13
  id: 'd821e85f6b50315e',
13
14
  context: 'browser',
14
15
  engines: {
@@ -27,27 +28,32 @@ describe('Environment', () => {
27
28
  });
28
29
 
29
30
  it('assigns a node context if a node engine is given', () => {
30
- assert.deepEqual(createEnvironment({engines: {node: '>= 10.0.0'}}), {
31
- id: '2320af923a717577',
32
- context: 'node',
33
- engines: {
34
- node: '>= 10.0.0',
31
+ assert.deepEqual(
32
+ fromEnvironmentId(createEnvironment({engines: {node: '>= 10.0.0'}})),
33
+ {
34
+ id: '2320af923a717577',
35
+ context: 'node',
36
+ engines: {
37
+ node: '>= 10.0.0',
38
+ },
39
+ includeNodeModules: false,
40
+ outputFormat: 'commonjs',
41
+ isLibrary: false,
42
+ shouldOptimize: false,
43
+ shouldScopeHoist: false,
44
+ sourceMap: undefined,
45
+ loc: undefined,
46
+ sourceType: 'module',
47
+ unstableSingleFileOutput: false,
35
48
  },
36
- includeNodeModules: false,
37
- outputFormat: 'commonjs',
38
- isLibrary: false,
39
- shouldOptimize: false,
40
- shouldScopeHoist: false,
41
- sourceMap: undefined,
42
- loc: undefined,
43
- sourceType: 'module',
44
- unstableSingleFileOutput: false,
45
- });
49
+ );
46
50
  });
47
51
 
48
52
  it('assigns a browser context if browser engines are given', () => {
49
53
  assert.deepEqual(
50
- createEnvironment({engines: {browsers: ['last 1 version']}}),
54
+ fromEnvironmentId(
55
+ createEnvironment({engines: {browsers: ['last 1 version']}}),
56
+ ),
51
57
  {
52
58
  id: '75603271034eff15',
53
59
  context: 'browser',
@@ -68,7 +74,7 @@ describe('Environment', () => {
68
74
  });
69
75
 
70
76
  it('assigns default engines for node', () => {
71
- assert.deepEqual(createEnvironment({context: 'node'}), {
77
+ assert.deepEqual(fromEnvironmentId(createEnvironment({context: 'node'})), {
72
78
  id: 'e45cc12216f7857d',
73
79
  context: 'node',
74
80
  engines: {
@@ -87,22 +93,25 @@ describe('Environment', () => {
87
93
  });
88
94
 
89
95
  it('assigns default engines for browsers', () => {
90
- assert.deepEqual(createEnvironment({context: 'browser'}), {
91
- id: 'd821e85f6b50315e',
92
- context: 'browser',
93
- engines: {
94
- browsers: ['> 0.25%'],
96
+ assert.deepEqual(
97
+ fromEnvironmentId(createEnvironment({context: 'browser'})),
98
+ {
99
+ id: 'd821e85f6b50315e',
100
+ context: 'browser',
101
+ engines: {
102
+ browsers: ['> 0.25%'],
103
+ },
104
+ includeNodeModules: true,
105
+ outputFormat: 'global',
106
+ isLibrary: false,
107
+ shouldOptimize: false,
108
+ shouldScopeHoist: false,
109
+ sourceMap: undefined,
110
+ loc: undefined,
111
+ sourceType: 'module',
112
+ unstableSingleFileOutput: false,
95
113
  },
96
- includeNodeModules: true,
97
- outputFormat: 'global',
98
- isLibrary: false,
99
- shouldOptimize: false,
100
- shouldScopeHoist: false,
101
- sourceMap: undefined,
102
- loc: undefined,
103
- sourceType: 'module',
104
- unstableSingleFileOutput: false,
105
- });
114
+ );
106
115
  });
107
116
  });
108
117
 
@@ -114,6 +123,6 @@ describe('createEnvironment', function () {
114
123
  /* ignore */
115
124
  }
116
125
  const environment = createEnvironment({});
117
- expect(environment.id).toEqual('d821e85f6b50315e');
126
+ expect(fromEnvironmentId(environment).id).toEqual('d821e85f6b50315e');
118
127
  });
119
128
  });
@@ -0,0 +1,192 @@
1
+ // @flow strict-local
2
+
3
+ import assert from 'assert';
4
+ import nullthrows from 'nullthrows';
5
+ import sinon from 'sinon';
6
+ import {ATLASPACK_VERSION} from '../src/constants';
7
+ import {DEFAULT_FEATURE_FLAGS, setFeatureFlags} from '@atlaspack/feature-flags';
8
+ import {setAllEnvironments, getAllEnvironments} from '@atlaspack/rust';
9
+ import {
10
+ loadEnvironmentsFromCache,
11
+ writeEnvironmentsToCache,
12
+ } from '../src/EnvironmentManager';
13
+ import {DEFAULT_OPTIONS} from './test-utils';
14
+ import {LMDBLiteCache} from '@atlaspack/cache';
15
+
16
+ const options = {
17
+ ...DEFAULT_OPTIONS,
18
+ cache: new LMDBLiteCache(DEFAULT_OPTIONS.cacheDir),
19
+ };
20
+
21
+ describe('EnvironmentManager', () => {
22
+ const env1 = {
23
+ id: 'd821e85f6b50315e',
24
+ context: 'browser',
25
+ engines: {browsers: ['> 0.25%']},
26
+ includeNodeModules: true,
27
+ outputFormat: 'global',
28
+ isLibrary: false,
29
+ shouldOptimize: false,
30
+ shouldScopeHoist: false,
31
+ loc: undefined,
32
+ sourceMap: undefined,
33
+ sourceType: 'module',
34
+ unstableSingleFileOutput: false,
35
+ };
36
+ const env2 = {
37
+ id: 'de92f48baa8448d2',
38
+ context: 'node',
39
+ engines: {
40
+ browsers: [],
41
+ node: '>= 8',
42
+ },
43
+ includeNodeModules: false,
44
+ outputFormat: 'commonjs',
45
+ isLibrary: true,
46
+ shouldOptimize: true,
47
+ shouldScopeHoist: true,
48
+ loc: null,
49
+ sourceMap: null,
50
+ sourceType: 'module',
51
+ unstableSingleFileOutput: false,
52
+ };
53
+
54
+ beforeEach(async () => {
55
+ await options.cache.ensure();
56
+
57
+ for (const key of options.cache.keys()) {
58
+ await options.cache.getNativeRef().delete(key);
59
+ }
60
+ setAllEnvironments([]);
61
+
62
+ setFeatureFlags({
63
+ ...DEFAULT_FEATURE_FLAGS,
64
+ environmentDeduplication: true,
65
+ });
66
+ });
67
+
68
+ it('should store environments by ID in the cache', async () => {
69
+ setAllEnvironments([env1]);
70
+ await writeEnvironmentsToCache(options.cache);
71
+
72
+ const cachedEnv1 = await options.cache.get(
73
+ `Environment/${ATLASPACK_VERSION}/${env1.id}`,
74
+ );
75
+ assert.deepEqual(cachedEnv1, env1, 'Environment 1 should be cached');
76
+ });
77
+
78
+ it('should list all environment IDs in the environment manager', async () => {
79
+ const environmentIds = [env1.id, env2.id];
80
+ setAllEnvironments([env1, env2]);
81
+ await writeEnvironmentsToCache(options.cache);
82
+
83
+ const cachedEnvIds = await options.cache.get(
84
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
85
+ );
86
+ const cachedIdsArray = nullthrows(cachedEnvIds);
87
+ assert.equal(
88
+ cachedIdsArray.length,
89
+ environmentIds.length,
90
+ 'Should have same number of IDs',
91
+ );
92
+ assert(
93
+ environmentIds.every((id) => cachedIdsArray.includes(id)),
94
+ 'All environment IDs should be present in cache',
95
+ );
96
+ });
97
+
98
+ it('should write all environments to cache using writeEnvironmentsToCache', async () => {
99
+ setAllEnvironments([env1, env2]);
100
+ await writeEnvironmentsToCache(options.cache);
101
+
102
+ // Verify each environment was stored individually
103
+ const cachedEnv1 = await options.cache.get(
104
+ `Environment/${ATLASPACK_VERSION}/${env1.id}`,
105
+ );
106
+ const cachedEnv2 = await options.cache.get(
107
+ `Environment/${ATLASPACK_VERSION}/${env2.id}`,
108
+ );
109
+ assert.deepEqual(cachedEnv1, env1, 'Environment 1 should be cached');
110
+ assert.deepEqual(cachedEnv2, env2, 'Environment 2 should be cached');
111
+
112
+ // Verify environment IDs were stored in manager
113
+ const cachedEnvIds = await options.cache.get(
114
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
115
+ );
116
+ const cachedIdsArray = nullthrows(cachedEnvIds);
117
+ assert(
118
+ cachedIdsArray.length === 2 &&
119
+ [env1.id, env2.id].every((id) => cachedIdsArray.includes(id)),
120
+ 'Environment IDs should be stored in manager',
121
+ );
122
+ });
123
+
124
+ it('should load environments from cache on loadRequestGraph on a subsequent build', async () => {
125
+ // Simulate cache written on a first build
126
+ setAllEnvironments([env1, env2]);
127
+ await writeEnvironmentsToCache(options.cache);
128
+
129
+ await loadEnvironmentsFromCache(options.cache);
130
+
131
+ const loadedEnvironments = getAllEnvironments();
132
+ assert.equal(
133
+ loadedEnvironments.length,
134
+ 2,
135
+ 'Should load 2 environments from cache',
136
+ );
137
+
138
+ const env1Loaded = loadedEnvironments.find((e) => e.id === env1.id);
139
+ const env2Loaded = loadedEnvironments.find((e) => e.id === env2.id);
140
+
141
+ assert.deepEqual(
142
+ env1Loaded,
143
+ env1,
144
+ 'First environment should match cached environment',
145
+ );
146
+ assert.deepEqual(
147
+ env2Loaded,
148
+ env2,
149
+ 'Second environment should match cached environment',
150
+ );
151
+ });
152
+
153
+ it('should handle empty cache gracefully without calling setAllEnvironments', async () => {
154
+ const setAllEnvironmentsSpy = sinon.spy(setAllEnvironments);
155
+
156
+ await assert.doesNotReject(
157
+ loadEnvironmentsFromCache(options.cache),
158
+ 'loadEnvironmentsFromCache should not throw when cache is empty',
159
+ );
160
+
161
+ assert.equal(
162
+ setAllEnvironmentsSpy.callCount,
163
+ 0,
164
+ 'setAllEnvironments should not be called when loading from empty cache',
165
+ );
166
+ });
167
+
168
+ it('should not load environments from a different version', async () => {
169
+ const setAllEnvironmentsSpy = sinon.spy(setAllEnvironments);
170
+ const differentVersion = '2.17.2'; // A different version than ATLASPACK_VERSION
171
+
172
+ // Store an environment with a different version
173
+ await options.cache.set(`Environment/${differentVersion}/${env1.id}`, env1);
174
+ await options.cache.set(`EnvironmentManager/${differentVersion}`, [
175
+ env1.id,
176
+ ]);
177
+
178
+ await loadEnvironmentsFromCache(options.cache);
179
+
180
+ assert.equal(
181
+ setAllEnvironmentsSpy.callCount,
182
+ 0,
183
+ 'setAllEnvironments should not be called when loading from different version',
184
+ );
185
+ const loadedEnvironments = getAllEnvironments();
186
+ assert.equal(
187
+ loadedEnvironments.length,
188
+ 0,
189
+ 'Should not load any environments from different version',
190
+ );
191
+ });
192
+ });
@@ -2,19 +2,22 @@
2
2
 
3
3
  import assert from 'assert';
4
4
  import {createEnvironment} from '../src/Environment';
5
+ import {fromEnvironmentId} from '../src/EnvironmentManager';
5
6
  import PublicEnvironment from '../src/public/Environment';
6
7
  import {DEFAULT_OPTIONS} from './test-utils';
7
8
 
8
9
  describe('Public Environment', () => {
9
10
  it('has correct support data for ChromeAndroid', () => {
10
11
  let env = new PublicEnvironment(
11
- createEnvironment({
12
- context: 'browser',
13
- engines: {
14
- browsers: ['last 1 Chrome version', 'last 1 ChromeAndroid version'],
15
- },
16
- outputFormat: 'esmodule',
17
- }),
12
+ fromEnvironmentId(
13
+ createEnvironment({
14
+ context: 'browser',
15
+ engines: {
16
+ browsers: ['last 1 Chrome version', 'last 1 ChromeAndroid version'],
17
+ },
18
+ outputFormat: 'esmodule',
19
+ }),
20
+ ),
18
21
  DEFAULT_OPTIONS,
19
22
  );
20
23
 
@@ -5,19 +5,44 @@ import nullthrows from 'nullthrows';
5
5
  import RequestTracker, {
6
6
  type RunAPI,
7
7
  cleanUpOrphans,
8
+ runInvalidation,
9
+ getBiggestFSEventsInvalidations,
10
+ invalidateRequestGraphFSEvents,
8
11
  } from '../src/RequestTracker';
9
12
  import {Graph} from '@atlaspack/graph';
13
+ import {LMDBLiteCache} from '@atlaspack/cache';
10
14
  import WorkerFarm from '@atlaspack/workers';
11
15
  import {DEFAULT_OPTIONS} from './test-utils';
12
16
  import {FILE_CREATE, FILE_UPDATE, INITIAL_BUILD} from '../src/constants';
13
17
  import {makeDeferredWithPromise} from '@atlaspack/utils';
14
18
  import {toProjectPath} from '../src/projectPath';
15
19
  import {DEFAULT_FEATURE_FLAGS, setFeatureFlags} from '../../feature-flags/src';
20
+ import sinon from 'sinon';
21
+ import type {AtlaspackOptions} from '../src/types';
16
22
 
17
- const options = DEFAULT_OPTIONS;
18
- const farm = new WorkerFarm({workerPath: require.resolve('../src/worker')});
23
+ const options = {
24
+ ...DEFAULT_OPTIONS,
25
+ cache: new LMDBLiteCache(DEFAULT_OPTIONS.cacheDir),
26
+ };
19
27
 
20
28
  describe('RequestTracker', () => {
29
+ let farm;
30
+ before(() => {
31
+ farm = new WorkerFarm({workerPath: require.resolve('../src/worker')});
32
+ });
33
+
34
+ beforeEach(async () => {
35
+ await options.cache.ensure();
36
+
37
+ for (const key of options.cache.keys()) {
38
+ await options.cache.getNativeRef().delete(key);
39
+ }
40
+ });
41
+
42
+ after(() => {
43
+ farm.end();
44
+ });
45
+
21
46
  it('should not run requests that have not been invalidated', async () => {
22
47
  let tracker = new RequestTracker({farm, options});
23
48
  await tracker.runRequest({
@@ -166,31 +191,6 @@ describe('RequestTracker', () => {
166
191
  assert(result === 'hello');
167
192
  });
168
193
 
169
- it('should reject all in progress requests when the abort controller aborts', async () => {
170
- let tracker = new RequestTracker({farm, options});
171
- let p = tracker
172
- .runRequest({
173
- id: 'abc',
174
- type: 7,
175
- run: async () => {
176
- await Promise.resolve('hello');
177
- },
178
- input: null,
179
- })
180
- .then(null, () => {
181
- /* do nothing */
182
- });
183
- // $FlowFixMe
184
- tracker.setSignal({aborted: true});
185
- await p;
186
- assert(
187
- tracker
188
- .getInvalidRequests()
189
- .map((req) => req.id)
190
- .includes('abc'),
191
- );
192
- });
193
-
194
194
  it('should write cache to disk and store index', async () => {
195
195
  let tracker = new RequestTracker({farm, options});
196
196
 
@@ -482,7 +482,7 @@ describe('RequestTracker', () => {
482
482
  input: null,
483
483
  });
484
484
  const requestId = tracker.graph.getNodeIdByContentKey('abc');
485
- const invalidated = await tracker.respondToFSEvents(
485
+ const {didInvalidate: invalidated} = await tracker.respondToFSEvents(
486
486
  [
487
487
  {
488
488
  type: 'update',
@@ -521,7 +521,7 @@ describe('RequestTracker', () => {
521
521
  input: null,
522
522
  });
523
523
  const requestId = tracker.graph.getNodeIdByContentKey('abc');
524
- const invalidated = await tracker.respondToFSEvents(
524
+ const {didInvalidate: invalidated} = await tracker.respondToFSEvents(
525
525
  [
526
526
  {
527
527
  type: 'create',
@@ -584,3 +584,98 @@ root --- node1 --- node2 ----------- orphan1 --- orphan2
584
584
  assert.equal(Array.from(graph.getAllEdges()).length, 3);
585
585
  });
586
586
  });
587
+
588
+ describe('runInvalidation', () => {
589
+ it('calls an invalidationFn and tracks the number of invalidated nodes', async () => {
590
+ const mockRequestTracker = {
591
+ getInvalidNodeCount: sinon.stub(),
592
+ };
593
+
594
+ mockRequestTracker.getInvalidNodeCount.returns(10000);
595
+ const result = await runInvalidation(mockRequestTracker, {
596
+ key: 'fsEvents',
597
+ fn: () => {
598
+ mockRequestTracker.getInvalidNodeCount.returns(30000);
599
+ return {
600
+ biggestInvalidations: [{path: 'my-file', count: 10000}],
601
+ };
602
+ },
603
+ });
604
+
605
+ assert.equal(result.key, 'fsEvents');
606
+ assert.equal(result.count, 20000);
607
+ assert.deepEqual(result.detail, {
608
+ biggestInvalidations: [{path: 'my-file', count: 10000}],
609
+ });
610
+ assert(result.duration > 0, 'Duration was not reported');
611
+ });
612
+ });
613
+
614
+ describe('invalidateRequestGraphFSEvents', () => {
615
+ it('calls requestGraph.respondToFSEvents and returns the biggest invalidations', async () => {
616
+ const requestGraph = {
617
+ respondToFSEvents: sinon.stub(),
618
+ };
619
+
620
+ requestGraph.respondToFSEvents.returns({
621
+ invalidationsByPath: new Map([
622
+ ['file-1', 10],
623
+ ['file-2', 5000],
624
+ ['file-3', 8000],
625
+ ]),
626
+ });
627
+ // $FlowFixMe
628
+ const options: AtlaspackOptions = {
629
+ unstableFileInvalidations: undefined,
630
+ };
631
+
632
+ const result = await invalidateRequestGraphFSEvents(requestGraph, options, [
633
+ {
634
+ path: 'file-1',
635
+ type: 'create',
636
+ },
637
+ {
638
+ path: 'file-2',
639
+ type: 'update',
640
+ },
641
+ {
642
+ path: 'file-3',
643
+ type: 'delete',
644
+ },
645
+ ]);
646
+
647
+ assert.deepEqual(result.biggestInvalidations, [
648
+ {path: 'file-3', count: 8000},
649
+ {path: 'file-2', count: 5000},
650
+ {path: 'file-1', count: 10},
651
+ ]);
652
+ assert.equal(requestGraph.respondToFSEvents.callCount, 1);
653
+ assert.deepEqual(requestGraph.respondToFSEvents.args[0], [
654
+ [
655
+ {path: 'file-1', type: 'create'},
656
+ {path: 'file-2', type: 'update'},
657
+ {path: 'file-3', type: 'delete'},
658
+ ],
659
+ options,
660
+ 10000,
661
+ true,
662
+ ]);
663
+ });
664
+ });
665
+
666
+ describe('getBiggestFSEventsInvalidations', () => {
667
+ it('returns the paths that invalidated the most nodes', () => {
668
+ const invalidationsByPath = new Map([
669
+ ['file-1', 10],
670
+ ['file-2', 5000],
671
+ ['file-3', 8000],
672
+ ['file-4', 1000],
673
+ ['file-5', 1000],
674
+ ]);
675
+
676
+ assert.deepEqual(getBiggestFSEventsInvalidations(invalidationsByPath, 2), [
677
+ {path: 'file-3', count: 8000},
678
+ {path: 'file-2', count: 5000},
679
+ ]);
680
+ });
681
+ });