| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2699,6 +2699,19 @@ This error has been deprecated since `require()` now supports loading synchronou | |||
| 2699 | 2699 | ES modules. When `require()` encounters an ES module that contains top-level | |
| 2700 | 2700 | `await`, it will throw [`ERR_REQUIRE_ASYNC_MODULE`][] instead. | |
| 2701 | 2701 | ||
| 2702 | + <a id="ERR_REQUIRE_ESM_RACE_CONDITION"></a> | ||
| 2703 | + | ||
| 2704 | + ### `ERR_REQUIRE_ESM_RACE_CONDITION` | ||
| 2705 | + | ||
| 2706 | + <!-- YAML | ||
| 2707 | + added: REPLACEME | ||
| 2708 | + --> | ||
| 2709 | + | ||
| 2710 | + > Stability: 1 - Experimental. | ||
| 2711 | + | ||
| 2712 | + An attempt was made to `require()` an [ES Module][] while another `import()` call | ||
| 2713 | + was already in progress to load it asynchronously. | ||
| 2714 | + | ||
| 2702 | 2715 | <a id="ERR_SCRIPT_EXECUTION_INTERRUPTED"></a> | |
| 2703 | 2716 | ||
| 2704 | 2717 | ### `ERR_SCRIPT_EXECUTION_INTERRUPTED` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1717,6 +1717,15 @@ E('ERR_REQUIRE_ESM', | |||
| 1717 | 1717 | 'all ES modules instead).\n'; | |
| 1718 | 1718 | return msg; | |
| 1719 | 1719 | }, Error); | |
| 1720 | + E('ERR_REQUIRE_ESM_RACE_CONDITION', (filename, parentFilename, isForAsyncLoaderHookWorker) => { | ||
| 1721 | + let raceMessage = `Cannot require() ES Module ${filename} because it is not yet fully loaded.\n`; | ||
| 1722 | + raceMessage += 'This may be caused by a race condition if the module is simultaneously dynamically '; | ||
| 1723 | + raceMessage += 'import()-ed via Promise.all().\n'; | ||
| 1724 | + raceMessage += 'Try await-ing the import() sequentially in a loop instead.\n'; | ||
| 1725 | + raceMessage += ` (From ${parentFilename ? `${parentFilename} in ` : ' '}`; | ||
| 1726 | + raceMessage += `${isForAsyncLoaderHookWorker ? 'loader hook worker thread' : 'non-loader-hook thread'})`; | ||
| 1727 | + return raceMessage; | ||
| 1728 | + }, Error); | ||
| 1720 | 1729 | E('ERR_SCRIPT_EXECUTION_INTERRUPTED', | |
| 1721 | 1730 | 'Script execution was interrupted by `SIGINT`', Error); | |
| 1722 | 1731 | E('ERR_SERVER_ALREADY_LISTEN', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -27,6 +27,7 @@ const { | |||
| 27 | 27 | ERR_REQUIRE_ASYNC_MODULE, | |
| 28 | 28 | ERR_REQUIRE_CYCLE_MODULE, | |
| 29 | 29 | ERR_REQUIRE_ESM, | |
| 30 | + ERR_REQUIRE_ESM_RACE_CONDITION, | ||
| 30 | 31 | ERR_UNKNOWN_MODULE_FORMAT, | |
| 31 | 32 | } = require('internal/errors').codes; | |
| 32 | 33 | const { getOptionValue } = require('internal/options'); | |
@@ -48,6 +49,7 @@ const { | |||
| 48 | 49 | kEvaluating, | |
| 49 | 50 | kEvaluationPhase, | |
| 50 | 51 | kInstantiated, | |
| 52 | + kUninstantiated, | ||
| 51 | 53 | kErrored, | |
| 52 | 54 | kSourcePhase, | |
| 53 | 55 | throwIfPromiseRejected, | |
@@ -101,24 +103,6 @@ const { translators } = require('internal/modules/esm/translators'); | |||
| 101 | 103 | const { defaultResolve } = require('internal/modules/esm/resolve'); | |
| 102 | 104 | const { defaultLoadSync, throwUnknownModuleFormat } = require('internal/modules/esm/load'); | |
| 103 | 105 | ||
| 104 | - /** | ||
| 105 | - * Generate message about potential race condition caused by requiring a cached module that has started | ||
| 106 | - * async linking. | ||
| 107 | - * @param {string} filename Filename of the module being required. | ||
| 108 | - * @param {string|undefined} parentFilename Filename of the module calling require(). | ||
| 109 | - * @param {boolean} isForAsyncLoaderHookWorker Whether this is for the async loader hook worker. | ||
| 110 | - * @returns {string} Error message. | ||
| 111 | - */ | ||
| 112 | - function getRaceMessage(filename, parentFilename, isForAsyncLoaderHookWorker) { | ||
| 113 | - let raceMessage = `Cannot require() ES Module ${filename} because it is not yet fully loaded.\n`; | ||
| 114 | - raceMessage += 'This may be caused by a race condition if the module is simultaneously dynamically '; | ||
| 115 | - raceMessage += 'import()-ed via Promise.all().\n'; | ||
| 116 | - raceMessage += 'Try await-ing the import() sequentially in a loop instead.\n'; | ||
| 117 | - raceMessage += ` (From ${parentFilename ? `${parentFilename} in ` : ' '}`; | ||
| 118 | - raceMessage += `${isForAsyncLoaderHookWorker ? 'loader hook worker thread' : 'non-loader-hook thread'})`; | ||
| 119 | - return raceMessage; | ||
| 120 | - } | ||
| 121 | - | ||
| 122 | 106 | /** | |
| 123 | 107 | * @typedef {import('../cjs/loader.js').Module} CJSModule | |
| 124 | 108 | */ | |
@@ -306,7 +290,7 @@ class ModuleLoader { | |||
| 306 | 290 | const parentFilename = urlToFilename(parent?.filename); | |
| 307 | 291 | // This race should only be possible on the loader hook thread. See https://github.com/nodejs/node/issues/59666 | |
| 308 | 292 | if (!job.module) { | |
| 309 | - assert.fail(getRaceMessage(filename, parentFilename), this.isForAsyncLoaderHookWorker); | ||
| 293 | + throw new ERR_REQUIRE_ESM_RACE_CONDITION(filename, parentFilename, this.isForAsyncLoaderHookWorker); | ||
| 310 | 294 | } | |
| 311 | 295 | const status = job.module.getStatus(); | |
| 312 | 296 | debug('Module status', job, status); | |
@@ -339,8 +323,8 @@ class ModuleLoader { | |||
| 339 | 323 | throwIfPromiseRejected(job.instantiated); | |
| 340 | 324 | } | |
| 341 | 325 | if (status !== kEvaluating) { | |
| 342 | - assert.fail(`Unexpected module status ${status}. ` + | ||
| 343 | - getRaceMessage(filename, parentFilename)); | ||
| 326 | + assert(status === kUninstantiated, `Unexpected module status ${status}`); | ||
| 327 | + throw new ERR_REQUIRE_ESM_RACE_CONDITION(filename, parentFilename, false); | ||
| 344 | 328 | } | |
| 345 | 329 | let message = `Cannot require() ES Module ${filename} in a cycle.`; | |
| 346 | 330 | if (parentFilename) { | |
@@ -376,7 +360,7 @@ class ModuleLoader { | |||
| 376 | 360 | #checkCachedJobForRequireESM(specifier, url, parentURL, job) { | |
| 377 | 361 | // This race should only be possible on the loader hook thread. See https://github.com/nodejs/node/issues/59666 | |
| 378 | 362 | if (!job.module) { | |
| 379 | - assert.fail(getRaceMessage(url, parentURL, this.isForAsyncLoaderHookWorker)); | ||
| 363 | + throw new ERR_REQUIRE_ESM_RACE_CONDITION(url, parentURL, this.isForAsyncLoaderHookWorker); | ||
| 380 | 364 | } | |
| 381 | 365 | // This module is being evaluated, which means it's imported in a previous link | |
| 382 | 366 | // in a cycle. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,6 +55,7 @@ const { getOptionValue } = require('internal/options'); | |||
| 55 | 55 | const noop = FunctionPrototype; | |
| 56 | 56 | const { | |
| 57 | 57 | ERR_REQUIRE_ASYNC_MODULE, | |
| 58 | + ERR_REQUIRE_ESM_RACE_CONDITION, | ||
| 58 | 59 | } = require('internal/errors').codes; | |
| 59 | 60 | let hasPausedEntry = false; | |
| 60 | 61 | ||
@@ -420,7 +421,8 @@ class ModuleJob extends ModuleJobBase { | |||
| 420 | 421 | // always handle CJS using the CJS loader to eliminate the quirks. | |
| 421 | 422 | return { __proto__: null, module: this.module, namespace: this.module.getNamespace() }; | |
| 422 | 423 | } | |
| 423 | - assert.fail(`Unexpected module status ${status}.`); | ||
| 424 | + assert(status === kUninstantiated, `Unexpected module status ${status}.`); | ||
| 425 | + throw new ERR_REQUIRE_ESM_RACE_CONDITION(); | ||
| 424 | 426 | } | |
| 425 | 427 | ||
| 426 | 428 | async run(isEntryPoint = false) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,9 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + require('../common'); | ||
| 3 | + const fixtures = require('../common/fixtures'); | ||
| 4 | + const assert = require('node:assert'); | ||
| 5 | + | ||
| 6 | + assert.throws( | ||
| 7 | + () => require(fixtures.path('import-require-cycle/race-condition.cjs')), | ||
| 8 | + { code: 'ERR_REQUIRE_ESM_RACE_CONDITION' }, | ||
| 9 | + ); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments