metro 0.70.3 → 0.71.0

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 (67) hide show
  1. package/package.json +20 -20
  2. package/src/Assets.js.flow +4 -4
  3. package/src/Bundler/util.js +1 -1
  4. package/src/Bundler/util.js.flow +2 -2
  5. package/src/Bundler.js +17 -10
  6. package/src/Bundler.js.flow +19 -14
  7. package/src/DeltaBundler/DeltaCalculator.js +13 -17
  8. package/src/DeltaBundler/DeltaCalculator.js.flow +15 -20
  9. package/src/DeltaBundler/Serializers/getAllFiles.js.flow +2 -2
  10. package/src/DeltaBundler/Serializers/getAssets.js.flow +2 -2
  11. package/src/DeltaBundler/Serializers/getExplodedSourceMap.js.flow +4 -4
  12. package/src/DeltaBundler/Serializers/getRamBundleInfo.js.flow +6 -6
  13. package/src/DeltaBundler/Serializers/helpers/getSourceMapInfo.js.flow +4 -4
  14. package/src/DeltaBundler/Serializers/helpers/processBytecodeModules.js.flow +2 -2
  15. package/src/DeltaBundler/Serializers/helpers/processModules.js.flow +2 -2
  16. package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +2 -2
  17. package/src/DeltaBundler/Serializers/sourceMapGenerator.js.flow +6 -6
  18. package/src/DeltaBundler/Serializers/sourceMapObject.js.flow +4 -4
  19. package/src/DeltaBundler/Serializers/sourceMapString.js.flow +2 -2
  20. package/src/DeltaBundler/Worker.js.flow +4 -4
  21. package/src/DeltaBundler/WorkerFarm.js.flow +4 -4
  22. package/src/DeltaBundler/getTransformCacheKey.js.flow +2 -2
  23. package/src/DeltaBundler/{traverseDependencies.js → graphOperations.js} +43 -32
  24. package/src/DeltaBundler/{traverseDependencies.js.flow → graphOperations.js.flow} +52 -37
  25. package/src/DeltaBundler/types.flow.js.flow +36 -30
  26. package/src/DeltaBundler.js +14 -6
  27. package/src/DeltaBundler.js.flow +14 -10
  28. package/src/HmrServer.js.flow +6 -6
  29. package/src/IncrementalBundler.js +1 -1
  30. package/src/IncrementalBundler.js.flow +8 -8
  31. package/src/ModuleGraph/node-haste/ModuleCache.js +1 -1
  32. package/src/ModuleGraph/node-haste/ModuleCache.js.flow +1 -1
  33. package/src/ModuleGraph/node-haste/node-haste.flow.js.flow +2 -2
  34. package/src/ModuleGraph/node-haste/node-haste.js +4 -4
  35. package/src/ModuleGraph/node-haste/node-haste.js.flow +13 -7
  36. package/src/ModuleGraph/output/indexed-ram-bundle.js.flow +2 -2
  37. package/src/ModuleGraph/output/plain-bundle.js.flow +2 -2
  38. package/src/ModuleGraph/output/reverse-dependency-map-references.js.flow +8 -8
  39. package/src/ModuleGraph/output/util.js.flow +2 -2
  40. package/src/ModuleGraph/types.flow.js.flow +37 -37
  41. package/src/ModuleGraph/worker/collectDependencies.js.flow +2 -2
  42. package/src/Server/symbolicate.js.flow +1 -1
  43. package/src/Server.js.flow +18 -18
  44. package/src/commands/build.js.flow +2 -2
  45. package/src/commands/serve.js.flow +2 -2
  46. package/src/index.js +32 -18
  47. package/src/index.js.flow +42 -32
  48. package/src/lib/bundleToBytecode.js.flow +2 -2
  49. package/src/lib/bundleToString.js.flow +2 -2
  50. package/src/lib/getPreludeCode.js.flow +2 -2
  51. package/src/lib/transformHelpers.js.flow +2 -2
  52. package/src/node-haste/DependencyGraph/ModuleResolution.js +2 -1
  53. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +5 -12
  54. package/src/node-haste/DependencyGraph/createHasteMap.js +9 -7
  55. package/src/node-haste/DependencyGraph/createHasteMap.js.flow +6 -9
  56. package/src/node-haste/DependencyGraph.js +31 -27
  57. package/src/node-haste/DependencyGraph.js.flow +43 -37
  58. package/src/node-haste/ModuleCache.js.flow +1 -1
  59. package/src/node-haste/lib/AssetPaths.js.flow +2 -2
  60. package/src/node-haste/lib/parsePlatformFilePath.js.flow +2 -2
  61. package/src/shared/output/RamBundle/as-indexed-file.js.flow +1 -1
  62. package/src/shared/output/RamBundle/buildSourcemapWithMetadata.js.flow +2 -2
  63. package/src/shared/types.flow.js.flow +14 -14
  64. package/src/DeltaBundler/computeDelta.js +0 -42
  65. package/src/DeltaBundler/computeDelta.js.flow +0 -47
  66. package/src/node-haste/DependencyGraph/types.js +0 -10
  67. package/src/node-haste/DependencyGraph/types.js.flow +0 -88
