metro 0.63.0 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/package.json +22 -22
  2. package/src/Assets.js +8 -2
  3. package/src/Bundler/util.js +17 -10
  4. package/src/Bundler/util.js.flow +13 -12
  5. package/src/Bundler.js +4 -0
  6. package/src/DeltaBundler/DeltaCalculator.js +6 -1
  7. package/src/DeltaBundler/Serializers/baseBytecodeBundle.js +10 -0
  8. package/src/DeltaBundler/Serializers/baseJSBundle.js +5 -0
  9. package/src/DeltaBundler/Serializers/getAllFiles.js +6 -0
  10. package/src/DeltaBundler/Serializers/getAssets.js +4 -0
  11. package/src/DeltaBundler/Serializers/getRamBundleInfo.js +6 -0
  12. package/src/DeltaBundler/Serializers/helpers/bytecode.js +5 -0
  13. package/src/DeltaBundler/Serializers/helpers/getSourceMapInfo.js +5 -0
  14. package/src/DeltaBundler/Serializers/helpers/processBytecodeModules.js +2 -0
  15. package/src/DeltaBundler/Serializers/helpers/processModules.js +2 -0
  16. package/src/DeltaBundler/Serializers/hmrJSBundle.js +8 -2
  17. package/src/DeltaBundler/Serializers/sourceMapGenerator.js +4 -0
  18. package/src/DeltaBundler/Serializers/sourceMapObject.js +4 -0
  19. package/src/DeltaBundler/Transformer.js +16 -0
  20. package/src/DeltaBundler/Worker.js +4 -0
  21. package/src/DeltaBundler/WorkerFarm.js +9 -0
  22. package/src/DeltaBundler/computeDelta.js +5 -0
  23. package/src/DeltaBundler/getTransformCacheKey.js +1 -1
  24. package/src/DeltaBundler/mergeDeltas.js +5 -0
  25. package/src/DeltaBundler/traverseDependencies.js +14 -0
  26. package/src/DeltaBundler.js +6 -1
  27. package/src/HmrServer.js +18 -0
  28. package/src/IncrementalBundler.js +16 -0
  29. package/src/ModuleGraph/node-haste/Package.js +5 -0
  30. package/src/ModuleGraph/node-haste/node-haste.flow.js.flow +0 -2
  31. package/src/ModuleGraph/node-haste/node-haste.js +3 -0
  32. package/src/ModuleGraph/node-haste/node-haste.js.flow +4 -2
  33. package/src/ModuleGraph/output/indexed-ram-bundle.js +10 -0
  34. package/src/ModuleGraph/output/multiple-files-ram-bundle.js +10 -0
  35. package/src/ModuleGraph/output/reverse-dependency-map-references.js +33 -9
  36. package/src/ModuleGraph/output/reverse-dependency-map-references.js.flow +28 -13
  37. package/src/ModuleGraph/output/util.js +59 -25
  38. package/src/ModuleGraph/output/util.js.flow +59 -23
  39. package/src/ModuleGraph/test-helpers.js +74 -2
  40. package/src/ModuleGraph/types.flow.js.flow +13 -8
  41. package/src/ModuleGraph/worker/JsFileWrapping.js +90 -12
  42. package/src/ModuleGraph/worker/JsFileWrapping.js.flow +34 -20
  43. package/src/ModuleGraph/worker/collectDependencies.js +329 -205
  44. package/src/ModuleGraph/worker/collectDependencies.js.flow +397 -209
  45. package/src/ModuleGraph/worker/generate.js.flow +2 -2
  46. package/src/ModuleGraph/worker/generateImportNames.js +2 -1
  47. package/src/ModuleGraph/worker/generateImportNames.js.flow +3 -4
  48. package/src/ModuleGraph/worker/mergeSourceMaps.js +5 -0
  49. package/src/Server/symbolicate.js +14 -0
  50. package/src/Server.js +16 -3
  51. package/src/Server.js.flow +1 -0
  52. package/src/cli-utils.js +4 -0
  53. package/src/cli.js +0 -0
  54. package/src/commands/build.js +10 -0
  55. package/src/commands/build.js.flow +2 -0
  56. package/src/commands/dependencies.js +4 -0
  57. package/src/commands/serve.js +5 -0
  58. package/src/commands/serve.js.flow +2 -0
  59. package/src/index.js +13 -1
  60. package/src/index.js.flow +2 -0
  61. package/src/integration_tests/basic_bundle/import-export/index.js +19 -2
  62. package/src/integration_tests/execBundle.js +2 -2
  63. package/src/integration_tests/metro.config.js +4 -0
  64. package/src/lib/BatchProcessor.js +1 -1
  65. package/src/lib/TerminalReporter.js +10 -0
  66. package/src/lib/attachWebsocketServer.js +5 -1
  67. package/src/lib/bundleToBytecode.js +7 -3
  68. package/src/lib/bundleToString.js +6 -1
  69. package/src/lib/debounceAsyncQueue.js +4 -0
  70. package/src/lib/getAppendScripts.js +2 -0
  71. package/src/lib/getPreludeCode.js +2 -0
  72. package/src/lib/getPrependedScripts.js +11 -0
  73. package/src/lib/logToConsole.js +1 -2
  74. package/src/lib/parseOptionsFromUrl.js +5 -0
  75. package/src/lib/reporting.js +1 -1
  76. package/src/lib/splitBundleOptions.js +1 -1
  77. package/src/lib/transformHelpers.js +19 -3
  78. package/src/lib/transformHelpers.js.flow +4 -4
  79. package/src/node-haste/DependencyGraph/ModuleResolution.js +10 -2
  80. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +6 -5
  81. package/src/node-haste/DependencyGraph.js +11 -2
  82. package/src/node-haste/DependencyGraph.js.flow +5 -0
  83. package/src/node-haste/Package.js +2 -0
  84. package/src/shared/output/RamBundle/as-assets.js +1 -2
  85. package/src/shared/output/RamBundle/as-indexed-file.js +2 -0
  86. package/src/shared/output/RamBundle/util.js +2 -2
  87. package/src/shared/output/RamBundle.js +9 -0
  88. package/src/shared/output/bundle.js +9 -0
  89. package/src/ModuleGraph/worker/optimizeDependencies.js +0 -122
  90. package/src/ModuleGraph/worker/optimizeDependencies.js.flow +0 -128
@@ -11,6 +11,7 @@
11
11
 
12
12
  function ownKeys(object, enumerableOnly) {
13
13
  var keys = Object.keys(object);
14
+
14
15
  if (Object.getOwnPropertySymbols) {
15
16
  var symbols = Object.getOwnPropertySymbols(object);
16
17
  if (enumerableOnly)
@@ -19,12 +20,14 @@ function ownKeys(object, enumerableOnly) {
19
20
  });
20
21
  keys.push.apply(keys, symbols);
21
22
  }
23
+
22
24
  return keys;
23
25
  }
24
26
 
25
27
  function _objectSpread(target) {
26
28
  for (var i = 1; i < arguments.length; i++) {
27
29
  var source = arguments[i] != null ? arguments[i] : {};
30
+
28
31
  if (i % 2) {
29
32
  ownKeys(Object(source), true).forEach(function(key) {
30
33
  _defineProperty(target, key, source[key]);
@@ -41,6 +44,7 @@ function _objectSpread(target) {
41
44
  });
42
45
  }
43
46
  }
47
+
44
48
  return target;
45
49
  }
46
50
 
@@ -55,55 +59,44 @@ function _defineProperty(obj, key, value) {
55
59
  } else {
56
60
  obj[key] = value;
57
61
  }
62
+
58
63
  return obj;
59
64
  }
60
65
 
