Skip to content

feat: use require to load esm #5366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

legendecas
Copy link

@legendecas legendecas commented May 13, 2025

PR Checklist

Overview

This allows compilers based on require.extensions continue to work, like ts-node with Node.js built-in TypeScript support enabled.

Hopefully unblock nodejs/node#57298.

Fixes: #5314
Fixes: #5317

Copy link

linux-foundation-easycla bot commented May 13, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: legendecas / name: Chengzhong Wu (5cde7f5)

@legendecas legendecas marked this pull request as ready for review May 26, 2025 00:56
@marco-ippolito
Copy link

friendly ping @JoshuaKGoldberg

@JoshuaKGoldberg
Copy link
Member

JoshuaKGoldberg commented Jun 9, 2025

Hey thanks for the ping! I was out for a bit and am catching up on things now. I'm going to try to get to testing this thoroughly this week (hopefully tomorrow or so). But the more folks who can test this out, the better.

Note that we're pretty close to releasing Mocha 12 (#5357). I also have a vague memory of someone mentioning somewhere that once Mocha drops support for pre-require(esm) versions of Node.js, this whole area of code could be simplified. I don't have the time to spelunk for it right now, but will if nobody posts that soon.

IMO it might make sense to either...

  • ⚡ Faster: Merge this in as a feature in Mocha 11.x, then take on the drastic simplification in Mocha 12
  • 🦺 More careful: merge this in as a feature in Mocha 12.0, then file the simplification as a followup (either Mocha 12 or Mocha 13, depending on how breaking it is)

I'm personally leaning to ⚡ since this change is pretty targeted, and because of how broken things are at the moment for Node.js versions with type stripping. cc @mochajs/committers - WDYT?

@JoshuaKGoldberg
Copy link
Member

Oh and @legendecas in the meantime, could you please try to fix the lint error? It's failing in CI.

This allows compilers based on `require.extensions` continue to work.
@legendecas
Copy link
Author

Fixed lint issue.

"Merge this in as a feature in Mocha 11.x, then take on the drastic simplification in Mocha 12" sounds good to me!

@mark-wiemer mark-wiemer self-requested a review June 10, 2025 02:15
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯 Fantastic! Thanks for sending this in, it's really clean and I haven't been able to break it locally when testing on a bunch of real-world repos.

We should definitely get another review from @mochajs/committers if possible just to be safe. But no blockers from me on merging to main in v11.

@voxpelli voxpelli requested a review from Copilot June 12, 2025 07:44
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for loading ESM syntax via Node’s require(esm) feature while preserving require.extensions hooks, and provides integration tests for both .js and .ts compilers.

  • Introduce tryImportAndRequire and requireModule in esm-utils.js to choose between import() and require() based on process.features.require_module.
  • Add integration tests and fixtures under test/compiler-cjs and test/compiler-fixtures to validate require.extensions-based compilers.
  • Update ESLint config to include the new test file.

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
lib/nodejs/esm-utils.js Replace single requireOrImport with two strategies and conditional override
test/integration/compiler-cjs.spec.js Add tests for .js and .ts extensions using fixtures
test/compiler-fixtures/js.fixture.js Fixture to override .js loader and compile files
test/compiler-fixtures/ts.fixture.js Fixture to override .ts loader and compile files
test/compiler-cjs/test.js ESM source file for .js test
test/compiler-cjs/test.js.compiled Compiled CJS output for .js test
test/compiler-cjs/test.ts ESM source file for .ts test
test/compiler-cjs/test.ts.compiled Compiled CJS output for .ts test
eslint.config.js Include the newly added test/compiler-cjs/test.js in linting
Comments suppressed due to low confidence (4)

lib/nodejs/esm-utils.js:86

  • It looks like the closing }; for the original exports.requireOrImport arrow function is left behind after replacing it with tryImportAndRequire. Consider removing this stray closing brace and semicolon to avoid a syntax error.
  };

test/compiler-cjs/test.ts:3

  • [nitpick] The test title uses cts which can be confusing—consider renaming to ts written in esm for clarity and consistency with the file extension.
describe('cts written in esm', () => {

test/compiler-cjs/test.ts.compiled:3

  • [nitpick] The compiled test also uses cts in its description; update this to ts written in esm to match the source and avoid confusion.
describe('cts written in esm', () => {

test/integration/compiler-cjs.spec.js:58

  • [nitpick] This expectation references cts written in esm; after renaming the test titles to ts written in esm, update this expectation string accordingly.
          'cts written in esm should work',

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants