From e8dd3ba0f32da34914e5d54f777ed03c57cead93 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 6 Apr 2022 17:42:57 -0400 Subject: [PATCH] Ensure the worker processes do not crash when parsing invalid syntax The original code **never** handled the cases where `@babel/core`'s `transform` method throws an error, it just _happened_ to be that we didn't hit this case (because babel tended not to `throw` during parsing). This updates to ensure that our worker will always resolve, sometimes with `{ code, metadata }` and other times (when an error happens) `{ error, stack }`. When we resolve with `{ error, stack }` the parent process will throw an error with that information (so that `ember build` exits non-zero, or `ember serve` shows the build failure and then rebuilds succesfully once the syntax error is fixed). (cherry picked from commit 91d78261206a606863b1198cc8965c3711487720) --- lib/parallel-api.js | 14 +++++++++++++- lib/worker.js | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/parallel-api.js b/lib/parallel-api.js index 7dd56b5..4453beb 100644 --- a/lib/parallel-api.js +++ b/lib/parallel-api.js @@ -242,7 +242,19 @@ function transformString(string, options, buildOptions) { let pool = getWorkerPool(); _logger.info('transformString is parallelizable'); let serializedObj = { babel : serialize(options.babel), 'cacheKey': options.cacheKey }; - return pool.exec('transform', [string, serializedObj]); + return pool + .exec('transform', [string, serializedObj]) + .then((result) => { + if (result.error) { + // when the worker has an error it still resolves, but it has `error` + // and `stack` properties instead of `code` + `metadata` + // + // throw an error to properly fail the "top level" process as needed + throw new Error(result.error + result.stack); + } + + return result; + }); } else { if (JOBS <= 1) { _logger.info('JOBS <= 1, skipping worker, using main thread'); diff --git a/lib/worker.js b/lib/worker.js index d120f71..c288842 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -7,13 +7,20 @@ const ParallelApi = require('./parallel-api'); // transpile the input string, using the input options function transform(string, options) { - return new Promise(resolve => { - let result = transpiler.transform(string, ParallelApi.deserialize(options)); + return Promise.resolve().then(() => { + try { + let result = transpiler.transform(string, ParallelApi.deserialize(options)); - resolve({ - code: result.code, - metadata: result.metadata - }); + return { + code: result.code, + metadata: result.metadata + }; + } catch (error) { + return { + error: error.message, + stack: error.stack, + }; + } }); }