metro 0.71.3 → 0.72.2

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 (108) hide show
  1. package/package.json +23 -21
  2. package/src/Assets.js +3 -2
  3. package/src/Assets.js.flow +3 -2
  4. package/src/Bundler.js +11 -2
  5. package/src/Bundler.js.flow +7 -1
  6. package/src/DeltaBundler/DeltaCalculator.js +83 -21
  7. package/src/DeltaBundler/DeltaCalculator.js.flow +61 -8
  8. package/src/DeltaBundler/Serializers/baseBytecodeBundle.js +3 -2
  9. package/src/DeltaBundler/Serializers/baseBytecodeBundle.js.flow +2 -1
  10. package/src/DeltaBundler/Serializers/helpers/bytecode.js +2 -2
  11. package/src/DeltaBundler/Serializers/helpers/bytecode.js.flow +2 -1
  12. package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +1 -3
  13. package/src/DeltaBundler/Transformer.js +27 -4
  14. package/src/DeltaBundler/Transformer.js.flow +18 -2
  15. package/src/DeltaBundler/Worker.flow.js +45 -1
  16. package/src/DeltaBundler/Worker.flow.js.flow +42 -1
  17. package/src/DeltaBundler/WorkerFarm.js +3 -2
  18. package/src/DeltaBundler/WorkerFarm.js.flow +3 -1
  19. package/src/DeltaBundler/graphOperations.js +170 -63
  20. package/src/DeltaBundler/graphOperations.js.flow +144 -64
  21. package/src/DeltaBundler/types.flow.js.flow +11 -5
  22. package/src/DeltaBundler.js.flow +1 -1
  23. package/src/HmrServer.js +11 -5
  24. package/src/HmrServer.js.flow +11 -4
  25. package/src/IncrementalBundler.js +22 -4
  26. package/src/IncrementalBundler.js.flow +23 -4
  27. package/src/ModuleGraph/node-haste/HasteFS.js.flow +1 -1
  28. package/src/ModuleGraph/node-haste/Package.js.flow +5 -5
  29. package/src/ModuleGraph/node-haste/node-haste.js +19 -8
  30. package/src/ModuleGraph/node-haste/node-haste.js.flow +43 -16
  31. package/src/ModuleGraph/output/indexed-ram-bundle.js.flow +5 -13
  32. package/src/ModuleGraph/output/multiple-files-ram-bundle.js.flow +4 -14
  33. package/src/ModuleGraph/output/util.js +3 -4
  34. package/src/ModuleGraph/output/util.js.flow +3 -3
  35. package/src/ModuleGraph/types.flow.js.flow +28 -5
  36. package/src/ModuleGraph/worker/collectDependencies.js +19 -30
  37. package/src/ModuleGraph/worker/collectDependencies.js.flow +23 -41
  38. package/src/Server.js +90 -32
  39. package/src/Server.js.flow +143 -44
  40. package/src/cli-utils.js.flow +1 -1
  41. package/src/commands/build.js +1 -2
  42. package/src/commands/build.js.flow +6 -9
  43. package/src/commands/dependencies.js +1 -1
  44. package/src/commands/serve.js +2 -1
  45. package/src/commands/serve.js.flow +7 -8
  46. package/src/index.flow.js +27 -16
  47. package/src/index.flow.js.flow +24 -15
  48. package/src/integration_tests/basic_bundle/require-context/conflict.js +25 -0
  49. package/src/integration_tests/basic_bundle/require-context/conflict.js.flow +27 -0
  50. package/src/integration_tests/basic_bundle/require-context/empty.js +29 -0
  51. package/src/integration_tests/basic_bundle/require-context/empty.js.flow +26 -0
  52. package/src/integration_tests/basic_bundle/require-context/matching.js +26 -0
  53. package/src/integration_tests/basic_bundle/require-context/matching.js.flow +27 -0
  54. package/src/integration_tests/basic_bundle/require-context/mode-eager.js +22 -0
  55. package/src/integration_tests/basic_bundle/require-context/mode-eager.js.flow +24 -0
  56. package/src/integration_tests/basic_bundle/require-context/mode-lazy-once.js +22 -0
  57. package/src/integration_tests/basic_bundle/require-context/mode-lazy-once.js.flow +24 -0
  58. package/src/integration_tests/basic_bundle/require-context/mode-lazy.js +22 -0
  59. package/src/integration_tests/basic_bundle/require-context/mode-lazy.js.flow +24 -0
  60. package/src/integration_tests/basic_bundle/require-context/mode-sync.js +20 -0
  61. package/src/integration_tests/basic_bundle/require-context/mode-sync.js.flow +22 -0
  62. package/src/integration_tests/basic_bundle/require-context/subdir/a.js +12 -0
  63. package/src/integration_tests/basic_bundle/require-context/subdir/a.js.flow +11 -0
  64. package/src/integration_tests/basic_bundle/require-context/subdir/b.js +18 -0
  65. package/src/integration_tests/basic_bundle/require-context/subdir/b.js.flow +11 -0
  66. package/src/integration_tests/basic_bundle/require-context/subdir/c.js +12 -0
  67. package/src/integration_tests/basic_bundle/require-context/subdir/c.js.flow +11 -0
  68. package/src/integration_tests/basic_bundle/require-context/subdir/nested/d.js +12 -0
  69. package/src/integration_tests/basic_bundle/require-context/subdir/nested/d.js.flow +11 -0
  70. package/src/integration_tests/basic_bundle/require-context/subdir-conflict/index.js +12 -0
  71. package/src/integration_tests/basic_bundle/require-context/subdir-conflict/index.js.flow +11 -0
  72. package/src/integration_tests/basic_bundle/require-context/utils.js +29 -0
  73. package/src/integration_tests/basic_bundle/require-context/utils.js.flow +44 -0
  74. package/src/lib/CountingSet.js +1 -0
  75. package/src/lib/CountingSet.js.flow +1 -0
  76. package/src/lib/RamBundleParser.js +1 -0
  77. package/src/lib/RamBundleParser.js.flow +1 -0
  78. package/src/lib/bundleToBytecode.js +3 -2
  79. package/src/lib/bundleToBytecode.js.flow +2 -2
  80. package/src/lib/contextModule.js +80 -0
  81. package/src/lib/contextModule.js.flow +86 -0
  82. package/src/lib/contextModuleTemplates.js +186 -0
  83. package/src/lib/contextModuleTemplates.js.flow +148 -0
  84. package/src/lib/getGraphId.js +17 -3
  85. package/src/lib/getGraphId.js.flow +12 -9
  86. package/src/lib/getPrependedScripts.js +15 -5
  87. package/src/lib/getPrependedScripts.js.flow +8 -1
  88. package/src/lib/parseCustomResolverOptions.js +26 -0
  89. package/src/lib/parseCustomResolverOptions.js.flow +38 -0
  90. package/src/lib/parseOptionsFromUrl.js +3 -0
  91. package/src/lib/parseOptionsFromUrl.js.flow +9 -18
  92. package/src/lib/splitBundleOptions.js +3 -0
  93. package/src/lib/splitBundleOptions.js.flow +3 -0
  94. package/src/lib/transformHelpers.js +68 -22
  95. package/src/lib/transformHelpers.js.flow +73 -16
  96. package/src/node-haste/DependencyGraph/ModuleResolution.js +19 -2
  97. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +8 -2
  98. package/src/node-haste/DependencyGraph/createHasteMap.js +7 -1
  99. package/src/node-haste/DependencyGraph/createHasteMap.js.flow +7 -1
  100. package/src/node-haste/DependencyGraph.js +39 -9
  101. package/src/node-haste/DependencyGraph.js.flow +63 -12
  102. package/src/node-haste/Module.js +1 -0
  103. package/src/node-haste/Module.js.flow +1 -0
  104. package/src/shared/output/bundle.flow.js +67 -0
  105. package/src/shared/output/bundle.flow.js.flow +89 -0
  106. package/src/shared/output/bundle.js +8 -55
  107. package/src/shared/output/bundle.js.flow +8 -75
  108. package/src/shared/types.flow.js.flow +7 -0
