Skip to content

Commit

Permalink
metro-buck: check validity of segments
Browse files Browse the repository at this point in the history
Reviewed By: davidaurelio

Differential Revision: D6496312

fbshipit-source-id: 586dc8d9f64d13cfddaf6bfe768e8f7b3442561a
  • Loading branch information
Jean Lauliac authored and facebook-github-bot committed Dec 14, 2017
1 parent 59c3e33 commit f871d25
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion Libraries/Utilities/asyncRequire.js
Expand Up @@ -13,6 +13,8 @@


'use strict'; 'use strict';


const dynamicRequire: number => mixed = (require: $FlowFixMe);

/** /**
* The bundler must register the dependency properly when generating a call to * The bundler must register the dependency properly when generating a call to
* `asyncRequire`, that allows us to call `require` dynamically with confidence * `asyncRequire`, that allows us to call `require` dynamically with confidence
Expand All @@ -24,7 +26,7 @@ function asyncRequire(moduleID: number): Promise<mixed> {
const {segmentId} = (require: $FlowFixMe).unpackModuleId(moduleID); const {segmentId} = (require: $FlowFixMe).unpackModuleId(moduleID);
return loadSegment(segmentId); return loadSegment(segmentId);
}) })
.then(() => require.call(null, (moduleID: $FlowFixMe))); .then(() => dynamicRequire(moduleID));
} }


let segmentLoaders = new Map(); let segmentLoaders = new Map();
Expand All @@ -45,6 +47,10 @@ function loadSegment(segmentId: number): Promise<void> {
if (segmentId === 0) { if (segmentId === 0) {
return; return;
} }
if (typeof global.__BUNDLE_DIGEST__ !== 'string') {
throw IncorrectBundleSetupError();
}
const globalDigest = global.__BUNDLE_DIGEST__;
let segmentLoader = segmentLoaders.get(segmentId); let segmentLoader = segmentLoaders.get(segmentId);
if (segmentLoader != null) { if (segmentLoader != null) {
return segmentLoader; return segmentLoader;
Expand All @@ -61,6 +67,19 @@ function loadSegment(segmentId: number): Promise<void> {
} }
resolve(); resolve();
}); });
}).then(() => {
const metaModuleId = (require: $FlowFixMe).packModuleId({
segmentId,
localId: 0,
});
const metaModule = dynamicRequire(metaModuleId);
const digest: string =
typeof metaModule === 'object' && metaModule != null
? (metaModule.BUNDLE_DIGEST: $FlowFixMe)
: 'undefined';
if (digest !== globalDigest) {
throw new IncompatibleSegmentError(globalDigest, digest);
}
}); });
segmentLoaders.set(segmentId, segmentLoader); segmentLoaders.set(segmentId, segmentLoader);
return segmentLoader; return segmentLoader;
Expand All @@ -76,4 +95,27 @@ class FetchSegmentNotAvailableError extends Error {
} }
} }


class IncorrectBundleSetupError extends Error {
constructor() {
super(
'To be able to use split segments, the bundler must define a global ' +
'constant `__BUNDLE_DIGEST__` that identifies the bundle uniquely.',
);
}
}
asyncRequire.IncorrectBundleSetupError = IncorrectBundleSetupError;

class IncompatibleSegmentError extends Error {
constructor(globalDigest, segmentDigest) {
super(
'The split segment that is being loaded has been built from a ' +
'different version of the code than the main segment. Or, the ' +
'bundler is setting up the module #0 of the segment incorrectly. ' +
`The global digest is \`${globalDigest}\` while the segment is ` +
`\`${segmentDigest}\`.`,
);
}
}
asyncRequire.IncompatibleSegmentError = IncompatibleSegmentError;

module.exports = asyncRequire; module.exports = asyncRequire;

0 comments on commit f871d25

Please sign in to comment.