61
- function _slicedToArray(arr, i) {
62
- return (
63
- _arrayWithHoles(arr) ||
64
- _iterableToArrayLimit(arr, i) ||
65
- _unsupportedIterableToArray(arr, i) ||
66
- _nonIterableRest()
67
- );
68
- }
66
+ function _objectWithoutProperties(source, excluded) {
67
+ if (source == null) return {};
69
68
 
70
- function _nonIterableRest() {
71
- throw new TypeError(
72
- "Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
73
- );
74
- }
69
+ var target = _objectWithoutPropertiesLoose(source, excluded);
75
70
 
76
- function _iterableToArrayLimit(arr, i) {
77
- if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr)))
78
- return;
79
- var _arr = [];
80
- var _n = true;
81
- var _d = false;
82
- var _e = undefined;
83
- try {
84
- for (
85
- var _i = arr[Symbol.iterator](), _s;
86
- !(_n = (_s = _i.next()).done);
87
- _n = true
88
- ) {
89
- _arr.push(_s.value);
90
- if (i && _arr.length === i) break;
91
- }
92
- } catch (err) {
93
- _d = true;
94
- _e = err;
95
- } finally {
96
- try {
97
- if (!_n && _i["return"] != null) _i["return"]();
98
- } finally {
99
- if (_d) throw _e;
71
+ var key, i;
72
+
73
+ if (Object.getOwnPropertySymbols) {
74
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
75
+
76
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
77
+ key = sourceSymbolKeys[i];
78
+ if (excluded.indexOf(key) >= 0) continue;
79
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
80
+ target[key] = source[key];
100
81
  }
101
82
  }
102
- return _arr;
83
+
84
+ return target;
103
85
  }
104
86
 
