Skip to content

Commit

Permalink
Ensure the worker processes do not crash when parsing invalid syntax
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
rwjblue committed Apr 7, 2022
1 parent 416732d commit 91d7826
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
14 changes: 13 additions & 1 deletion lib/parallel-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
19 changes: 13 additions & 6 deletions lib/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}
});
}

Expand Down

0 comments on commit 91d7826

Please sign in to comment.