diff --git a/lib/nodejs/esm-utils.js b/lib/nodejs/esm-utils.js index fd26665595..77541d7f51 100644 --- a/lib/nodejs/esm-utils.js +++ b/lib/nodejs/esm-utils.js @@ -101,9 +101,24 @@ const requireModule = async (file, esmDecorator) => { try { return dealWithExports(await formattedImport(file, esmDecorator)); } catch (importErr) { + // If a --require module throws in a Node.js version that doesn't yet support .ts files, + // the fallback import() will throw an uninformative error about the file extension. + // What we actually care about is the original require() error. + // See: https://github.com/mochajs/mocha/issues/5393 + if ( + /\.(cts|mts|ts)$/.test(file) || + importErr.code === 'ERR_UNKNOWN_FILE_EXTENSION' + ) { + throw requireErr; + } + + // Similarly, for an exports/imports mismatch such as a missing 'default', + // the require() error will be more informative for users. + // See: https://github.com/mochajs/mocha/issues/5411 if (importErr.code === 'ERR_INTERNAL_ASSERTION') { throw requireErr; } + throw importErr; } } diff --git a/test/node-unit/esm-utils.spec.js b/test/node-unit/esm-utils.spec.js index e751ce3caf..2ca4cbfc34 100644 --- a/test/node-unit/esm-utils.spec.js +++ b/test/node-unit/esm-utils.spec.js @@ -20,6 +20,21 @@ describe('esm-utils', function () { } ); }); + + it('should show a syntax error message when importing a TypeScript file with invalid syntax', async function () { + return expect( + () => + esmUtils.requireOrImport( + '../../test/node-unit/fixtures/broken-syntax.ts' + ), + 'to be rejected with error satisfying', + { + name: 'SyntaxError', + message: + /Invalid or unexpected token|Expected ident/ + } + ); + }); }); describe('loadFilesAsync()', function () { diff --git a/test/node-unit/fixtures/broken-syntax.ts b/test/node-unit/fixtures/broken-syntax.ts new file mode 100644 index 0000000000..550b2f0afd --- /dev/null +++ b/test/node-unit/fixtures/broken-syntax.ts @@ -0,0 +1 @@ +@!