metro 0.80.9 → 0.80.10

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 (60) hide show
  1. package/package.json +18 -18
  2. package/src/DeltaBundler/Serializers/baseJSBundle.js +1 -0
  3. package/src/DeltaBundler/Serializers/baseJSBundle.js.flow +1 -0
  4. package/src/DeltaBundler/Serializers/getRamBundleInfo.js +1 -0
  5. package/src/DeltaBundler/Serializers/getRamBundleInfo.js.flow +1 -0
  6. package/src/DeltaBundler/Serializers/helpers/getSourceMapInfo.js +1 -1
  7. package/src/DeltaBundler/Serializers/helpers/getSourceMapInfo.js.flow +2 -1
  8. package/src/DeltaBundler/Serializers/sourceMapGenerator.js +1 -0
  9. package/src/DeltaBundler/Serializers/sourceMapGenerator.js.flow +3 -0
  10. package/src/DeltaBundler/Serializers/sourceMapString.js +14 -2
  11. package/src/DeltaBundler/Serializers/sourceMapString.js.flow +18 -2
  12. package/src/DeltaBundler/Transformer.js +1 -1
  13. package/src/DeltaBundler/Transformer.js.flow +4 -2
  14. package/src/DeltaBundler/types.flow.js.flow +2 -1
  15. package/src/ModuleGraph/worker/collectDependencies.js +54 -4
  16. package/src/ModuleGraph/worker/collectDependencies.js.flow +69 -4
  17. package/src/Server.js +113 -10
  18. package/src/Server.js.flow +130 -10
  19. package/src/cli/parseKeyValueParamArray.js +4 -5
  20. package/src/cli/parseKeyValueParamArray.js.flow +5 -3
  21. package/src/index.flow.js +7 -0
  22. package/src/index.flow.js.flow +8 -0
  23. package/src/integration_tests/basic_bundle/excluded_from_file_map.js +8 -0
  24. package/src/integration_tests/basic_bundle/excluded_from_file_map.js.flow +11 -0
  25. package/src/integration_tests/basic_bundle/import-export/export-7.js +5 -0
  26. package/src/integration_tests/basic_bundle/import-export/export-7.js.flow +15 -0
  27. package/src/integration_tests/basic_bundle/import-export/export-8.js +10 -0
  28. package/src/integration_tests/basic_bundle/import-export/export-8.js.flow +15 -0
  29. package/src/integration_tests/basic_bundle/import-export/index.js +9 -1
  30. package/src/integration_tests/basic_bundle/import-export/index.js.flow +9 -0
  31. package/src/integration_tests/basic_bundle/import-export/utils.js +1 -0
  32. package/src/integration_tests/basic_bundle/import-export/utils.js.flow +14 -0
  33. package/src/integration_tests/basic_bundle/not_a_source_file.xyz +1 -0
  34. package/src/integration_tests/metro.config.js +1 -0
  35. package/src/lib/BatchProcessor.js +3 -0
  36. package/src/lib/BatchProcessor.js.flow +4 -0
  37. package/src/lib/JsonReporter.js +30 -3
  38. package/src/lib/JsonReporter.js.flow +40 -7
  39. package/src/lib/TerminalReporter.js +4 -0
  40. package/src/lib/TerminalReporter.js.flow +12 -1
  41. package/src/lib/getAppendScripts.js +4 -1
  42. package/src/lib/getAppendScripts.js.flow +5 -1
  43. package/src/lib/parseOptionsFromUrl.js +4 -0
  44. package/src/lib/parseOptionsFromUrl.js.flow +4 -0
  45. package/src/lib/reporting.d.ts +6 -0
  46. package/src/lib/reporting.js.flow +6 -0
  47. package/src/lib/splitBundleOptions.js +1 -0
  48. package/src/lib/splitBundleOptions.js.flow +1 -0
  49. package/src/node-haste/DependencyGraph/ModuleResolution.js +10 -9
  50. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +16 -14
  51. package/src/node-haste/DependencyGraph.js +8 -4
  52. package/src/node-haste/DependencyGraph.js.flow +12 -4
  53. package/src/node-haste/Module.js +1 -1
  54. package/src/node-haste/Module.js.flow +1 -1
  55. package/src/node-haste/ModuleCache.js +28 -14
  56. package/src/node-haste/ModuleCache.js.flow +43 -18
  57. package/src/shared/output/bundle.flow.js +2 -2
  58. package/src/shared/output/bundle.flow.js.flow +2 -2
  59. package/src/shared/types.flow.js +10 -0
  60. package/src/shared/types.flow.js.flow +9 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metro",
