module: do not warn when require(esm) comes from node_modules · nodejs/node@e01dd4b
@@ -70,6 +70,7 @@ const {
7070 module_export_private_symbol,
7171 module_parent_private_symbol,
7272},
73+ isInsideNodeModules,
7374} = internalBinding('util');
74757576const { kEvaluated, createRequiredModuleFacade } = internalBinding('module_wrap');
@@ -126,6 +127,7 @@ const {
126127 kEmptyObject,
127128 setOwnProperty,
128129 getLazy,
130+ isUnderNodeModules,
129131} = require('internal/util');
130132const {
131133 makeContextifyScript,
@@ -1314,6 +1316,7 @@ Module.prototype.require = function(id) {
13141316}
13151317};
131613181319+let emittedRequireModuleWarning = false;
13171320/**
13181321 * Resolved path to `process.argv[1]` will be lazily placed here
13191322 * (needed for setting breakpoint when called with `--inspect-brk`).
@@ -1341,29 +1344,46 @@ function loadESMFromCJS(mod, filename) {
13411344setOwnProperty(process, 'mainModule', undefined);
13421345} else {
13431346const parent = mod[kModuleParent];
1344-let messagePrefix;
1345-if (parent) {
1346-// In the case of the module calling `require()`, it's more useful to know its absolute path.
1347-let from = parent.filename || parent.id;
1348-// In the case of the module being require()d, it's more useful to know the id passed into require().
1349-const to = mod.id || mod.filename;
1350-if (from === 'internal/preload') {
1351-from = '--require';
1352-} else if (from === '<repl>') {
1353-from = 'The REPL';
1354-} else if (from === '.') {
1355-from = 'The entry point';
1356-} else {
1357-from &&= `CommonJS module ${from}`;
1347+1348+if (!emittedRequireModuleWarning) {
1349+let shouldEmitWarning = false;
1350+// Check if the require() comes from node_modules.
1351+if (parent) {
1352+shouldEmitWarning = !isUnderNodeModules(parent.filename);
1353+} else if (mod[kIsCachedByESMLoader]) {
1354+// It comes from the require() built for `import cjs` and doesn't have a parent recorded
1355+// in the CJS module instance. Inspect the stack trace to see if the require()
1356+// comes from node_modules and reduce the noise. If there are more than 100 frames,
1357+// just give up and assume it is under node_modules.
1358+shouldEmitWarning = !isInsideNodeModules(100, true);
13581359}
1359-if (from && to) {
1360-messagePrefix = `${from} is loading ES Module ${to} using require().\n`;
1360+if (shouldEmitWarning) {
1361+let messagePrefix;
1362+if (parent) {
1363+// In the case of the module calling `require()`, it's more useful to know its absolute path.
1364+let from = parent.filename || parent.id;
1365+// In the case of the module being require()d, it's more useful to know the id passed into require().
1366+const to = mod.id || mod.filename;
1367+if (from === 'internal/preload') {
1368+from = '--require';
1369+} else if (from === '<repl>') {
1370+from = 'The REPL';
1371+} else if (from === '.') {
1372+from = 'The entry point';
1373+} else {
1374+from &&= `CommonJS module ${from}`;
1375+}
1376+if (from && to) {
1377+messagePrefix = `${from} is loading ES Module ${to} using require().\n`;
1378+}
1379+}
1380+emitExperimentalWarning('Support for loading ES Module in require()',
1381+messagePrefix,
1382+undefined,
1383+parent?.require);
1384+emittedRequireModuleWarning = true;
13611385}
13621386}
1363-emitExperimentalWarning('Support for loading ES Module in require()',
1364-messagePrefix,
1365-undefined,
1366-parent?.require);
13671387const {
13681388 wrap,
13691389 namespace,