metro 0.80.8 → 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 (65) 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 +17 -3
  13. package/src/DeltaBundler/Transformer.js.flow +20 -4
  14. package/src/DeltaBundler/types.flow.js.flow +2 -1
  15. package/src/ModuleGraph/worker/JsFileWrapping.js +3 -2
  16. package/src/ModuleGraph/worker/JsFileWrapping.js.flow +4 -1
  17. package/src/ModuleGraph/worker/collectDependencies.js +54 -4
  18. package/src/ModuleGraph/worker/collectDependencies.js.flow +69 -4
  19. package/src/Server.js +113 -10
  20. package/src/Server.js.flow +131 -10
  21. package/src/cli/parseKeyValueParamArray.js +4 -5
  22. package/src/cli/parseKeyValueParamArray.js.flow +5 -3
  23. package/src/index.flow.js +7 -0
  24. package/src/index.flow.js.flow +8 -0
  25. package/src/integration_tests/basic_bundle/excluded_from_file_map.js +8 -0
  26. package/src/integration_tests/basic_bundle/excluded_from_file_map.js.flow +11 -0
  27. package/src/integration_tests/basic_bundle/import-export/export-7.js +5 -0
  28. package/src/integration_tests/basic_bundle/import-export/export-7.js.flow +15 -0
  29. package/src/integration_tests/basic_bundle/import-export/export-8.js +10 -0
  30. package/src/integration_tests/basic_bundle/import-export/export-8.js.flow +15 -0
  31. package/src/integration_tests/basic_bundle/import-export/index.js +9 -1
  32. package/src/integration_tests/basic_bundle/import-export/index.js.flow +9 -0
  33. package/src/integration_tests/basic_bundle/import-export/utils.js +1 -0
  34. package/src/integration_tests/basic_bundle/import-export/utils.js.flow +14 -0
  35. package/src/integration_tests/basic_bundle/not_a_source_file.xyz +1 -0
  36. package/src/integration_tests/metro.config.js +1 -0
  37. package/src/lib/BatchProcessor.js +3 -0
  38. package/src/lib/BatchProcessor.js.flow +4 -0
  39. package/src/lib/JsonReporter.js +30 -3
  40. package/src/lib/JsonReporter.js.flow +50 -5
  41. package/src/lib/TerminalReporter.js +4 -24
  42. package/src/lib/TerminalReporter.js.flow +13 -32
  43. package/src/lib/getAppendScripts.js +4 -1
  44. package/src/lib/getAppendScripts.js.flow +5 -1
  45. package/src/lib/logToConsole.js.flow +1 -0
  46. package/src/lib/parseOptionsFromUrl.js +4 -0
  47. package/src/lib/parseOptionsFromUrl.js.flow +4 -0
  48. package/src/lib/reporting.d.ts +9 -5
  49. package/src/lib/reporting.js.flow +9 -5
  50. package/src/lib/splitBundleOptions.js +1 -0
  51. package/src/lib/splitBundleOptions.js.flow +1 -0
  52. package/src/node-haste/DependencyGraph/ModuleResolution.js +10 -9
  53. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +16 -14
  54. package/src/node-haste/DependencyGraph.js +8 -4
  55. package/src/node-haste/DependencyGraph.js.flow +12 -4
  56. package/src/node-haste/Module.js +1 -1
  57. package/src/node-haste/Module.js.flow +1 -1
  58. package/src/node-haste/ModuleCache.js +28 -14
  59. package/src/node-haste/ModuleCache.js.flow +43 -18
  60. package/src/node-haste/lib/AssetPaths.js +1 -1
  61. package/src/node-haste/lib/AssetPaths.js.flow +1 -1
  62. package/src/shared/output/bundle.flow.js +2 -2
  63. package/src/shared/output/bundle.flow.js.flow +2 -2
  64. package/src/shared/types.flow.js +10 -0
  65. 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.8",
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.8",
38
- "metro-cache": "0.80.8",
39
- "metro-cache-key": "0.80.8",
40
- "metro-config": "0.80.8",
41
- "metro-core": "0.80.8",
42
- "metro-file-map": "0.80.8",
43
- "metro-resolver": "0.80.8",
44
- "metro-runtime": "0.80.8",
45
- "metro-source-map": "0.80.8",
46
- "metro-symbolicate": "0.80.8",
47
- "metro-transform-plugins": "0.80.8",
48
- "metro-transform-worker": "0.80.8",
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.8",
70
- "metro-memory-fs": "0.80.8",
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,
@@ -88,7 +88,16 @@ class Transformer {
88
88
  sha1 = this._getSha1(filePath);
89
89
  }
