Repository: nodejs/node
Pull request: esm: throw `ERR_REQUIRE_ESM` instead of `ERR_INTERNAL_ASSERTION`

With `--experimental-detect-module` being on by default, trying to `require()` a file with ESM syntax would result in an failed assertion if `--experimental-require-module` was not passed. Instead of an assertion, let's throw the usual error.

Fixes: https://github.com/nodejs/node/issues/54773

<!--
Before submitting a pull request, please read:

- the CONTRIBUTING guide at https://github.com/nodejs/node/blob/HEAD/CONTRIBUTING.md
- the commit message formatting guidelines at
  https://github.com/nodejs/node/blob/HEAD/doc/contributing/pull-requests.md#commit-message-guidelines

For code changes:
1. Include tests for any bug fixes or new features.
2. Update documentation if relevant.
3. Ensure that `make -j4 test` (UNIX), or `vcbuild test` (Windows) passes.

If you believe this PR should be highlighted in the Node.js CHANGELOG
please add the `notable-change` label.

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
-->


Changed files:
filename: lib/internal/modules/esm/loader.js
patch: @@ -326,8 +326,6 @@ class ModuleLoader {
    * @returns {ModuleJobBase}
    */
   getModuleJobForRequire(specifier, parentURL, importAttributes) {
-    assert(getOptionValue('--experimental-require-module'));
-
     const parsed = URLParse(specifier);
     if (parsed != null) {
       const protocol = parsed.protocol;
@@ -346,6 +344,9 @@ class ModuleLoader {
     }
 
     const { url, format } = resolveResult;
+    if (!getOptionValue('--experimental-require-module')) {
+      throw new ERR_REQUIRE_ESM(url, true);
+    }
     const resolvedImportAttributes = resolveResult.importAttributes ?? importAttributes;
     let job = this.loadCache.get(url, resolvedImportAttributes.type);
     if (job !== undefined) {

filename: test/es-module/test-typescript.mjs
patch: @@ -28,6 +28,18 @@ test('execute a TypeScript file with imports', async () => {
   strictEqual(result.code, 0);
 });
 
+test('execute a TypeScript file with imports', async () => {
+  const result = await spawnPromisified(process.execPath, [
+    '--no-warnings',
+    '--eval',
+    `assert.throws(() => require(${JSON.stringify(fixtures.path('typescript/ts/test-import-fs.ts'))}), {code: 'ERR_REQUIRE_ESM'})`,
+  ]);
+
+  strictEqual(result.stderr, '');
+  strictEqual(result.stdout, '');
+  strictEqual(result.code, 0);
+});
+
 test('execute a TypeScript file with imports with default-type module', async () => {
   const result = await spawnPromisified(process.execPath, [
     '--experimental-strip-types',