packager: Module: get rid of callbacks

Summary: By getting rid of callbacks, we get a code that's pretty halved in size, and much easier to read, but we also fix bugs! When some of the code of Module would throw, we wouldn't catch it, meaning that packager would crash entirely. That's the case for when we have a Haste name mistach, for example. This changeste fixes that by instead capturing exceptions through the Promise chain, that bubble up all the way to the `Server` and reasonnably handled. People can then fix the Haste nane mismatch and refresh right away, and it'll work as expected.

Reviewed By: davidaurelio

Differential Revision: D5137408

fbshipit-source-id: b9e938b93e8d23738af49106bbae1fce97d7a5db
This commit is contained in:
Jean Lauliac 2017-05-26 10:11:13 -07:00 committed by Facebook Github Bot
parent e9fc7311c4
commit 21e3d4db20
1 changed files with 32 additions and 79 deletions

View File

@ -265,80 +265,44 @@ class Module {
return {...result, id: this._getHasteName(), source};
}
_transformCodeForCallback(
async _transformCodeFor(
cacheProps: ReadTransformProps,
callback: (error: ?Error, result: ?TransformedCode) => void,
) {
): Promise<TransformedCode> {
const {_transformCode} = this;
invariant(_transformCode != null, 'missing code transform funtion');
const {sourceCode, transformOptions} = cacheProps;
return _transformCode(this, sourceCode, transformOptions).then(
freshResult => process.nextTick(callback, undefined, freshResult),
error => process.nextTick(callback, error),
);
return await _transformCode(this, sourceCode, transformOptions);
}
_transformAndStoreCodeGlobally(
async _transformAndStoreCodeGlobally(
cacheProps: ReadTransformProps,
globalCache: GlobalTransformCache,
callback: (error: ?Error, result: ?TransformedCode) => void,
) {
this._transformCodeForCallback(
cacheProps,
(transformError, transformResult) => {
if (transformError != null) {
callback(transformError);
return;
}
invariant(
transformResult != null,
'Inconsistent state: there is no error, but no results either.',
);
globalCache.store(cacheProps, transformResult);
callback(undefined, transformResult);
},
);
): Promise<TransformedCode> {
const result = await this._transformCodeFor(cacheProps);
globalCache.store(cacheProps, result);
return result;
}
_getTransformedCode(
async _getTransformedCode(
cacheProps: ReadTransformProps,
callback: (error: ?Error, result: ?TransformedCode) => void,
) {
): Promise<TransformedCode> {
const {_globalCache} = this;
if (_globalCache == null || !_globalCache.shouldFetch(cacheProps)) {
this._transformCodeForCallback(cacheProps, callback);
return;
return await this._transformCodeFor(cacheProps);
}
_globalCache.fetch(cacheProps).then(
globalCachedResult =>
process.nextTick(() => {
if (globalCachedResult == null) {
this._transformAndStoreCodeGlobally(
cacheProps,
_globalCache,
callback,
);
return;
}
callback(undefined, globalCachedResult);
}),
globalCacheError => process.nextTick(() => callback(globalCacheError)),
);
const globalCachedResult = await _globalCache.fetch(cacheProps);
if (globalCachedResult != null) {
return globalCachedResult;
}
return await this._transformAndStoreCodeGlobally(cacheProps, _globalCache);
}
_getAndCacheTransformedCode(
async _getAndCacheTransformedCode(
cacheProps: ReadTransformProps,
callback: (error: ?Error, result: ?TransformedCode) => void,
) {
this._getTransformedCode(cacheProps, (error, result) => {
if (error) {
callback(error);
return;
}
invariant(result != null, 'missing result');
this._options.transformCache.writeSync({...cacheProps, result});
callback(undefined, result);
});
): Promise<TransformedCode> {
const result = await this._getTransformedCode(cacheProps);
this._options.transformCache.writeSync({...cacheProps, result});
return result;
}
/**
@ -411,30 +375,19 @@ class Module {
if (promise != null) {
return promise;
}
const freshPromise = Promise.resolve().then(() => {
const freshPromise = (async () => {
const cacheProps = this._getCacheProps(transformOptions, key);
return new Promise((resolve, reject) => {
this._getAndCacheTransformedCode(
cacheProps,
(transformError, freshResult) => {
if (transformError) {
reject(transformError);
return;
}
invariant(freshResult != null, 'inconsistent state');
resolve(
this._finalizeReadResult(cacheProps.sourceCode, freshResult),
);
},
);
}).then(result => {
this._readResultsByOptionsKey.set(key, {
result,
outdatedDependencies: [],
});
return result;
const freshResult = await this._getAndCacheTransformedCode(cacheProps);
const finalResult = this._finalizeReadResult(
cacheProps.sourceCode,
freshResult,
);
this._readResultsByOptionsKey.set(key, {
result: finalResult,
outdatedDependencies: [],
});
});
return finalResult;
})();
this._readPromises.set(key, freshPromise);
return freshPromise;
}