90
90
  let fullKey = Buffer.concat([partialKey, Buffer.from(sha1, "hex")]);
91
- const result = await cache.get(fullKey);
91
+ let result;
92
+ try {
93
+ result = await cache.get(fullKey);
94
+ } catch (error) {
95
+ this._config.reporter.update({
96
+ type: "cache_read_error",
97
+ error,
98
+ });
99
+ throw error;
100
+ }
92
101
  const data = result
93
102
  ? {
94
103
  result,
@@ -102,7 +111,12 @@ class Transformer {
102
111
  if (sha1 !== data.sha1) {
103
112
  fullKey = Buffer.concat([partialKey, Buffer.from(data.sha1, "hex")]);
104
113
  }
105
- void cache.set(fullKey, data.result);
114
+ cache.set(fullKey, data.result).catch((error) => {
115
+ this._config.reporter.update({
116
+ type: "cache_write_error",
117
+ error,
118
+ });
119
+ });
106
120
  return {
107
121
  ...data.result,
108
122
  unstable_transformResultKey: fullKey.toString(),
@@ -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,
@@ -131,7 +133,16 @@ class Transformer {
131
133
  }
132
134
 
133
135
  let fullKey = Buffer.concat([partialKey, Buffer.from(sha1, 'hex')]);
134
- const result = await cache.get(fullKey);
136
+ let result;
137
+ try {
138
+ result = await cache.get(fullKey);
139
+ } catch (error) {
140
+ this._config.reporter.update({
141
+ type: 'cache_read_error',
142
+ error,
143
+ });
144
+ throw error;
145
+ }
135
146
 
136
147
  // A valid result from the cache is used directly; otherwise we call into
137
148
  // the transformer to computed the corresponding result.
@@ -154,7 +165,12 @@ class Transformer {
154
165
  }
155
166
 
156
167
  // Fire-and-forget cache set promise.
157
- void cache.set(fullKey, data.result);
168
+ cache.set(fullKey, data.result).catch(error => {
169
+ this._config.reporter.update({
170
+ type: 'cache_write_error',
171
+ error,
172
+ });
173
+ });
158
174
 
159
175
  return {
160
176
  ...data.result,
@@ -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
  }>;
@@ -56,7 +56,8 @@ function wrapModule(
56
56
  importDefaultName,
57
57
  importAllName,
58
58
  dependencyMapName,
59
- globalPrefix
59
+ globalPrefix,
60
+ skipRequireRename
60
61
  ) {
61
62
  const params = buildParameters(
62
63
  importDefaultName,
@@ -66,7 +67,7 @@ function wrapModule(
66
67
  const factory = functionFromProgram(fileAst.program, params);
67
68
  const def = t.callExpression(t.identifier(`${globalPrefix}__d`), [factory]);
68
69
  const ast = t.file(t.program([t.expressionStatement(def)]));
69
- const requireName = renameRequires(ast);
70
+ const requireName = skipRequireRename ? "require" : renameRequires(ast);
70
71
  return {
71
72
  ast,
72
73
  requireName,
@@ -32,6 +32,7 @@ function wrapModule(
32
32
  importAllName: string,
33
33
  dependencyMapName: string,
34
34
  globalPrefix: string,
35
+ skipRequireRename: boolean,
35
36
  ): {
36
37
  ast: BabelNodeFile,
37
38
  requireName: string,
@@ -45,7 +46,9 @@ function wrapModule(
45
46
  const def = t.callExpression(t.identifier(`${globalPrefix}__d`), [factory]);
46
47
  const ast = t.file(t.program([t.expressionStatement(def)]));
47
48
 
48
- const requireName = renameRequires(ast);
49
+ // `require` doesn't need to be scoped when Metro serializes to iife because the local function
50
+ // `require` will be used instead of the global one.
51
+ const requireName = skipRequireRename ? 'require' : renameRequires(ast);
49
52
 
50
53
  return {ast, requireName};
51
54
  }
@@ -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,