105
- function _arrayWithHoles(arr) {
106
- if (Array.isArray(arr)) return arr;
87
+ function _objectWithoutPropertiesLoose(source, excluded) {
88
+ if (source == null) return {};
89
+ var target = {};
90
+ var sourceKeys = Object.keys(source);
91
+ var key, i;
92
+
93
+ for (i = 0; i < sourceKeys.length; i++) {
94
+ key = sourceKeys[i];
95
+ if (excluded.indexOf(key) >= 0) continue;
96
+ target[key] = source[key];
97
+ }
98
+
99
+ return target;
107
100
  }
108
101
 
109
102
  function _toConsumableArray(arr) {
@@ -142,10 +135,14 @@ function _arrayWithoutHoles(arr) {
142
135
 
143
136
  function _arrayLikeToArray(arr, len) {
144
137
  if (len == null || len > arr.length) len = arr.length;
138
+
145
139
  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
140
+
146
141
  return arr2;
147
142
  }
148
143
 
144
+ const invariant = require("invariant");
145
+
149
146
  const nullthrows = require("nullthrows");
150
147
 
151
148
  const generate = require("@babel/generator").default;
@@ -156,32 +153,7 @@ const traverse = require("@babel/traverse").default;
156
153
 
157
154
  const types = require("@babel/types");
158
155
 
159
- /**
160
- * Produces a Babel template that will throw at runtime when the require call
161
- * is reached. This makes dynamic require errors catchable by libraries that
162
- * want to use them.
163
- */
164
- const dynamicRequireErrorTemplate = template(`
165
- (function(line) {
166
- throw new Error(
167
- 'Dynamic require defined at line ' + line + '; not supported by Metro',
168
- );
169
- })(LINE)
170
- `);
171
- /**
172
- * Produces a Babel template that transforms an "import(...)" call into a
173
- * "require(...)" call to the asyncRequire specified.
174
- */
175
-
176
- const makeAsyncRequireTemplate = template(`
177
- require(ASYNC_REQUIRE_MODULE_PATH)(MODULE_ID, MODULE_NAME)
178
- `);
179
- const makeAsyncPrefetchTemplate = template(`
180
- require(ASYNC_REQUIRE_MODULE_PATH).prefetch(MODULE_ID, MODULE_NAME)
181
- `);
182
- const makeJSResourceTemplate = template(`
183
- require(ASYNC_REQUIRE_MODULE_PATH).resource(MODULE_ID, MODULE_NAME)
184
- `);
156
+ const isImport = types.isImport;
185
157
  /**
186
158
  * Transform all the calls to `require()` and `import()` in a file into ID-
187
159
  * independent code, and return the list of dependencies. For example, a call
@@ -193,17 +165,25 @@ const makeJSResourceTemplate = template(`
193
165
  */
194
166
 
195
167
  function collectDependencies(ast, options) {
168
+ var _options$dependencyRe, _options$dependencyTr;
169
+
196
170
  const visited = new WeakSet();
197
171
  const state = {
198
172
  asyncRequireModulePathStringLiteral: null,
199
- dependency: 0,
200
173
  dependencyCalls: new Set(),
201
- dependencyData: new Map(),
202
- dependencyIndexes: new Map(),
174
+ dependencyRegistry:
175
+ (_options$dependencyRe = options.dependencyRegistry) !== null &&
176
+ _options$dependencyRe !== void 0
177
+ ? _options$dependencyRe
178
+ : new DefaultModuleDependencyRegistry(),
179
+ dependencyTransformer:
180
+ (_options$dependencyTr = options.dependencyTransformer) !== null &&
181
+ _options$dependencyTr !== void 0
182
+ ? _options$dependencyTr
183
+ : DefaultDependencyTransformer,
203
184
  dependencyMapIdentifier: null,
204
185
  dynamicRequires: options.dynamicRequires,
205
186
  keepRequireNames: options.keepRequireNames,
206
- disableRequiresTransform: !!options.disableRequiresTransform,
207
187
  allowOptionalDependencies: options.allowOptionalDependencies
208
188
  };
209
189
  const visitor = {
@@ -212,37 +192,52 @@ function collectDependencies(ast, options) {
212
192
  return;
213
193
  }
214
194
 
215
- const callee = path.get("callee");
216
- const name = callee.node.name;
195
+ const callee = path.node.callee;
196
+ const name = callee.type === "Identifier" ? callee.name : null;
217
197
 
218
- if (callee.isImport()) {
198
+ if (isImport(callee)) {
219
199
  processImportCall(path, state, {
220
- prefetchOnly: false
200
+ asyncType: "async"
221
201
  });
222
202
  return;
223
203
  }
224
204
 
225
205
  if (name === "__prefetchImport" && !path.scope.getBinding(name)) {
226
206
  processImportCall(path, state, {
227
- prefetchOnly: true
207
+ asyncType: "prefetch"
208
+ });
209
+ return;
210
+ }
211
+
212
+ if (name === "__jsResource" && !path.scope.getBinding(name)) {
213
+ processImportCall(path, state, {
214
+ asyncType: "async",
215
+ jsResource: true
228
216
  });
229
217
  return;
230
218
  }
231
219
 
232
220
  if (
233
- (name === "__jsResource" ||
234
- name === "__conditionallySplitJSResource") &&
221
+ name === "__conditionallySplitJSResource" &&
235
222
  !path.scope.getBinding(name)
236
223
  ) {
224
+ const args = path.get("arguments");
225
+ invariant(Array.isArray(args), "Expected arguments to be an array");
237
226
  processImportCall(path, state, {
238
- prefetchOnly: false,
239
- jsResource: true
227
+ asyncType: "async",
228
+ jsResource: true,
229
+ splitCondition: args[1]
240
230
  });
241
231
  return;
242
232
  }
243
233
 
244
- if (state.dependencyCalls.has(name) && !path.scope.getBinding(name)) {
245
- visited.add(processRequireCall(path, state).node);
234
+ if (
235
+ name != null &&
236
+ state.dependencyCalls.has(name) &&
237
+ !path.scope.getBinding(name)
238
+ ) {
239
+ processRequireCall(path, state);
240
+ visited.add(path.node);
246
241
  }
247
242
  },
248
243
 
@@ -270,18 +265,19 @@ function collectDependencies(ast, options) {
270
265
  );
271
266
  }
272
267
  };
273
- traverse(ast, visitor, null, state); // Compute the list of dependencies.
268
+ traverse(ast, visitor, null, state);
269
+ const collectedDependencies = state.dependencyRegistry.getDependencies(); // Compute the list of dependencies.
274
270
 
275
- const dependencies = new Array(state.dependency);
271
+ const dependencies = new Array(collectedDependencies.length);
276
272
 
277
- for (const _ref of state.dependencyData) {
278
- var _ref2 = _slicedToArray(_ref, 2);
273
+ for (const _ref of collectedDependencies) {
274
+ const index = _ref.index,
275
+ name = _ref.name,
276
+ dependencyData = _objectWithoutProperties(_ref, ["index", "name"]);
279
277
 
280
- const name = _ref2[0];
281
- const data = _ref2[1];
282
- dependencies[nullthrows(state.dependencyIndexes.get(name))] = {
278
+ dependencies[index] = {
283
279
  name,
284
- data
280
+ data: dependencyData
285
281
  };
286
282
  }
287
283
 
@@ -294,168 +290,110 @@ function collectDependencies(ast, options) {
294
290
 
295
291
  function collectImports(path, state) {
296
292
  if (path.node.source) {
297
- const dep = getDependency(
293
+ registerDependency(
298
294
  state,
299
- path.node.source.value,
300
295
  {
301
- prefetchOnly: false
296
+ name: path.node.source.value,
297
+ asyncType: null,
298
+ optional: false
302
299
  },
303
300
  path
304
301
  );
305
- dep.data.asyncType = null;
306
302
  }
307
303
  }
308
304
 
309
- function processImportCall(path, state, opts) {
305
+ function processImportCall(path, state, options) {
310
306
  const name = getModuleNameFromCallArgs(path);
311
307
 
312
308
  if (name == null) {
313
309
  throw new InvalidRequireCallError(path);
314
310
  }
315
311
 
316
- const options = _objectSpread(
317
- _objectSpread({}, opts),
318
- {},
312
+ const dep = registerDependency(
313
+ state,
319
314
  {
320
- isOptional: isOptionalDependency(name, path, state)
321
- }
322
- );
323
-
324
- const dep = getDependency(state, name, options, path);
325
-
326
- if (!options.prefetchOnly && dep.data.asyncType === "prefetch") {
327
- dep.data.asyncType = "async";
328
- }
329
-
330
- if (state.disableRequiresTransform) {
331
- return path;
332
- }
333
-
334
- const ASYNC_REQUIRE_MODULE_PATH = state.asyncRequireModulePathStringLiteral;
335
- const MODULE_ID = types.memberExpression(
336
- state.dependencyMapIdentifier,
337
- types.numericLiteral(dep.index),
338
- true
315
+ name,
316
+ asyncType: options.asyncType,
317
+ splitCondition: options.splitCondition,
318
+ optional: isOptionalDependency(name, path, state)
319
+ },
320
+ path
339
321
  );
340
- const MODULE_NAME = types.stringLiteral(name);
322
+ const transformer = state.dependencyTransformer;
341
323
 
342
324
  if (options.jsResource) {
343
- path.replaceWith(
344
- makeJSResourceTemplate({
345
- ASYNC_REQUIRE_MODULE_PATH,
346
- MODULE_ID,
347
- MODULE_NAME
348
- })
349
- );
350
- } else if (!options.prefetchOnly) {
351
- path.replaceWith(
352
- makeAsyncRequireTemplate({
353
- ASYNC_REQUIRE_MODULE_PATH,
354
- MODULE_ID,
355
- MODULE_NAME
356
- })
357
- );
325
+ transformer.transformJSResource(path, dep, state);
326
+ } else if (options.asyncType === "async") {
327
+ transformer.transformImportCall(path, dep, state);
358
328
  } else {
359
- path.replaceWith(
360
- makeAsyncPrefetchTemplate({
361
- ASYNC_REQUIRE_MODULE_PATH,
362
- MODULE_ID,
363
- MODULE_NAME
364
- })
365
- );
329
+ transformer.transformPrefetch(path, dep, state);
366
330
  }
367
-
368
- return path;
369
331
  }
370
332
 
371
333
  function processRequireCall(path, state) {
372
334
  const name = getModuleNameFromCallArgs(path);
335
+ const transformer = state.dependencyTransformer;
373
336
 
374
337
  if (name == null) {
375
338
  if (state.dynamicRequires === "reject") {
376
339
  throw new InvalidRequireCallError(path);
377
340
  }
378
341
 
379
- path.replaceWith(
380
- dynamicRequireErrorTemplate({
381
- LINE: "" + path.node.loc.start.line
382
- })
383
- );
384
- return path;
342
+ transformer.transformIllegalDynamicRequire(path, state);
343
+ return;
385
344
  }
386
345
 
387
- const dep = getDependency(
346
+ const dep = registerDependency(
388
347
  state,
389
- name,
390
348
  {
391
- prefetchOnly: false,
392
- isOptional: isOptionalDependency(name, path, state)
349
+ name,
350
+ asyncType: null,
351
+ optional: isOptionalDependency(name, path, state)
393
352
  },
394
353
  path
395
354
  );
396
- dep.data.asyncType = null;
397
-
398
- if (state.disableRequiresTransform) {
399
- return path;
400
- }
401
-
402
- const moduleIDExpression = types.memberExpression(
403
- state.dependencyMapIdentifier,
404
- types.numericLiteral(dep.index),
405
- true
406
- );
407
- path.node.arguments = state.keepRequireNames
408
- ? [moduleIDExpression, types.stringLiteral(name)]
409
- : [moduleIDExpression];
410
- return path;
355
+ transformer.transformSyncRequire(path, dep, state);
411
356
  }
412
357
 
413
358
  function getNearestLocFromPath(path) {
414
- var _path;
359
+ var _current;
360
+
361
+ let current = path;
415
362
 
416
- while (path && !path.node.loc) {
417
- path = path.parentPath;
363
+ while (current && !current.node.loc) {
364
+ current = current.parentPath;
418
365
  }
419
366
 
420
- return (_path = path) === null || _path === void 0 ? void 0 : _path.node.loc;
367
+ return (_current = current) === null || _current === void 0
368
+ ? void 0
369
+ : _current.node.loc;
421
370
  }
422
371
 
423
- function getDependency(state, name, options, path) {
372
+ function registerDependency(state, qualifier, path) {
373
+ const dependency = state.dependencyRegistry.registerDependency(qualifier);
424
374
  const loc = getNearestLocFromPath(path);
425
- let index = state.dependencyIndexes.get(name);
426
- let data = state.dependencyData.get(name);
427
-
428
- if (!data) {
429
- index = state.dependency++;
430
- data = {
431
- asyncType: "async",
432
- locs: []
433
- };
434
-
435
- if (options.prefetchOnly) {
436
- data.asyncType = "prefetch";
437
- }
438
-
439
- if (options.isOptional) {
440
- data.isOptional = true;
441
- }
442
-
443
- state.dependencyIndexes.set(name, index);
444
- state.dependencyData.set(name, data);
445
- }
446
375
 
447
376
  if (loc != null) {
448
- data.locs.push(loc);
377
+ dependency.locs.push(loc);
449
378
  }
450
379
 
451
- return {
452
- index: nullthrows(index),
453
- data: nullthrows(data)
454
- };
380
+ return dependency;
455
381
  }
456
382
 
457
- const isOptionalDependency = (name, path, state) => {
458
- const allowOptionalDependencies = state.allowOptionalDependencies;
383
+ function isOptionalDependency(name, path, state) {
384
+ var _state$asyncRequireMo;
385
+
386
+ const allowOptionalDependencies = state.allowOptionalDependencies; // The async require module is a 'built-in'. Resolving should never fail -> treat it as non-optional.
387
+
388
+ if (
389
+ name ===
390
+ ((_state$asyncRequireMo = state.asyncRequireModulePathStringLiteral) ===
391
+ null || _state$asyncRequireMo === void 0
392
+ ? void 0
393
+ : _state$asyncRequireMo.value)
394
+ ) {
395
+ return false;
396
+ }
459
397
 
460
398
  const isExcluded = () =>
461
399
  Array.isArray(allowOptionalDependencies.exclude) &&
@@ -473,7 +411,11 @@ const isOptionalDependency = (name, path, state) => {
473
411
  if (p.node.type === "BlockStatement") {
474
412
  // A single-level should have the tryStatement immediately followed BlockStatement
475
413
  // with the key 'block' to distinguish from the finally block, which has key = 'finalizer'
476
- return p.parentPath.node.type === "TryStatement" && p.key === "block";
414
+ return (
415
+ p.parentPath != null &&
416
+ p.parentPath.node.type === "TryStatement" &&
417
+ p.key === "block"
418
+ );
477
419
  }
478
420
 
479
421
  sCount += 1;
@@ -483,17 +425,18 @@ const isOptionalDependency = (name, path, state) => {
483
425
  }
484
426
 
485
427
  return false;
486
- };
428
+ }
487
429
 
488
430
  function getModuleNameFromCallArgs(path) {
489
431
  const expectedCount =
490
432
  path.node.callee.name === "__conditionallySplitJSResource" ? 2 : 1;
433
+ const args = path.get("arguments");
491
434
 
492
- if (path.get("arguments").length !== expectedCount) {
435
+ if (!Array.isArray(args) || args.length !== expectedCount) {
493
436
  throw new InvalidRequireCallError(path);
494
437
  }
495
438
 
496
- const result = path.get("arguments.0").evaluate();
439
+ const result = args[0].evaluate();
497
440
 
498
441
  if (result.confident && typeof result.value === "string") {
499
442
  return result.value;
@@ -505,8 +448,8 @@ function getModuleNameFromCallArgs(path) {
505
448
  collectDependencies.getModuleNameFromCallArgs = getModuleNameFromCallArgs;
506
449
 
507
450
  class InvalidRequireCallError extends Error {
508
- constructor(_ref3) {
509
- let node = _ref3.node;
451
+ constructor(_ref2) {
452
+ let node = _ref2.node;
510
453
  const line = node.loc && node.loc.start && node.loc.start.line;
511
454
  super(
512
455
  `Invalid call at line ${line || "<unknown>"}: ${generate(node).code}`
@@ -515,4 +458,185 @@ class InvalidRequireCallError extends Error {
515
458
  }
516
459
 
517
460
  collectDependencies.InvalidRequireCallError = InvalidRequireCallError;
461
+ /**
462
+ * Produces a Babel template that will throw at runtime when the require call
463
+ * is reached. This makes dynamic require errors catchable by libraries that
464
+ * want to use them.
465
+ */
466
+
467
+ const dynamicRequireErrorTemplate = template.statement(`
468
+ (function(line) {
469
+ throw new Error(
470
+ 'Dynamic require defined at line ' + line + '; not supported by Metro',
471
+ );
472
+ })(LINE)
473
+ `);
474
+ /**
475
+ * Produces a Babel template that transforms an "import(...)" call into a
476
+ * "require(...)" call to the asyncRequire specified.
477
+ */
478
+
479
+ const makeAsyncRequireTemplate = template.statement(`
480
+ require(ASYNC_REQUIRE_MODULE_PATH)(MODULE_ID, MODULE_NAME)
481
+ `);
482
+ const makeAsyncPrefetchTemplate = template.statement(`
483
+ require(ASYNC_REQUIRE_MODULE_PATH).prefetch(MODULE_ID, MODULE_NAME)
484
+ `);
485
+ const makeJSResourceTemplate = template.statement(`
486
+ require(ASYNC_REQUIRE_MODULE_PATH).resource(MODULE_ID, MODULE_NAME)
487
+ `);
488
+ const DefaultDependencyTransformer = {
489
+ transformSyncRequire(path, dependency, state) {
490
+ const moduleIDExpression = createModuleIDExpression(dependency, state);
491
+ path.node.arguments = state.keepRequireNames
492
+ ? [moduleIDExpression, types.stringLiteral(dependency.name)]
493
+ : [moduleIDExpression];
494
+ },
495
+
496
+ transformImportCall(path, dependency, state) {
497
+ path.replaceWith(
498
+ makeAsyncRequireTemplate({
499
+ ASYNC_REQUIRE_MODULE_PATH: nullthrows(
500
+ state.asyncRequireModulePathStringLiteral
501
+ ),
502
+ MODULE_ID: createModuleIDExpression(dependency, state),
503
+ MODULE_NAME: createModuleNameLiteral(dependency)
504
+ })
505
+ );
506
+ },
507
+
508
+ transformJSResource(path, dependency, state) {
509
+ path.replaceWith(
510
+ makeJSResourceTemplate({
511
+ ASYNC_REQUIRE_MODULE_PATH: nullthrows(
512
+ state.asyncRequireModulePathStringLiteral
513
+ ),
514
+ MODULE_ID: createModuleIDExpression(dependency, state),
515
+ MODULE_NAME: createModuleNameLiteral(dependency)
516
+ })
517
+ );
518
+ },
519
+
520
+ transformPrefetch(path, dependency, state) {
521
+ path.replaceWith(
522
+ makeAsyncPrefetchTemplate({
523
+ ASYNC_REQUIRE_MODULE_PATH: nullthrows(
524
+ state.asyncRequireModulePathStringLiteral
525
+ ),
526
+ MODULE_ID: createModuleIDExpression(dependency, state),
527
+ MODULE_NAME: createModuleNameLiteral(dependency)
528
+ })
529
+ );
530
+ },
531
+
532
+ transformIllegalDynamicRequire(path, state) {
533
+ var _path$node$loc$start$, _path$node$loc;
534
+
535
+ path.replaceWith(
536
+ dynamicRequireErrorTemplate({
537
+ LINE: types.numericLiteral(
538
+ (_path$node$loc$start$ =
539
+ (_path$node$loc = path.node.loc) === null ||
540
+ _path$node$loc === void 0
541
+ ? void 0
542
+ : _path$node$loc.start.line) !== null &&
543
+ _path$node$loc$start$ !== void 0
544
+ ? _path$node$loc$start$
545
+ : 0
546
+ )
547
+ })
548
+ );
549
+ }
550
+ };
551
+
552
+ function createModuleIDExpression(dependency, state) {
553
+ return types.memberExpression(
554
+ nullthrows(state.dependencyMapIdentifier),
555
+ types.numericLiteral(dependency.index),
556
+ true
557
+ );
558
+ }
559
+
560
+ function createModuleNameLiteral(dependency) {
561
+ return types.stringLiteral(dependency.name);
562
+ }
563
+
564
+ class DefaultModuleDependencyRegistry {
565
+ constructor() {
566
+ _defineProperty(this, "_dependencies", new Map());
567
+ }
568
+
569
+ registerDependency(qualifier) {
570
+ let dependency = this._dependencies.get(qualifier.name);
571
+
572
+ if (dependency == null) {
573
+ const newDependency = {
574
+ name: qualifier.name,
575
+ asyncType: qualifier.asyncType,
576
+ locs: [],
577
+ index: this._dependencies.size
578
+ };
579
+
580
+ if (qualifier.optional) {
581
+ newDependency.isOptional = true;
582
+ }
583
+
584
+ dependency = newDependency;
585
+
586
+ this._dependencies.set(qualifier.name, dependency);
587
+ } else {
588
+ const original = dependency;
589
+ dependency = collapseDependencies(original, qualifier);
590
+
591
+ if (original !== dependency) {
592
+ this._dependencies.set(qualifier.name, dependency);
593
+ }
594
+ }
595
+
596
+ return dependency;
597
+ }
598
+
599
+ getDependencies() {
600
+ return Array.from(this._dependencies.values());
601
+ }
602
+ }
603
+
604
+ function collapseDependencies(dependency, qualifier) {
605
+ let collapsed = dependency; // A previously optionally required dependency was required non-optionaly.
606
+ // Mark it non optional for the whole module
607
+
608
+ if (collapsed.isOptional && !qualifier.optional) {
609
+ collapsed = _objectSpread(
610
+ _objectSpread({}, dependency),
611
+ {},
612
+ {
613
+ isOptional: false
614
+ }
615
+ );
616
+ } // A previously asynchronously (or prefetch) required module was required synchronously.
617
+ // Make the dependency sync.
618
+
619
+ if (collapsed.asyncType != null && qualifier.asyncType == null) {
620
+ collapsed = _objectSpread(
621
+ _objectSpread({}, dependency),
622
+ {},
623
+ {
624
+ asyncType: null
625
+ }
626
+ );
627
+ } // A prefetched dependency was required async in the module. Mark it as async.
628
+
629
+ if (collapsed.asyncType === "prefetch" && qualifier.asyncType === "async") {
630
+ collapsed = _objectSpread(
631
+ _objectSpread({}, dependency),
632
+ {},
633
+ {
634
+ asyncType: "async"
635
+ }
636
+ );
637
+ }
638
+
639
+ return collapsed;
640
+ }
641
+
518
642
  module.exports = collectDependencies;