diff --git a/README.md b/README.md
index 3eac28c..aa8f650 100644
--- a/README.md
+++ b/README.md
@@ -142,6 +142,7 @@ Unlike `VM`, `NodeVM` allows you to require modules in the same way that you wou
* `require.root` - Restricted path(s) where local modules can be required (default: every path).
* `require.mock` - Collection of mock modules (both external or built-in).
* `require.context` - `host` (default) to require modules in the host and proxy them into the sandbox. `sandbox` to load, compile, and require modules in the sandbox. Except for `events`, built-in modules are always required in the host and proxied into the sandbox.
+* `require.pathContext` - A callback allowing custom context to be determined per module. Parameters are the module name, and extension. The callback must return `host` or `sandbox` as per above.
* `require.import` - An array of modules to be loaded into NodeVM on start.
* `require.resolve` - An additional lookup function in case a module wasn't found in one of the traditional node lookup paths.
* `require.customRequire` - Use instead of the `require` function to load modules from the host.
diff --git a/lib/nodevm.js b/lib/nodevm.js
index a55a0e2..488f34b 100644
--- a/lib/nodevm.js
+++ b/lib/nodevm.js
@@ -17,6 +17,17 @@
* @return {*} The required module object.
*/
+/**
+ * This callback will be called to specify the context to use "per" module.
+ *
+ * NOTE: many interoperating modules must live in the same context.
+ *
+ * @callback pathContextCallback
+ * @param {string} moduleName - Name of the module requested.
+ * @param {string} extensionType - The type of extension (node, js, json)
+ * @return {("host"|"sandbox")} The context for this module.
+ */
+
const fs = require('fs');
const pa = require('path');
const {
@@ -180,11 +191,13 @@ class NodeVM extends VM {
* @param {("host"|"sandbox")} [options.require.context="host"] - host
to require modules in host and proxy them to sandbox.
* sandbox
to load, compile and require modules in sandbox.
* Builtin modules except events
always required in host and proxied to sandbox.
+ * @param {pathContextCallback} [options.require.pathContext] - A callback per-module path to customize "where" to load a module.
+ * Builtin modules except events
always required in host and proxied to sandbox.
* @param {string[]} [options.require.import] - Array of modules to be loaded into NodeVM on start.
* @param {resolveCallback} [options.require.resolve] - An additional lookup function in case a module wasn't
* found in one of the traditional node lookup paths.
* @param {customRequire} [options.require.customRequire=require] - Custom require to require host and built-in modules.
- * @param {boolean} [option.require.strict=true] - Load required modules in strict mode.
+ * @param {boolean} [options.require.strict=true] - Load required modules in strict mode.
* @param {boolean} [options.nesting=false] -
* WARNING: Allowing this is a security risk as scripts can create a NodeVM which can require any host module.
* Allow nesting of VMs.
diff --git a/lib/resolver-compat.js b/lib/resolver-compat.js
index 0ef30ee..2780b67 100644
--- a/lib/resolver-compat.js
+++ b/lib/resolver-compat.js
@@ -291,6 +291,8 @@ function resolverFromOptions(vm, options, override, compiler) {
const builtins = genBuiltinsFromOptions(vm, builtinOpt, mockOpt, override);
+ const pathContext = options.pathContext || (() => context);
+
if (!externalOpt) return new Resolver(fsOpt, builtins, [], hostRequire);
let checkPath;
@@ -344,7 +346,7 @@ function resolverFromOptions(vm, options, override, compiler) {
transitive = context === 'sandbox' && externalOpt.transitive;
}
externals = external.map(makeExternalMatcher);
- return new LegacyResolver(fsOpt, builtins, checkPath, [], () => context, newCustomResolver, hostRequire, compiler, strict, externals, transitive);
+ return new LegacyResolver(fsOpt, builtins, checkPath, [], pathContext, newCustomResolver, hostRequire, compiler, strict, externals, transitive);
}
exports.resolverFromOptions = resolverFromOptions;
diff --git a/package-lock.json b/package-lock.json
index 5e61b0d..f4e8dd5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "vm2",
- "version": "3.9.11",
+ "version": "3.9.16",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "vm2",
- "version": "3.9.11",
+ "version": "3.9.16",
"license": "MIT",
"dependencies": {
"acorn": "^8.7.0",