Skip to content

Commit a7b231a

Browse files
Jean Lauliacfacebook-github-bot
Jean Lauliac
authored andcommitted
metro: introduce asyncRequire function
Reviewed By: davidaurelio Differential Revision: D6498107 fbshipit-source-id: a9c4ab634e60f19b7058205eddcd248f57f63500
1 parent 3d5dc87 commit a7b231a

File tree

2 files changed

+79
-58
lines changed

2 files changed

+79
-58
lines changed

Libraries/Utilities/BundleSegments.js

-58
This file was deleted.

Libraries/Utilities/asyncRequire.js

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*
9+
* @flow
10+
* @format
11+
* @providesModule asyncRequire
12+
*/
13+
14+
'use strict';
15+
16+
/**
17+
* The bundler must register the dependency properly when generating a call to
18+
* `asyncRequire`, that allows us to call `require` dynamically with confidence
19+
* the module ID is indeed valid and available.
20+
*/
21+
function asyncRequire(moduleID: number): Promise<mixed> {
22+
return Promise.resolve()
23+
.then(() => {
24+
const {segmentId} = (require: $FlowFixMe).unpackModuleId(moduleID);
25+
return loadSegment(segmentId);
26+
})
27+
.then(() => require.call(null, (moduleID: $FlowFixMe)));
28+
}
29+
30+
let segmentLoaders = new Map();
31+
32+
/**
33+
* Ensure that a bundle segment is ready for use, for example requiring some of
34+
* its module. We cache load promises so as to avoid calling `fetchSegment`
35+
* twice for the same bundle. We assume that once a segment is fetched/loaded,
36+
* it is never gettting removed during this instance of the JavaScript VM.
37+
*
38+
* Segment #0 is the main segment, that is always available by definition, so
39+
* we never try to load anything.
40+
*
41+
* We don't use async/await syntax to avoid depending on `regeneratorRuntime`.
42+
*/
43+
function loadSegment(segmentId: number): Promise<void> {
44+
return Promise.resolve().then(() => {
45+
if (segmentId === 0) {
46+
return;
47+
}
48+
let segmentLoader = segmentLoaders.get(segmentId);
49+
if (segmentLoader != null) {
50+
return segmentLoader;
51+
}
52+
const {fetchSegment} = global;
53+
if (fetchSegment == null) {
54+
throw new FetchSegmentNotAvailableError();
55+
}
56+
segmentLoader = new Promise((resolve, reject) => {
57+
fetchSegment(segmentId, error => {
58+
if (error != null) {
59+
reject(error);
60+
return;
61+
}
62+
resolve();
63+
});
64+
});
65+
segmentLoaders.set(segmentId, segmentLoader);
66+
return segmentLoader;
67+
});
68+
}
69+
70+
class FetchSegmentNotAvailableError extends Error {
71+
constructor() {
72+
super(
73+
'When bundle splitting is enabled, the `global.fetchSegment` function ' +
74+
'must be provided to be able to load particular bundle segments.',
75+
);
76+
}
77+
}
78+
79+
module.exports = asyncRequire;

0 commit comments

Comments
 (0)