javascriptnode.jsecmascript-6commonjs

Run CommonJS code in ESM Module using runInThisContext


A third party dependency returns a javascript code which I would like to execute using vm.runInThisContext.

Unfortunately the javascript module systems missmatch as my script has to be EcmaScriptModule and the generated javascript code can only be generated as CommonJs.

I tried different options of runInThisContext but wasn't able to make it work.

Here is a simplified version of my problem:

example.mjs

import vm from "node:vm";

// Code to be executed
const code = `
  require("path").resolve("test.mjs");
`;

// Execute code in the current context
vm.runInThisContext(code);
node test.mjs

evalmachine.<anonymous>:2
  require("path").resolve("test.mjs");
  ^

ReferenceError: require is not defined
    at evalmachine.<anonymous>:2:3
    at Script.runInThisContext (node:vm:129:12)
    at Object.runInThisContext (node:vm:307:38)
    at test.mjs:9:4
    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

Is there any solution for this cross module problem?


Solution

  • I found a solution which works in cjs and esm thanks to the great answer from @sujeet

    const getRequire = async () => {
      if (typeof require !== "undefined") return require;
      const { createRequire } = await import("module");
      return createRequire(import.meta.url);
    };
    
    const code = `
      (require) =>
        require("path").resolve("test.mjs");
    `;
    
    const result = vm.runInThisContext(code)(await getRequire());