metro 0.72.0 → 0.72.1

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 (71) hide show
  1. package/package.json +21 -21
  2. package/src/Bundler.js +11 -2
  3. package/src/Bundler.js.flow +7 -1
  4. package/src/DeltaBundler/DeltaCalculator.js +83 -21
  5. package/src/DeltaBundler/DeltaCalculator.js.flow +61 -8
  6. package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +1 -3
  7. package/src/DeltaBundler/Transformer.js +27 -4
  8. package/src/DeltaBundler/Transformer.js.flow +18 -2
  9. package/src/DeltaBundler/Worker.flow.js +45 -1
  10. package/src/DeltaBundler/Worker.flow.js.flow +42 -1
  11. package/src/DeltaBundler/WorkerFarm.js +3 -2
  12. package/src/DeltaBundler/WorkerFarm.js.flow +3 -1
  13. package/src/DeltaBundler/graphOperations.js +131 -20
  14. package/src/DeltaBundler/graphOperations.js.flow +106 -17
  15. package/src/DeltaBundler/types.flow.js.flow +6 -3
  16. package/src/HmrServer.js +2 -0
  17. package/src/HmrServer.js.flow +2 -0
  18. package/src/IncrementalBundler.js +6 -0
  19. package/src/IncrementalBundler.js.flow +6 -0
  20. package/src/ModuleGraph/node-haste/HasteFS.js.flow +1 -1
  21. package/src/ModuleGraph/node-haste/node-haste.js +2 -4
  22. package/src/ModuleGraph/node-haste/node-haste.js.flow +1 -3
  23. package/src/ModuleGraph/output/indexed-ram-bundle.js.flow +5 -13
  24. package/src/ModuleGraph/output/multiple-files-ram-bundle.js.flow +4 -14
  25. package/src/ModuleGraph/output/util.js.flow +1 -1
  26. package/src/ModuleGraph/worker/collectDependencies.js.flow +1 -1
  27. package/src/Server.js +4 -0
  28. package/src/Server.js.flow +37 -10
  29. package/src/integration_tests/basic_bundle/require-context/conflict.js +25 -0
  30. package/src/integration_tests/basic_bundle/require-context/conflict.js.flow +27 -0
  31. package/src/integration_tests/basic_bundle/require-context/empty.js +29 -0
  32. package/src/integration_tests/basic_bundle/require-context/empty.js.flow +26 -0
  33. package/src/integration_tests/basic_bundle/require-context/matching.js +26 -0
  34. package/src/integration_tests/basic_bundle/require-context/matching.js.flow +27 -0
  35. package/src/integration_tests/basic_bundle/require-context/mode-eager.js +22 -0
  36. package/src/integration_tests/basic_bundle/require-context/mode-eager.js.flow +24 -0
  37. package/src/integration_tests/basic_bundle/require-context/mode-lazy-once.js +22 -0
  38. package/src/integration_tests/basic_bundle/require-context/mode-lazy-once.js.flow +24 -0
  39. package/src/integration_tests/basic_bundle/require-context/mode-lazy.js +22 -0
  40. package/src/integration_tests/basic_bundle/require-context/mode-lazy.js.flow +24 -0
  41. package/src/integration_tests/basic_bundle/require-context/mode-sync.js +20 -0
  42. package/src/integration_tests/basic_bundle/require-context/mode-sync.js.flow +22 -0
  43. package/src/integration_tests/basic_bundle/require-context/subdir/a.js +12 -0
  44. package/src/integration_tests/basic_bundle/require-context/subdir/a.js.flow +11 -0
  45. package/src/integration_tests/basic_bundle/require-context/subdir/b.js +18 -0
  46. package/src/integration_tests/basic_bundle/require-context/subdir/b.js.flow +11 -0
  47. package/src/integration_tests/basic_bundle/require-context/subdir/c.js +12 -0
  48. package/src/integration_tests/basic_bundle/require-context/subdir/c.js.flow +11 -0
  49. package/src/integration_tests/basic_bundle/require-context/subdir/nested/d.js +12 -0
  50. package/src/integration_tests/basic_bundle/require-context/subdir/nested/d.js.flow +11 -0
  51. package/src/integration_tests/basic_bundle/require-context/subdir-conflict/index.js +12 -0
  52. package/src/integration_tests/basic_bundle/require-context/subdir-conflict/index.js.flow +11 -0
  53. package/src/integration_tests/basic_bundle/require-context/utils.js +29 -0
  54. package/src/integration_tests/basic_bundle/require-context/utils.js.flow +44 -0
  55. package/src/lib/CountingSet.js +1 -0
  56. package/src/lib/CountingSet.js.flow +1 -0
  57. package/src/lib/contextModule.js +80 -0
  58. package/src/lib/contextModule.js.flow +86 -0
  59. package/src/lib/contextModuleTemplates.js +186 -0
  60. package/src/lib/contextModuleTemplates.js.flow +148 -0
  61. package/src/lib/getGraphId.js +2 -1
  62. package/src/lib/getGraphId.js.flow +3 -0
  63. package/src/lib/getPrependedScripts.js +2 -0
  64. package/src/lib/getPrependedScripts.js.flow +2 -0
  65. package/src/lib/parseOptionsFromUrl.js.flow +7 -18
  66. package/src/lib/transformHelpers.js +41 -9
  67. package/src/lib/transformHelpers.js.flow +46 -9
  68. package/src/node-haste/DependencyGraph/ModuleResolution.js +1 -0
  69. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +3 -2
  70. package/src/node-haste/DependencyGraph.js +5 -0
  71. package/src/node-haste/DependencyGraph.js.flow +14 -1
