From 06732d9272715618f92dc9d00c8bc5a83c1c38ff Mon Sep 17 00:00:00 2001 From: Jean Lauliac Date: Fri, 26 May 2017 10:11:13 -0700 Subject: [PATCH] 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 --- .../metro-bundler/src/node-haste/Module.js | 111 +++++------------- 1 file changed, 32 insertions(+), 79 deletions(-) diff --git a/packages/metro-bundler/src/node-haste/Module.js b/packages/metro-bundler/src/node-haste/Module.js index 17269be8..c8080665 100644 --- a/packages/metro-bundler/src/node-haste/Module.js +++ b/packages/metro-bundler/src/node-haste/Module.js @@ -265,80 +265,44 @@ class Module { return {...result, id: this._getHasteName(), source}; } - _transformCodeForCallback( + async _transformCodeFor( cacheProps: ReadTransformProps, - callback: (error: ?Error, result: ?TransformedCode) => void, - ) { + ): Promise { 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 { + const result = await this._transformCodeFor(cacheProps); + globalCache.store(cacheProps, result); + return result; } - _getTransformedCode( + async _getTransformedCode( cacheProps: ReadTransformProps, - callback: (error: ?Error, result: ?TransformedCode) => void, - ) { + ): Promise { 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 { + 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; }