diff --git a/.eslintignore b/.eslintignore index 7e0189b..51340c9 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ /test.js /node-* -/lib/events.js \ No newline at end of file +/lib/events.js +/test/additional-modules/my-es-module/index.js \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index 25f90fe..ceb1c0d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -82,7 +82,7 @@ export interface VMRequire { /** Collection of mock modules (both external or built-in). */ mock?: any; /* An additional lookup function in case a module wasn't found in one of the traditional node lookup paths. */ - resolve?: (moduleName: string, parentDirname: string) => string | undefined; + resolve?: (moduleName: string, parentDirname: string) => string | { path: string, module?: string } | undefined; /** Custom require to require host and built-in modules. */ customRequire?: (id: string) => any; /** Load modules in strict mode. (default: true) */ diff --git a/lib/resolver-compat.js b/lib/resolver-compat.js index c903118..a6d6ffc 100644 --- a/lib/resolver-compat.js +++ b/lib/resolver-compat.js @@ -322,8 +322,13 @@ function resolverFromOptions(vm, options, override, compiler) { } const resolved = customResolver(x, path); if (!resolved) return undefined; - if (externals) externals.push(new RegExp('^' + escapeRegExp(resolved))); - return resolver.loadAsFileOrDirecotry(resolved, extList); + if (typeof resolved === 'string') { + if (externals) externals.push(new RegExp('^' + escapeRegExp(resolved))); + return resolver.loadAsFileOrDirecotry(resolved, extList); + } + const {module=x, path: resolvedPath} = resolved; + if (externals) externals.push(new RegExp('^' + escapeRegExp(resolvedPath))); + return resolver.loadNodeModules(module, [resolvedPath], extList); }; } diff --git a/test/additional-modules/my-es-module/index.cjs b/test/additional-modules/my-es-module/index.cjs new file mode 100644 index 0000000..3ce63b7 --- /dev/null +++ b/test/additional-modules/my-es-module/index.cjs @@ -0,0 +1 @@ +module.exports = {additional_cjs_module: true}; \ No newline at end of file diff --git a/test/additional-modules/my-es-module/index.js b/test/additional-modules/my-es-module/index.js new file mode 100644 index 0000000..d64be1d --- /dev/null +++ b/test/additional-modules/my-es-module/index.js @@ -0,0 +1 @@ +export default {additional_es_module: true}; \ No newline at end of file diff --git a/test/additional-modules/my-es-module/package.json b/test/additional-modules/my-es-module/package.json new file mode 100644 index 0000000..31b4500 --- /dev/null +++ b/test/additional-modules/my-es-module/package.json @@ -0,0 +1,12 @@ +{ + "main": "index.js", + "type": "module", + "exports": { + ".": { + "default": { + "require": "./index.cjs", + "default": "./index.js" + } + } + } +} diff --git a/test/nodevm.js b/test/nodevm.js index 9d450d2..58addb3 100644 --- a/test/nodevm.js +++ b/test/nodevm.js @@ -239,6 +239,17 @@ describe('modules', () => { assert.ok(vm.run("require('my-module')", __filename)); }); + it('can resolve conditional exports with a custom resolver', () => { + const vm = new NodeVM({ + require: { + external: ['my-es-module'], + resolve: () => ({ path: path.resolve(__dirname, 'additional-modules') }) + } + }); + + assert.ok(vm.run("require('my-es-module')", __filename)); + }); + it('allows for multiple root folders', () => { const vm = new NodeVM({ require: {