|
4 | 4 | * This source code is licensed under the MIT license found in the
|
5 | 5 | * LICENSE file in the root directory of this source tree.
|
6 | 6 | *
|
| 7 | + * @flow strict-local |
7 | 8 | * @format
|
8 |
| - * @flow strict |
| 9 | + * @oncall react_native |
9 | 10 | */
|
10 | 11 |
|
11 |
| -'use strict'; |
| 12 | +type Options = {isPrefetchOnly: boolean, ...}; |
| 13 | +type MetroRequire = { |
| 14 | + (number): mixed, |
| 15 | + importAll: number => mixed, |
| 16 | + ... |
| 17 | +}; |
| 18 | + |
| 19 | +declare var require: MetroRequire; |
| 20 | + |
| 21 | +const DEFAULT_OPTIONS = {isPrefetchOnly: false}; |
| 22 | + |
| 23 | +type DependencyMapPaths = ?$ReadOnly<{[moduleID: number | string]: mixed}>; |
| 24 | + |
| 25 | +declare var __METRO_GLOBAL_PREFIX__: string; |
| 26 | + |
| 27 | +async function asyncRequireImpl( |
| 28 | + moduleID: number, |
| 29 | + paths: DependencyMapPaths, |
| 30 | + options: Options, |
| 31 | +): Promise<mixed> { |
| 32 | + const loadBundle: (bundlePath: mixed) => Promise<void> = |
| 33 | + global[`${__METRO_GLOBAL_PREFIX__}__loadBundleAsync`]; |
12 | 34 |
|
13 |
| -// $FlowExpectedError Flow does not know about Metro's require extensions. |
14 |
| -const dynamicRequire = (require: {importAll: mixed => mixed}); |
15 |
| -module.exports = function (moduleID: mixed): Promise<mixed> { |
16 |
| - return Promise.resolve().then(() => dynamicRequire.importAll(moduleID)); |
| 35 | + if (loadBundle != null) { |
| 36 | + const stringModuleID = String(moduleID); |
| 37 | + const bundlePath = nullthrows(paths)[stringModuleID]; |
| 38 | + if (bundlePath != null) { |
| 39 | + // NOTE: Errors will be swallowed by asyncRequire.prefetch |
| 40 | + await loadBundle(bundlePath); |
| 41 | + } |
| 42 | + } |
| 43 | + |
| 44 | + if (!options.isPrefetchOnly) { |
| 45 | + return require.importAll(moduleID); |
| 46 | + } |
| 47 | + |
| 48 | + return undefined; |
| 49 | +} |
| 50 | + |
| 51 | +async function asyncRequire( |
| 52 | + moduleID: number, |
| 53 | + paths: DependencyMapPaths, |
| 54 | + moduleName?: string, |
| 55 | +): Promise<mixed> { |
| 56 | + return asyncRequireImpl(moduleID, paths, DEFAULT_OPTIONS); |
| 57 | +} |
| 58 | + |
| 59 | +asyncRequire.prefetch = function ( |
| 60 | + moduleID: number, |
| 61 | + paths: DependencyMapPaths, |
| 62 | + moduleName?: string, |
| 63 | +): void { |
| 64 | + asyncRequireImpl(moduleID, paths, {isPrefetchOnly: true}).then( |
| 65 | + () => {}, |
| 66 | + () => {}, |
| 67 | + ); |
17 | 68 | };
|
| 69 | + |
| 70 | +module.exports = asyncRequire; |
| 71 | + |
| 72 | +// Inline definition to save on a dependency |
| 73 | +function nullthrows<T>(value: ?T): T { |
| 74 | + if (value == null) { |
| 75 | + throw new Error('Unexpected null or undefined'); |
| 76 | + } |
| 77 | + return value; |
| 78 | +} |
0 commit comments