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:
parent
e9fc7311c4
commit
21e3d4db20
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue