GeezerVison is showing github.com — module: unflag --experimental-require-module · nodejs/node@06206af
File treeExpand file treeCollapse file tree Open diff view settings fixtures/es-module-loaders
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/cli.md +23-3Lines changed: 23 additions & 3 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -1034,6 +1034,10 @@ following permissions are restricted: | 1034 | 1034 | added: | 1035 | 1035 | - v22.0.0 | 1036 | 1036 | - v20.17.0 | | 1037 | +changes: | | 1038 | + - version: REPLACEME | | 1039 | + pr-url: https://github.com/nodejs/node/pull/55085 | | 1040 | + description: This is now true by default. | 1037 | 1041 | --> | 1038 | 1042 |
| 1039 | 1043 | > Stability: 1.1 - Active Development | @@ -1659,6 +1663,24 @@ added: v16.6.0 | 1659 | 1663 |
| 1660 | 1664 | Use this flag to disable top-level await in REPL. | 1661 | 1665 |
| | 1666 | +### `--no-experimental-require-module` | | 1667 | + | | 1668 | +<!-- YAML | | 1669 | +added: | | 1670 | + - v22.0.0 | | 1671 | + - v20.17.0 | | 1672 | +changes: | | 1673 | + - version: REPLACEME | | 1674 | + pr-url: https://github.com/nodejs/node/pull/55085 | | 1675 | + description: This is now false by default. | | 1676 | +--> | | 1677 | + | | 1678 | +> Stability: 1.1 - Active Development | | 1679 | +
| | 1680 | +Disable support for loading a synchronous ES module graph in `require()`. | | 1681 | + | | 1682 | +See [Loading ECMAScript modules using `require()`][]. | | 1683 | + | 1662 | 1684 | ### `--no-experimental-websocket` | 1663 | 1685 |
| 1664 | 1686 | <!-- YAML | @@ -1875,9 +1897,7 @@ added: | 1875 | 1897 | - v20.17.0 | 1876 | 1898 | --> | 1877 | 1899 |
| 1878 | | -This flag is only useful when `--experimental-require-module` is enabled. | 1879 | | - | 1880 | | -If the ES module being `require()`'d contains top-level await, this flag | | 1900 | +If the ES module being `require()`'d contains top-level `await`, this flag | 1881 | 1901 | allows Node.js to evaluate the module, try to locate the | 1882 | 1902 | top-level awaits, and print their location to help users find them. | 1883 | 1903 |
| |
Collapse file Copy file name to clipboardExpand all lines: doc/api/errors.md +16-7Lines changed: 16 additions & 7 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2426,8 +2426,8 @@ object. | 2426 | 2426 |
| 2427 | 2427 | > Stability: 1 - Experimental | 2428 | 2428 |
| 2429 | | -When trying to `require()` a [ES Module][] under `--experimental-require-module`, | 2430 | | -a CommonJS to ESM or ESM to CommonJS edge participates in an immediate cycle. | | 2429 | +When trying to `require()` a [ES Module][], a CommonJS to ESM or ESM to CommonJS edge | | 2430 | +participates in an immediate cycle. | 2431 | 2431 | This is not allowed because ES Modules cannot be evaluated while they are | 2432 | 2432 | already being evaluated. | 2433 | 2433 |
| @@ -2441,8 +2441,8 @@ module, and should be done lazily in an inner function. | 2441 | 2441 |
| 2442 | 2442 | > Stability: 1 - Experimental | 2443 | 2443 |
| 2444 | | -When trying to `require()` a [ES Module][] under `--experimental-require-module`, | 2445 | | -the module turns out to be asynchronous. That is, it contains top-level await. | | 2444 | +When trying to `require()` a [ES Module][], the module turns out to be asynchronous. | | 2445 | +That is, it contains top-level await. | 2446 | 2446 |
| 2447 | 2447 | To see where the top-level await is, use | 2448 | 2448 | `--experimental-print-required-tla` (this would execute the modules | @@ -2452,12 +2452,20 @@ before looking for the top-level awaits). | 2452 | 2452 |
| 2453 | 2453 | ### `ERR_REQUIRE_ESM` | 2454 | 2454 |
| 2455 | | -> Stability: 1 - Experimental | | 2455 | +<!-- YAML | | 2456 | +changes: | | 2457 | + - version: REPLACEME | | 2458 | + pr-url: https://github.com/nodejs/node/pull/55085 | | 2459 | + description: require() now supports loading synchronous ES modules by default. | | 2460 | +--> | | 2461 | + | | 2462 | +> Stability: 0 - Deprecated | 2456 | 2463 |
| 2457 | 2464 | An attempt was made to `require()` an [ES Module][]. | 2458 | 2465 |
| 2459 | | -To enable `require()` for synchronous module graphs (without | 2460 | | -top-level `await`), use `--experimental-require-module`. | | 2466 | +This error has been deprecated since `require()` now supports loading synchronous | | 2467 | +ES modules. When `require()` encounters an ES module that contains top-level | | 2468 | +`await`, it will throw [`ERR_REQUIRE_ASYNC_MODULE`][] instead. | 2461 | 2469 |
| 2462 | 2470 | <a id="ERR_SCRIPT_EXECUTION_INTERRUPTED"></a> | 2463 | 2471 |
| @@ -4061,6 +4069,7 @@ Type stripping is not supported for files descendent of a `node_modules` directo | 4061 | 4069 | [`ERR_INVALID_ARG_TYPE`]: #err_invalid_arg_type | 4062 | 4070 | [`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: #err_missing_message_port_in_transfer_list | 4063 | 4071 | [`ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST`]: #err_missing_transferable_in_transfer_list | | 4072 | +[`ERR_REQUIRE_ASYNC_MODULE`]: #err_require_async_module | 4064 | 4073 | [`EventEmitter`]: events.md#class-eventemitter | 4065 | 4074 | [`MessagePort`]: worker_threads.md#class-messageport | 4066 | 4075 | [`Object.getPrototypeOf`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/esm.md +1-1Lines changed: 1 addition & 1 deletion - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -468,7 +468,7 @@ compatibility. | 468 | 468 | ### `require` | 469 | 469 |
| 470 | 470 | The CommonJS module `require` currently only supports loading synchronous ES | 471 | | -modules when `--experimental-require-module` is enabled. | | 471 | +modules (that is, ES modules that do not use top-level `await`). | 472 | 472 |
| 473 | 473 | See [Loading ECMAScript modules using `require()`][] for details. | 474 | 474 |
| |
Collapse file Copy file name to clipboardExpand all lines: doc/api/modules.md +20-13Lines changed: 20 additions & 13 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -170,15 +170,18 @@ relative, and based on the real path of the files making the calls to | 170 | 170 |
| 171 | 171 | ## Loading ECMAScript modules using `require()` | 172 | 172 |
| | 173 | +<!-- YAML | | 174 | +changes: | | 175 | + - version: REPLACEME | | 176 | + pr-url: https://github.com/nodejs/node/pull/55085 | | 177 | + description: require() now supports loading synchronous ES modules by default. | | 178 | +--> | | 179 | + | 173 | 180 | The `.mjs` extension is reserved for [ECMAScript Modules][]. | 174 | | -Currently, if the flag `--experimental-require-module` is not used, loading | 175 | | -an ECMAScript module using `require()` will throw a [`ERR_REQUIRE_ESM`][] | 176 | | -error, and users need to use [`import()`][] instead. See | 177 | | -[Determining module system][] section for more info | | 181 | +See [Determining module system][] section for more info | 178 | 182 | regarding which files are parsed as ECMAScript modules. | 179 | 183 |
| 180 | | -If `--experimental-require-module` is enabled, and the ECMAScript module being | 181 | | -loaded by `require()` meets the following requirements: | | 184 | +`require()` only supports loading ECMAScript modules that meet the following requirements: | 182 | 185 |
| 183 | 186 | * The module is fully synchronous (contains no top-level `await`); and | 184 | 187 | * One of these conditions are met: | @@ -187,8 +190,8 @@ loaded by `require()` meets the following requirements: | 187 | 190 | 3. The file has a `.js` extension, the closest `package.json` does not contain | 188 | 191 | `"type": "commonjs"`, and the module contains ES module syntax. | 189 | 192 |
| 190 | | -`require()` will load the requested module as an ES Module, and return | 191 | | -the module namespace object. In this case it is similar to dynamic | | 193 | +If the ES Module being loaded meet the requirements, `require()` can load it and | | 194 | +return the module namespace object. In this case it is similar to dynamic | 192 | 195 | `import()` but is run synchronously and returns the name space object | 193 | 196 | directly. | 194 | 197 |
| @@ -207,7 +210,7 @@ class Point { | 207 | 210 | export default Point; | 208 | 211 | ``` | 209 | 212 |
| 210 | | -A CommonJS module can load them with `require()` under `--experimental-detect-module`: | | 213 | +A CommonJS module can load them with `require()`: | 211 | 214 |
| 212 | 215 | ```cjs | 213 | 216 | const distance = require('./distance.mjs'); | @@ -236,13 +239,19 @@ conventions. Code authored directly in CommonJS should avoid depending on it. | 236 | 239 | If the module being `require()`'d contains top-level `await`, or the module | 237 | 240 | graph it `import`s contains top-level `await`, | 238 | 241 | [`ERR_REQUIRE_ASYNC_MODULE`][] will be thrown. In this case, users should | 239 | | -load the asynchronous module using `import()`. | | 242 | +load the asynchronous module using [`import()`][]. | 240 | 243 |
| 241 | 244 | If `--experimental-print-required-tla` is enabled, instead of throwing | 242 | 245 | `ERR_REQUIRE_ASYNC_MODULE` before evaluation, Node.js will evaluate the | 243 | 246 | module, try to locate the top-level awaits, and print their location to | 244 | 247 | help users fix them. | 245 | 248 |
| | 249 | +Support for loading ES modules using `require()` is currently | | 250 | +experimental and can be disabled using `--no-experimental-require-module`. | | 251 | +When `require()` actually encounters an ES module for the | | 252 | +first time in the process, it will emit an experimental warning. The | | 253 | +warning is expected to be removed when this feature stablizes. | | 254 | + | 246 | 255 | ## All together | 247 | 256 |
| 248 | 257 | <!-- type=misc --> | @@ -272,8 +281,7 @@ require(X) from module at path Y | 272 | 281 |
| 273 | 282 | MAYBE_DETECT_AND_LOAD(X) | 274 | 283 | 1. If X parses as a CommonJS module, load X as a CommonJS module. STOP. | 275 | | -2. Else, if `--experimental-require-module` is | 276 | | - enabled, and the source code of X can be parsed as ECMAScript module using | | 284 | +2. Else, if the source code of X can be parsed as ECMAScript module using | 277 | 285 | <a href="esm.md#resolver-algorithm-specification">DETECT_MODULE_SYNTAX defined in | 278 | 286 | the ESM resolver</a>, | 279 | 287 | a. Load X as an ECMAScript module. STOP. | @@ -1190,7 +1198,6 @@ This section was moved to | 1190 | 1198 | [`"main"`]: packages.md#main | 1191 | 1199 | [`"type"`]: packages.md#type | 1192 | 1200 | [`ERR_REQUIRE_ASYNC_MODULE`]: errors.md#err_require_async_module | 1193 | | -[`ERR_REQUIRE_ESM`]: errors.md#err_require_esm | 1194 | 1201 | [`ERR_UNSUPPORTED_DIR_IMPORT`]: errors.md#err_unsupported_dir_import | 1195 | 1202 | [`MODULE_NOT_FOUND`]: errors.md#module_not_found | 1196 | 1203 | [`__dirname`]: #__dirname | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/packages.md +2-4Lines changed: 2 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -172,8 +172,7 @@ There is the CommonJS module loader: | 172 | 172 | * It treats all files that lack `.json` or `.node` extensions as JavaScript | 173 | 173 | text files. | 174 | 174 | * It can only be used to [load ECMASCript modules from CommonJS modules][] if | 175 | | - the module graph is synchronous (that contains no top-level `await`) when | 176 | | - `--experimental-require-module` is enabled. | | 175 | + the module graph is synchronous (that contains no top-level `await`). | 177 | 176 | When used to load a JavaScript text file that is not an ECMAScript module, | 178 | 177 | the file will be loaded as a CommonJS module. | 179 | 178 |
| @@ -662,8 +661,7 @@ specific to least specific as conditions should be defined: | 662 | 661 | * `"require"` - matches when the package is loaded via `require()`. The | 663 | 662 | referenced file should be loadable with `require()` although the condition | 664 | 663 | matches regardless of the module format of the target file. Expected | 665 | | - formats include CommonJS, JSON, native addons, and ES modules | 666 | | - if `--experimental-require-module` is enabled. _Always mutually | | 664 | + formats include CommonJS, JSON, native addons, and ES modules. _Always mutually | 667 | 665 | exclusive with `"import"`._ | 668 | 666 | * `"module-sync"` - matches no matter the package is loaded via `import`, | 669 | 667 | `import()` or `require()`. The format is expected to be ES modules that does | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -438,7 +438,6 @@ function initializeCJS() { | 438 | 438 | Module._extensions['.ts'] = loadTS; | 439 | 439 | } | 440 | 440 | if (getOptionValue('--experimental-require-module')) { | 441 | | - emitExperimentalWarning('Support for loading ES Module in require()'); | 442 | 441 | Module._extensions['.mjs'] = loadESMFromCJS; | 443 | 442 | if (tsEnabled) { | 444 | 443 | Module._extensions['.mts'] = loadESMFromCJS; | @@ -1386,6 +1385,7 @@ function loadESMFromCJS(mod, filename) { | 1386 | 1385 | // ESM won't be accessible via process.mainModule. | 1387 | 1386 | setOwnProperty(process, 'mainModule', undefined); | 1388 | 1387 | } else { | | 1388 | + emitExperimentalWarning('Support for loading ES Module in require()'); | 1389 | 1389 | const { | 1390 | 1390 | wrap, | 1391 | 1391 | namespace, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/load.js -10Lines changed: 0 additions & 10 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -131,11 +131,6 @@ async function defaultLoad(url, context = kEmptyObject) { | 131 | 131 |
| 132 | 132 | validateAttributes(url, format, importAttributes); | 133 | 133 |
| 134 | | - // Use the synchronous commonjs translator which can deal with cycles. | 135 | | - if (format === 'commonjs' && getOptionValue('--experimental-require-module')) { | 136 | | - format = 'commonjs-sync'; | 137 | | - } | 138 | | - | 139 | 134 | if (getOptionValue('--experimental-strip-types') && | 140 | 135 | (format === 'module-typescript' || format === 'commonjs-typescript') && | 141 | 136 | isUnderNodeModules(url)) { | @@ -191,11 +186,6 @@ function defaultLoadSync(url, context = kEmptyObject) { | 191 | 186 |
| 192 | 187 | validateAttributes(url, format, importAttributes); | 193 | 188 |
| 194 | | - // Use the synchronous commonjs translator which can deal with cycles. | 195 | | - if (format === 'commonjs' && getOptionValue('--experimental-require-module')) { | 196 | | - format = 'commonjs-sync'; | 197 | | - } | 198 | | - | 199 | 189 | return { | 200 | 190 | __proto__: null, | 201 | 191 | format, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/loader.js +4-4Lines changed: 4 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -373,15 +373,15 @@ class ModuleLoader { | 373 | 373 |
| 374 | 374 | defaultLoadSync ??= require('internal/modules/esm/load').defaultLoadSync; | 375 | 375 | const loadResult = defaultLoadSync(url, { format, importAttributes }); | 376 | | - const { | 377 | | - format: finalFormat, | 378 | | - source, | 379 | | - } = loadResult; | | 376 | + | | 377 | + // Use the synchronous commonjs translator which can deal with cycles. | | 378 | + const finalFormat = loadResult.format === 'commonjs' ? 'commonjs-sync' : loadResult.format; | 380 | 379 |
| 381 | 380 | if (finalFormat === 'wasm') { | 382 | 381 | assert.fail('WASM is currently unsupported by require(esm)'); | 383 | 382 | } | 384 | 383 |
| | 384 | + const { source } = loadResult; | 385 | 385 | const isMain = (parentURL === undefined); | 386 | 386 | const wrap = this.#translate(url, finalFormat, source, isMain); | 387 | 387 | assert(wrap instanceof ModuleWrap, `Translator used for require(${url}) should not be async`); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/module_job.js +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -361,6 +361,7 @@ class ModuleJobSync extends ModuleJobBase { | 361 | 361 | } | 362 | 362 |
| 363 | 363 | runSync() { | | 364 | + // TODO(joyeecheung): add the error decoration logic from the async instantiate. | 364 | 365 | this.module.instantiateSync(); | 365 | 366 | setHasStartedUserESMExecution(); | 366 | 367 | const namespace = this.module.evaluateSync(); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/utils.js +2-4Lines changed: 2 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -75,17 +75,15 @@ function initializeDefaultConditions() { | 75 | 75 | const userConditions = getOptionValue('--conditions'); | 76 | 76 | const noAddons = getOptionValue('--no-addons'); | 77 | 77 | const addonConditions = noAddons ? [] : ['node-addons']; | 78 | | - | | 78 | + const moduleConditions = getOptionValue('--experimental-require-module') ? ['module-sync'] : []; | 79 | 79 | defaultConditions = ObjectFreeze([ | 80 | 80 | 'node', | 81 | 81 | 'import', | | 82 | + ...moduleConditions, | 82 | 83 | ...addonConditions, | 83 | 84 | ...userConditions, | 84 | 85 | ]); | 85 | 86 | defaultConditionsSet = new SafeSet(defaultConditions); | 86 | | - if (getOptionValue('--experimental-require-module')) { | 87 | | - defaultConditionsSet.add('module-sync'); | 88 | | - } | 89 | 87 | } | 90 | 88 |
| 91 | 89 | /** | |
|