GeezerVison is showing github.com — module: only put directly require-d ESM into require.cache · nodejs/node@728472a
File treeExpand file treeCollapse file tree Open diff view settings fixtures/es-modules/esm-in-require-cache
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/loader.js -14Lines changed: 0 additions & 14 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -17,7 +17,6 @@ const { | 17 | 17 | const { | 18 | 18 | kIsExecuting, | 19 | 19 | kRequiredModuleSymbol, | 20 | | - Module: CJSModule, | 21 | 20 | } = require('internal/modules/cjs/loader'); | 22 | 21 | const { imported_cjs_symbol } = internalBinding('symbols'); | 23 | 22 |
| @@ -560,19 +559,6 @@ class ModuleLoader { | 560 | 559 | throw new ERR_UNKNOWN_MODULE_FORMAT(format, url); | 561 | 560 | } | 562 | 561 |
| 563 | | - // Populate the CJS cache with a facade for ESM in case subsequent require(esm) is | 564 | | - // looking it up from the cache. The parent module of the CJS cache entry would be the | 565 | | - // first CJS module that loads it with require(). This is an approximation, because | 566 | | - // ESM caches more and it does not get re-loaded and updated every time an `import` is | 567 | | - // encountered, unlike CJS require(), and we only use the parent entry to provide | 568 | | - // more information in error messages. | 569 | | - if (format === 'module') { | 570 | | - const parentFilename = urlToFilename(parentURL); | 571 | | - const parent = parentFilename ? CJSModule._cache[parentFilename] : undefined; | 572 | | - const cjsModule = lazyLoadTranslators().cjsEmplaceModuleCacheEntryForURL(url, parent); | 573 | | - debug('cjsEmplaceModuleCacheEntryForURL', url, parent, cjsModule); | 574 | | - } | 575 | | - | 576 | 562 | const result = FunctionPrototypeCall(translator, this, url, source, parentURL === undefined); | 577 | 563 | assert(result instanceof ModuleWrap); | 578 | 564 | return result; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/translators.js +16-3Lines changed: 16 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -154,9 +154,22 @@ function loadCJSModule(module, source, url, filename, isMain) { | 154 | 154 | // requires a separate cache to be populated as well as introducing several quirks. This is not ideal. | 155 | 155 | const job = cascadedLoader.getModuleJobForRequireInImportedCJS(specifier, url, importAttributes); | 156 | 156 | job.runSync(); | 157 | | - const mod = cjsCache.get(job.url); | 158 | | - assert(mod, `Imported CJS module ${url} failed to load module ${job.url} using require()`); | 159 | | - if (!job.module.synthetic && !mod.loaded) { | | 157 | + let mod = cjsCache.get(job.url); | | 158 | + assert(job.module, `Imported CJS module ${url} failed to load module ${job.url} using require() due to race condition`); | | 159 | + | | 160 | + if (job.module.synthetic) { | | 161 | + assert(mod, `Imported CJS module ${url} failed to load module ${job.url} using require() due to missed cache`); | | 162 | + return mod.exports; | | 163 | + } | | 164 | + | | 165 | + // The module being required is a source text module. | | 166 | + if (!mod) { | | 167 | + mod = cjsEmplaceModuleCacheEntry(job.url); | | 168 | + cjsCache.set(job.url, mod); | | 169 | + } | | 170 | + // The module has been cached by the re-invented require. Update the exports object | | 171 | + // from the namespace object and return the evaluated exports. | | 172 | + if (!mod.loaded) { | 160 | 173 | debug('populateCJSExportsFromESM from require(esm) in imported CJS', url, mod, job.module); | 161 | 174 | populateCJSExportsFromESM(mod, job.module, job.module.getNamespace()); | 162 | 175 | mod.loaded = true; | |
Collapse file Copy file name to clipboard +26Lines changed: 26 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// This tests the behavior of ESM in require.cache when it's loaded from import. | | 2 | + | | 3 | +import '../common/index.mjs'; | | 4 | +import assert from 'node:assert'; | | 5 | +import * as fixtures from '../common/fixtures.mjs'; | | 6 | +const filename = fixtures.path('es-modules', 'esm-in-require-cache', 'esm.mjs'); | | 7 | +import { Module } from 'node:module'; | | 8 | + | | 9 | +// Imported ESM should not be in the require cache. | | 10 | +let { name } = await import('../fixtures/es-modules/esm-in-require-cache/import-esm.mjs'); | | 11 | +assert.strictEqual(name, 'esm'); | | 12 | +assert(!Module._cache[filename]); | | 13 | + | | 14 | +({ name } = await import('../fixtures/es-modules/esm-in-require-cache/esm.mjs')); | | 15 | +assert.strictEqual(name, 'esm'); | | 16 | +assert(!Module._cache[filename]); | | 17 | + | | 18 | +// Requiring ESM indirectly should not put it in the cache. | | 19 | +({ name } = await import('../fixtures/es-modules/esm-in-require-cache/require-import-esm.cjs')); | | 20 | +assert.strictEqual(name, 'esm'); | | 21 | +assert(!Module._cache[filename]); | | 22 | + | | 23 | +// After being required directly, it should be in the cache. | | 24 | +({ name } = await import('../fixtures/es-modules/esm-in-require-cache/import-require-esm.mjs')); | | 25 | +assert.strictEqual(name, 'esm'); | | 26 | +assert(Module._cache[filename]); |
Collapse file Copy file name to clipboard +25Lines changed: 25 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// This tests the behavior of ESM in require.cache when it's loaded from require. | | 2 | +'use strict'; | | 3 | +require('../common'); | | 4 | +const assert = require('node:assert'); | | 5 | +const fixtures = require('../common/fixtures'); | | 6 | +const filename = fixtures.path('es-modules', 'esm-in-require-cache', 'esm.mjs'); | | 7 | + | | 8 | +// Requiring ESM indirectly should not put it in the cache. | | 9 | +let { name } = require('../fixtures/es-modules/esm-in-require-cache/import-esm.mjs'); | | 10 | +assert.strictEqual(name, 'esm'); | | 11 | +assert(!require.cache[filename]); | | 12 | + | | 13 | +({ name } = require('../fixtures/es-modules/esm-in-require-cache/require-import-esm.cjs')); | | 14 | +assert.strictEqual(name, 'esm'); | | 15 | +assert(!require.cache[filename]); | | 16 | + | | 17 | +// After being required directly, it should be in the cache. | | 18 | +({ name } = require('../fixtures/es-modules/esm-in-require-cache/esm.mjs')); | | 19 | +assert.strictEqual(name, 'esm'); | | 20 | +assert(require.cache[filename]); | | 21 | +delete require.cache[filename]; | | 22 | + | | 23 | +({ name } = require('../fixtures/es-modules/esm-in-require-cache/import-require-esm.mjs')); | | 24 | +assert.strictEqual(name, 'esm'); | | 25 | +assert(require.cache[filename]); |
Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +export const name = 'esm'; |
Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +export { name } from './esm.mjs'; |
Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +export { name, cache } from './require-esm.cjs' |
Collapse file Copy file name to clipboard +9Lines changed: 9 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +const path = require('path'); | | 2 | + | | 3 | +const name = require('./esm.mjs').name; | | 4 | +exports.name = name; | | 5 | + | | 6 | +const filename = path.join(__dirname, 'esm.mjs'); | | 7 | +const cache = require.cache[filename]; | | 8 | +exports.cache = require.cache[filename]; | | 9 | + |
Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +exports.name = require('./import-esm.mjs').name; |
|