GeezerVison is showing github.com — module: only emit require(esm) warning under --trace-require-module · nodejs/node@de313b2
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/cli.md +13Lines changed: 13 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2387,6 +2387,18 @@ added: | 2387 | 2387 | Prints a stack trace whenever an environment is exited proactively, | 2388 | 2388 | i.e. invoking `process.exit()`. | 2389 | 2389 |
| | 2390 | +### `--trace-require-module=mode` | | 2391 | + | | 2392 | +<!-- YAML | | 2393 | +added: | | 2394 | + - REPLACEME | | 2395 | +--> | | 2396 | + | | 2397 | +Prints information about usage of [Loading ECMAScript modules using `require()`][]. | | 2398 | + | | 2399 | +When `mode` is `all`, all usage is printed. When `mode` is `no-node-modules`, usage | | 2400 | +from the `node_modules` folder is excluded. | | 2401 | + | 2390 | 2402 | ### `--trace-sigint` | 2391 | 2403 |
| 2392 | 2404 | <!-- YAML | @@ -2865,6 +2877,7 @@ one is included in the list below. | 2865 | 2877 | * `--trace-event-file-pattern` | 2866 | 2878 | * `--trace-events-enabled` | 2867 | 2879 | * `--trace-exit` | | 2880 | +* `--trace-require-module` | 2868 | 2881 | * `--trace-sigint` | 2869 | 2882 | * `--trace-sync-io` | 2870 | 2883 | * `--trace-tls` | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/modules.md +10-4Lines changed: 10 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -175,7 +175,13 @@ added: | 175 | 175 | - v22.0.0 | 176 | 176 | - v20.17.0 | 177 | 177 | changes: | 178 | | - - version: REPLACEME | | 178 | + - version: | | 179 | + - REPLACEME | | 180 | + pr-url: https://github.com/nodejs/node/pull/56194 | | 181 | + description: This feature no longer emits an experimental warning by default, | | 182 | + though the warning can still be emitted by --trace-require-module. | | 183 | + - version: | | 184 | + - REPLACEME | 179 | 185 | pr-url: https://github.com/nodejs/node/pull/55085 | 180 | 186 | description: This feature is no longer behind the `--experimental-require-module` CLI flag. | 181 | 187 | - version: REPLACEME | @@ -315,9 +321,8 @@ help users fix them. | 315 | 321 |
| 316 | 322 | Support for loading ES modules using `require()` is currently | 317 | 323 | experimental and can be disabled using `--no-experimental-require-module`. | 318 | | -When `require()` actually encounters an ES module for the | 319 | | -first time in the process, it will emit an experimental warning. The | 320 | | -warning is expected to be removed when this feature stablizes. | | 324 | +To print where this feature is used, use [`--trace-require-module`][]. | | 325 | + | 321 | 326 | This feature can be detected by checking if | 322 | 327 | [`process.features.require_module`][] is `true`. | 323 | 328 |
| @@ -1266,6 +1271,7 @@ This section was moved to | 1266 | 1271 | [GLOBAL_FOLDERS]: #loading-from-the-global-folders | 1267 | 1272 | [`"main"`]: packages.md#main | 1268 | 1273 | [`"type"`]: packages.md#type | | 1274 | +[`--trace-require-module`]: cli.md#--trace-require-modulemode | 1269 | 1275 | [`ERR_REQUIRE_ASYNC_MODULE`]: errors.md#err_require_async_module | 1270 | 1276 | [`ERR_UNSUPPORTED_DIR_IMPORT`]: errors.md#err_unsupported_dir_import | 1271 | 1277 | [`MODULE_NOT_FOUND`]: errors.md#module_not_found | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js +17-12Lines changed: 17 additions & 12 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1316,7 +1316,7 @@ Module.prototype.require = function(id) { | 1316 | 1316 | } | 1317 | 1317 | }; | 1318 | 1318 |
| 1319 | | -let emittedRequireModuleWarning = false; | | 1319 | +let requireModuleWarningMode; | 1320 | 1320 | /** | 1321 | 1321 | * Resolved path to `process.argv[1]` will be lazily placed here | 1322 | 1322 | * (needed for setting breakpoint when called with `--inspect-brk`). | @@ -1345,17 +1345,22 @@ function loadESMFromCJS(mod, filename) { | 1345 | 1345 | } else { | 1346 | 1346 | const parent = mod[kModuleParent]; | 1347 | 1347 |
| 1348 | | - if (!emittedRequireModuleWarning) { | | 1348 | + requireModuleWarningMode ??= getOptionValue('--trace-require-module'); | | 1349 | + if (requireModuleWarningMode) { | 1349 | 1350 | 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); | | 1351 | + if (requireModuleWarningMode === 'no-node-modules') { | | 1352 | + // Check if the require() comes from node_modules. | | 1353 | + if (parent) { | | 1354 | + shouldEmitWarning = !isUnderNodeModules(parent.filename); | | 1355 | + } else if (mod[kIsCachedByESMLoader]) { | | 1356 | + // It comes from the require() built for `import cjs` and doesn't have a parent recorded | | 1357 | + // in the CJS module instance. Inspect the stack trace to see if the require() | | 1358 | + // comes from node_modules and reduce the noise. If there are more than 100 frames, | | 1359 | + // just give up and assume it is under node_modules. | | 1360 | + shouldEmitWarning = !isInsideNodeModules(100, true); | | 1361 | + } | | 1362 | + } else { | | 1363 | + shouldEmitWarning = true; | 1359 | 1364 | } | 1360 | 1365 | if (shouldEmitWarning) { | 1361 | 1366 | let messagePrefix; | @@ -1381,7 +1386,7 @@ function loadESMFromCJS(mod, filename) { | 1381 | 1386 | messagePrefix, | 1382 | 1387 | undefined, | 1383 | 1388 | parent?.require); | 1384 | | - emittedRequireModuleWarning = true; | | 1389 | + requireModuleWarningMode = true; | 1385 | 1390 | } | 1386 | 1391 | } | 1387 | 1392 | const { | |
Collapse file Copy file name to clipboardExpand all lines: src/node_options.cc +13Lines changed: 13 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -150,6 +150,11 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors, | 150 | 150 | errors->push_back("--heapsnapshot-near-heap-limit must not be negative"); | 151 | 151 | } | 152 | 152 |
| | 153 | + if (!trace_require_module.empty() && trace_require_module != "all" && | | 154 | + trace_require_module != "no-node-modules") { | | 155 | + errors->push_back("invalid value for --trace-require-module"); | | 156 | + } | | 157 | + | 153 | 158 | if (test_runner) { | 154 | 159 | if (syntax_check_only) { | 155 | 160 | errors->push_back("either --test or --check can be used, not both"); | @@ -734,6 +739,14 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | 734 | 739 | "set module system to use by default", | 735 | 740 | &EnvironmentOptions::type, | 736 | 741 | kAllowedInEnvvar); | | 742 | + | | 743 | + AddOption( | | 744 | + "--trace-require-module", | | 745 | + "Print access to require(esm). Options are 'all' (print all usage) and " | | 746 | + "'no-node-modules' (excluding usage from the node_modules folder)", | | 747 | + &EnvironmentOptions::trace_require_module, | | 748 | + kAllowedInEnvvar); | | 749 | + | 737 | 750 | AddOption("--extra-info-on-fatal-exception", | 738 | 751 | "hide extra information on fatal exception that causes exit", | 739 | 752 | &EnvironmentOptions::extra_info_on_fatal_exception, | |
Collapse file Copy file name to clipboardExpand all lines: src/node_options.h +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -199,6 +199,7 @@ class EnvironmentOptions : public Options { | 199 | 199 | bool trace_uncaught = false; | 200 | 200 | bool trace_warnings = false; | 201 | 201 | bool trace_promises = false; | | 202 | + std::string trace_require_module; | 202 | 203 | bool extra_info_on_fatal_exception = true; | 203 | 204 | std::string unhandled_rejections; | 204 | 205 | std::vector<std::string> userland_loaders; | |
Collapse file Copy file name to clipboardExpand all lines: test/es-module/test-require-module-preload.js -11Lines changed: 0 additions & 11 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -5,8 +5,6 @@ const { spawnSyncAndAssert } = require('../common/child_process'); | 5 | 5 | const { fixturesDir } = require('../common/fixtures'); | 6 | 6 |
| 7 | 7 | function testPreload(preloadFlag) { | 8 | | - // The warning is only emitted when ESM is loaded by --require. | 9 | | - const isRequire = preloadFlag === '--require'; | 10 | 8 | // Test named exports. | 11 | 9 | { | 12 | 10 | spawnSyncAndAssert( | @@ -22,8 +20,6 @@ function testPreload(preloadFlag) { | 22 | 20 | }, | 23 | 21 | { | 24 | 22 | stdout: 'A', | 25 | | - stderr: isRequire ? | 26 | | - /ExperimentalWarning: --require is loading ES Module .*module-named-exports\.mjs using require/ : undefined, | 27 | 23 | trim: true, | 28 | 24 | } | 29 | 25 | ); | @@ -43,8 +39,6 @@ function testPreload(preloadFlag) { | 43 | 39 | cwd: fixturesDir | 44 | 40 | }, | 45 | 41 | { | 46 | | - stderr: isRequire ? | 47 | | - /ExperimentalWarning: --require is loading ES Module .*import-esm\.mjs using require/ : undefined, | 48 | 42 | stdout: /^world\s+A$/, | 49 | 43 | trim: true, | 50 | 44 | } | @@ -66,8 +60,6 @@ function testPreload(preloadFlag) { | 66 | 60 | }, | 67 | 61 | { | 68 | 62 | stdout: /^ok\s+A$/, | 69 | | - stderr: isRequire ? | 70 | | - /ExperimentalWarning: --require is loading ES Module .*cjs-exports\.mjs using require/ : undefined, | 71 | 63 | trim: true, | 72 | 64 | } | 73 | 65 | ); | @@ -90,8 +82,6 @@ function testPreload(preloadFlag) { | 90 | 82 | }, | 91 | 83 | { | 92 | 84 | stdout: /^world\s+A$/, | 93 | | - stderr: isRequire ? | 94 | | - /ExperimentalWarning: --require is loading ES Module .*require-cjs\.mjs using require/ : undefined, | 95 | 85 | trim: true, | 96 | 86 | } | 97 | 87 | ); | @@ -117,7 +107,6 @@ testPreload('--import'); | 117 | 107 | }, | 118 | 108 | { | 119 | 109 | stdout: /^package-type-module\s+A$/, | 120 | | - stderr: /ExperimentalWarning: --require is loading ES Module .*package-type-module[\\/]index\.js using require/, | 121 | 110 | trim: true, | 122 | 111 | } | 123 | 112 | ); | |
Collapse file Copy file name to clipboardExpand all lines: test/es-module/test-require-module-warning.js +11-3Lines changed: 11 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | 'use strict'; | 2 | 2 |
| 3 | | -// This checks the warning and the stack trace emitted by the require(esm) | 4 | | -// experimental warning. It can get removed when `require(esm)` becomes stable. | 5 | | - | | 3 | +// This checks the warning and the stack trace emitted by --trace-require-module=all. | 6 | 4 | require('../common'); | 7 | 5 | const { spawnSyncAndAssert } = require('../common/child_process'); | 8 | 6 | const fixtures = require('../common/fixtures'); | 9 | 7 | const assert = require('assert'); | 10 | 8 |
| 11 | 9 | spawnSyncAndAssert(process.execPath, [ | 12 | 10 | '--trace-warnings', | | 11 | + '--trace-require-module=all', | 13 | 12 | fixtures.path('es-modules', 'require-module.js'), | 14 | 13 | ], { | 15 | 14 | trim: true, | @@ -33,3 +32,12 @@ spawnSyncAndAssert(process.execPath, [ | 33 | 32 | ); | 34 | 33 | } | 35 | 34 | }); | | 35 | + | | 36 | +spawnSyncAndAssert(process.execPath, [ | | 37 | + '--trace-require-module=1', | | 38 | + fixtures.path('es-modules', 'require-module.js'), | | 39 | +], { | | 40 | + status: 9, | | 41 | + trim: true, | | 42 | + stderr: /invalid value for --trace-require-module/ | | 43 | +}); |
Collapse file Copy file name to clipboardExpand all lines: test/es-module/test-require-module.js -10Lines changed: 0 additions & 10 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 3 | 3 |
| 4 | 4 | const common = require('../common'); | 5 | 5 | const assert = require('assert'); | 6 | | -const path = require('path'); | 7 | | - | 8 | | -// Only the first load will trigger the warning. | 9 | | -common.expectWarning( | 10 | | - 'ExperimentalWarning', | 11 | | - `CommonJS module ${__filename} is loading ES Module ` + | 12 | | - `${path.resolve(__dirname, '../fixtures/es-module-loaders/module-named-exports.mjs')} using require().\n` + | 13 | | - 'Support for loading ES Module in require() is an experimental feature ' + | 14 | | - 'and might change at any time' | 15 | | -); | 16 | 6 |
| 17 | 7 | // Test named exports. | 18 | 8 | { | |
Collapse file Copy file name to clipboardExpand all lines: test/es-module/test-require-node-modules-warning.js +18-6Lines changed: 18 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | 'use strict'; | 2 | 2 |
| 3 | | -// This checks the experimental warning for require(esm) is disabled when the | 4 | | -// require() comes from node_modules. | | 3 | +// This checks the warning and the stack trace emitted by | | 4 | +// --trace-require-module=no-node-modules. | 5 | 5 | require('../common'); | 6 | 6 | const { spawnSyncAndAssert } = require('../common/child_process'); | 7 | 7 | const fixtures = require('../common/fixtures'); | @@ -14,7 +14,10 @@ const warningRE = /Support for loading ES Module in require\(\)/; | 14 | 14 | // require() in non-node_modules -> esm in node_modules should warn. | 15 | 15 | spawnSyncAndAssert( | 16 | 16 | process.execPath, | 17 | | - [fixtures.path('es-modules', 'test_node_modules', 'require-esm.js')], | | 17 | + [ | | 18 | + '--trace-require-module=no-node-modules', | | 19 | + fixtures.path('es-modules', 'test_node_modules', 'require-esm.js'), | | 20 | + ], | 18 | 21 | { | 19 | 22 | trim: true, | 20 | 23 | stderr: warningRE, | @@ -26,7 +29,10 @@ spawnSyncAndAssert( | 26 | 29 | // should not warn. | 27 | 30 | spawnSyncAndAssert( | 28 | 31 | process.execPath, | 29 | | - [fixtures.path('es-modules', 'test_node_modules', 'require-require-esm.js')], | | 32 | + [ | | 33 | + '--trace-require-module=no-node-modules', | | 34 | + fixtures.path('es-modules', 'test_node_modules', 'require-require-esm.js'), | | 35 | + ], | 30 | 36 | { | 31 | 37 | trim: true, | 32 | 38 | stderr: '', | @@ -38,7 +44,10 @@ spawnSyncAndAssert( | 38 | 44 | // should not warn. | 39 | 45 | spawnSyncAndAssert( | 40 | 46 | process.execPath, | 41 | | - [fixtures.path('es-modules', 'test_node_modules', 'import-require-esm.mjs')], | | 47 | + [ | | 48 | + '--trace-require-module=no-node-modules', | | 49 | + fixtures.path('es-modules', 'test_node_modules', 'import-require-esm.mjs'), | | 50 | + ], | 42 | 51 | { | 43 | 52 | trim: true, | 44 | 53 | stderr: '', | @@ -50,7 +59,10 @@ spawnSyncAndAssert( | 50 | 59 | // require() in node_modules -> esm in node_modules should not warn. | 51 | 60 | spawnSyncAndAssert( | 52 | 61 | process.execPath, | 53 | | - [fixtures.path('es-modules', 'test_node_modules', 'import-import-require-esm.mjs')], | | 62 | + [ | | 63 | + '--trace-require-module=no-node-modules', | | 64 | + fixtures.path('es-modules', 'test_node_modules', 'import-import-require-esm.mjs'), | | 65 | + ], | 54 | 66 | { | 55 | 67 | trim: true, | 56 | 68 | stderr: '', | |
|