3
- "version": "0.80.9",
3
+ "version": "0.80.10",
4
4
  "description": "🚇 The JavaScript bundler for React Native.",
5
5
  "main": "src/index.js",
6
6
  "bin": "src/cli.js",
@@ -27,34 +27,34 @@
27
27
  "debug": "^2.2.0",
28
28
  "denodeify": "^1.2.1",
29
29
  "error-stack-parser": "^2.0.6",
30
+ "flow-enums-runtime": "^0.0.6",
30
31
  "graceful-fs": "^4.2.4",
31
- "hermes-parser": "0.20.1",
32
+ "hermes-parser": "0.23.0",
32
33
  "image-size": "^1.0.2",
33
34
  "invariant": "^2.2.4",
34
35
  "jest-worker": "^29.6.3",
35
36
  "jsc-safe-url": "^0.2.2",
36
37
  "lodash.throttle": "^4.1.1",
37
- "metro-babel-transformer": "0.80.9",
38
- "metro-cache": "0.80.9",
39
- "metro-cache-key": "0.80.9",
40
- "metro-config": "0.80.9",
41
- "metro-core": "0.80.9",
42
- "metro-file-map": "0.80.9",
43
- "metro-resolver": "0.80.9",
44
- "metro-runtime": "0.80.9",
45
- "metro-source-map": "0.80.9",
46
- "metro-symbolicate": "0.80.9",
47
- "metro-transform-plugins": "0.80.9",
48
- "metro-transform-worker": "0.80.9",
38
+ "metro-babel-transformer": "0.80.10",
39
+ "metro-cache": "0.80.10",
40
+ "metro-cache-key": "0.80.10",
41
+ "metro-config": "0.80.10",
42
+ "metro-core": "0.80.10",
43
+ "metro-file-map": "0.80.10",
44
+ "metro-resolver": "0.80.10",
45
+ "metro-runtime": "0.80.10",
46
+ "metro-source-map": "0.80.10",
47
+ "metro-symbolicate": "0.80.10",
48
+ "metro-transform-plugins": "0.80.10",
49
+ "metro-transform-worker": "0.80.10",
49
50
  "mime-types": "^2.1.27",
50
51
  "node-fetch": "^2.2.0",
51
52
  "nullthrows": "^1.1.1",
52
- "rimraf": "^3.0.2",
53
53
  "serialize-error": "^2.1.0",
54
54
  "source-map": "^0.5.6",
55
55
  "strip-ansi": "^6.0.0",
56
56
  "throat": "^5.0.0",
57
- "ws": "^7.5.1",
57
+ "ws": "^7.5.10",
58
58
  "yargs": "^17.6.2"
59
59
  },
60
60
  "devDependencies": {
@@ -66,8 +66,8 @@
66
66
  "dedent": "^0.7.0",
67
67
  "jest-snapshot": "^29.6.3",
68
68
  "jest-snapshot-serializer-raw": "^1.2.0",
69
- "metro-babel-register": "0.80.9",
70
- "metro-memory-fs": "0.80.9",
69
+ "metro-babel-register": "0.80.10",
70
+ "metro-memory-fs": "0.80.10",
71
71
  "mock-req": "^0.2.0",
72
72
  "mock-res": "^0.6.0",
73
73
  "stack-trace": "^0.0.10"
@@ -35,6 +35,7 @@ function baseJSBundle(entryPoint, preModules, graph, options) {
35
35
  shouldAddToIgnoreList: options.shouldAddToIgnoreList,
36
36
  sourceMapUrl: options.sourceMapUrl,
37
37
  sourceUrl: options.sourceUrl,
38
+ getSourceUrl: options.getSourceUrl,
38
39
  }),
39
40
  processModulesOptions
40
41
  )
@@ -67,6 +67,7 @@ function baseJSBundle(
67
67
  shouldAddToIgnoreList: options.shouldAddToIgnoreList,
68
68
  sourceMapUrl: options.sourceMapUrl,
69
69
  sourceUrl: options.sourceUrl,
70
+ getSourceUrl: options.getSourceUrl,
70
71
  }),
71
72
  processModulesOptions,
72
73
  )
@@ -21,6 +21,7 @@ async function getRamBundleInfo(entryPoint, pre, graph, options) {
21
21
  excludeSource: options.excludeSource,
22
22
  processModuleFilter: options.processModuleFilter,
23
23
  shouldAddToIgnoreList: options.shouldAddToIgnoreList,
24
+ getSourceUrl: options.getSourceUrl,
24
25
  }),
25
26
  name: path.basename(module.path),
26
27
  sourcePath: module.path,
@@ -65,6 +65,7 @@ async function getRamBundleInfo(
65
65
  excludeSource: options.excludeSource,
66
66
  processModuleFilter: options.processModuleFilter,
67
67
  shouldAddToIgnoreList: options.shouldAddToIgnoreList,
68
+ getSourceUrl: options.getSourceUrl,
68
69
  }),
69
70
  name: path.basename(module.path),
70
71
  sourcePath: module.path,
@@ -5,7 +5,7 @@ function getSourceMapInfo(module, options) {
5
5
  return {
6
6
  ...getJsOutput(module).data,
7
7
  isIgnored: options.shouldAddToIgnoreList(module),
8
- path: module.path,
8
+ path: options?.getSourceUrl?.(module) ?? module.path,
9
9
  source: options.excludeSource ? "" : getModuleSource(module),
10
10
  };
11
11
  }