@@ -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,
@@ -295,46 +307,26 @@ async function processModule<T>(
295
307
  graph.dependencies.set(module.path, module);
296
308
 
297
309
  // Diff dependencies (1/2): remove dependencies that have changed or been removed.
298
- for (const [relativePath, prevDependency] of previousDependencies) {
299
- const curDependency = currentDependencies.get(relativePath);
310
+ for (const [key, prevDependency] of previousDependencies) {
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
- removeDependency(
308
- module,
309
- relativePath,
310
- prevDependency,
311
- graph,
312
- delta,
313
- options,
314
- );
316
+ removeDependency(module, key, prevDependency, graph, delta, options);
315
317
  }
316
318
  }
317
319
 
318
320
  // Diff dependencies (2/2): add dependencies that have changed or been added.
319
321
  const promises = [];
320
- for (const [relativePath, curDependency] of currentDependencies) {
321
- const prevDependency = previousDependencies.get(relativePath);
322
+ for (const [key, curDependency] of currentDependencies) {
323
+ const prevDependency = previousDependencies.get(key);
322
324
  if (
323
325
  !prevDependency ||
324
- prevDependency.absolutePath !== curDependency.absolutePath ||
325
- (options.experimentalImportBundleSupport &&
326
- prevDependency.data.data.asyncType !==
327
- curDependency.data.data.asyncType)
326
+ !dependenciesEqual(prevDependency, curDependency, options)
328
327
  ) {
329
328
  promises.push(
330
- addDependency(
331
- module,
332
- relativePath,
333
- curDependency,
334
- graph,
335
- delta,
336
- options,
337
- ),
329
+ addDependency(module, key, curDependency, graph, delta, options),
338
330
  );
339
331
  }
340
332
  }
@@ -359,9 +351,39 @@ async function processModule<T>(
359
351
  return module;
360
352
  }
361
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
+
362
384
  async function addDependency<T>(
363
385
  parentModule: Module<T>,
364
- relativePath: string,
386
+ key: string,
365
387
  dependency: Dependency,
366
388
  graph: Graph<T>,
367
389
  delta: Delta,
@@ -420,18 +442,18 @@ async function addDependency<T>(
420
442
  // This means the parent's dependencies can get desynced from
421
443
  // inverseDependencies and the other fields in the case of lazy edges.
422
444
  // Not an optimal representation :(
423
- parentModule.dependencies.set(relativePath, dependency);
445
+ parentModule.dependencies.set(key, dependency);
424
446
  }
425
447
 
426
448
  function removeDependency<T>(
427
449
  parentModule: Module<T>,
428
- relativePath: string,
450
+ key: string,
429
451
  dependency: Dependency,
430
452
  graph: Graph<T>,
431
453
  delta: Delta,
432
454
  options: InternalOptions<T>,
433
455
  ): void {
434
- parentModule.dependencies.delete(relativePath);
456
+ parentModule.dependencies.delete(key);
435
457
 
436
458
  const {absolutePath} = dependency;
437
459
 
@@ -461,42 +483,98 @@ function removeDependency<T>(
461
483
  }
462
484
  }
463
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
+
464
504
  function resolveDependencies<T>(
505
+ graph: Graph<T>,
465
506
  parentPath: string,
466
507
  dependencies: $ReadOnlyArray<TransformResultDependency>,
467
508
  options: InternalOptions<T>,
468
509
  ): Map<string, Dependency> {
469
- const resolve = (parentPath: string, result: TransformResultDependency) => {
470
- const relativePath = result.name;
471
- try {
472
- return [
473
- relativePath,
474
- {
475
- absolutePath: options.resolve(parentPath, relativePath),
476
- data: result,
477
- },
478
- ];
479
- } catch (error) {
480
- // Ignore unavailable optional dependencies. They are guarded
481
- // with a try-catch block and will be handled during runtime.
482
- if (result.data.isOptional !== true) {
483
- throw error;
510
+ const maybeResolvedDeps = new Map();
511
+ for (const dep of dependencies) {
512
+ let resolvedDep;
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
+
534
+ resolvedDep = {
535
+ absolutePath,
536
+ data: dep,
537
+ };
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
+ }
484
554
  }
485
555
  }
486
- return undefined;
487
- };
488
556
 
489
- const resolved = dependencies.reduce(
490
- (list: Array<[string, Dependency]>, result: TransformResultDependency) => {
491
- const resolvedPath = resolve(parentPath, result);
492
- if (resolvedPath) {
493
- list.push(resolvedPath);
494
- }
495
- return list;
496
- },
497
- [],
498
- );
499
- return new Map(resolved);
557
+ const key = dep.data.key;
558
+ if (maybeResolvedDeps.has(key)) {
559
+ throw new Error(
560
+ `resolveDependencies: Found duplicate dependency key '${key}' in ${parentPath}`,
561
+ );
562
+ }
563
+ maybeResolvedDeps.set(key, resolvedDep);
564
+ }
565
+
566
+ const resolvedDeps = new Map();
567
+ // Return just the dependencies we successfully resolved.
568
+ // FIXME: This has a bad bug affecting all dependencies *after* an unresolved
569
+ // optional dependency. We'll need to propagate the nulls all the way to the
570
+ // serializer and the require() runtime to keep the dependency map from being
571
+ // desynced from the contents of the module.
572
+ for (const [key, resolvedDep] of maybeResolvedDeps) {
573
+ if (resolvedDep) {
574
+ resolvedDeps.set(key, resolvedDep);
575
+ }
576
+ }
577
+ return resolvedDeps;
500
578
  }
501
579
 
502
580
  /**
@@ -604,8 +682,8 @@ function releaseModule<T>(
604
682
  delta: Delta,
605
683
  options: InternalOptions<T>,
606
684
  ) {
607
- for (const [relativePath, dependency] of module.dependencies) {
608
- removeDependency(module, relativePath, dependency, graph, delta, options);
685
+ for (const [key, dependency] of module.dependencies) {
686
+ removeDependency(module, key, dependency, graph, delta, options);
609
687
  }
610
688
  graph.privateState.gc.color.set(module.path, 'black');
611
689
  if (!graph.privateState.gc.possibleCycleRoots.has(module.path)) {
@@ -631,6 +709,7 @@ function freeModule<T>(module: Module<T>, graph: Graph<T>, delta: Delta) {
631
709
  delta.earlyInverseDependencies.delete(module.path);
632
710
  graph.privateState.gc.possibleCycleRoots.delete(module.path);
633
711
  graph.privateState.gc.color.delete(module.path);
712
+ graph.privateState.resolvedContexts.delete(module.path);
634
713
  }
635
714
 
636
715
  // Mark a module as a possible cycle root
@@ -749,4 +828,5 @@ module.exports = {
749
828
  initialTraverseDependencies,
750
829
  traverseDependencies,
751
830
  reorderGraph,
831
+ markModifiedContextModules,
752
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
 
@@ -31,10 +32,13 @@ export type TransformResultDependency = {
31
32
  +name: string,
32
33
 
33
34
  /**
34
- * Extra data returned by the dependency extractor. Whatever is added here is
35
- * blindly piped by Metro to the serializers.
35
+ * Extra data returned by the dependency extractor.
36
36
  */
37
37
  +data: {
38
+ /**
39
+ * A locally unique key for this dependency within the current module.
40
+ */
41
+ +key: string,
38
42
  /**
39
43
  * If not null, this dependency is due to a dynamic `import()` or `__prefetchImport()` call.
40
44
  */
@@ -104,9 +108,10 @@ export type TransformResultWithSource<T = MixedOutput> = $ReadOnly<{
104
108
  getSource: () => Buffer,
105
109
  }>;
106
110
 
107
- export type TransformFn<T = MixedOutput> = string => Promise<
108
- TransformResultWithSource<T>,
109
- >;
111
+ export type TransformFn<T = MixedOutput> = (
112
+ string,
113
+ ?RequireContext,
114
+ ) => Promise<TransformResultWithSource<T>>;
110
115
  export type AllowOptionalDependenciesWithOptions = {
111
116
  +exclude: Array<string>,
112
117
  };
@@ -120,6 +125,7 @@ export type Options<T = MixedOutput> = {
120
125
  +transformOptions: TransformInputOptions,
121
126
  +onProgress: ?(numProcessed: number, total: number) => mixed,
122
127
  +experimentalImportBundleSupport: boolean,
128
+ +unstable_allowRequireContext: boolean,
123
129
  +shallow: boolean,
124
130
  };
125
131
 
@@ -112,7 +112,7 @@ class DeltaBundler<T = MixedOutput> {
112
112
  return await deltaCalculator.getDelta({reset, shallow});
113
113
  }
114
114
 
115
- listen(graph: Graph<T>, callback: () => mixed): () => void {
115
+ listen(graph: Graph<T>, callback: () => Promise<void>): () => void {
116
116
  const deltaCalculator = this._deltaCalculators.get(graph);
117
117
 
118
118
  if (!deltaCalculator) {
package/src/HmrServer.js CHANGED
@@ -31,12 +31,14 @@ const {
31
31
  Logger: { createActionStartEntry, createActionEndEntry, log },
32
32
  } = require("metro-core");
33
33
 
34
- const { VERSION: BYTECODE_VERSION } = require("metro-hermes-compiler");
35
-
36
34
  const nullthrows = require("nullthrows");
37
35
 
38
36
  const url = require("url");
39
37
 
38
+ function getBytecodeVersion() {
39
+ return require("metro-hermes-compiler").VERSION;
40
+ }
41
+
40
42
  function send(sendFns, message) {
41
43
  const strMessage = JSON.stringify(message);
42
44
  sendFns.forEach((sendFn) => sendFn(strMessage));
@@ -75,9 +77,9 @@ class HmrServer {
75
77
  const options = parseOptionsFromUrl(
76
78
  requestUrl,
77
79
  new Set(this._config.resolver.platforms),
78
- BYTECODE_VERSION
80
+ getBytecodeVersion()
79
81
  );
80
- const { entryFile, transformOptions, graphOptions } =
82
+ const { entryFile, resolverOptions, transformOptions, graphOptions } =
81
83
  splitBundleOptions(options);
82
84
  /**
83
85
  * `entryFile` is relative to projectRoot, we need to use resolution function
@@ -86,7 +88,8 @@ class HmrServer {
86
88
 
87
89
  const resolutionFn = await transformHelpers.getResolveDependencyFn(
88
90
  this._bundler.getBundler(),
89
- transformOptions.platform
91
+ transformOptions.platform,
92
+ resolverOptions
90
93
  );
91
94
  const resolvedEntryFilePath = resolutionFn(
92
95
  ((_this$_config$server$ = this._config.server.unstable_serverRoot) !==
@@ -96,9 +99,12 @@ class HmrServer {
96
99
  entryFile
97
100
  );
98
101
  const graphId = getGraphId(resolvedEntryFilePath, transformOptions, {
102
+ resolverOptions,
99
103
  shallow: graphOptions.shallow,
100
104
  experimentalImportBundleSupport:
101
105
  this._config.transformer.experimentalImportBundleSupport,
106
+ unstable_allowRequireContext:
107
+ this._config.transformer.unstable_allowRequireContext,
102
108
  });
103
109
 
104
110
  const revPromise = this._bundler.getRevisionByGraphId(graphId);
@@ -31,14 +31,13 @@ const transformHelpers = require('./lib/transformHelpers');
31
31
  const {
32
32
  Logger: {createActionStartEntry, createActionEndEntry, log},
33
33
  } = require('metro-core');
34
- const {VERSION: BYTECODE_VERSION} = require('metro-hermes-compiler');
35
34
  const nullthrows = require('nullthrows');
36
35
  const url = require('url');
37
36
 
38
37
  type $ReturnType<F> = $Call<<A, R>((...A) => R) => R, F>;
39
38
  export type EntryPointURL = $ReturnType<typeof url.parse>;
40
39
 
41
- type Client = {
40
+ export type Client = {
42
41
  optedIntoHMR: boolean,
43
42
  revisionIds: Array<RevisionId>,
44
43
  +sendFn: string => void,
@@ -51,6 +50,10 @@ type ClientGroup = {
51
50
  +unlisten: () => void,
52
51
  };
53
52
 
53
+ function getBytecodeVersion() {
54
+ return require('metro-hermes-compiler').VERSION;
55
+ }
56
+
54
57
  function send(sendFns: Array<(string) => void>, message: HmrMessage): void {
55
58
  const strMessage = JSON.stringify(message);
56
59
  sendFns.forEach((sendFn: string => void) => sendFn(strMessage));
@@ -103,9 +106,9 @@ class HmrServer<TClient: Client> {
103
106
  const options = parseOptionsFromUrl(
104
107
  requestUrl,
105
108
  new Set(this._config.resolver.platforms),
106
- BYTECODE_VERSION,
109
+ getBytecodeVersion(),
107
110
  );
108
- const {entryFile, transformOptions, graphOptions} =
111
+ const {entryFile, resolverOptions, transformOptions, graphOptions} =
109
112
  splitBundleOptions(options);
110
113
 
111
114
  /**
@@ -115,6 +118,7 @@ class HmrServer<TClient: Client> {
115
118
  const resolutionFn = await transformHelpers.getResolveDependencyFn(
116
119
  this._bundler.getBundler(),
117
120
  transformOptions.platform,
121
+ resolverOptions,
118
122
  );
119
123
  const resolvedEntryFilePath = resolutionFn(
120
124
  (this._config.server.unstable_serverRoot ?? this._config.projectRoot) +
@@ -122,9 +126,12 @@ class HmrServer<TClient: Client> {
122
126
  entryFile,
123
127
  );
124
128
  const graphId = getGraphId(resolvedEntryFilePath, transformOptions, {
129
+ resolverOptions,
125
130
  shallow: graphOptions.shallow,
126
131
  experimentalImportBundleSupport:
127
132
  this._config.transformer.experimentalImportBundleSupport,
133
+ unstable_allowRequireContext:
134
+ this._config.transformer.unstable_allowRequireContext,
128
135
  });
129
136
  const revPromise = this._bundler.getRevisionByGraphId(graphId);
130
137
  if (!revPromise) {
@@ -71,6 +71,7 @@ class IncrementalBundler {
71
71
  async buildGraphForEntries(
72
72
  entryFiles,
73
73
  transformOptions,
74
+ resolverOptions,
74
75
  otherOptions = {
75
76
  onProgress: null,
76
77
  shallow: false,
@@ -80,19 +81,23 @@ class IncrementalBundler {
80
81
  const graph = await this._deltaBundler.buildGraph(absoluteEntryFiles, {
81
82
  resolve: await transformHelpers.getResolveDependencyFn(
82
83
  this._bundler,
83
- transformOptions.platform
84
+ transformOptions.platform,
85
+ resolverOptions
84
86
  ),
85
87
  transform: await transformHelpers.getTransformFn(
86
88
  absoluteEntryFiles,
87
89
  this._bundler,
88
90
  this._deltaBundler,
89
91
  this._config,
90
- transformOptions
92
+ transformOptions,
93
+ resolverOptions
91
94
  ),
92
95
  transformOptions,
93
96
  onProgress: otherOptions.onProgress,
94
97
  experimentalImportBundleSupport:
95
98
  this._config.transformer.experimentalImportBundleSupport,
99
+ unstable_allowRequireContext:
100
+ this._config.transformer.unstable_allowRequireContext,
96
101
  shallow: otherOptions.shallow,
97
102
  });
98
103
 
@@ -109,6 +114,7 @@ class IncrementalBundler {
109
114
  async getDependencies(
110
115
  entryFiles,
111
116
  transformOptions,
117
+ resolverOptions,
112
118
  otherOptions = {
113
119
  onProgress: null,
114
120
  shallow: false,
@@ -120,19 +126,23 @@ class IncrementalBundler {
120
126
  {
121
127
  resolve: await transformHelpers.getResolveDependencyFn(
122
128
  this._bundler,
123
- transformOptions.platform
129
+ transformOptions.platform,
130
+ resolverOptions
124
131
  ),
125
132
  transform: await transformHelpers.getTransformFn(
126
133
  absoluteEntryFiles,
127
134
  this._bundler,
128
135
  this._deltaBundler,
129
136
  this._config,
130
- transformOptions
137
+ transformOptions,
138
+ resolverOptions
131
139
  ),
132
140
  transformOptions,
133
141
  onProgress: otherOptions.onProgress,
134
142
  experimentalImportBundleSupport:
135
143
  this._config.transformer.experimentalImportBundleSupport,
144
+ unstable_allowRequireContext:
145
+ this._config.transformer.unstable_allowRequireContext,
136
146
  shallow: otherOptions.shallow,
137
147
  }
138
148
  );
@@ -142,6 +152,7 @@ class IncrementalBundler {
142
152
  async buildGraph(
143
153
  entryFile,
144
154
  transformOptions,
155
+ resolverOptions,
145
156
  otherOptions = {
146
157
  onProgress: null,
147
158
  shallow: false,
@@ -150,12 +161,14 @@ class IncrementalBundler {
150
161
  const graph = await this.buildGraphForEntries(
151
162
  [entryFile],
152
163
  transformOptions,
164
+ resolverOptions,
153
165
  otherOptions
154
166
  );
155
167
  const { type: _, ...transformOptionsWithoutType } = transformOptions;
156
168
  const prepend = await getPrependedScripts(
157
169
  this._config,
158
170
  transformOptionsWithoutType,
171
+ resolverOptions,
159
172
  this._bundler,
160
173
  this._deltaBundler
161
174
  );
@@ -169,15 +182,19 @@ class IncrementalBundler {
169
182
  async initializeGraph(
170
183
  entryFile,
171
184
  transformOptions,
185
+ resolverOptions,
172
186
  otherOptions = {
173
187
  onProgress: null,
174
188
  shallow: false,
175
189
  }
176
190
  ) {
177
191
  const graphId = getGraphId(entryFile, transformOptions, {
192
+ resolverOptions,
178
193
  shallow: otherOptions.shallow,
179
194
  experimentalImportBundleSupport:
180
195
  this._config.transformer.experimentalImportBundleSupport,
196
+ unstable_allowRequireContext:
197
+ this._config.transformer.unstable_allowRequireContext,
181
198
  });
182
199
  const revisionId = createRevisionId();
183
200
 
@@ -185,6 +202,7 @@ class IncrementalBundler {
185
202
  const { graph, prepend } = await this.buildGraph(
186
203
  entryFile,
187
204
  transformOptions,
205
+ resolverOptions,
188
206
  otherOptions
189
207
  );
190
208
  return {