https://github.com/zachleat/javascript-eval-modules
Playground for testing various dynamic script execution methods in JavaScript
https://github.com/zachleat/javascript-eval-modules
Last synced: 9 months ago
JSON representation
Playground for testing various dynamic script execution methods in JavaScript
- Host: GitHub
- URL: https://github.com/zachleat/javascript-eval-modules
- Owner: zachleat
- Created: 2024-09-19T19:39:26.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-06-05T21:43:44.000Z (about 1 year ago)
- Last Synced: 2025-06-05T22:23:58.066Z (about 1 year ago)
- Language: JavaScript
- Homepage:
- Size: 27.3 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# 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`](https://github.com/zachleat/import-module-string) (the approach I currently use and recommend for ESM code) and [`node-retrieve-globals`](https://github.com/zachleat/node-retrieve-globals/) (legacy but more CommonJS friendly), whose features I have documented in a separate compatibility table below.
* [`vm` Node.js documentation](https://nodejs.org/docs/latest/api/vm.html)
* [MDN docs for `eval`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)
* [`import("data:…")` approach from `2ality.com`](https://2ality.com/2019/10/eval-via-import.html)
* [`import("blob:…")` approach suggested by David Bushnell](https://github.com/dbushell/dinossr/blob/main/src/bundle/import.ts#L13) (not currently supported in Node.js but works in Deno!)
## Runtime Native Methods
JavaScript Feature
Module#_compile
Function()
vm.Script
vm.Module
import("data:…") (or blob:…)
Assign module.exports (CommonJS-only)
Yes
No
Yes
No5
No
export (ESM-only)
No
No
No
Yes1
Yes
require
Yes
Yes
Yes
Yes1
No6
import (ESM-only)
No4
No4
No4
Yes1
No7
Dynamic import()
Yes
Yes
Yes2
Yes1
No7
Top level async or await
Faux3
Faux3
Faux3
Yes1
Yes
Can leak to global scope
Yes
Yes
No
No
Yes
Runtime Compatibility
Node.js
Any
Node.js
Node.js
Any
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`](https://nodejs.org/docs/latest/api/module.html#modulecreaterequirefilename)
7. `import` of runtime built-ins (e.g. `node:` prefixed modules in Node.js) are allowed.
## npm Packages
JavaScript Feature
npm:node-retrieve-globals
npm:import-module-string
Assign module.exports (CommonJS-only)
Yes
No
export (ESM-only)
No
Yes
require
Yes
Yes
import (ESM-only)
No
Yes
Dynamic import()
Yes
Yes
Top level async or await
Faux3
Yes
Can leak to global scope
Yes
Yes
Runtime Compatibility
Node.js
Any
## Alternate methods
* A lot of the pain here is due to an experimental `vm.Module`. If you already have access to a bundler (e.g. `esbuild`), use that to output CommonJS code and run it through `Module#_compile` to bypass current limitations with dynamic ESM in Node.js.
* [Vite writes a temporary file to the filesystem](https://github.com/vitejs/vite/blob/77d5165e2f252bfecbb0eebccc6f04dc8be0c5ba/packages/vite/src/node/config.ts#L1172-L1184) to workaround this issue.
* Some [more discussion on Mastodon](https://fediverse.zachleat.com/@zachleat/111580482330587997).