From 69144e96c2686d3ecc73b0423dcf163a40bfc7a0 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Thu, 2 Oct 2025 05:49:26 +0200 Subject: [PATCH] module: use sync cjs when importing cts PR-URL: https://github.com/nodejs/node/pull/60072 Fixes: https://github.com/nodejs/node/issues/59963 Reviewed-By: Yongsheng Zhang Reviewed-By: Geoffrey Booth --- lib/internal/modules/esm/loader.js | 4 +++- test/es-module/test-typescript-commonjs.mjs | 10 ++++++++++ test/es-module/test-typescript-module.mjs | 11 +++++++++++ test/fixtures/typescript/cts/issue-59963/a.cts | 3 +++ test/fixtures/typescript/cts/issue-59963/b.mts | 2 ++ test/fixtures/typescript/cts/issue-59963/c.cts | 2 ++ test/fixtures/typescript/mts/issue-59963/a.mts | 3 +++ test/fixtures/typescript/mts/issue-59963/b.cts | 3 +++ test/fixtures/typescript/mts/issue-59963/c.mts | 1 + 9 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/typescript/cts/issue-59963/a.cts create mode 100644 test/fixtures/typescript/cts/issue-59963/b.mts create mode 100644 test/fixtures/typescript/cts/issue-59963/c.cts create mode 100644 test/fixtures/typescript/mts/issue-59963/a.mts create mode 100644 test/fixtures/typescript/mts/issue-59963/b.cts create mode 100644 test/fixtures/typescript/mts/issue-59963/c.mts diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 02ec3183bc..300da51afe 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -504,7 +504,9 @@ class ModuleLoader { const loadResult = this.#loadSync(url, { format, importAttributes }); // Use the synchronous commonjs translator which can deal with cycles. - const finalFormat = loadResult.format === 'commonjs' ? 'commonjs-sync' : loadResult.format; + const finalFormat = + loadResult.format === 'commonjs' || + loadResult.format === 'commonjs-typescript' ? 'commonjs-sync' : loadResult.format; if (finalFormat === 'wasm') { assert.fail('WASM is currently unsupported by require(esm)'); diff --git a/test/es-module/test-typescript-commonjs.mjs b/test/es-module/test-typescript-commonjs.mjs index e757cfd231..548f440e59 100644 --- a/test/es-module/test-typescript-commonjs.mjs +++ b/test/es-module/test-typescript-commonjs.mjs @@ -174,3 +174,13 @@ test('expect failure of a .cts file requiring esm in node_modules', async () => match(result.stderr, /ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING/); strictEqual(result.code, 1); }); + +test('cts -> require mts -> import cts', async () => { + const result = await spawnPromisified(process.execPath, [ + fixtures.path('typescript/cts/issue-59963/a.cts'), + ]); + + strictEqual(result.stderr, ''); + strictEqual(result.stdout, 'Hello from c.cts\n'); + strictEqual(result.code, 0); +}); diff --git a/test/es-module/test-typescript-module.mjs b/test/es-module/test-typescript-module.mjs index 6a43808b82..eab2fc620f 100644 --- a/test/es-module/test-typescript-module.mjs +++ b/test/es-module/test-typescript-module.mjs @@ -98,3 +98,14 @@ test('execute .ts file importing a module', async () => { strictEqual(result.stdout, 'Hello, TypeScript!\n'); strictEqual(result.code, 0); }); + +test('mts -> import cts -> require mts', async () => { + const result = await spawnPromisified(process.execPath, [ + '--no-warnings', + fixtures.path('typescript/mts/issue-59963/a.mts'), + ]); + + strictEqual(result.stderr, ''); + strictEqual(result.stdout, 'Hello from c.mts\n'); + strictEqual(result.code, 0); +}); diff --git a/test/fixtures/typescript/cts/issue-59963/a.cts b/test/fixtures/typescript/cts/issue-59963/a.cts new file mode 100644 index 0000000000..8826591bd3 --- /dev/null +++ b/test/fixtures/typescript/cts/issue-59963/a.cts @@ -0,0 +1,3 @@ +const { message } = require("./b.mts"); +interface Foo {}; +console.log(message); diff --git a/test/fixtures/typescript/cts/issue-59963/b.mts b/test/fixtures/typescript/cts/issue-59963/b.mts new file mode 100644 index 0000000000..bd3cf1998f --- /dev/null +++ b/test/fixtures/typescript/cts/issue-59963/b.mts @@ -0,0 +1,2 @@ +interface Foo {}; +export { message } from "./c.cts"; diff --git a/test/fixtures/typescript/cts/issue-59963/c.cts b/test/fixtures/typescript/cts/issue-59963/c.cts new file mode 100644 index 0000000000..20dc004237 --- /dev/null +++ b/test/fixtures/typescript/cts/issue-59963/c.cts @@ -0,0 +1,2 @@ +const message: string = "Hello from c.cts"; +module.exports = { message }; diff --git a/test/fixtures/typescript/mts/issue-59963/a.mts b/test/fixtures/typescript/mts/issue-59963/a.mts new file mode 100644 index 0000000000..99c938acf5 --- /dev/null +++ b/test/fixtures/typescript/mts/issue-59963/a.mts @@ -0,0 +1,3 @@ +import { message } from "./b.cts"; +interface Foo {}; +console.log(message); diff --git a/test/fixtures/typescript/mts/issue-59963/b.cts b/test/fixtures/typescript/mts/issue-59963/b.cts new file mode 100644 index 0000000000..75b724f21c --- /dev/null +++ b/test/fixtures/typescript/mts/issue-59963/b.cts @@ -0,0 +1,3 @@ +const { message } = require("./c.mts"); +interface Foo {}; +module.exports = { message }; diff --git a/test/fixtures/typescript/mts/issue-59963/c.mts b/test/fixtures/typescript/mts/issue-59963/c.mts new file mode 100644 index 0000000000..4e7f88ba12 --- /dev/null +++ b/test/fixtures/typescript/mts/issue-59963/c.mts @@ -0,0 +1 @@ +export const message: string = "Hello from c.mts";