@@ -34,7 +34,7 @@ const {
3434const { Module, resolveForCJSWithHooks } = require ( 'internal/modules/cjs/loader' ) ;
3535const { fileURLToPath, isURL, URLParse, pathToFileURL } = require ( 'internal/url' ) ;
3636const { kEmptyObject, isWindows } = require ( 'internal/util' ) ;
37- const { validateObject, validateString } = require ( 'internal/validators' ) ;
37+ const { validateObject, validateOneOf , validateString } = require ( 'internal/validators' ) ;
3838const {
3939 codes : {
4040 ERR_INVALID_ARG_VALUE ,
@@ -51,14 +51,10 @@ const {
5151
5252/**
5353 * Normalize the parent URL for cache clearing.
54- * @param {string|URL|undefined } parentURL
55- * @returns {{ parentURL: string|undefined , parentPath: string|undefined } }
54+ * @param {string|URL } parentURL
55+ * @returns {{ parentURL: string, parentPath: string|undefined } }
5656 */
5757function normalizeClearCacheParent ( parentURL ) {
58- if ( parentURL === undefined ) {
59- return { __proto__ : null , parentURL : undefined , parentPath : undefined } ;
60- }
61-
6258 if ( isURL ( parentURL ) ) {
6359 let parentPath ;
6460 if ( parentURL . protocol === 'file:' && parentURL . search === '' && parentURL . hash === '' ) {
@@ -268,61 +264,85 @@ function isRelative(pathToCheck) {
268264}
269265
270266/**
271- * Clear CommonJS and/or ESM module cache entries.
272- * @param {string|URL } specifier
273- * @param {object } [options]
274- * @param {string|URL } [options.parentURL]
275- * @returns {{ require: boolean, import: boolean } }
267+ * Clear module resolution and/or module caches.
268+ * @param {string|URL } specifier What would've been passed into import() or require().
269+ * @param {{
270+ * parentURL: string|URL,
271+ * importAttributes?: Record<string, string>,
272+ * resolver: 'import'|'require',
273+ * caches: 'resolution'|'module'|'all',
274+ * }} options
276275 */
277- function clearCache ( specifier , options = kEmptyObject ) {
276+ function clearCache ( specifier , options ) {
278277 const isSpecifierURL = isURL ( specifier ) ;
279278 if ( ! isSpecifierURL ) {
280279 validateString ( specifier , 'specifier' ) ;
281280 }
282281
283282 validateObject ( options , 'options' ) ;
284283 const { parentURL, parentPath } = normalizeClearCacheParent ( options . parentURL ) ;
285- const result = { __proto__ : null , require : false , import : false } ;
286284
287- try {
288- const deleteCommonjsCachesForFilename = ( filename ) => {
289- let deleted = false ;
290- const cachedModule = Module . _cache [ filename ] ;
291- if ( cachedModule !== undefined ) {
292- delete Module . _cache [ filename ] ;
293- deleted = true ;
294- deleteModuleFromParents ( cachedModule ) ;
295- }
296- return deleted ;
297- } ;
285+ const { resolver, caches } = options ;
286+ validateOneOf ( resolver , 'options.resolver' , [ 'import' , 'require' ] ) ;
287+ validateOneOf ( caches , 'options.caches' , [ 'resolution' , 'module' , 'all' ] ) ;
298288
299- const filename = resolveClearCacheFilename ( specifier , parentPath ) ;
300- if ( filename ) {
301- result . require = deleteCommonjsCachesForFilename ( filename ) ;
302- }
289+ const importAttributes = options . importAttributes ?? kEmptyObject ;
290+ if ( options . importAttributes !== undefined ) {
291+ validateObject ( options . importAttributes , 'options.importAttributes' ) ;
292+ }
293+
294+ const clearResolution = caches === 'resolution' || caches === 'all' ;
295+ const clearModule = caches === 'module' || caches === 'all' ;
303296
304- if ( parentURL !== undefined ) {
305- const url = resolveClearCacheURL ( specifier , parentURL ) ;
306- const resolvedPath = getFilePathFromClearCacheURL ( url ) ;
307- if ( resolvedPath && resolvedPath !== filename ) {
308- if ( deleteCommonjsCachesForFilename ( resolvedPath ) ) {
309- result . require = true ;
310- }
297+ // Resolve the specifier when module cache clearing is needed.
298+ // Must be done BEFORE clearing resolution caches since resolution
299+ // may rely on the resolve cache.
300+ let resolvedFilename = null ;
301+ let resolvedURL = null ;
302+
303+ if ( clearModule ) {
304+ if ( resolver === 'require' ) {
305+ resolvedFilename = resolveClearCacheFilename ( specifier , parentPath ) ;
306+ if ( resolvedFilename ) {
307+ resolvedURL = pathToFileURL ( resolvedFilename ) . href ;
308+ }
309+ } else {
310+ resolvedURL = resolveClearCacheURL ( specifier , parentURL ) ;
311+ if ( resolvedURL ) {
312+ resolvedFilename = getFilePathFromClearCacheURL ( resolvedURL ) ;
311313 }
312314 }
315+ }
313316
314- const url = resolveClearCacheURL ( specifier , parentURL ) ;
317+ // Clear resolution cache. Only ESM has a structured resolution cache;
318+ // CJS resolution results are not separately cached.
319+ if ( clearResolution && resolver === 'import' ) {
320+ const specifierStr = isSpecifierURL ? specifier . href : specifier ;
315321 const cascadedLoader =
316322 require ( 'internal/modules/esm/loader' ) . getOrInitializeCascadedLoader ( ) ;
317- const loadDeleted = deleteLoadCacheEntries ( cascadedLoader . loadCache , url ) ;
318- const { clearCjsCache } = require ( 'internal/modules/esm/translators' ) ;
319- const cjsCacheDeleted = clearCjsCache ( url ) ;
320- result . import = loadDeleted || cjsCacheDeleted ;
321- } catch {
322- // Best effort: avoid throwing for require cache clearing.
323+ cascadedLoader . deleteResolveCacheEntry ( specifierStr , parentURL , importAttributes ) ;
323324 }
324325
325- return result ;
326+ // Clear module caches everywhere in Node.js.
327+ if ( clearModule ) {
328+ // CJS Module._cache
329+ if ( resolvedFilename ) {
330+ const cachedModule = Module . _cache [ resolvedFilename ] ;
331+ if ( cachedModule !== undefined ) {
332+ delete Module . _cache [ resolvedFilename ] ;
333+ deleteModuleFromParents ( cachedModule ) ;
334+ }
335+ }
336+
337+ // ESM load cache and translators cjsCache
338+ if ( resolvedURL ) {
339+ const cascadedLoader =
340+ require ( 'internal/modules/esm/loader' ) . getOrInitializeCascadedLoader ( ) ;
341+ deleteLoadCacheEntries ( cascadedLoader . loadCache , resolvedURL ) ;
342+ const { clearCjsCache } = require ( 'internal/modules/esm/translators' ) ;
343+ clearCjsCache ( resolvedURL ) ;
344+ }
345+ }
326346}
327347
328348module . exports = {
0 commit comments