Skip to content

Commit 2d6b8cd

Browse files
Use native node:vm module when available
1 parent ccf877e commit 2d6b8cd

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
lines changed

.changeset/upset-ducks-sin.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@cloudflare/unenv-preset": patch
3+
---
4+
5+
Use native node:vm module when available
6+
7+
It is enabled starting on 2025-10-01 or when the `enable_nodejs_vm_module` compatibility flag is set.

packages/unenv-preset/src/preset.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export function getCloudflarePreset({
7777
const traceEventsOverrides = getTraceEventsOverrides(compat);
7878
const domainOverrides = getDomainOverrides(compat);
7979
const wasiOverrides = getWasiOverrides(compat);
80+
const vmOverrides = getVmOverrides(compat);
8081

8182
// "dynamic" as they depend on the compatibility date and flags
8283
const dynamicNativeModules = [
@@ -90,6 +91,7 @@ export function getCloudflarePreset({
9091
...traceEventsOverrides.nativeModules,
9192
...domainOverrides.nativeModules,
9293
...wasiOverrides.nativeModules,
94+
...vmOverrides.nativeModules,
9395
];
9496

9597
// "dynamic" as they depend on the compatibility date and flags
@@ -104,6 +106,7 @@ export function getCloudflarePreset({
104106
...traceEventsOverrides.hybridModules,
105107
...domainOverrides.hybridModules,
106108
...wasiOverrides.hybridModules,
109+
...vmOverrides.hybridModules,
107110
];
108111

109112
return {
@@ -510,3 +513,39 @@ function getWasiOverrides({
510513
hybridModules: [],
511514
};
512515
}
516+
517+
/**
518+
* Returns the overrides for `node:vm` (unenv or workerd)
519+
*
520+
* The native vm implementation:
521+
* - is enabled starting from 2025-10-01
522+
* - can be enabled with the "enable_nodejs_vm_module" flag
523+
* - can be disabled with the "disable_nodejs_vm_module" flag
524+
*/
525+
function getVmOverrides({
526+
compatibilityDate,
527+
compatibilityFlags,
528+
}: {
529+
compatibilityDate: string;
530+
compatibilityFlags: string[];
531+
}): { nativeModules: string[]; hybridModules: string[] } {
532+
const disabledByFlag = compatibilityFlags.includes(
533+
"disable_nodejs_vm_module"
534+
);
535+
536+
const enabledByFlag = compatibilityFlags.includes("enable_nodejs_vm_module");
537+
const enabledByDate = compatibilityDate >= "2025-10-01";
538+
539+
const enabled = (enabledByFlag || enabledByDate) && !disabledByFlag;
540+
541+
// The native `vm` module implements all the node APIs so we can use it directly
542+
return enabled
543+
? {
544+
nativeModules: ["vm"],
545+
hybridModules: [],
546+
}
547+
: {
548+
nativeModules: [],
549+
hybridModules: [],
550+
};
551+
}

packages/wrangler/e2e/unenv-preset/preset.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,39 @@ const localTestConfigs: TestConfig[] = [
347347
},
348348
},
349349
],
350+
// node:vm
351+
[
352+
{
353+
name: "vm disabled by date",
354+
compatibilityDate: "2024-09-23",
355+
expectRuntimeFlags: {
356+
enable_nodejs_vm_module: false,
357+
},
358+
},
359+
{
360+
name: "vm enabled by date",
361+
compatibilityDate: "2025-10-01",
362+
expectRuntimeFlags: {
363+
enable_nodejs_vm_module: true,
364+
},
365+
},
366+
{
367+
name: "vm enabled by flag",
368+
compatibilityDate: "2024-09-23",
369+
compatibilityFlags: ["enable_nodejs_vm_module"],
370+
expectRuntimeFlags: {
371+
enable_nodejs_vm_module: true,
372+
},
373+
},
374+
{
375+
name: "vm disabled by flag",
376+
compatibilityDate: "2025-10-01",
377+
compatibilityFlags: ["disable_nodejs_vm_module"],
378+
expectRuntimeFlags: {
379+
enable_nodejs_vm_module: false,
380+
},
381+
},
382+
],
350383
].flat() as TestConfig[];
351384

352385
describe.each(localTestConfigs)(

packages/wrangler/e2e/unenv-preset/worker/index.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,36 @@ export const WorkerdTests: Record<string, () => void> = {
645645
/not implemented/
646646
);
647647
},
648+
649+
async testVm() {
650+
const vm = await import("node:vm");
651+
652+
assertTypeOfProperties(vm, {
653+
Script: "function",
654+
constants: "object",
655+
compileFunction: "function",
656+
createContext: "function",
657+
createScript: "function",
658+
isContext: "function",
659+
measureMemory: "function",
660+
runInContext: "function",
661+
runInThisContext: "function",
662+
runInNewContext: "function",
663+
});
664+
665+
assertTypeOfProperties(vm.default, {
666+
Script: "function",
667+
compileFunction: "function",
668+
constants: "object",
669+
createContext: "function",
670+
isContext: "function",
671+
measureMemory: "function",
672+
runInContext: "function",
673+
runInNewContext: "function",
674+
runInThisContext: "function",
675+
createScript: "function",
676+
});
677+
},
648678
};
649679

650680
/**

0 commit comments

Comments
 (0)