Skip to content
Merged
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module.exports = [
},
{
files: [
'test/compiler-esm/*.js'
'test/compiler-esm/*.{js,mjs}'
],
languageOptions: {
sourceType: 'module',
Expand Down
7 changes: 6 additions & 1 deletion lib/nodejs/esm-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,19 @@ const tryImportAndRequire = async (file, esmDecorator) => {
// and `require.cache` effective, while allowing us to load ESM modules
// and CJS modules in the same way.
const requireModule = async (file, esmDecorator) => {
if (path.extname(file) === '.mjs') {
return formattedImport(file, esmDecorator);
}
try {
return require(file);
} catch (err) {
// Import if require fails.
return dealWithExports(await formattedImport(file, esmDecorator));
}
}
};

// We only assign this `requireOrImport` function once based on Node version
// We check for file extensions in `requireModule` and `tryImportAndRequire`
if (process.features.require_module) {
exports.requireOrImport = requireModule;
} else {
Expand Down
11 changes: 11 additions & 0 deletions test/compiler-esm/test-tla.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const obj = { foo: 'bar' };

describe('esm written in esm with top-level-await', () => {
it('should work', () => {
expect(obj, 'to equal', { foo: 'bar' });
});
});

await undefined;

export const foo = 'bar';
11 changes: 11 additions & 0 deletions test/compiler-esm/test-tla.mjs.compiled
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const obj = { foo: 'bar' };

describe('esm written in esm with top-level-await', () => {
it('should work', () => {
expect(obj, 'to equal', { foo: 'bar' });
});
});

await undefined;

export const foo = 'bar';
9 changes: 9 additions & 0 deletions test/compiler-esm/test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const obj = {foo: 'bar'};

describe('esm written in esm', () => {
it('should work', () => {
expect(obj, 'to equal', {foo: 'bar'});
});
});

export const foo = 'bar';
9 changes: 9 additions & 0 deletions test/compiler-esm/test.mjs.compiled
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const obj = {foo: 'bar'};

describe('esm written in esm', () => {
it('should work', () => {
expect(obj, 'to equal', {foo: 'bar'});
});
});

export const foo = 'bar';
61 changes: 22 additions & 39 deletions test/integration/compiler-esm-only-loader.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ var path = require('node:path');

// Regression test for https://github.com/mochajs/mocha/issues/5380
describe('support ESM only module loader packages', function () {
it('should support ESM .js extension', function (done) {
/**
* Load the filename using an ESM-only loader and expect things to work
* @param {string} filename Name of the file to load
* @param {Function} done A Mocha done callback for when the test ends
*/
function loadAndExpect(filename, done) {
exec(
'"' +
process.execPath +
'" "' +
path.join('bin', 'mocha') +
'" -R json --require "@test/esm-only-loader" "test/compiler-esm/*.js"',
`" -R json --require "@test/esm-only-loader" "${filename}"`,
{cwd: path.join(__dirname, '..', '..')},
function (error, stdout) {
if (error && !stdout) {
Expand All @@ -24,48 +29,26 @@ describe('support ESM only module loader packages', function () {
expect(results.tests[index], 'to have property', 'fullTitle');
titles.push(results.tests[index].fullTitle);
}
expect(
titles,
'to contain',
'esm written in esm should work',
).and(
'to contain',
'esm written in esm with top-level-await should work',
).and('to have length', 2);
expect(titles, 'to contain', 'esm written in esm should work')
.and(
'to contain',
'esm written in esm with top-level-await should work'
)
.and('to have length', 2);
done();
}
);
}

it('should support ESM .js extension', function (done) {
loadAndExpect('test/compiler-esm/*.js', done);
});

it('should support ESM .ts extension', function (done) {
exec(
'"' +
process.execPath +
'" "' +
path.join('bin', 'mocha') +
'" -R json --require "@test/esm-only-loader" "test/compiler-esm/*.ts"',
{cwd: path.join(__dirname, '..', '..')},
function (error, stdout) {
if (error && !stdout) {
return done(error);
}
var results = JSON.parse(stdout);
expect(results, 'to have property', 'tests');
var titles = [];
for (var index = 0; index < results.tests.length; index += 1) {
expect(results.tests[index], 'to have property', 'fullTitle');
titles.push(results.tests[index].fullTitle);
}
expect(
titles,
'to contain',
'esm written in esm should work',
).and(
'to contain',
'esm written in esm with top-level-await should work',
).and('to have length', 2);
done();
}
);
loadAndExpect('test/compiler-esm/*.ts', done);
});

it('should support ESM .mjs extension', function (done) {
loadAndExpect('test/compiler-esm/*.mjs', done);
});
});
61 changes: 22 additions & 39 deletions test/integration/compiler-esm.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ var exec = require('node:child_process').exec;
var path = require('node:path');

describe('support ESM module loader compilers', function () {
it('should support ESM .js extension', function (done) {
/**
* Runs `exec` on an ESM setup for the given file
* @param {string} filename Path to the file to load
* @param {Function} done A Mocha done callback for when the test ends
*/
function loadAndExpect(filename, done) {
exec(
'"' +
process.execPath +
'" "' +
path.join('bin', 'mocha') +
'" -R json --require test/compiler-fixtures/esm.fixture "test/compiler-esm/*.js"',
`" -R json --require test/compiler-fixtures/esm.fixture "${filename}"`,
{cwd: path.join(__dirname, '..', '..')},
function (error, stdout) {
if (error && !stdout) {
Expand All @@ -23,48 +28,26 @@ describe('support ESM module loader compilers', function () {
expect(results.tests[index], 'to have property', 'fullTitle');
titles.push(results.tests[index].fullTitle);
}
expect(
titles,
'to contain',
'esm written in esm should work',
).and(
'to contain',
'esm written in esm with top-level-await should work',
).and('to have length', 2);
expect(titles, 'to contain', 'esm written in esm should work')
.and(
'to contain',
'esm written in esm with top-level-await should work'
)
.and('to have length', 2);
done();
}
);
}

it('should support ESM .js extension', function (done) {
loadAndExpect('test/compiler-esm/*.js', done);
});

it('should support ESM .ts extension', function (done) {
exec(
'"' +
process.execPath +
'" "' +
path.join('bin', 'mocha') +
'" -R json --require test/compiler-fixtures/esm.fixture "test/compiler-esm/*.ts"',
{cwd: path.join(__dirname, '..', '..')},
function (error, stdout) {
if (error && !stdout) {
return done(error);
}
var results = JSON.parse(stdout);
expect(results, 'to have property', 'tests');
var titles = [];
for (var index = 0; index < results.tests.length; index += 1) {
expect(results.tests[index], 'to have property', 'fullTitle');
titles.push(results.tests[index].fullTitle);
}
expect(
titles,
'to contain',
'esm written in esm should work',
).and(
'to contain',
'esm written in esm with top-level-await should work',
).and('to have length', 2);
done();
}
);
loadAndExpect('test/compiler-esm/*.ts', done);
});

it('should support ESM .mjs extension', function (done) {
loadAndExpect('test/compiler-esm/*.mjs', done);
});
});
Loading