@@ -50,13 +50,14 @@ class WorkerFarm {
50
50
  }
51
51
  }
52
52
 
53
- async transform(filename, options) {
53
+ async transform(filename, options, fileBuffer) {
54
54
  try {
55
55
  const data = await this._worker.transform(
56
56
  filename,
57
57
  options,
58
58
  this._config.projectRoot,
59
- this._transformerConfig
59
+ this._transformerConfig,
60
+ fileBuffer
60
61
  );
61
62
  Logger.log(data.transformFileStartLogEntry);
62
63
  Logger.log(data.transformFileEndLogEntry);
@@ -78,6 +78,7 @@ class WorkerFarm {
78
78
  async transform(
79
79
  filename: string,
80
80
  options: TransformOptions,
81
+ fileBuffer?: Buffer,
81
82
  ): Promise<TransformerResult> {
82
83
  try {
83
84
  const data = await this._worker.transform(
@@ -85,6 +86,7 @@ class WorkerFarm {
85
86
  options,
86
87
  this._config.projectRoot,
87
88
  this._transformerConfig,
89
+ fileBuffer,
88
90
  );
89
91
 
90
92
  Logger.log(data.transformFileStartLogEntry);
@@ -107,7 +109,7 @@ class WorkerFarm {
107
109
  workerPath: string,
108
110
  exposedMethods: $ReadOnlyArray<string>,
109
111
  numWorkers: number,
110
- ) {
112
+ ): any {
111
113
  const env = {
112
114
  ...process.env,
113
115
  // Force color to print syntax highlighted code frames.
@@ -31,6 +31,52 @@
31
31
 
32
32
  var _CountingSet = _interopRequireDefault(require("../lib/CountingSet"));
33
33
 
34
+ var _contextModule = require("../lib/contextModule");
35
+
36
+ var path = _interopRequireWildcard(require("path"));
37
+
38
+ function _getRequireWildcardCache(nodeInterop) {
39
+ if (typeof WeakMap !== "function") return null;
40
+ var cacheBabelInterop = new WeakMap();
41
+ var cacheNodeInterop = new WeakMap();
42
+ return (_getRequireWildcardCache = function (nodeInterop) {
43
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
44
+ })(nodeInterop);
45
+ }
46
+
47
+ function _interopRequireWildcard(obj, nodeInterop) {
48
+ if (!nodeInterop && obj && obj.__esModule) {
49
+ return obj;
50
+ }
51
+ if (obj === null || (typeof obj !== "object" && typeof obj !== "function")) {
52
+ return { default: obj };
53
+ }
54
+ var cache = _getRequireWildcardCache(nodeInterop);
55
+ if (cache && cache.has(obj)) {
56
+ return cache.get(obj);
57
+ }
58
+ var newObj = {};
59
+ var hasPropertyDescriptor =
60
+ Object.defineProperty && Object.getOwnPropertyDescriptor;
61
+ for (var key in obj) {
62
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
63
+ var desc = hasPropertyDescriptor
64
+ ? Object.getOwnPropertyDescriptor(obj, key)
65
+ : null;
66
+ if (desc && (desc.get || desc.set)) {
67
+ Object.defineProperty(newObj, key, desc);
68
+ } else {
69
+ newObj[key] = obj[key];
70
+ }
71
+ }
72
+ }
73
+ newObj.default = obj;
74
+ if (cache) {
75
+ cache.set(obj, newObj);
76
+ }
77
+ return newObj;
78
+ }
79
+
34
80
  function _interopRequireDefault(obj) {
35
81
  return obj && obj.__esModule ? obj : { default: obj };
36
82
  }
@@ -45,6 +91,7 @@ function createGraph(options) {
45
91
  dependencies: new Map(),
46
92
  importBundleNames: new Set(),
47
93
  privateState: {
94
+ resolvedContexts: new Map(),
48
95
  gc: {
49
96
  color: new Map(),
50
97
  possibleCycleRoots: new Set(),
@@ -78,7 +125,7 @@ function getInternalOptions({
78
125
  * dependency graph.
79
126
  * Instead of traversing the whole graph each time, it just calculates the
80
127
  * difference between runs by only traversing the added/removed dependencies.
81
- * To do so, it uses the passed passed graph dependencies and it mutates it.
128
+ * To do so, it uses the passed graph dependencies and it mutates it.
82
129
  * The paths parameter contains the absolute paths of the root files that the
83
130
  * method should traverse. Normally, these paths should be the modified files
84
131
  * since the last traversal.
@@ -176,12 +223,14 @@ async function traverseDependenciesForSingleFile(path, graph, delta, options) {
176
223
  }
177
224
 
178
225
  async function processModule(path, graph, delta, options) {
179
- // Transform the file via the given option.
226
+ const resolvedContext = graph.privateState.resolvedContexts.get(path); // Transform the file via the given option.
180
227
  // TODO: Unbind the transform method from options
181
- const result = await options.transform(path); // Get the absolute path of all sub-dependencies (some of them could have been
228
+
229
+ const result = await options.transform(path, resolvedContext); // Get the absolute path of all sub-dependencies (some of them could have been
182
230
  // moved but maintain the same relative path).
183
231
 
184
232
  const currentDependencies = resolveDependencies(
233
+ graph,
185
234
  path,
186
235
  result.dependencies,
187
236
  options
@@ -206,10 +255,7 @@ async function processModule(path, graph, delta, options) {
206
255
 
207
256
  if (
208
257
  !curDependency ||
209
- curDependency.absolutePath !== prevDependency.absolutePath ||
210
- (options.experimentalImportBundleSupport &&
211
- curDependency.data.data.asyncType !==
212
- prevDependency.data.data.asyncType)
258
+ !dependenciesEqual(prevDependency, curDependency, options)
213
259
  ) {
214
260
  removeDependency(module, key, prevDependency, graph, delta, options);
215
261
  }
@@ -222,10 +268,7 @@ async function processModule(path, graph, delta, options) {
222
268
 
223
269
  if (
224
270
  !prevDependency ||
225
- prevDependency.absolutePath !== curDependency.absolutePath ||
226
- (options.experimentalImportBundleSupport &&
227
- prevDependency.data.data.asyncType !==
228
- curDependency.data.data.asyncType)
271
+ !dependenciesEqual(prevDependency, curDependency, options)
229
272
  ) {
230
273
  promises.push(
231
274
  addDependency(module, key, curDependency, graph, delta, options)
@@ -249,6 +292,29 @@ async function processModule(path, graph, delta, options) {
249
292
  return module;
250
293
  }
251
294
 
295
+ function dependenciesEqual(a, b, options) {
296
+ return (
297
+ a === b ||
298
+ (a.absolutePath === b.absolutePath &&
299
+ (!options.experimentalImportBundleSupport ||
300
+ a.data.data.asyncType === b.data.data.asyncType) &&
301
+ contextParamsEqual(a.data.data.contextParams, b.data.data.contextParams))
302
+ );
303
+ }
304
+
305
+ function contextParamsEqual(a, b) {
306
+ return (
307
+ a === b ||
308
+ (a == null && b == null) ||
309
+ (a != null &&
310
+ b != null &&
311
+ a.recursive === b.recursive &&
312
+ a.filter.pattern === b.filter.pattern &&
313
+ a.filter.flags === b.filter.flags &&
314
+ a.mode === b.mode)
315
+ );
316
+ }
317
+
252
318
  async function addDependency(
253
319
  parentModule,
254
320
  key,
@@ -350,23 +416,66 @@ function removeDependency(
350
416
  releaseModule(module, graph, delta, options);
351
417
  }
352
418
  }
419
+ /**
420
+ * Collect a list of context modules which include a given file.
421
+ */
353
422
 
354
- function resolveDependencies(parentPath, dependencies, options) {
423
+ function markModifiedContextModules(graph, filePath, modifiedPaths) {
424
+ for (const [absolutePath, context] of graph.privateState.resolvedContexts) {
425
+ if (
426
+ !modifiedPaths.has(absolutePath) &&
427
+ (0, _contextModule.fileMatchesContext)(filePath, context)
428
+ ) {
429
+ modifiedPaths.add(absolutePath);
430
+ }
431
+ }
432
+ }
433
+
434
+ function resolveDependencies(graph, parentPath, dependencies, options) {
355
435
  const maybeResolvedDeps = new Map();
356
436
 
357
437
  for (const dep of dependencies) {
358
- let resolvedDep;
438
+ let resolvedDep; // `require.context`
439
+
440
+ const { contextParams } = dep.data;
359
441
 
360
- try {
442
+ if (contextParams) {
443
+ // Ensure the filepath has uniqueness applied to ensure multiple `require.context`
444
+ // statements can be used to target the same file with different properties.
445
+ const from = path.join(parentPath, "..", dep.name);
446
+ const absolutePath = (0, _contextModule.deriveAbsolutePathFromContext)(
447
+ from,
448
+ contextParams
449
+ );
450
+ const resolvedContext = {
451
+ from,
452
+ mode: contextParams.mode,
453
+ recursive: contextParams.recursive,
454
+ filter: new RegExp(
455
+ contextParams.filter.pattern,
456
+ contextParams.filter.flags
457
+ ),
458
+ };
459
+ graph.privateState.resolvedContexts.set(absolutePath, resolvedContext);
361
460
  resolvedDep = {
362
- absolutePath: options.resolve(parentPath, dep.name),
461
+ absolutePath,
363
462
  data: dep,
364
463
  };
365
- } catch (error) {
366
- // Ignore unavailable optional dependencies. They are guarded
367
- // with a try-catch block and will be handled during runtime.
368
- if (dep.data.isOptional !== true) {
369
- throw error;
464
+ } else {
465
+ try {
466
+ resolvedDep = {
467
+ absolutePath: options.resolve(parentPath, dep.name),
468
+ data: dep,
469
+ }; // This dependency may have existed previously as a require.context -
470
+ // clean it up.
471
+
472
+ graph.privateState.resolvedContexts.delete(resolvedDep.absolutePath);
473
+ } catch (error) {
474
+ // Ignore unavailable optional dependencies. They are guarded
475
+ // with a try-catch block and will be handled during runtime.
476
+ if (dep.data.isOptional !== true) {
477
+ throw error;
478
+ }
370
479
  }
371
480
  }
372
481
 
@@ -508,6 +617,7 @@ function freeModule(module, graph, delta) {
508
617
  delta.earlyInverseDependencies.delete(module.path);
509
618
  graph.privateState.gc.possibleCycleRoots.delete(module.path);
510
619
  graph.privateState.gc.color.delete(module.path);
620
+ graph.privateState.resolvedContexts.delete(module.path);
511
621
  } // Mark a module as a possible cycle root
512
622
 
513
623
  function markAsPossibleCycleRoot(module, graph) {
@@ -634,4 +744,5 @@ module.exports = {
634
744
  initialTraverseDependencies,
635
745
  traverseDependencies,
636
746
  reorderGraph,
747
+ markModifiedContextModules,
637
748
  };
@@ -30,6 +30,8 @@
30
30
 
31
31
  'use strict';
32
32
 
33
+ import type {RequireContextParams} from '../ModuleGraph/worker/collectDependencies';
34
+ import type {RequireContext} from '../lib/contextModule';
33
35
  import type {
34
36
  Dependency,
35
37
  Graph,
@@ -40,7 +42,12 @@ import type {
40
42
  } from './types.flow';
41
43
 
42
44
  import CountingSet from '../lib/CountingSet';
45
+ import {
46
+ deriveAbsolutePathFromContext,
47
+ fileMatchesContext,
48
+ } from '../lib/contextModule';
43
49
 
50
+ import * as path from 'path';
44
51
  const invariant = require('invariant');
45
52
  const nullthrows = require('nullthrows');
46
53
 
@@ -63,6 +70,8 @@ type NodeColor =
63
70
 
64
71
  // Private state for the graph that persists between operations.
65
72
  export opaque type PrivateState = {
73
+ /** Resolved context parameters from `require.context`. */
74
+ +resolvedContexts: Map<string, RequireContext>,
66
75
  +gc: {
67
76
  // GC state for nodes in the graph (graph.dependencies)
68
77
  +color: Map<string, NodeColor>,
@@ -79,6 +88,7 @@ function createGraph<T>(options: GraphInputOptions): Graph<T> {
79
88
  dependencies: new Map(),
80
89
  importBundleNames: new Set(),
81
90
  privateState: {
91
+ resolvedContexts: new Map(),
82
92
  gc: {
83
93
  color: new Map(),
84
94
  possibleCycleRoots: new Set(),
@@ -144,7 +154,7 @@ function getInternalOptions<T>({
144
154
  * dependency graph.
145
155
  * Instead of traversing the whole graph each time, it just calculates the
146
156
  * difference between runs by only traversing the added/removed dependencies.
147
- * To do so, it uses the passed passed graph dependencies and it mutates it.
157
+ * To do so, it uses the passed graph dependencies and it mutates it.
148
158
  * The paths parameter contains the absolute paths of the root files that the
149
159
  * method should traverse. Normally, these paths should be the modified files
150
160
  * since the last traversal.
@@ -266,13 +276,15 @@ async function processModule<T>(
266
276
  delta: Delta,
267
277
  options: InternalOptions<T>,
268
278
  ): Promise<Module<T>> {
279
+ const resolvedContext = graph.privateState.resolvedContexts.get(path);
269
280
  // Transform the file via the given option.
270
281
  // TODO: Unbind the transform method from options
271
- const result = await options.transform(path);
282
+ const result = await options.transform(path, resolvedContext);
272
283
 
273
284
  // Get the absolute path of all sub-dependencies (some of them could have been
274
285
  // moved but maintain the same relative path).
275
286
  const currentDependencies = resolveDependencies(
287
+ graph,
276
288
  path,
277
289
  result.dependencies,
278
290
  options,
@@ -299,10 +311,7 @@ async function processModule<T>(
299
311
  const curDependency = currentDependencies.get(key);
300
312
  if (
301
313
  !curDependency ||
302
- curDependency.absolutePath !== prevDependency.absolutePath ||
303
- (options.experimentalImportBundleSupport &&
304
- curDependency.data.data.asyncType !==
305
- prevDependency.data.data.asyncType)
314
+ !dependenciesEqual(prevDependency, curDependency, options)
306
315
  ) {
307
316
  removeDependency(module, key, prevDependency, graph, delta, options);
308
317
  }
@@ -314,10 +323,7 @@ async function processModule<T>(
314
323
  const prevDependency = previousDependencies.get(key);
315
324
  if (
316
325
  !prevDependency ||
317
- prevDependency.absolutePath !== curDependency.absolutePath ||
318
- (options.experimentalImportBundleSupport &&
319
- prevDependency.data.data.asyncType !==
320
- curDependency.data.data.asyncType)
326
+ !dependenciesEqual(prevDependency, curDependency, options)
321
327
  ) {
322
328
  promises.push(
323
329
  addDependency(module, key, curDependency, graph, delta, options),
@@ -345,6 +351,36 @@ async function processModule<T>(
345
351
  return module;
346
352
  }
347
353
 
354
+ function dependenciesEqual(
355
+ a: Dependency,
356
+ b: Dependency,
357
+ options: $ReadOnly<{experimentalImportBundleSupport: boolean, ...}>,
358
+ ): boolean {
359
+ return (
360
+ a === b ||
361
+ (a.absolutePath === b.absolutePath &&
362
+ (!options.experimentalImportBundleSupport ||
363
+ a.data.data.asyncType === b.data.data.asyncType) &&
364
+ contextParamsEqual(a.data.data.contextParams, b.data.data.contextParams))
365
+ );
366
+ }
367
+
368
+ function contextParamsEqual(
369
+ a: ?RequireContextParams,
370
+ b: ?RequireContextParams,
371
+ ): boolean {
372
+ return (
373
+ a === b ||
374
+ (a == null && b == null) ||
375
+ (a != null &&
376
+ b != null &&
377
+ a.recursive === b.recursive &&
378
+ a.filter.pattern === b.filter.pattern &&
379
+ a.filter.flags === b.filter.flags &&
380
+ a.mode === b.mode)
381
+ );
382
+ }
383
+
348
384
  async function addDependency<T>(
349
385
  parentModule: Module<T>,
350
386
  key: string,
@@ -447,7 +483,26 @@ function removeDependency<T>(
447
483
  }
448
484
  }
449
485
 
486
+ /**
487
+ * Collect a list of context modules which include a given file.
488
+ */
489
+ function markModifiedContextModules<T>(
490
+ graph: Graph<T>,
491
+ filePath: string,
492
+ modifiedPaths: Set<string>,
493
+ ) {
494
+ for (const [absolutePath, context] of graph.privateState.resolvedContexts) {
495
+ if (
496
+ !modifiedPaths.has(absolutePath) &&
497
+ fileMatchesContext(filePath, context)
498
+ ) {
499
+ modifiedPaths.add(absolutePath);
500
+ }
501
+ }
502
+ }
503
+
450
504
  function resolveDependencies<T>(
505
+ graph: Graph<T>,
451
506
  parentPath: string,
452
507
  dependencies: $ReadOnlyArray<TransformResultDependency>,
453
508
  options: InternalOptions<T>,
@@ -455,18 +510,50 @@ function resolveDependencies<T>(
455
510
  const maybeResolvedDeps = new Map();
456
511
  for (const dep of dependencies) {
457
512
  let resolvedDep;
458
- try {
513
+
514
+ // `require.context`
515
+ const {contextParams} = dep.data;
516
+ if (contextParams) {
517
+ // Ensure the filepath has uniqueness applied to ensure multiple `require.context`
518
+ // statements can be used to target the same file with different properties.
519
+ const from = path.join(parentPath, '..', dep.name);
520
+ const absolutePath = deriveAbsolutePathFromContext(from, contextParams);
521
+
522
+ const resolvedContext: RequireContext = {
523
+ from,
524
+ mode: contextParams.mode,
525
+ recursive: contextParams.recursive,
526
+ filter: new RegExp(
527
+ contextParams.filter.pattern,
528
+ contextParams.filter.flags,
529
+ ),
530
+ };
531
+
532
+ graph.privateState.resolvedContexts.set(absolutePath, resolvedContext);
533
+
459
534
  resolvedDep = {
460
- absolutePath: options.resolve(parentPath, dep.name),
535
+ absolutePath,
461
536
  data: dep,
462
537
  };
463
- } catch (error) {
464
- // Ignore unavailable optional dependencies. They are guarded
465
- // with a try-catch block and will be handled during runtime.
466
- if (dep.data.isOptional !== true) {
467
- throw error;
538
+ } else {
539
+ try {
540
+ resolvedDep = {
541
+ absolutePath: options.resolve(parentPath, dep.name),
542
+ data: dep,
543
+ };
544
+
545
+ // This dependency may have existed previously as a require.context -
546
+ // clean it up.
547
+ graph.privateState.resolvedContexts.delete(resolvedDep.absolutePath);
548
+ } catch (error) {
549
+ // Ignore unavailable optional dependencies. They are guarded
550
+ // with a try-catch block and will be handled during runtime.
551
+ if (dep.data.isOptional !== true) {
552
+ throw error;
553
+ }
468
554
  }
469
555
  }
556
+
470
557
  const key = dep.data.key;
471
558
  if (maybeResolvedDeps.has(key)) {
472
559
  throw new Error(
@@ -622,6 +709,7 @@ function freeModule<T>(module: Module<T>, graph: Graph<T>, delta: Delta) {
622
709
  delta.earlyInverseDependencies.delete(module.path);
623
710
  graph.privateState.gc.possibleCycleRoots.delete(module.path);
624
711
  graph.privateState.gc.color.delete(module.path);
712
+ graph.privateState.resolvedContexts.delete(module.path);
625
713
  }
626
714
 
627
715
  // Mark a module as a possible cycle root
@@ -740,4 +828,5 @@ module.exports = {
740
828
  initialTraverseDependencies,
741
829
  traverseDependencies,
742
830
  reorderGraph,
831
+ markModifiedContextModules,
743
832
  };
@@ -11,6 +11,7 @@
11
11
  'use strict';
12
12
 
13
13
  import type {RequireContextParams} from '../ModuleGraph/worker/collectDependencies';
14
+ import type {RequireContext} from '../lib/contextModule';
14
15
  import type {PrivateState} from './graphOperations';
15
16
  import type {JsTransformOptions} from 'metro-transform-worker';
16
17
 
@@ -107,9 +108,10 @@ export type TransformResultWithSource<T = MixedOutput> = $ReadOnly<{
107
108
  getSource: () => Buffer,
108
109
  }>;
109
110
 
110
- export type TransformFn<T = MixedOutput> = string => Promise<
111
- TransformResultWithSource<T>,
112
- >;
111
+ export type TransformFn<T = MixedOutput> = (
112
+ string,
113
+ ?RequireContext,
114
+ ) => Promise<TransformResultWithSource<T>>;
113
115
  export type AllowOptionalDependenciesWithOptions = {
114
116
  +exclude: Array<string>,
115
117
  };
@@ -123,6 +125,7 @@ export type Options<T = MixedOutput> = {
123
125
  +transformOptions: TransformInputOptions,
124
126
  +onProgress: ?(numProcessed: number, total: number) => mixed,
125
127
  +experimentalImportBundleSupport: boolean,
128
+ +unstable_allowRequireContext: boolean,
126
129
  +shallow: boolean,
127
130
  };
128
131
 
package/src/HmrServer.js CHANGED
@@ -99,6 +99,8 @@ class HmrServer {
99
99
  shallow: graphOptions.shallow,
100
100
  experimentalImportBundleSupport:
101
101
  this._config.transformer.experimentalImportBundleSupport,
102
+ unstable_allowRequireContext:
103
+ this._config.transformer.unstable_allowRequireContext,
102
104
  });
103
105
 
104
106
  const revPromise = this._bundler.getRevisionByGraphId(graphId);
@@ -125,6 +125,8 @@ class HmrServer<TClient: Client> {
125
125
  shallow: graphOptions.shallow,
126
126
  experimentalImportBundleSupport:
127
127
  this._config.transformer.experimentalImportBundleSupport,
128
+ unstable_allowRequireContext:
129
+ this._config.transformer.unstable_allowRequireContext,
128
130
  });
129
131
  const revPromise = this._bundler.getRevisionByGraphId(graphId);
130
132
  if (!revPromise) {
@@ -93,6 +93,8 @@ class IncrementalBundler {
93
93
  onProgress: otherOptions.onProgress,
94
94
  experimentalImportBundleSupport:
95
95
  this._config.transformer.experimentalImportBundleSupport,
96
+ unstable_allowRequireContext:
97
+ this._config.transformer.unstable_allowRequireContext,
96
98
  shallow: otherOptions.shallow,
97
99
  });
98
100
 
@@ -133,6 +135,8 @@ class IncrementalBundler {
133
135
  onProgress: otherOptions.onProgress,
134
136
  experimentalImportBundleSupport:
135
137
  this._config.transformer.experimentalImportBundleSupport,
138
+ unstable_allowRequireContext:
139
+ this._config.transformer.unstable_allowRequireContext,
136
140
  shallow: otherOptions.shallow,
137
141
  }
138
142
  );
@@ -178,6 +182,8 @@ class IncrementalBundler {
178
182
  shallow: otherOptions.shallow,
179
183
  experimentalImportBundleSupport:
180
184
  this._config.transformer.experimentalImportBundleSupport,
185
+ unstable_allowRequireContext:
186
+ this._config.transformer.unstable_allowRequireContext,
181
187
  });
182
188
  const revisionId = createRevisionId();
183
189
 
@@ -123,6 +123,8 @@ class IncrementalBundler {
123
123
  onProgress: otherOptions.onProgress,
124
124
  experimentalImportBundleSupport:
125
125
  this._config.transformer.experimentalImportBundleSupport,
126
+ unstable_allowRequireContext:
127
+ this._config.transformer.unstable_allowRequireContext,
126
128
  shallow: otherOptions.shallow,
127
129
  });
128
130
 
@@ -164,6 +166,8 @@ class IncrementalBundler {
164
166
  onProgress: otherOptions.onProgress,
165
167
  experimentalImportBundleSupport:
166
168
  this._config.transformer.experimentalImportBundleSupport,
169
+ unstable_allowRequireContext:
170
+ this._config.transformer.unstable_allowRequireContext,
167
171
  shallow: otherOptions.shallow,
168
172
  },
169
173
  );
@@ -218,6 +222,8 @@ class IncrementalBundler {
218
222
  shallow: otherOptions.shallow,
219
223
  experimentalImportBundleSupport:
220
224
  this._config.transformer.experimentalImportBundleSupport,
225
+ unstable_allowRequireContext:
226
+ this._config.transformer.unstable_allowRequireContext,
221
227
  });
222
228
  const revisionId = createRevisionId();
223
229
  const revisionPromise = (async () => {
@@ -58,7 +58,7 @@ module.exports = class HasteFS {
58
58
  return Array.from<string>(this.files.keys());
59
59
  }
60
60
 
61
- matchFiles() {
61
+ matchFiles(): $FlowFixMeEmpty {
62
62
  throw new Error('HasteFS.matchFiles is not implemented yet.');
63
63
  }
64
64
 
@@ -181,10 +181,8 @@ exports.createResolveFn = function (options) {
181
181
  const from =
182
182
  sourcePath != null
183
183
  ? new Module(sourcePath, moduleCache, getTransformedFile(sourcePath))
184
- : NULL_MODULE;
185
- const allowHaste = !isNodeModules(from.path); // $FlowFixMe -- error revealed by types-first codemod
184
+ : NULL_MODULE; // $FlowFixMe -- error revealed by types-first codemod
186
185
 
187
- return moduleResolver.resolveDependency(from, id, allowHaste, platform)
188
- .path;
186
+ return moduleResolver.resolveDependency(from, id, true, platform).path;
189
187
  };
190
188
  };
@@ -213,9 +213,7 @@ exports.createResolveFn = function (options: ResolveOptions): ResolveFn {
213
213
  sourcePath != null
214
214
  ? new Module(sourcePath, moduleCache, getTransformedFile(sourcePath))
215
215
  : NULL_MODULE;
216
- const allowHaste = !isNodeModules(from.path);
217
216
  // $FlowFixMe -- error revealed by types-first codemod
218
- return moduleResolver.resolveDependency(from, id, allowHaste, platform)
219
- .path;
217
+ return moduleResolver.resolveDependency(from, id, true, platform).path;
220
218
  };
221
219
  };
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  'use strict';
12
- import type {IdsForPathFn, Dependency} from '../types.flow';
12
+ import type {Dependency} from '../types.flow';
13
13
  import type {BasicSourceMap} from '../../../../metro-source-map/src/source-map';
14
14
 
15
15
  import type {Module, OutputFn, OutputFnArg} from '../types.flow';
@@ -33,18 +33,10 @@ function asIndexedRamBundle({
33
33
  preloadedModules,
34
34
  ramGroupHeads,
35
35
  requireCalls,
36
- }: $TEMPORARY$object<{
37
- dependencyMapReservedName?: ?string,
38
- enableIDInlining: boolean,
39
- filename: string,
40
- globalPrefix: string,
41
- idsForPath: IdsForPathFn,
42
- modules: Iterable<Module>,
43
- preloadedModules: Set<string>,
36
+ }: $ReadOnly<{
37
+ ...OutputFnArg,
38
+ preloadedModules: $ReadOnlySet<string>,
44
39
  ramGroupHeads: ?$ReadOnlyArray<string>,
45
- requireCalls: Iterable<Module>,
46
- segmentID: number,
47
- sourceMapPath?: ?string,
48
40
  }>): {
49
41
  code: string | Buffer,
50
42
  extraFiles?: Iterable<[string, string | Buffer]>,
@@ -137,7 +129,7 @@ function* subtree(
137
129
  }
138
130
 
139
131
  function createBuilder(
140
- preloadedModules: Set<string>,
132
+ preloadedModules: $ReadOnlySet<string>,
141
133
  ramGroupHeads: ?$ReadOnlyArray<string>,
142
134
  ): OutputFn<IndexMap> {
143
135
  return (x: OutputFnArg) =>