@@ -24,6 +24,7 @@ function getSourceMapInfo(
24
24
  options: {
25
25
  +excludeSource: boolean,
26
26
  +shouldAddToIgnoreList: (Module<>) => boolean,
27
+ getSourceUrl: ?(module: Module<>) => string,
27
28
  },
28
29
  ): {
29
30
  +map: Array<MetroSourceMapSegmentTuple>,
@@ -37,7 +38,7 @@ function getSourceMapInfo(
37
38
  return {
38
39
  ...getJsOutput(module).data,
39
40
  isIgnored: options.shouldAddToIgnoreList(module),
40
- path: module.path,
41
+ path: options?.getSourceUrl?.(module) ?? module.path,
41
42
  source: options.excludeSource ? '' : getModuleSource(module),
42
43
  };
43
44
  }
@@ -19,6 +19,7 @@ function getSourceMapInfosImpl(isBlocking, onDone, modules, options) {
19
19
  const info = getSourceMapInfo(mod, {
20
20
  excludeSource: options.excludeSource,
21
21
  shouldAddToIgnoreList: options.shouldAddToIgnoreList,
22
+ getSourceUrl: options.getSourceUrl,
22
23
  });
23
24
  sourceMapInfos.push(info);
24
25
  return false;
@@ -24,6 +24,7 @@ export type SourceMapGeneratorOptions = $ReadOnly<{
24
24
  excludeSource: boolean,
25
25
  processModuleFilter: (module: Module<>) => boolean,
26
26
  shouldAddToIgnoreList: (module: Module<>) => boolean,
27
+ getSourceUrl: ?(module: Module<>) => string,
27
28
  }>;
28
29
 
29
30
  function getSourceMapInfosImpl(
@@ -43,9 +44,11 @@ function getSourceMapInfosImpl(
43
44
  }
44
45
 
45
46
  const mod = modulesToProcess.shift();
47
+ // $FlowFixMe[incompatible-call]
46
48
  const info = getSourceMapInfo(mod, {
47
49
  excludeSource: options.excludeSource,
48
50
  shouldAddToIgnoreList: options.shouldAddToIgnoreList,
51
+ getSourceUrl: options.getSourceUrl,
49
52
  });
50
53
  sourceMapInfos.push(info);
51
54
  return false;
@@ -1,9 +1,21 @@
1
1
  "use strict";
2
2
 
3
- const { sourceMapGenerator } = require("./sourceMapGenerator");
3
+ const {
4
+ sourceMapGenerator,
5
+ sourceMapGeneratorNonBlocking,
6
+ } = require("./sourceMapGenerator");
4
7
  function sourceMapString(modules, options) {
5
8
  return sourceMapGenerator(modules, options).toString(undefined, {
6
9
  excludeSource: options.excludeSource,
7
10
  });
8
11
  }
9
- module.exports = sourceMapString;
12
+ async function sourceMapStringNonBlocking(modules, options) {
13
+ const generator = await sourceMapGeneratorNonBlocking(modules, options);
14
+ return generator.toString(undefined, {
15
+ excludeSource: options.excludeSource,
16
+ });
17
+ }
18
+ module.exports = {
19
+ sourceMapString,
20
+ sourceMapStringNonBlocking,
21
+ };
@@ -14,7 +14,10 @@
14
14
  import type {Module} from '../types.flow';
15
15
  import type {SourceMapGeneratorOptions} from './sourceMapGenerator';
16
16
 
17
- const {sourceMapGenerator} = require('./sourceMapGenerator');
17
+ const {
18
+ sourceMapGenerator,
19
+ sourceMapGeneratorNonBlocking,
20
+ } = require('./sourceMapGenerator');
18
21
 
19
22
  function sourceMapString(
20
23
  modules: $ReadOnlyArray<Module<>>,
@@ -25,4 +28,17 @@ function sourceMapString(
25
28
  });
26
29
  }
27
30
 
28
- module.exports = sourceMapString;
31
+ async function sourceMapStringNonBlocking(
32
+ modules: $ReadOnlyArray<Module<>>,
33
+ options: SourceMapGeneratorOptions,
34
+ ): Promise<string> {
35
+ const generator = await sourceMapGeneratorNonBlocking(modules, options);
36
+ return generator.toString(undefined, {
37
+ excludeSource: options.excludeSource,
38
+ });
39
+ }
40
+
41
+ module.exports = {
42
+ sourceMapString,
43
+ sourceMapStringNonBlocking,
44
+ };
@@ -64,7 +64,7 @@ class Transformer {
64
64
  const localPath = path.relative(this._config.projectRoot, filePath);
65
65
  const partialKey = stableHash([
66
66
  this._baseHash,
67
- localPath,
67
+ path.sep === "/" ? localPath : localPath.replaceAll(path.sep, "/"),
68
68
  customTransformOptions,
69
69
  dev,
70
70
  experimentalImportSupport,
@@ -105,8 +105,10 @@ class Transformer {
105
105
  // This is the hash related to the global Bundler config.
106
106
  this._baseHash,
107
107
 
108
- // Path.
109
- localPath,
108
+ // Project-relative, posix-separated path for portability. Necessary in
109
+ // addition to content hash because transformers receive path as an
110
+ // input, and may apply e.g. extension-based logic.
111
+ path.sep === '/' ? localPath : localPath.replaceAll(path.sep, '/'),
110
112
 
111
113
  customTransformOptions,
112
114
  dev,
@@ -23,7 +23,7 @@ export type MixedOutput = {
23
23
  +type: string,
24
24
  };
25
25
 
26
- export type AsyncDependencyType = 'async' | 'prefetch' | 'weak';
26
+ export type AsyncDependencyType = 'async' | 'maybeSync' | 'prefetch' | 'weak';
27
27
 
28
28
  export type TransformResultDependency = $ReadOnly<{
29
29
  /**
@@ -175,4 +175,5 @@ export type SerializerOptions = $ReadOnly<{
175
175
  shouldAddToIgnoreList: (Module<>) => boolean,
176
176
  sourceMapUrl: ?string,
177
177
  sourceUrl: ?string,
178
+ getSourceUrl: ?(Module<>) => string,
178
179
  }>;
@@ -67,6 +67,21 @@ function collectDependencies(ast, options) {
67
67
  visited.add(path.node);
68
68
  return;
69
69
  }
70
+ if (
71
+ callee.type === "MemberExpression" &&
72
+ callee.object.type === "Identifier" &&
73
+ callee.object.name === "require" &&
74
+ callee.property.type === "Identifier" &&
75
+ callee.property.name === "unstable_importMaybeSync" &&
76
+ !callee.computed &&
77
+ !path.scope.getBinding("require")
78
+ ) {
79
+ processImportCall(path, state, {
80
+ asyncType: "maybeSync",
81
+ });
82
+ visited.add(path.node);
83
+ return;
84
+ }
70
85
  if (
71
86
  name != null &&
72
87
  state.dependencyCalls.has(name) &&
@@ -261,10 +276,21 @@ function processImportCall(path, state, options) {
261
276
  path
262
277
  );
263
278
  const transformer = state.dependencyTransformer;
264
- if (options.asyncType === "async") {
265
- transformer.transformImportCall(path, dep, state);
266
- } else {
267
- transformer.transformPrefetch(path, dep, state);
279
+ switch (options.asyncType) {
280
+ case "async":
281
+ transformer.transformImportCall(path, dep, state);
282
+ break;
283
+ case "maybeSync":
284
+ transformer.transformImportMaybeSyncCall(path, dep, state);
285
+ break;
286
+ case "prefetch":
287
+ transformer.transformPrefetch(path, dep, state);
288
+ break;
289
+ case "weak":
290
+ throw new Error("Unreachable");
291
+ default:
292
+ options.asyncType;
293
+ throw new Error("Unreachable");
268
294
  }
269
295
  }
270
296
  function processRequireCall(path, state) {
@@ -380,6 +406,12 @@ const makeAsyncPrefetchTemplate = template.expression(`
380
406
  const makeAsyncPrefetchTemplateWithName = template.expression(`
381
407
  require(ASYNC_REQUIRE_MODULE_PATH).prefetch(MODULE_ID, DEPENDENCY_MAP.paths, MODULE_NAME)
382
408
  `);
409
+ const makeAsyncImportMaybeSyncTemplate = template.expression(`
410
+ require(ASYNC_REQUIRE_MODULE_PATH).unstable_importMaybeSync(MODULE_ID, DEPENDENCY_MAP.paths)
411
+ `);
412
+ const makeAsyncImportMaybeSyncTemplateWithName = template.expression(`
413
+ require(ASYNC_REQUIRE_MODULE_PATH).unstable_importMaybeSync(MODULE_ID, DEPENDENCY_MAP.paths, MODULE_NAME)
414
+ `);
383
415
  const makeResolveWeakTemplate = template.expression(`
384
416
  MODULE_ID
385
417
  `);
@@ -409,6 +441,24 @@ const DefaultDependencyTransformer = {
409
441
  };
410
442
  path.replaceWith(makeNode(opts));
411
443
  },
444
+ transformImportMaybeSyncCall(path, dependency, state) {
445
+ const makeNode = state.keepRequireNames
446
+ ? makeAsyncImportMaybeSyncTemplateWithName
447
+ : makeAsyncImportMaybeSyncTemplate;
448
+ const opts = {
449
+ ASYNC_REQUIRE_MODULE_PATH: nullthrows(
450
+ state.asyncRequireModulePathStringLiteral
451
+ ),
452
+ MODULE_ID: createModuleIDExpression(dependency, state),
453
+ DEPENDENCY_MAP: nullthrows(state.dependencyMapIdentifier),
454
+ ...(state.keepRequireNames
455
+ ? {
456
+ MODULE_NAME: createModuleNameLiteral(dependency),
457
+ }
458
+ : null),
459
+ };
460
+ path.replaceWith(makeNode(opts));
461
+ },
412
462
  transformPrefetch(path, dependency, state) {
413
463
  const makeNode = state.keepRequireNames
414
464
  ? makeAsyncPrefetchTemplateWithName
@@ -112,6 +112,11 @@ export interface DependencyTransformer {
112
112
  dependency: InternalDependency,
113
113
  state: State,
114
114
  ): void;
115
+ transformImportMaybeSyncCall(
116
+ path: NodePath<>,
117
+ dependency: InternalDependency,
118
+ state: State,
119
+ ): void;
115
120
  transformPrefetch(
116
121
  path: NodePath<>,
117
122
  dependency: InternalDependency,
@@ -214,6 +219,26 @@ function collectDependencies(
214
219
  return;
215
220
  }
216
221
 
222
+ // Match `require.unstable_importMaybeSync`
223
+ if (
224
+ callee.type === 'MemberExpression' &&
225
+ // `require`
226
+ callee.object.type === 'Identifier' &&
227
+ callee.object.name === 'require' &&
228
+ // `unstable_importMaybeSync`
229
+ callee.property.type === 'Identifier' &&
230
+ callee.property.name === 'unstable_importMaybeSync' &&
231
+ !callee.computed &&
232
+ // Ensure `require` refers to the global and not something else.
233
+ !path.scope.getBinding('require')
234
+ ) {
235
+ processImportCall(path, state, {
236
+ asyncType: 'maybeSync',
237
+ });
238
+ visited.add(path.node);
239
+ return;
240
+ }
241
+
217
242
  if (
218
243
  name != null &&
219
244
  state.dependencyCalls.has(name) &&
@@ -456,10 +481,21 @@ function processImportCall(
456
481
 
457
482
  const transformer = state.dependencyTransformer;
458
483
 
459
- if (options.asyncType === 'async') {
460
- transformer.transformImportCall(path, dep, state);
461
- } else {
462
- transformer.transformPrefetch(path, dep, state);
484
+ switch (options.asyncType) {
485
+ case 'async':
486
+ transformer.transformImportCall(path, dep, state);
487
+ break;
488
+ case 'maybeSync':
489
+ transformer.transformImportMaybeSyncCall(path, dep, state);
490
+ break;
491
+ case 'prefetch':
492
+ transformer.transformPrefetch(path, dep, state);
493
+ break;
494
+ case 'weak':
495
+ throw new Error('Unreachable');
496
+ default:
497
+ options.asyncType as empty;
498
+ throw new Error('Unreachable');
463
499
  }
464
500
  }
465
501
 
@@ -639,6 +675,14 @@ const makeAsyncPrefetchTemplateWithName = template.expression(`
639
675
  require(ASYNC_REQUIRE_MODULE_PATH).prefetch(MODULE_ID, DEPENDENCY_MAP.paths, MODULE_NAME)
640
676
  `);
641
677
 
678
+ const makeAsyncImportMaybeSyncTemplate = template.expression(`
679
+ require(ASYNC_REQUIRE_MODULE_PATH).unstable_importMaybeSync(MODULE_ID, DEPENDENCY_MAP.paths)
680
+ `);
681
+
682
+ const makeAsyncImportMaybeSyncTemplateWithName = template.expression(`
683
+ require(ASYNC_REQUIRE_MODULE_PATH).unstable_importMaybeSync(MODULE_ID, DEPENDENCY_MAP.paths, MODULE_NAME)
684
+ `);
685
+
642
686
  const makeResolveWeakTemplate = template.expression(`
643
687
  MODULE_ID
644
688
  `);
@@ -683,6 +727,27 @@ const DefaultDependencyTransformer: DependencyTransformer = {
683
727
  path.replaceWith(makeNode(opts));
684
728
  },
685
729
 
730
+ transformImportMaybeSyncCall(
731
+ path: NodePath<>,
732
+ dependency: InternalDependency,
733
+ state: State,
734
+ ): void {
735
+ const makeNode = state.keepRequireNames
736
+ ? makeAsyncImportMaybeSyncTemplateWithName
737
+ : makeAsyncImportMaybeSyncTemplate;
738
+ const opts = {
739
+ ASYNC_REQUIRE_MODULE_PATH: nullthrows(
740
+ state.asyncRequireModulePathStringLiteral,
741
+ ),
742
+ MODULE_ID: createModuleIDExpression(dependency, state),
743
+ DEPENDENCY_MAP: nullthrows(state.dependencyMapIdentifier),
744
+ ...(state.keepRequireNames
745
+ ? {MODULE_NAME: createModuleNameLiteral(dependency)}
746
+ : null),
747
+ };
748
+ path.replaceWith(makeNode(opts));
749
+ },
750
+
686
751
  transformPrefetch(
687
752
  path: NodePath<>,
688
753
  dependency: InternalDependency,
package/src/Server.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ var _types = require("./shared/types.flow");
3
4
  const { getAsset } = require("./Assets");
4
5
  const baseJSBundle = require("./DeltaBundler/Serializers/baseJSBundle");
5
6
  const getAllFiles = require("./DeltaBundler/Serializers/getAllFiles");
@@ -8,7 +9,9 @@ const {
8
9
  getExplodedSourceMap,
9
10
  } = require("./DeltaBundler/Serializers/getExplodedSourceMap");
10
11
  const getRamBundleInfo = require("./DeltaBundler/Serializers/getRamBundleInfo");
11
- const sourceMapString = require("./DeltaBundler/Serializers/sourceMapString");
12
+ const {
13
+ sourceMapStringNonBlocking,
14
+ } = require("./DeltaBundler/Serializers/sourceMapString");
12
15
  const IncrementalBundler = require("./IncrementalBundler");
13
16
  const ResourceNotFoundError = require("./IncrementalBundler/ResourceNotFoundError");
14
17
  const bundleToString = require("./lib/bundleToString");
@@ -60,6 +63,22 @@ class Server {
60
63
  this._reporter = config.reporter;
61
64
  this._logger = Logger;
62
65
  this._platforms = new Set(this._config.resolver.platforms);
66
+ this._allowedSuffixesForSourceRequests = [
67
+ ...new Set(
68
+ [
69
+ ...this._config.resolver.sourceExts,
70
+ ...this._config.watcher.additionalExts,
71
+ ...this._config.resolver.assetExts,
72
+ ].map((ext) => "." + ext)
73
+ ),
74
+ ];
75
+ this._sourceRequestRoutingMap = [
76
+ ["/[metro-project]/", path.resolve(this._config.projectRoot)],
77
+ ...this._config.watchFolders.map((watchFolder, index) => [
78
+ `/[metro-watchFolders]/${index}/`,
79
+ path.resolve(watchFolder),
80
+ ]),
81
+ ];
63
82
  this._isEnded = false;
64
83
  this._createModuleId = config.serializer.createModuleIdFactory();
65
84
  this._bundler = new IncrementalBundler(config, {
@@ -128,6 +147,8 @@ class Server {
128
147
  this._config.server.unstable_serverRoot ?? this._config.projectRoot,
129
148
  shouldAddToIgnoreList: (module) =>
130
149
  this._shouldAddModuleToIgnoreList(module),
150
+ getSourceUrl: (module) =>
151
+ this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
131
152
  };
132
153
  let bundleCode = null;
133
154
  let bundleMap = null;
@@ -150,12 +171,14 @@ class Server {
150
171
  ).code;
151
172
  }
152
173
  if (!bundleMap) {
153
- bundleMap = sourceMapString(
174
+ bundleMap = await sourceMapStringNonBlocking(
154
175
  [...prepend, ...this._getSortedModules(graph)],
155
176
  {
156
177
  excludeSource: serializerOptions.excludeSource,
157
178
  processModuleFilter: this._config.serializer.processModuleFilter,
158
179
  shouldAddToIgnoreList: bundleOptions.shouldAddToIgnoreList,
180
+ getSourceUrl: (module) =>
181
+ this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
159
182
  }
160
183
  );
161
184
  }
@@ -215,6 +238,8 @@ class Server {
215
238
  this._config.server.unstable_serverRoot ?? this._config.projectRoot,
216
239
  shouldAddToIgnoreList: (module) =>
217
240
  this._shouldAddModuleToIgnoreList(module),
241
+ getSourceUrl: (module) =>
242
+ this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
218
243
  });
219
244
  }
220
245
  async getAssets(options) {
@@ -342,7 +367,7 @@ class Server {
342
367
  async _processRequest(req, res, next) {
343
368
  const originalUrl = req.url;
344
369
  req.url = this._rewriteAndNormalizeUrl(req.url);
345
- const urlObj = url.parse(req.url, true);
370
+ const urlObj = url.parse(decodeURI(req.url), true);
346
371
  const { host } = req.headers;
347
372
  debug(
348
373
  `Handling request: ${host ? "http://" + host : ""}${req.url}` +
@@ -393,9 +418,58 @@ class Server {
393
418
  } else if (pathname === "/symbolicate") {
394
419
  await this._symbolicate(req, res);
395
420
  } else {
396
- next();
421
+ let handled = false;
422
+ for (const [pathnamePrefix, normalizedRootDir] of this
423
+ ._sourceRequestRoutingMap) {
424
+ if (pathname.startsWith(pathnamePrefix)) {
425
+ const relativePathname = pathname.substr(pathnamePrefix.length);
426
+ await this._processSourceRequest(
427
+ relativePathname,
428
+ normalizedRootDir,
429
+ res
430
+ );
431
+ handled = true;
432
+ break;
433
+ }
434
+ }
435
+ if (!handled) {
436
+ next();
437
+ }
397
438
  }
398
439
  }
440
+ async _processSourceRequest(relativePathname, rootDir, res) {
441
+ if (
442
+ !this._allowedSuffixesForSourceRequests.some((suffix) =>
443
+ relativePathname.endsWith(suffix)
444
+ )
445
+ ) {
446
+ res.writeHead(404);
447
+ res.end();
448
+ return;
449
+ }
450
+ const depGraph = await this._bundler.getBundler().getDependencyGraph();
451
+ const filePath = path.join(rootDir, relativePathname);
452
+ try {
453
+ depGraph.getSha1(filePath);
454
+ } catch {
455
+ res.writeHead(404);
456
+ res.end();
457
+ return;
458
+ }
459
+ const mimeType = mime.lookup(path.basename(relativePathname));
460
+ res.setHeader("Content-Type", mimeType);
461
+ const stream = fs.createReadStream(filePath);
462
+ stream.pipe(res);
463
+ stream.on("error", (error) => {
464
+ if (error.code === "ENOENT") {
465
+ res.writeHead(404);
466
+ res.end();
467
+ } else {
468
+ res.writeHead(500);
469
+ res.end();
470
+ }
471
+ });
472
+ }
399
473
  _createRequestProcessor({
400
474
  createStartEntry,
401
475
  createEndEntry,
@@ -673,6 +747,8 @@ class Server {
673
747
  this._config.server.unstable_serverRoot ?? this._config.projectRoot,
674
748
  shouldAddToIgnoreList: (module) =>
675
749
  this._shouldAddModuleToIgnoreList(module),
750
+ getSourceUrl: (module) =>
751
+ this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
676
752
  }
677
753
  );
678
754
  bundlePerfLogger.point("serializingBundle_end");
@@ -795,12 +871,17 @@ class Server {
795
871
  if (serializerOptions.modulesOnly) {
796
872
  prepend = [];
797
873
  }
798
- return sourceMapString([...prepend, ...this._getSortedModules(graph)], {
799
- excludeSource: serializerOptions.excludeSource,
800
- processModuleFilter: this._config.serializer.processModuleFilter,
801
- shouldAddToIgnoreList: (module) =>
802
- this._shouldAddModuleToIgnoreList(module),
803
- });
874
+ return await sourceMapStringNonBlocking(
875
+ [...prepend, ...this._getSortedModules(graph)],
876
+ {
877
+ excludeSource: serializerOptions.excludeSource,
878
+ processModuleFilter: this._config.serializer.processModuleFilter,
879
+ shouldAddToIgnoreList: (module) =>
880
+ this._shouldAddModuleToIgnoreList(module),
881
+ getSourceUrl: (module) =>
882
+ this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
883
+ }
884
+ );
804
885
  },
805
886
  finish({ mres, result }) {
806
887
  mres.setHeader("Content-Type", "application/json");
@@ -1057,6 +1138,7 @@ class Server {
1057
1138
  shallow: false,
1058
1139
  sourceMapUrl: null,
1059
1140
  sourceUrl: null,
1141
+ sourcePaths: _types.SourcePathsMode.Absolute,
1060
1142
  };
1061
1143
  _getServerRootDir() {
1062
1144
  return this._config.server.unstable_serverRoot ?? this._config.projectRoot;
@@ -1074,6 +1156,27 @@ class Server {
1074
1156
  this._config.serializer.isThirdPartyModule(module)
1075
1157
  );
1076
1158
  }
1159
+ _getModuleSourceUrl(module, mode) {
1160
+ switch (mode) {
1161
+ case _types.SourcePathsMode.ServerUrl:
1162
+ for (const [pathnamePrefix, normalizedRootDir] of this
1163
+ ._sourceRequestRoutingMap) {
1164
+ if (module.path.startsWith(normalizedRootDir + path.sep)) {
1165
+ const relativePath = module.path.slice(
1166
+ normalizedRootDir.length + 1
1167
+ );
1168
+ const relativePathPosix = relativePath.split(path.sep).join("/");
1169
+ return pathnamePrefix + encodeURI(relativePathPosix);
1170
+ }
1171
+ }
1172
+ const modulePathPosix = module.path.split(path.sep).join("/");
1173
+ return modulePathPosix.startsWith("/")
1174
+ ? encodeURI(modulePathPosix)
1175
+ : "/" + encodeURI(modulePathPosix);
1176
+ case _types.SourcePathsMode.Absolute:
1177
+ return module.path;
1178
+ }
1179
+ }
1077
1180
  }
1078
1181
  function* zip(xs, ys) {
1079
1182
  const ysIter = ys[Symbol.iterator]();