diff --git a/src/index.ts b/src/index.ts index 4fd27a2..4e7eeb4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,8 +3,6 @@ import module, { type LoadHookContext } from 'node:module' const namespace = 'no-cache://' const namespaceLength = namespace.length -const noCacheModules = new Set() - declare global { interface ImportAttributes { cache?: 'no' @@ -23,11 +21,12 @@ export function init(): () => void { const hooks = module.registerHooks({ resolve(specifier, context, nextResolve) { + const parentUUID = getParentUUID(context.parentURL) const fromNoCache = !module.isBuiltin(specifier) && (specifier.startsWith(namespace) || context.importAttributes?.cache === 'no' || - (context.parentURL && noCacheModules.has(context.parentURL))) + parentUUID) if (!fromNoCache) { return nextResolve(specifier, context) @@ -38,19 +37,12 @@ export function init(): () => void { } const resolved = nextResolve(specifier, context) - resolved.url = `${resolved.url}?${crypto.randomUUID()}` - noCacheModules.add(resolved.url) - + resolved.url = appendUUID(resolved.url, parentUUID || crypto.randomUUID()) return resolved }, load(url, context, nextLoad) { cleanupImportAttributes(context) - - if (url.startsWith(namespace)) { - url = url.slice(namespaceLength, -37 /* length of ? + uuid */) - } - return nextLoad(url, context) }, }) @@ -61,6 +53,17 @@ export function init(): () => void { }) } +function getParentUUID(parentURL: string | undefined) { + if (!parentURL) return + return new URL(parentURL).searchParams.get('no-cache') ?? undefined +} + +function appendUUID(url: string, uuid: string): string { + const parsed = new URL(url) + parsed.searchParams.set('no-cache', uuid) + return parsed.toString() +} + function cleanupImportAttributes(context: LoadHookContext): void { if (!context.importAttributes?.cache) return const attrs = Object.assign(Object.create(null), context.importAttributes) diff --git a/tests/fixtures/circular.js b/tests/fixtures/circular.js new file mode 100644 index 0000000..78bc6a8 --- /dev/null +++ b/tests/fixtures/circular.js @@ -0,0 +1,2 @@ +import './mod.js' +export const circular = 'circular' diff --git a/tests/fixtures/mod.js b/tests/fixtures/mod.js index 43205ea..8141d32 100644 --- a/tests/fixtures/mod.js +++ b/tests/fixtures/mod.js @@ -5,3 +5,4 @@ export * from './rand.js' export const cjs = require('./cjs.cjs') export const requireESM = require('./require-esm.js') export const url = import.meta.url +export * from './circular.js' diff --git a/tests/index.test.js b/tests/index.test.js index 2d3e125..8a6592a 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -18,7 +18,7 @@ test('import attributes', async () => { const { uuid, url, cjs, requireESM } = await import('./fixtures/mod.js', { with: { cache: 'no' }, }) - assert.match(url, /\?[0-9a-f-]{36}$/) + assert.match(url, /\?no-cache=[0-9a-f-]{36}$/) const { uuid: uuid2,