diff --git a/bin/handlebars.mjs b/bin/handlebars.mjs index 24ff8fd7..bfe0c05b 100644 --- a/bin/handlebars.mjs +++ b/bin/handlebars.mjs @@ -125,6 +125,12 @@ Precompiler.loadTemplates(argv, function (err, opts) { if (opts.help || (!opts.templates.length && !opts.version)) { parser.showHelp('log'); } else { - Precompiler.cli(opts); + // cli() is async (returns a Promise), so errors would become unhandled + // rejections. Re-throw via nextTick to surface them as uncaught exceptions. + Promise.resolve(Precompiler.cli(opts)).catch((error) => { + process.nextTick(() => { + throw error; + }); + }); } }); diff --git a/tasks/tests/cli.test.js b/tasks/tests/cli.test.js index 9547a016..0b7edb5a 100644 --- a/tasks/tests/cli.test.js +++ b/tasks/tests/cli.test.js @@ -1,4 +1,5 @@ const fs = require('fs'); +const { exec } = require('child_process'); const { execCommand, FileTestHelper } = require('cli-testlab'); const Handlebars = require('../../lib'); @@ -245,6 +246,21 @@ describe('bin/handlebars', function () { }); }); + describe('error handling', function () { + it('should not produce unhandled promise rejections on async errors', async function () { + const { stderr } = await new Promise((resolve) => { + exec( + `node --unhandled-rejections=warn ./bin/handlebars.mjs -i "
test
" -N test --map /nonexistent/dir/test.map`, + (error, stdout, stderr) => { + resolve({ exitCode: error ? error.code : 0, stderr }); + } + ); + }); + + expect(stderr).not.toMatch(/unhandled/i); + }); + }); + describe('negated boolean flags', function () { it('--no-amd negates --amd (issue #1673)', async function () { const result = await execCommand(