From 4dd23ae5ae145806ee76fe8b196286f37ee2802c Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 13 Oct 2023 11:00:58 -0700 Subject: [PATCH] do not call custom resolver with builtin moduleId --- src/esmockModule.js | 14 +++++++---- tests/local/customResolverParent.js | 6 ++++- .../esmock.node.resolver-custom.test.js | 24 ++++++++++++++++--- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/esmockModule.js b/src/esmockModule.js index 0a5cbb5..0177184 100644 --- a/src/esmockModule.js +++ b/src/esmockModule.js @@ -17,6 +17,9 @@ const isDirPathRe = /^\.?\.?([a-zA-Z]:)?(\/|\\)/ const nextId = ((id = 0) => () => ++id)() const objProto = Object.getPrototypeOf({}) const isPlainObj = o => Object.getPrototypeOf(o) === objProto +const iscoremodule = resolvewith.iscoremodule +const protocolNodeRe = /^node:/ +const addprotocolnode = p => protocolNodeRe.test(p) ? p : `node:${p}` // assigning the object to its own prototypal inheritor can error, eg // 'Cannot assign to read only property \'F_OK\' of object \'#\'' @@ -46,7 +49,7 @@ const esmockModuleApply = (defLive, def, fileURL) => { // if safe, an extra "default.default" is added for compatibility with // babel-generated dist cjs files which also define "default.default" - if (!resolvewith.iscoremodule(fileURL) && Object.isExtensible(def.default)) + if (!iscoremodule(fileURL) && Object.isExtensible(def.default)) def.default.default = def.default return def @@ -59,7 +62,7 @@ const esmockModuleIsESM = (fileURL, isesm) => { if (typeof isesm === 'boolean') return isesm - isesm = !resolvewith.iscoremodule(fileURL) + isesm = !iscoremodule(fileURL) && isDirPathRe.test(fileURL) && esmockIsESMRe.test(fs.readFileSync(fileURL, 'utf-8')) @@ -108,6 +111,9 @@ const esmockModuleCreate = async (treeid, def, id, fileURL, opt) => { return mockModuleKey } +const esmockResolve = (id, parent, opt) => ( + iscoremodule(id) ? addprotocolnode(id) : opt.resolver(id, parent)) + const esmockModuleId = async (parent, treeid, defs, ids, opt, mocks, id) => { ids = ids || Object.keys(defs) id = ids[0] @@ -115,7 +121,7 @@ const esmockModuleId = async (parent, treeid, defs, ids, opt, mocks, id) => { if (!id) return mocks - const fileURL = opt.resolver(id, parent) + const fileURL = esmockResolve(id, parent, opt) if (!fileURL && opt.isModuleNotFoundError !== false && id !== 'import') throw esmockErr.errModuleIdNotFound(id, parent) @@ -125,7 +131,7 @@ const esmockModuleId = async (parent, treeid, defs, ids, opt, mocks, id) => { } const esmockModule = async (moduleId, parent, defs, gdefs, opt) => { - const moduleFileURL = opt.resolver(moduleId, parent) + const moduleFileURL = esmockResolve(moduleId, parent, opt) if (!moduleFileURL) throw esmockErr.errModuleIdNotFound(moduleId, parent) diff --git a/tests/local/customResolverParent.js b/tests/local/customResolverParent.js index 32f1c7f..e6e5cb6 100644 --- a/tests/local/customResolverParent.js +++ b/tests/local/customResolverParent.js @@ -1,5 +1,9 @@ import child from 'RESOLVECUSTOM' +import path from 'node:path' + +const pathbasenameresult = path.basename('/the/very/happy-dog.png') export { - child + child, + pathbasenameresult } diff --git a/tests/tests-node/esmock.node.resolver-custom.test.js b/tests/tests-node/esmock.node.resolver-custom.test.js index 31b7ba6..84b9f85 100644 --- a/tests/tests-node/esmock.node.resolver-custom.test.js +++ b/tests/tests-node/esmock.node.resolver-custom.test.js @@ -26,16 +26,15 @@ async function resolve (specifier, context, next) { : specifier, context) } -const loader = ` +module.register && module.register(` data:text/javascript, ${encodeURIComponent(resolverCustom)} -export ${encodeURIComponent(resolve)}`.slice(1) +export ${encodeURIComponent(resolve)}`.slice(1)) test('should use custom resolver', async () => { if (!module.register) return assert.ok('skip test') - module.register(loader) const customResolverParent = await esmock( '../local/customResolverParent.js', {}, { RESOLVECUSTOM: ({ isMocked: true }) @@ -46,3 +45,22 @@ test('should use custom resolver', async () => { assert.ok(customResolverParent.child.isCustomResolverChild) assert.ok(customResolverParent.child.isMocked) }) + +test('should not call custom resover with builtin moduleIds', async () => { + if (!module.register) + return assert.ok('skip test') + + const customResolverParent = await esmock( + '../local/customResolverParent.js', {}, { + RESOLVECUSTOM: ({ isMocked: true }), + path: { basename: () => 'basenametest' } + }, { + resolver: resolverCustom + }) + + assert.ok(customResolverParent.child.isCustomResolverChild) + assert.ok(customResolverParent.child.isMocked) + assert.strictEqual( + customResolverParent.pathbasenameresult, + 'basenametest') +})