Dynamic Script Evaluation in JavaScript

You have a String of JavaScript code. How can you execute it? This is a playground for testing various dynamic script execution methods in Node.js and what features they support.

This is research for import-module-string (the approach I currently use and recommend for ESM code) and node-retrieve-globals (legacy but more CommonJS friendly), whose features I have documented in a separate compatibility table below.

Runtime Native Methods

JavaScript FeatureModule#_compileFunction()vm.Scriptvm.Moduleimport("data:…") (or blob:…)
Assign module.exports (CommonJS-only)YesNoYesNo5No
export (ESM-only)NoNoNoYes1Yes
requireYesYesYesYes1No6
import (ESM-only)No4No4No4Yes1No7
Dynamic import()YesYesYes2Yes1No7
Top level async or awaitFaux3Faux3Faux3Yes1Yes
Can leak to global scopeYesYesNoNoYes
Runtime CompatibilityNode.jsAnyNode.jsNode.jsAny

Notes:

  1. Requires --experimental-vm-modules. Use outputs an ExperimentalWarning to the console.
  2. Requires vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER an experimental Node feature added in v21.7.0, v20.12.0. Any use outputs an ExperimentalWarning to the console.
  3. Requires the code to be wrapped in an (async () => {})() IIFE wrapper.
  4. Can use esm-import-transformer to transform static import to dynamic import() or require: https://github.com/zachleat/esm-import-transformer
  5. Probably shimmable but not worth it.
  6. require is shimmable in Node.js via node:module#createRequire
  7. import of runtime built-ins (e.g. node: prefixed modules in Node.js) are allowed.

npm Packages

JavaScript Featurenpm:node-retrieve-globalsnpm:import-module-string
Assign module.exports (CommonJS-only)YesNo
export (ESM-only)NoYes
requireYesYes
import (ESM-only)NoYes
Dynamic import()YesYes
Top level async or awaitFaux3Yes
Can leak to global scopeYesYes
Runtime CompatibilityNode.jsAny

Alternate methods