From 3b1795285b5b5db9f7831307671ea59cd2f2d137 Mon Sep 17 00:00:00 2001 From: Paul Bouchon Date: Mon, 10 Aug 2026 17:14:01 -0400 Subject: [PATCH] module: fix --check on ambiguous ESM files A `.js` file with no `"type"` in the nearest package.json has no format of its own, and `defaultGetFormat()` reports it as null. `--check` passed that null straight to `wrapSafe()`, which parses as CommonJS. Module syntax makes that parse bail out early, so the file was reported as valid and `--check` exited 0 even though it is not valid JavaScript under either goal. At load time the goal for such a file is decided by looking for module syntax in the source. Decide it the same way here, so the file is parsed as a module and its real syntax error is reported. Files whose format is known are unaffected, as are ambiguous files without module syntax, which are still parsed as CommonJS. Fixes: https://github.com/nodejs/node/issues/65202 Signed-off-by: Paul Bouchon --- lib/internal/main/check_syntax.js | 12 ++++++++++++ test/fixtures/syntax/bad_syntax_esm_ambiguous.js | 2 ++ test/sequential/test-cli-syntax-bad.js | 3 +++ 3 files changed, 17 insertions(+) create mode 100644 test/fixtures/syntax/bad_syntax_esm_ambiguous.js diff --git a/lib/internal/main/check_syntax.js b/lib/internal/main/check_syntax.js index 16e367c4e089..7bc7bbc1ede4 100644 --- a/lib/internal/main/check_syntax.js +++ b/lib/internal/main/check_syntax.js @@ -67,6 +67,18 @@ async function checkSyntax(source, filename) { format = await defaultGetFormat(new URL(url)); } + // A `.js` file with no `"type"` in the nearest package.json has no format of + // its own. At load time the goal is decided by looking for module syntax in + // the source, so decide it the same way here. Otherwise such a file is only + // ever parsed as CommonJS, where module syntax makes the parse bail out + // before any syntax error in the rest of the file is reported. + if (format === null || format === undefined) { + const { containsModuleSyntax } = internalBinding('contextify'); + if (containsModuleSyntax(source, filename)) { + format = 'module'; + } + } + if (format === 'module') { const { ModuleWrap } = internalBinding('module_wrap'); new ModuleWrap(filename, undefined, source, 0, 0); diff --git a/test/fixtures/syntax/bad_syntax_esm_ambiguous.js b/test/fixtures/syntax/bad_syntax_esm_ambiguous.js new file mode 100644 index 000000000000..511f42994f90 --- /dev/null +++ b/test/fixtures/syntax/bad_syntax_esm_ambiguous.js @@ -0,0 +1,2 @@ +import fs from 'node:fs'; +var = ; diff --git a/test/sequential/test-cli-syntax-bad.js b/test/sequential/test-cli-syntax-bad.js index e967ff36ac28..0cf9d020b30f 100644 --- a/test/sequential/test-cli-syntax-bad.js +++ b/test/sequential/test-cli-syntax-bad.js @@ -21,6 +21,9 @@ const syntaxErrorRE = /^SyntaxError: \b/m; 'syntax/bad_syntax', 'syntax/bad_syntax_shebang.js', 'syntax/bad_syntax_shebang', + // A `.js` file with no `"type"` in the nearest package.json, whose module + // syntax makes it load as ESM. Refs: https://github.com/nodejs/node/issues/65202 + 'syntax/bad_syntax_esm_ambiguous.js', ].forEach((file) => { const path = fixtures.path(file);