Skip to content

Commit c64490e

Browse files
GeoffreyBoothtargos
authored andcommitted
esm: improve check for ESM syntax
PR-URL: #50127 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 16a0798 commit c64490e

5 files changed

Lines changed: 207 additions & 65 deletions

File tree

lib/internal/modules/cjs/loader.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ const {
9090
makeContextifyScript,
9191
runScriptInThisContext,
9292
} = require('internal/vm');
93+
const { containsModuleSyntax } = internalBinding('contextify');
9394

9495
const assert = require('internal/assert');
9596
const fs = require('fs');
@@ -104,7 +105,6 @@ const {
104105
const {
105106
getCjsConditions,
106107
initializeCjsConditions,
107-
hasEsmSyntax,
108108
loadBuiltinModule,
109109
makeRequireFunction,
110110
normalizeReferrerURL,
@@ -1315,7 +1315,7 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) {
13151315
} catch (err) {
13161316
if (process.mainModule === cjsModuleInstance) {
13171317
const { enrichCJSError } = require('internal/modules/esm/translators');
1318-
enrichCJSError(err, content);
1318+
enrichCJSError(err, content, filename);
13191319
}
13201320
throw err;
13211321
}
@@ -1400,10 +1400,11 @@ Module._extensions['.js'] = function(module, filename) {
14001400
const pkg = packageJsonReader.readPackageScope(filename) || { __proto__: null };
14011401
// Function require shouldn't be used in ES modules.
14021402
if (pkg.data?.type === 'module') {
1403+
// This is an error path because `require` of a `.js` file in a `"type": "module"` scope is not allowed.
14031404
const parent = moduleParentCache.get(module);
14041405
const parentPath = parent?.filename;
14051406
const packageJsonPath = path.resolve(pkg.path, 'package.json');
1406-
const usesEsm = hasEsmSyntax(content);
1407+
const usesEsm = containsModuleSyntax(content, filename);
14071408
const err = new ERR_REQUIRE_ESM(filename, usesEsm, parentPath,
14081409
packageJsonPath);
14091410
// Attempt to reconstruct the parent require frame.

lib/internal/modules/esm/translators.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ function lazyTypes() {
3030
return _TYPES = require('internal/util/types');
3131
}
3232

33+
const { containsModuleSyntax } = internalBinding('contextify');
3334
const assert = require('internal/assert');
3435
const { readFileSync } = require('fs');
3536
const { dirname, extname, isAbsolute } = require('path');
3637
const {
37-
hasEsmSyntax,
3838
loadBuiltinModule,
3939
stripBOM,
4040
} = require('internal/modules/helpers');
@@ -166,11 +166,11 @@ translators.set('module', async function moduleStrategy(url, source, isMain) {
166166
* Provide a more informative error for CommonJS imports.
167167
* @param {Error | any} err
168168
* @param {string} [content] Content of the file, if known.
169-
* @param {string} [filename] Useful only if `content` is unknown.
169+
* @param {string} [filename] The filename of the erroring module.
170170
*/
171171
function enrichCJSError(err, content, filename) {
172172
if (err != null && ObjectGetPrototypeOf(err) === SyntaxErrorPrototype &&
173-
hasEsmSyntax(content || readFileSync(filename, 'utf-8'))) {
173+
containsModuleSyntax(content, filename)) {
174174
// Emit the warning synchronously because we are in the middle of handling
175175
// a SyntaxError that will throw and likely terminate the process before an
176176
// asynchronous warning would be emitted.
@@ -217,7 +217,7 @@ function loadCJSModule(module, source, url, filename) {
217217
importModuleDynamically, // importModuleDynamically
218218
).function;
219219
} catch (err) {
220-
enrichCJSError(err, source, url);
220+
enrichCJSError(err, source, filename);
221221
throw err;
222222
}
223223

@@ -344,7 +344,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
344344
assert(module === CJSModule._cache[filename]);
345345
CJSModule._load(filename);
346346
} catch (err) {
347-
enrichCJSError(err, source, url);
347+
enrichCJSError(err, source, filename);
348348
throw err;
349349
}
350350
} : loadCJSModule;

lib/internal/modules/helpers.js

Lines changed: 0 additions & 23 deletions