From 06853c6079fd47b94da1fc0097a9b80a9f75ef2a Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 19:22:41 +0000 Subject: [PATCH 01/13] PnP resolver --- src/pnpResolver.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/pnpResolver.js diff --git a/src/pnpResolver.js b/src/pnpResolver.js new file mode 100644 index 0000000..859565c --- /dev/null +++ b/src/pnpResolver.js @@ -0,0 +1,17 @@ +import { isBuiltin } from 'node:module' +import { pathToFileURL } from 'node:url' +import pnpapi from 'pnpapi' + +export default (id, parent) => { + if (isBuiltin(id)) { + return id.startsWith('node:') ? id : `node:${id}` + } + + if (id === 'import') { + return null + } + + const path = pnpapi.resolveRequest(id, parent) + + return path !== null ? pathToFileURL(path).href : null +} From 37ff27fb1236ca9728cb9e77b3b316fc62435bba Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 19:35:18 +0000 Subject: [PATCH 02/13] add esmockResolver module --- src/esmockReslover.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/esmockReslover.js diff --git a/src/esmockReslover.js b/src/esmockReslover.js new file mode 100644 index 0000000..a2a4a8d --- /dev/null +++ b/src/esmockReslover.js @@ -0,0 +1,5 @@ +import resolvewithplus from 'resolvewithplus' + +const pnpResolver = process.versions.pnp && (await import('./pnpResolver.js')).default; + +export default async opts => opts.resolver || pnpResolver || resolvewithplus \ No newline at end of file From b948324075495da151d22ee962d774c2ccf4aef8 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 19:36:57 +0000 Subject: [PATCH 03/13] add missing newline --- src/esmockReslover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/esmockReslover.js b/src/esmockReslover.js index a2a4a8d..f740adb 100644 --- a/src/esmockReslover.js +++ b/src/esmockReslover.js @@ -2,4 +2,4 @@ import resolvewithplus from 'resolvewithplus' const pnpResolver = process.versions.pnp && (await import('./pnpResolver.js')).default; -export default async opts => opts.resolver || pnpResolver || resolvewithplus \ No newline at end of file +export default async opts => opts.resolver || pnpResolver || resolvewithplus From 69b3343f69f02cd5ae9e0b4f9283ca1b53d703f6 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 19:40:35 +0000 Subject: [PATCH 04/13] use esmockResolver --- src/esmockModule.js | 7 +++++-- src/{esmockReslover.js => esmockResolver.js} | 0 2 files changed, 5 insertions(+), 2 deletions(-) rename src/{esmockReslover.js => esmockResolver.js} (100%) diff --git a/src/esmockModule.js b/src/esmockModule.js index 3adc68d..7ab4524 100644 --- a/src/esmockModule.js +++ b/src/esmockModule.js @@ -2,6 +2,7 @@ import fs from 'fs' import resolvewith from 'resolvewithplus' import esmockErr from './esmockErr.js' import esmockIsESMRe from './esmockIsESMRe.js' +import esmockResolver from './esmockResolver.js' import { esmockTreeIdSet, @@ -116,7 +117,8 @@ const esmockModuleId = async (parent, treeid, defs, ids, opt, mocks, id) => { if (!id) return mocks - const fileURL = opt.resolver(id, parent) + const resolver = await esmockResolver(opt) + const fileURL = resolver(id, parent) if (!fileURL && opt.isModuleNotFoundError !== false && id !== 'import') throw esmockErr.errModuleIdNotFound(id, parent) @@ -126,7 +128,8 @@ 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 resolver = await esmockResolver(opt) + const moduleFileURL = resolver(moduleId, parent) if (!moduleFileURL) throw esmockErr.errModuleIdNotFound(moduleId, parent) diff --git a/src/esmockReslover.js b/src/esmockResolver.js similarity index 100% rename from src/esmockReslover.js rename to src/esmockResolver.js From a4c226e337eea787436e2655c263b4b0eea1e289 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 19:42:43 +0000 Subject: [PATCH 05/13] fix formatting --- src/esmockResolver.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/esmockResolver.js b/src/esmockResolver.js index f740adb..8473a60 100644 --- a/src/esmockResolver.js +++ b/src/esmockResolver.js @@ -1,5 +1,6 @@ import resolvewithplus from 'resolvewithplus' -const pnpResolver = process.versions.pnp && (await import('./pnpResolver.js')).default; +const pnpResolver = process.versions.pnp && + (await import('./pnpResolver.js')).default export default async opts => opts.resolver || pnpResolver || resolvewithplus From b52367975fa7748cc025accb54f3ba5fb259da64 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 19:50:43 +0000 Subject: [PATCH 06/13] keep PnP detection logic inside pnpResolver.js --- src/esmockResolver.js | 4 +--- src/pnpResolver.js | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/esmockResolver.js b/src/esmockResolver.js index 8473a60..42599a5 100644 --- a/src/esmockResolver.js +++ b/src/esmockResolver.js @@ -1,6 +1,4 @@ import resolvewithplus from 'resolvewithplus' - -const pnpResolver = process.versions.pnp && - (await import('./pnpResolver.js')).default +import pnpResolver from './pnpResolver.js' export default async opts => opts.resolver || pnpResolver || resolvewithplus diff --git a/src/pnpResolver.js b/src/pnpResolver.js index 859565c..26edf29 100644 --- a/src/pnpResolver.js +++ b/src/pnpResolver.js @@ -1,8 +1,9 @@ import { isBuiltin } from 'node:module' import { pathToFileURL } from 'node:url' -import pnpapi from 'pnpapi' -export default (id, parent) => { +const pnpapi = process.versions.pnp && (await import('pnpapi')).default + +export default pnpapi && ((id, parent) => { if (isBuiltin(id)) { return id.startsWith('node:') ? id : `node:${id}` } @@ -14,4 +15,4 @@ export default (id, parent) => { const path = pnpapi.resolveRequest(id, parent) return path !== null ? pathToFileURL(path).href : null -} +}) From 48c6d442d8f79582aed5f396d7deb9e26c2a1da2 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 19:54:26 +0000 Subject: [PATCH 07/13] fix build script --- tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/package.json b/tests/package.json index 63c715f..dc23784 100644 --- a/tests/package.json +++ b/tests/package.json @@ -26,7 +26,7 @@ "sinon": "^12.0.1" }, "scripts": { - "mini:esmock": "cd .. && cd src && npx esbuild esmock.js --minify --bundle --allow-overwrite --platform=node --format=esm --outfile=esmock.js", + "mini:esmock": "cd .. && cd src && npx esbuild esmock.js --minify --bundle --allow-overwrite --platform=node --format=esm --external:pnpapi --outfile=esmock.js", "mini:esmockLoader": "cd .. && cd src && npx esbuild esmockLoader.js --minify --bundle --allow-overwrite --platform=node --format=esm --outfile=esmockLoader.js", "mini": "npm run mini:esmock && npm run mini:esmockLoader", "isnodelt18": "node -e \"+process.versions.node.split('.')[0] < 18 || process.exit(1)\"", From bc4d0a20f67038165dd19251ef24079328335b0f Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 20:19:50 +0000 Subject: [PATCH 08/13] simplify resolver construction --- src/esmockArgs.js | 5 ++++- src/esmockModule.js | 7 ++----- src/esmockResolver.js | 4 ---- 3 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 src/esmockResolver.js diff --git a/src/esmockArgs.js b/src/esmockArgs.js index 5be05cc..141bd75 100644 --- a/src/esmockArgs.js +++ b/src/esmockArgs.js @@ -1,4 +1,5 @@ -import resolver from 'resolvewithplus' +import resolvewithplus from 'resolvewithplus' +import pnpResolver from './pnpResolver.js' // extracts path or fileurl from stack, // ' at (/root/test.js:11:31)' -> /root/test.js @@ -7,6 +8,8 @@ import resolver from 'resolvewithplus' // ' at file:///D:/a/test.js:7:9' -> file:///D:/a/test.js const stackpathre = /^.*(\(|at )(.*):[\d]*:[\d]*.*$/ +const resolver = pnpResolver || resolvewithplus + // this function normalizes "overloaded" args signatures, returning // one predictable args list. ex, // [moduleId, defs, gdefs, opts] diff --git a/src/esmockModule.js b/src/esmockModule.js index 7ab4524..3adc68d 100644 --- a/src/esmockModule.js +++ b/src/esmockModule.js @@ -2,7 +2,6 @@ import fs from 'fs' import resolvewith from 'resolvewithplus' import esmockErr from './esmockErr.js' import esmockIsESMRe from './esmockIsESMRe.js' -import esmockResolver from './esmockResolver.js' import { esmockTreeIdSet, @@ -117,8 +116,7 @@ const esmockModuleId = async (parent, treeid, defs, ids, opt, mocks, id) => { if (!id) return mocks - const resolver = await esmockResolver(opt) - const fileURL = resolver(id, parent) + const fileURL = opt.resolver(id, parent) if (!fileURL && opt.isModuleNotFoundError !== false && id !== 'import') throw esmockErr.errModuleIdNotFound(id, parent) @@ -128,8 +126,7 @@ const esmockModuleId = async (parent, treeid, defs, ids, opt, mocks, id) => { } const esmockModule = async (moduleId, parent, defs, gdefs, opt) => { - const resolver = await esmockResolver(opt) - const moduleFileURL = resolver(moduleId, parent) + const moduleFileURL = opt.resolver(moduleId, parent) if (!moduleFileURL) throw esmockErr.errModuleIdNotFound(moduleId, parent) diff --git a/src/esmockResolver.js b/src/esmockResolver.js deleted file mode 100644 index 42599a5..0000000 --- a/src/esmockResolver.js +++ /dev/null @@ -1,4 +0,0 @@ -import resolvewithplus from 'resolvewithplus' -import pnpResolver from './pnpResolver.js' - -export default async opts => opts.resolver || pnpResolver || resolvewithplus From 12324e5744ad0c83ee330c69e410d6bc6b5cfbe6 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 22:34:12 +0000 Subject: [PATCH 09/13] test for PnP resolver --- tests/local/pnp/api.js | 1 + tests/local/pnp/disable.js | 1 + tests/local/pnp/enable.js | 14 ++++++++ .../esmock.node.resolver-pnp.test.js | 35 +++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 tests/local/pnp/api.js create mode 100644 tests/local/pnp/disable.js create mode 100644 tests/local/pnp/enable.js create mode 100644 tests/tests-node/esmock.node.resolver-pnp.test.js diff --git a/tests/local/pnp/api.js b/tests/local/pnp/api.js new file mode 100644 index 0000000..b1c6ea4 --- /dev/null +++ b/tests/local/pnp/api.js @@ -0,0 +1 @@ +export default {} diff --git a/tests/local/pnp/disable.js b/tests/local/pnp/disable.js new file mode 100644 index 0000000..87f0a8c --- /dev/null +++ b/tests/local/pnp/disable.js @@ -0,0 +1 @@ +delete process.versions.pnp \ No newline at end of file diff --git a/tests/local/pnp/enable.js b/tests/local/pnp/enable.js new file mode 100644 index 0000000..2f7344c --- /dev/null +++ b/tests/local/pnp/enable.js @@ -0,0 +1,14 @@ +import module from 'node:module' + +async function resolve (specifier, context, next) { + return next( + specifier === 'pnpapi' + ? '../tests/local/pnp/api.js' + : specifier, context) +} + +module.register && module.register(` +data:text/javascript, +export ${encodeURIComponent(resolve)}`.slice(1)) + +process.versions.pnp = '3' diff --git a/tests/tests-node/esmock.node.resolver-pnp.test.js b/tests/tests-node/esmock.node.resolver-pnp.test.js new file mode 100644 index 0000000..cb43606 --- /dev/null +++ b/tests/tests-node/esmock.node.resolver-pnp.test.js @@ -0,0 +1,35 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import module from 'node:module' +import { fileURLToPath } from 'node:url' +import resolvewithplus from 'resolvewithplus' +import '../local/pnp/enable.js' +import esmock from 'esmock' +import '../local/pnp/disable.js' +import pnpapi from '../local/pnp/api.js' + +const resolver = (id, parent) => { + const url = resolvewithplus(id, parent) + return url !== null ? fileURLToPath(url) : null +} + +test.beforeEach(() => { + delete pnpapi.resolveRequest +}) + +test('should work with pnp resolver', async (t) => { + if (!module.register) + return assert.ok('skip test') + + pnpapi.resolveRequest = t.mock.fn(resolver) + + const main = await esmock('../local/main.js', { + '../local/mainUtil.js': { + createString: () => 'test string' + } + }) + + assert.equal(typeof main, 'function') + assert.strictEqual(main(), 'main string, test string') + assert.equal(pnpapi.resolveRequest.mock.callCount(), 2) +}) From dfbd5e195de910447dc05488a32f4a2bb10d7725 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 22:35:48 +0000 Subject: [PATCH 10/13] missing newline --- tests/local/pnp/disable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/local/pnp/disable.js b/tests/local/pnp/disable.js index 87f0a8c..5d0632d 100644 --- a/tests/local/pnp/disable.js +++ b/tests/local/pnp/disable.js @@ -1 +1 @@ -delete process.versions.pnp \ No newline at end of file +delete process.versions.pnp From 92a1d707058d78db8f9f11cdda54d47d55417489 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 22:39:30 +0000 Subject: [PATCH 11/13] fix formatting --- tests/tests-node/esmock.node.resolver-pnp.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests-node/esmock.node.resolver-pnp.test.js b/tests/tests-node/esmock.node.resolver-pnp.test.js index cb43606..474bf08 100644 --- a/tests/tests-node/esmock.node.resolver-pnp.test.js +++ b/tests/tests-node/esmock.node.resolver-pnp.test.js @@ -17,7 +17,7 @@ test.beforeEach(() => { delete pnpapi.resolveRequest }) -test('should work with pnp resolver', async (t) => { +test('should work with pnp resolver', async t => { if (!module.register) return assert.ok('skip test') From 0f162ca4fb49d6eae0d7c48d720fa3d1dc30cc75 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 22:40:42 +0000 Subject: [PATCH 12/13] don't use 't' variable --- tests/tests-node/esmock.node.resolver-pnp.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tests-node/esmock.node.resolver-pnp.test.js b/tests/tests-node/esmock.node.resolver-pnp.test.js index 474bf08..02825ce 100644 --- a/tests/tests-node/esmock.node.resolver-pnp.test.js +++ b/tests/tests-node/esmock.node.resolver-pnp.test.js @@ -17,11 +17,11 @@ test.beforeEach(() => { delete pnpapi.resolveRequest }) -test('should work with pnp resolver', async t => { +test('should work with pnp resolver', async ({ mock }) => { if (!module.register) return assert.ok('skip test') - pnpapi.resolveRequest = t.mock.fn(resolver) + pnpapi.resolveRequest = mock.fn(resolver) const main = await esmock('../local/main.js', { '../local/mainUtil.js': { From bc3bf3054a962850d8c19d521cd5d26685427102 Mon Sep 17 00:00:00 2001 From: Vladimir Grenaderov Date: Sat, 14 Oct 2023 22:50:58 +0000 Subject: [PATCH 13/13] fix test on node18 --- tests/local/pnp/enable.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/local/pnp/enable.js b/tests/local/pnp/enable.js index 2f7344c..bbbbd68 100644 --- a/tests/local/pnp/enable.js +++ b/tests/local/pnp/enable.js @@ -7,8 +7,6 @@ async function resolve (specifier, context, next) { : specifier, context) } -module.register && module.register(` +module.register && (process.versions.pnp = '3') && module.register(` data:text/javascript, export ${encodeURIComponent(resolve)}`.slice(1)) - -process.versions.pnp = '3'