@@ -18,17 +18,17 @@ import type {Readable} from 'stream';
18
18
  const {Worker: JestWorker} = require('jest-worker');
19
19
  const {Logger} = require('metro-core');
20
20
 
21
- type WorkerInterface = {|
21
+ type WorkerInterface = {
22
22
  getStdout(): Readable,
23
23
  getStderr(): Readable,
24
24
  end(): void,
25
25
  ...Worker,
26
- |};
26
+ };
27
27
 
28
- type TransformerResult = $ReadOnly<{|
28
+ type TransformerResult = $ReadOnly<{
29
29
  result: TransformResult<>,
30
30
  sha1: string,
31
- |}>;
31
+ }>;
32
32
 
33
33
  class WorkerFarm {
34
34
  _config: ConfigT;
@@ -21,11 +21,11 @@ type CacheKeyProvider = {
21
21
  getCacheKey?: JsTransformerConfig => string,
22
22
  };
23
23
 
24
- function getTransformCacheKey(opts: {|
24
+ function getTransformCacheKey(opts: {
25
25
  +cacheVersion: string,
26
26
  +projectRoot: string,
27
27
  +transformerConfig: TransformerConfig,
28
- |}): string {
28
+ }): string {
29
29
  const {transformerPath, transformerConfig} = opts.transformerConfig;
30
30
 
31
31
  // eslint-disable-next-line no-useless-call
@@ -9,7 +9,16 @@
9
9
  */
10
10
  "use strict";
11
11
 
12
- const nullthrows = require("nullthrows");
12
+ const nullthrows = require("nullthrows"); // Private state for the graph that persists between operations.
13
+
14
+ function createGraph(options) {
15
+ return {
16
+ ...options,
17
+ dependencies: new Map(),
18
+ importBundleNames: new Set(),
19
+ privateState: {},
20
+ };
21
+ }
13
22
 
14
23
  function getInternalOptions({
15
24
  transform,
@@ -51,10 +60,7 @@ async function traverseDependencies(paths, graph, options) {
51
60
  const internalOptions = getInternalOptions(options);
52
61
 
53
62
  for (const path of paths) {
54
- // Only process the path if it's part of the dependency graph. It's possible
55
- // that this method receives a path that is no longer part of it (e.g if a
56
- // module gets removed from the dependency graph and just afterwards it gets
57
- // modified), and we have to ignore these cases.
63
+ // Start traversing from modules that are already part of the dependency graph.
58
64
  if (graph.dependencies.get(path)) {
59
65
  delta.modified.add(path);
60
66
  await traverseDependenciesForSingleFile(
@@ -67,30 +73,15 @@ async function traverseDependencies(paths, graph, options) {
67
73
  }
68
74
 
69
75
  const added = new Map();
70
- const modified = new Map();
71
- const deleted = new Set();
72
-
73
- for (const path of delta.deleted) {
74
- // If a dependency has been marked both as added and deleted, it means that
75
- // this is a renamed file (or that dependency has been removed from one path
76
- // but added back in a different path). In this case the addition and
77
- // deletion "get cancelled".
78
- if (!delta.added.has(path)) {
79
- deleted.add(path);
80
- }
81
-
82
- delta.modified.delete(path);
83
- delta.added.delete(path);
84
- }
85
76
 
86
77
  for (const path of delta.added) {
87
78
  added.set(path, nullthrows(graph.dependencies.get(path)));
88
79
  }
89
80
 
81
+ const modified = new Map();
82
+
90
83
  for (const path of delta.modified) {
91
- // Similarly to the above, a file can be marked as both added and modified
92
- // when its path and dependencies have changed. In this case, we only
93
- // consider the addition.
84
+ // Only report a module as modified if we're not already reporting it as added.
94
85
  if (!delta.added.has(path)) {
95
86
  modified.set(path, nullthrows(graph.dependencies.get(path)));
96
87
  }
@@ -99,7 +90,7 @@ async function traverseDependencies(paths, graph, options) {
99
90
  return {
100
91
  added,
101
92
  modified,
102
- deleted,
93
+ deleted: delta.deleted,
103
94
  };
104
95
  }
105
96
 
@@ -112,7 +103,7 @@ async function initialTraverseDependencies(graph, options) {
112
103
  };
113
104
  const internalOptions = getInternalOptions(options);
114
105
  await Promise.all(
115
- graph.entryPoints.map((path) =>
106
+ [...graph.entryPoints].map((path) =>
116
107
  traverseDependenciesForSingleFile(path, graph, delta, internalOptions)
117
108
  )
118
109
  );
@@ -134,6 +125,7 @@ async function traverseDependenciesForSingleFile(path, graph, delta, options) {
134
125
 
135
126
  async function processModule(path, graph, delta, options) {
136
127
  // Transform the file via the given option.
128
+ // TODO: Unbind the transform method from options
137
129
  const result = await options.transform(path); // Get the absolute path of all sub-dependencies (some of them could have been
138
130
  // moved but maintain the same relative path).
139
131
 
@@ -224,7 +216,15 @@ async function addDependency(parentModule, path, graph, delta, options) {
224
216
  return;
225
217
  }
226
218
 
227
- delta.added.add(path);
219
+ if (delta.deleted.has(path)) {
220
+ // Mark the addition by clearing a prior deletion.
221
+ delta.deleted.delete(path);
222
+ } else {
223
+ // Mark the addition in the added set.
224
+ delta.added.add(path);
225
+ delta.modified.delete(path);
226
+ }
227
+
228
228
  delta.inverseDependencies.set(path, new Set([parentModule.path]));
229
229
  options.onDependencyAdd();
230
230
  const module = await processModule(path, graph, delta, options);
@@ -305,7 +305,7 @@ function canSafelyRemoveFromParentModule(
305
305
 
306
306
  const undeletedInverseDependencies = Array.from(
307
307
  topInverseDependencies
308
- ).filter((x) => !delta.deleted.has(x));
308
+ ).filter((x) => graph.dependencies.has(x));
309
309
  /**
310
310
  * We can only mark the `visited` Set of modules to be safely removable if
311
311
  * 1. We do not have top a level module to compare with parentModule.
@@ -362,14 +362,26 @@ function removeDependency(
362
362
  }
363
363
  }
364
364
 
365
- delta.deleted.add(module.path); // Now we need to iterate through the module dependencies in order to
365
+ if (delta.added.has(module.path)) {
366
+ // Mark the deletion by clearing a prior addition.
367
+ delta.added.delete(module.path);
368
+ } else {
369
+ // Mark the deletion in the deleted set.
370
+ delta.deleted.add(module.path);
371
+ delta.modified.delete(module.path);
372
+ } // This module is not used anywhere else! We can clear it from the bundle.
373
+ // Clean up all the state associated with this module in order to correctly
374
+ // re-add it if we encounter it again.
375
+
376
+ graph.dependencies.delete(module.path);
377
+ delta.inverseDependencies.delete(module.path); // Now we need to iterate through the module dependencies in order to
366
378
  // clean up everything (we cannot read the module because it may have
367
379
  // been deleted).
368
380
 
369
381
  Array.from(module.dependencies.values())
370
382
  .filter(
371
383
  (dependency) =>
372
- !delta.deleted.has(dependency.absolutePath) &&
384
+ graph.dependencies.has(dependency.absolutePath) &&
373
385
  dependency.absolutePath !== parentModule.path
374
386
  )
375
387
  .forEach((dependency) =>
@@ -380,9 +392,7 @@ function removeDependency(
380
392
  delta,
381
393
  canBeRemovedSafely
382
394
  )
383
- ); // This module is not used anywhere else!! we can clear it from the bundle
384
-
385
- graph.dependencies.delete(module.path);
395
+ );
386
396
  }
387
397
 
388
398
  function resolveDependencies(parentPath, dependencies, options) {
@@ -464,6 +474,7 @@ function reorderDependencies(graph, module, orderedDependencies, options) {
464
474
  }
465
475
 
466
476
  module.exports = {
477
+ createGraph,
467
478
  initialTraverseDependencies,
468
479
  traverseDependencies,
469
480
  reorderGraph,
@@ -13,6 +13,7 @@
13
13
  import type {
14
14
  Dependency,
15
15
  Graph,
16
+ GraphInputOptions,
16
17
  Module,
17
18
  Options,
18
19
  TransformResultDependency,
@@ -20,6 +21,20 @@ import type {
20
21
 
21
22
  const nullthrows = require('nullthrows');
22
23
 
24
+ // Private state for the graph that persists between operations.
25
+ export opaque type PrivateState = {
26
+ // TODO: Track e.g. GC scheduling here.
27
+ };
28
+
29
+ function createGraph<T>(options: GraphInputOptions): Graph<T> {
30
+ return {
31
+ ...options,
32
+ dependencies: new Map(),
33
+ importBundleNames: new Set(),
34
+ privateState: {},
35
+ };
36
+ }
37
+
23
38
  type Result<T> = {
24
39
  added: Map<string, Module<T>>,
25
40
  modified: Map<string, Module<T>>,
@@ -32,21 +47,21 @@ type Result<T> = {
32
47
  * files have been modified. This allows to return the added modules before the
33
48
  * modified ones (which is useful for things like Hot Module Reloading).
34
49
  **/
35
- type Delta = $ReadOnly<{|
50
+ type Delta = $ReadOnly<{
36
51
  added: Set<string>,
37
52
  modified: Set<string>,
38
53
  deleted: Set<string>,
39
54
  inverseDependencies: Map<string, Set<string>>,
40
- |}>;
55
+ }>;
41
56
 
42
- type InternalOptions<T> = $ReadOnly<{|
57
+ type InternalOptions<T> = $ReadOnly<{
43
58
  experimentalImportBundleSupport: boolean,
44
59
  onDependencyAdd: () => mixed,
45
60
  onDependencyAdded: () => mixed,
46
- resolve: $PropertyType<Options<T>, 'resolve'>,
47
- transform: $PropertyType<Options<T>, 'transform'>,
61
+ resolve: Options<T>['resolve'],
62
+ transform: Options<T>['transform'],
48
63
  shallow: boolean,
49
- |}>;
64
+ }>;
50
65
 
51
66
  function getInternalOptions<T>({
52
67
  transform,
@@ -94,10 +109,7 @@ async function traverseDependencies<T>(
94
109
  const internalOptions = getInternalOptions(options);
95
110
 
96
111
  for (const path of paths) {
97
- // Only process the path if it's part of the dependency graph. It's possible
98
- // that this method receives a path that is no longer part of it (e.g if a
99
- // module gets removed from the dependency graph and just afterwards it gets
100
- // modified), and we have to ignore these cases.
112
+ // Start traversing from modules that are already part of the dependency graph.
101
113
  if (graph.dependencies.get(path)) {
102
114
  delta.modified.add(path);
103
115
 
@@ -111,30 +123,13 @@ async function traverseDependencies<T>(
111
123
  }
112
124
 
113
125
  const added = new Map();
114
- const modified = new Map();
115
- const deleted = new Set();
116
-
117
- for (const path of delta.deleted) {
118
- // If a dependency has been marked both as added and deleted, it means that
119
- // this is a renamed file (or that dependency has been removed from one path
120
- // but added back in a different path). In this case the addition and
121
- // deletion "get cancelled".
122
- if (!delta.added.has(path)) {
123
- deleted.add(path);
124
- }
125
-
126
- delta.modified.delete(path);
127
- delta.added.delete(path);
128
- }
129
-
130
126
  for (const path of delta.added) {
131
127
  added.set(path, nullthrows(graph.dependencies.get(path)));
132
128
  }
133
129
 
130
+ const modified = new Map();
134
131
  for (const path of delta.modified) {
135
- // Similarly to the above, a file can be marked as both added and modified
136
- // when its path and dependencies have changed. In this case, we only
137
- // consider the addition.
132
+ // Only report a module as modified if we're not already reporting it as added.
138
133
  if (!delta.added.has(path)) {
139
134
  modified.set(path, nullthrows(graph.dependencies.get(path)));
140
135
  }
@@ -143,7 +138,7 @@ async function traverseDependencies<T>(
143
138
  return {
144
139
  added,
145
140
  modified,
146
- deleted,
141
+ deleted: delta.deleted,
147
142
  };
148
143
  }
149
144
 
@@ -161,7 +156,7 @@ async function initialTraverseDependencies<T>(
161
156
  const internalOptions = getInternalOptions(options);
162
157
 
163
158
  await Promise.all(
164
- graph.entryPoints.map((path: string) =>
159
+ [...graph.entryPoints].map((path: string) =>
165
160
  traverseDependenciesForSingleFile(path, graph, delta, internalOptions),
166
161
  ),
167
162
  );
@@ -197,6 +192,7 @@ async function processModule<T>(
197
192
  options: InternalOptions<T>,
198
193
  ): Promise<Module<T>> {
199
194
  // Transform the file via the given option.
195
+ // TODO: Unbind the transform method from options
200
196
  const result = await options.transform(path);
201
197
 
202
198
  // Get the absolute path of all sub-dependencies (some of them could have been
@@ -304,7 +300,14 @@ async function addDependency<T>(
304
300
  return;
305
301
  }
306
302
 
307
- delta.added.add(path);
303
+ if (delta.deleted.has(path)) {
304
+ // Mark the addition by clearing a prior deletion.
305
+ delta.deleted.delete(path);
306
+ } else {
307
+ // Mark the addition in the added set.
308
+ delta.added.add(path);
309
+ delta.modified.delete(path);
310
+ }
308
311
  delta.inverseDependencies.set(path, new Set([parentModule.path]));
309
312
 
310
313
  options.onDependencyAdd();
@@ -385,7 +388,7 @@ function canSafelyRemoveFromParentModule<T>(
385
388
 
386
389
  const undeletedInverseDependencies = Array.from(
387
390
  topInverseDependencies,
388
- ).filter(x => !delta.deleted.has(x));
391
+ ).filter(x => graph.dependencies.has(x));
389
392
 
390
393
  /**
391
394
  * We can only mark the `visited` Set of modules to be safely removable if
@@ -443,7 +446,20 @@ function removeDependency<T>(
443
446
  }
444
447
  }
445
448
 
446
- delta.deleted.add(module.path);
449
+ if (delta.added.has(module.path)) {
450
+ // Mark the deletion by clearing a prior addition.
451
+ delta.added.delete(module.path);
452
+ } else {
453
+ // Mark the deletion in the deleted set.
454
+ delta.deleted.add(module.path);
455
+ delta.modified.delete(module.path);
456
+ }
457
+
458
+ // This module is not used anywhere else! We can clear it from the bundle.
459
+ // Clean up all the state associated with this module in order to correctly
460
+ // re-add it if we encounter it again.
461
+ graph.dependencies.delete(module.path);
462
+ delta.inverseDependencies.delete(module.path);
447
463
 
448
464
  // Now we need to iterate through the module dependencies in order to
449
465
  // clean up everything (we cannot read the module because it may have
@@ -451,7 +467,7 @@ function removeDependency<T>(
451
467
  Array.from(module.dependencies.values())
452
468
  .filter(
453
469
  dependency =>
454
- !delta.deleted.has(dependency.absolutePath) &&
470
+ graph.dependencies.has(dependency.absolutePath) &&
455
471
  dependency.absolutePath !== parentModule.path,
456
472
  )
457
473
  .forEach(dependency =>
@@ -463,8 +479,6 @@ function removeDependency<T>(
463
479
  canBeRemovedSafely,
464
480
  ),
465
481
  );
466
- // This module is not used anywhere else!! we can clear it from the bundle
467
- graph.dependencies.delete(module.path);
468
482
  }
469
483
 
470
484
  function resolveDependencies<T>(
@@ -559,6 +573,7 @@ function reorderDependencies<T>(
559
573
  }
560
574
 
561
575
  module.exports = {
576
+ createGraph,
562
577
  initialTraverseDependencies,
563
578
  traverseDependencies,
564
579
  reorderGraph,
@@ -10,16 +10,17 @@
10
10
 
11
11
  'use strict';
12
12
 
13
+ import type {PrivateState} from './graphOperations';
13
14
  import type {JsTransformOptions} from 'metro-transform-worker';
14
15
 
15
- export type MixedOutput = {|
16
+ export type MixedOutput = {
16
17
  +data: mixed,
17
18
  +type: string,
18
- |};
19
+ };
19
20
 
20
21
  export type AsyncDependencyType = 'async' | 'prefetch';
21
22
 
22
- export type TransformResultDependency = {|
23
+ export type TransformResultDependency = {
23
24
  /**
24
25
  * The literal name provided to a require or import call. For example 'foo' in
25
26
  * case of `require('foo')`.
@@ -30,7 +31,7 @@ export type TransformResultDependency = {|
30
31
  * Extra data returned by the dependency extractor. Whatever is added here is
31
32
  * blindly piped by Metro to the serializers.
32
33
  */
33
- +data: {|
34
+ +data: {
34
35
  /**
35
36
  * If not null, this dependency is due to a dynamic `import()` or `__prefetchImport()` call.
36
37
  */
@@ -38,30 +39,30 @@ export type TransformResultDependency = {|
38
39
  /**
39
40
  * The condition for splitting on this dependency edge.
40
41
  */
41
- +splitCondition?: {|
42
+ +splitCondition?: {
42
43
  +mobileConfigName: string,
43
- |},
44
+ },
44
45
  /**
45
46
  * The dependency is enclosed in a try/catch block.
46
47
  */
47
48
  +isOptional?: boolean,
48
49
 
49
50
  +locs: $ReadOnlyArray<BabelSourceLocation>,
50
- |},
51
- |};
51
+ },
52
+ };
52
53
 
53
- export type Dependency = {|
54
+ export type Dependency = {
54
55
  +absolutePath: string,
55
56
  +data: TransformResultDependency,
56
- |};
57
+ };
57
58
 
58
- export type Module<T = MixedOutput> = {|
59
+ export type Module<T = MixedOutput> = {
59
60
  +dependencies: Map<string, Dependency>,
60
61
  +inverseDependencies: Set<string>,
61
62
  +output: $ReadOnlyArray<T>,
62
63
  +path: string,
63
64
  +getSource: () => Buffer,
64
- |};
65
+ };
65
66
 
66
67
  export type Dependencies<T = MixedOutput> = Map<string, Module<T>>;
67
68
 
@@ -74,51 +75,56 @@ export type TransformInputOptions = $Diff<
74
75
  },
75
76
  >;
76
77
 
77
- export type Graph<T = MixedOutput> = {|
78
- dependencies: Dependencies<T>,
79
- importBundleNames: Set<string>,
80
- +entryPoints: $ReadOnlyArray<string>,
78
+ export type GraphInputOptions = $ReadOnly<{
79
+ entryPoints: $ReadOnlySet<string>,
81
80
  // Unused in core but useful for custom serializers / experimentalSerializerHook
82
- +transformOptions: TransformInputOptions,
83
- |};
81
+ transformOptions: TransformInputOptions,
82
+ }>;
83
+
84
+ export type Graph<T = MixedOutput> = {
85
+ ...$ReadOnly<GraphInputOptions>,
86
+ dependencies: Dependencies<T>,
87
+ +importBundleNames: Set<string>,
88
+ +privateState: PrivateState,
89
+ };
84
90
 
85
- export type TransformResult<T = MixedOutput> = $ReadOnly<{|
91
+ export type TransformResult<T = MixedOutput> = $ReadOnly<{
86
92
  dependencies: $ReadOnlyArray<TransformResultDependency>,
87
93
  output: $ReadOnlyArray<T>,
88
- |}>;
94
+ }>;
89
95
 
90
- export type TransformResultWithSource<T = MixedOutput> = $ReadOnly<{|
96
+ export type TransformResultWithSource<T = MixedOutput> = $ReadOnly<{
91
97
  ...TransformResult<T>,
92
98
  getSource: () => Buffer,
93
- |}>;
99
+ }>;
94
100
 
95
101
  export type TransformFn<T = MixedOutput> = string => Promise<
96
102
  TransformResultWithSource<T>,
97
103
  >;
98
- export type AllowOptionalDependenciesWithOptions = {|
104
+ export type AllowOptionalDependenciesWithOptions = {
99
105
  +exclude: Array<string>,
100
- |};
106
+ };
101
107
  export type AllowOptionalDependencies =
102
108
  | boolean
103
109
  | AllowOptionalDependenciesWithOptions;
104
110
 
105
- export type Options<T = MixedOutput> = {|
111
+ export type Options<T = MixedOutput> = {
106
112
  +resolve: (from: string, to: string) => string,
107
113
  +transform: TransformFn<T>,
108
114
  +transformOptions: TransformInputOptions,
109
115
  +onProgress: ?(numProcessed: number, total: number) => mixed,
110
116
  +experimentalImportBundleSupport: boolean,
111
117
  +shallow: boolean,
112
- |};
118
+ };
113
119
 
114
- export type DeltaResult<T = MixedOutput> = {|
120
+ export type DeltaResult<T = MixedOutput> = {
115
121
  +added: Map<string, Module<T>>,
116
122
  +modified: Map<string, Module<T>>,
117
123
  +deleted: Set<string>,
118
124
  +reset: boolean,
119
- |};
125
+ };
120
126
 
121
- export type SerializerOptions = {|
127
+ export type SerializerOptions = {
122
128
  +asyncRequireModulePath: string,
123
129
  +createModuleId: string => number,
124
130
  +dev: boolean,
@@ -132,4 +138,4 @@ export type SerializerOptions = {|
132
138
  +serverRoot: string,
133
139
  +sourceMapUrl: ?string,
134
140
  +sourceUrl: ?string,
135
- |};
141
+ };
@@ -11,6 +11,8 @@
11
11
 
12
12
  const DeltaCalculator = require("./DeltaBundler/DeltaCalculator");
13
13
 
14
+ const { EventEmitter } = require("events");
15
+
14
16
  /**
15
17
  * `DeltaBundler` uses the `DeltaTransformer` to build bundle deltas. This
16
18
  * module handles all the transformer instances so it can support multiple
@@ -20,8 +22,8 @@ const DeltaCalculator = require("./DeltaBundler/DeltaCalculator");
20
22
  class DeltaBundler {
21
23
  _deltaCalculators = new Map();
22
24
 
23
- constructor(bundler) {
24
- this._bundler = bundler;
25
+ constructor(changeEventSource) {
26
+ this._changeEventSource = changeEventSource;
25
27
  }
26
28
 
27
29
  end() {
@@ -31,8 +33,11 @@ class DeltaBundler {
31
33
  }
32
34
 
33
35
  async getDependencies(entryPoints, options) {
34
- const depGraph = await this._bundler.getDependencyGraph();
35
- const deltaCalculator = new DeltaCalculator(entryPoints, depGraph, options);
36
+ const deltaCalculator = new DeltaCalculator(
37
+ new Set(entryPoints),
38
+ this._changeEventSource,
39
+ options
40
+ );
36
41
  await deltaCalculator.getDelta({
37
42
  reset: true,
38
43
  shallow: options.shallow,
@@ -45,8 +50,11 @@ class DeltaBundler {
45
50
  // To get just the dependencies, use getDependencies which will not leak graphs.
46
51
 
47
52
  async buildGraph(entryPoints, options) {
48
- const depGraph = await this._bundler.getDependencyGraph();
49
- const deltaCalculator = new DeltaCalculator(entryPoints, depGraph, options);
53
+ const deltaCalculator = new DeltaCalculator(
54
+ new Set(entryPoints),
55
+ this._changeEventSource,
56
+ options
57
+ );
50
58
  await deltaCalculator.getDelta({
51
59
  reset: true,
52
60
  shallow: options.shallow,
@@ -10,7 +10,6 @@
10
10
 
11
11
  'use strict';
12
12
 
13
- import type Bundler from './Bundler';
14
13
  import type {
15
14
  DeltaResult,
16
15
  Dependencies,
@@ -21,6 +20,7 @@ import type {
21
20
  } from './DeltaBundler/types.flow';
22
21
 
23
22
  const DeltaCalculator = require('./DeltaBundler/DeltaCalculator');
23
+ const {EventEmitter} = require('events');
24
24
 
25
25
  export type {
26
26
  DeltaResult,
@@ -41,11 +41,11 @@ export type {
41
41
  * `clientId` param (which maps a client to a specific delta transformer).
42
42
  */
43
43
  class DeltaBundler<T = MixedOutput> {
44
- _bundler: Bundler;
44
+ _changeEventSource: EventEmitter;
45
45
  _deltaCalculators: Map<Graph<T>, DeltaCalculator<T>> = new Map();
46
46
 
47
- constructor(bundler: Bundler) {
48
- this._bundler = bundler;
47
+ constructor(changeEventSource: EventEmitter) {
48
+ this._changeEventSource = changeEventSource;
49
49
  }
50
50
 
51
51
  end(): void {
@@ -59,9 +59,11 @@ class DeltaBundler<T = MixedOutput> {
59
59
  entryPoints: $ReadOnlyArray<string>,
60
60
  options: Options<T>,
61
61
  ): Promise<Dependencies<T>> {
62
- const depGraph = await this._bundler.getDependencyGraph();
63
-
64
- const deltaCalculator = new DeltaCalculator(entryPoints, depGraph, options);
62
+ const deltaCalculator = new DeltaCalculator(
63
+ new Set(entryPoints),
64
+ this._changeEventSource,
65
+ options,
66
+ );
65
67
 
66
68
  await deltaCalculator.getDelta({reset: true, shallow: options.shallow});
67
69
  const graph = deltaCalculator.getGraph();
@@ -77,9 +79,11 @@ class DeltaBundler<T = MixedOutput> {
77
79
  entryPoints: $ReadOnlyArray<string>,
78
80
  options: Options<T>,
79
81
  ): Promise<Graph<T>> {
80
- const depGraph = await this._bundler.getDependencyGraph();
81
-
82
- const deltaCalculator = new DeltaCalculator(entryPoints, depGraph, options);
82
+ const deltaCalculator = new DeltaCalculator(
83
+ new Set(entryPoints),
84
+ this._changeEventSource,
85
+ options,
86
+ );
83
87
 
84
88
  await deltaCalculator.getDelta({reset: true, shallow: options.shallow});
85
89
  const graph = deltaCalculator.getGraph();
@@ -39,18 +39,18 @@ const url = require('url');
39
39
  type $ReturnType<F> = $Call<<A, R>((...A) => R) => R, F>;
40
40
  export type EntryPointURL = $ReturnType<typeof url.parse>;
41
41
 
42
- type Client = {|
42
+ type Client = {
43
43
  optedIntoHMR: boolean,
44
44
  revisionIds: Array<RevisionId>,
45
45
  +sendFn: string => void,
46
- |};
46
+ };
47
47
 
48
- type ClientGroup = {|
48
+ type ClientGroup = {
49
49
  +clients: Set<Client>,
50
50
  clientUrl: EntryPointURL,
51
51
  revisionId: RevisionId,
52
52
  +unlisten: () => void,
53
- |};
53
+ };
54
54
 
55
55
  function send(sendFns: Array<(string) => void>, message: HmrMessage): void {
56
56
  const strMessage = JSON.stringify(message);
@@ -252,7 +252,7 @@ class HmrServer<TClient: Client> {
252
252
 
253
253
  async _handleFileChange(
254
254
  group: ClientGroup,
255
- options: {|isInitialUpdate: boolean|},
255
+ options: {isInitialUpdate: boolean},
256
256
  ): Promise<void> {
257
257
  const optedIntoHMR = [...group.clients].some(
258
258
  (client: Client) => client.optedIntoHMR,
@@ -292,7 +292,7 @@ class HmrServer<TClient: Client> {
292
292
 
293
293
  async _prepareMessage(
294
294
  group: ClientGroup,
295
- options: {|isInitialUpdate: boolean|},
295
+ options: {isInitialUpdate: boolean},
296
296
  ): Promise<HmrUpdateMessage | HmrErrorMessage> {
297
297
  try {
298
298
  const revPromise = this._bundler.getRevision(group.revisionId);