diff --git a/Libraries/Utilities/BundleSegments.js b/Libraries/Utilities/BundleSegments.js deleted file mode 100644 index 2e96937e5a225d..00000000000000 --- a/Libraries/Utilities/BundleSegments.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - * @providesModule BundleSegments - */ - -'use strict'; - -let segmentLoaders = new Map(); - -/** - * Ensure that a bundle segment is ready for use, for example requiring some of - * its module. We cache load promises so as to avoid calling `fetchSegment` twice - * for the same bundle. We assume that once a segment is fetched/loaded, it is - * never gettting removed during this instance of the JavaScript VM. - * - * We don't use async/await syntax to avoid depending on `regeneratorRuntime`. - */ -function loadForModule(moduleID: number): Promise { - return Promise.resolve().then(() => { - const {segmentId} = (require: $FlowFixMe).unpackModuleId(moduleID); - if (segmentId === 0) { - return; - } - let segmentLoader = segmentLoaders.get(segmentId); - if (segmentLoader != null) { - return segmentLoader; - } - - const {fetchSegment} = global; - if (fetchSegment == null) { - throw new Error( - 'When bundle splitting is enabled, the `global.fetchSegment` function ' + - 'must be provided to be able to load particular bundle segments.', - ); - } - segmentLoader = new Promise((resolve, reject) => { - fetchSegment(segmentId, error => { - if (error != null) { - reject(error); - return; - } - resolve(); - }); - }); - segmentLoaders.set(segmentId, segmentLoader); - return segmentLoader; - }); -} - -module.exports = {loadForModule}; diff --git a/Libraries/Utilities/asyncRequire.js b/Libraries/Utilities/asyncRequire.js new file mode 100644 index 00000000000000..3a403b8dd91e2a --- /dev/null +++ b/Libraries/Utilities/asyncRequire.js @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @flow + * @format + * @providesModule asyncRequire + */ + +'use strict'; + +/** + * The bundler must register the dependency properly when generating a call to + * `asyncRequire`, that allows us to call `require` dynamically with confidence + * the module ID is indeed valid and available. + */ +function asyncRequire(moduleID: number): Promise { + return Promise.resolve() + .then(() => { + const {segmentId} = (require: $FlowFixMe).unpackModuleId(moduleID); + return loadSegment(segmentId); + }) + .then(() => require.call(null, (moduleID: $FlowFixMe))); +} + +let segmentLoaders = new Map(); + +/** + * Ensure that a bundle segment is ready for use, for example requiring some of + * its module. We cache load promises so as to avoid calling `fetchSegment` + * twice for the same bundle. We assume that once a segment is fetched/loaded, + * it is never gettting removed during this instance of the JavaScript VM. + * + * Segment #0 is the main segment, that is always available by definition, so + * we never try to load anything. + * + * We don't use async/await syntax to avoid depending on `regeneratorRuntime`. + */ +function loadSegment(segmentId: number): Promise { + return Promise.resolve().then(() => { + if (segmentId === 0) { + return; + } + let segmentLoader = segmentLoaders.get(segmentId); + if (segmentLoader != null) { + return segmentLoader; + } + const {fetchSegment} = global; + if (fetchSegment == null) { + throw new FetchSegmentNotAvailableError(); + } + segmentLoader = new Promise((resolve, reject) => { + fetchSegment(segmentId, error => { + if (error != null) { + reject(error); + return; + } + resolve(); + }); + }); + segmentLoaders.set(segmentId, segmentLoader); + return segmentLoader; + }); +} + +class FetchSegmentNotAvailableError extends Error { + constructor() { + super( + 'When bundle splitting is enabled, the `global.fetchSegment` function ' + + 'must be provided to be able to load particular bundle segments.', + ); + } +} + +module.exports = asyncRequire;