diff --git a/lib/nodejs/esm-utils.js b/lib/nodejs/esm-utils.js index 3cea8af249..aecf31b0f7 100644 --- a/lib/nodejs/esm-utils.js +++ b/lib/nodejs/esm-utils.js @@ -1,5 +1,6 @@ const path = require('node:path'); const url = require('node:url'); +const debug = require('debug')('mocha:esm-utils'); const forward = x => x; @@ -93,11 +94,20 @@ const requireModule = async (file, esmDecorator) => { try { return require(file); } catch (err) { - // Import if require fails. - return dealWithExports(await formattedImport(file, esmDecorator)); + debug('requireModule caught err: %O', err.message); + if ( + err instanceof SyntaxError && + err.message.includes("does not provide an export named 'default'") + ) { + throw err; + } else { + // Import if require fails. + return dealWithExports(await formattedImport(file, esmDecorator)); + } } } +debug('assigning requireOrImport, require_module === %O', process.features.require_module); if (process.features.require_module) { exports.requireOrImport = requireModule; } else { diff --git a/test/node-unit/esm-utils.spec.js b/test/node-unit/esm-utils.spec.js index 184756eb5d..e751ce3caf 100644 --- a/test/node-unit/esm-utils.spec.js +++ b/test/node-unit/esm-utils.spec.js @@ -5,15 +5,32 @@ const sinon = require('sinon'); const url = require('node:url'); describe('esm-utils', function () { - beforeEach(function () { - sinon.stub(esmUtils, 'doImport').resolves({}); - }); - - afterEach(function () { - sinon.restore(); + describe('requireOrImport', function () { + it('should show an informative error message for a broken default import', async function () { + return expect( + () => + esmUtils.requireOrImport( + '../../test/node-unit/fixtures/broken-default-import.mjs' + ), + 'to be rejected with error satisfying', + { + name: 'SyntaxError', + message: + "The requested module './module-without-default-export.mjs' does not provide an export named 'default'" + } + ); + }); }); describe('loadFilesAsync()', function () { + beforeEach(function () { + sinon.stub(esmUtils, 'doImport').resolves({}); + }); + + afterEach(function () { + sinon.restore(); + }); + it('should not decorate imported module if no decorator passed', async function () { await esmUtils.loadFilesAsync( ['/foo/bar.mjs'], diff --git a/test/node-unit/fixtures/broken-default-import.mjs b/test/node-unit/fixtures/broken-default-import.mjs new file mode 100644 index 0000000000..523103014e --- /dev/null +++ b/test/node-unit/fixtures/broken-default-import.mjs @@ -0,0 +1,3 @@ +import moduleWithoutDefaultExport from './module-without-default-export.mjs'; + +moduleWithoutDefaultExport; diff --git a/test/node-unit/fixtures/module-without-default-export.mjs b/test/node-unit/fixtures/module-without-default-export.mjs new file mode 100644 index 0000000000..46d3ca8c61 --- /dev/null +++ b/test/node-unit/fixtures/module-without-default-export.mjs @@ -0,0 +1 @@ +export const value = 42;