Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/unenv-preset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
},
"peerDependencies": {
"unenv": "2.0.0-rc.21",
"workerd": "^1.20250924.0"
"workerd": "^1.20250927.0"
},
"peerDependenciesMeta": {
"workerd": {
Expand Down
52 changes: 2 additions & 50 deletions packages/unenv-preset/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const nativeModules = [
];

// Modules implemented via a mix of workerd APIs and polyfills.
const hybridModules = ["console"];
const hybridModules = ["console", "process"];

/**
* Creates the Cloudflare preset for the given compatibility date and compatibility flags
Expand All @@ -72,7 +72,6 @@ export function getCloudflarePreset({
const http2Overrides = getHttp2Overrides(compat);
const osOverrides = getOsOverrides(compat);
const fsOverrides = getFsOverrides(compat);
const processOverrides = getProcessOverrides(compat);

// "dynamic" as they depend on the compatibility date and flags
const dynamicNativeModules = [
Expand All @@ -81,7 +80,6 @@ export function getCloudflarePreset({
...http2Overrides.nativeModules,
...osOverrides.nativeModules,
...fsOverrides.nativeModules,
...processOverrides.nativeModules,
];

// "dynamic" as they depend on the compatibility date and flags
Expand All @@ -91,7 +89,6 @@ export function getCloudflarePreset({
...http2Overrides.hybridModules,
...osOverrides.hybridModules,
...fsOverrides.hybridModules,
...processOverrides.hybridModules,
];

return {
Expand Down Expand Up @@ -125,7 +122,7 @@ export function getCloudflarePreset({
clearImmediate: false,
setImmediate: false,
console: "@cloudflare/unenv-preset/node/console",
...processOverrides.inject,
process: "@cloudflare/unenv-preset/node/process",
},
polyfill: ["@cloudflare/unenv-preset/polyfill/performance"],
external: dynamicNativeModules.flatMap((p) => [p, `node:${p}`]),
Expand Down Expand Up @@ -308,48 +305,3 @@ function getFsOverrides({
hybridModules: [],
};
}

/**
* Returns the overrides for `node:process` and `node:fs/promises`
*
* The native process v2 implementation:
* - is enabled starting from 2025-09-15
* - can be enabled with the "enable_nodejs_process_v2" flag
* - can be disabled with the "disable_nodejs_process_v2" flag
*/
function getProcessOverrides({
compatibilityDate,
compatibilityFlags,
}: {
compatibilityDate: string;
compatibilityFlags: string[];
}): {
nativeModules: string[];
hybridModules: string[];
inject: { process: string | false };
} {
const disabledV2ByFlag = compatibilityFlags.includes(
"disable_nodejs_process_v2"
);

const enabledV2ByFlag = compatibilityFlags.includes(
"enable_nodejs_process_v2"
);
const enabledV2ByDate = compatibilityDate >= "2025-09-15";

const isV2 = (enabledV2ByFlag || enabledV2ByDate) && !disabledV2ByFlag;

return isV2
? {
nativeModules: ["process"],
hybridModules: [],
// We can use the native global, return `false` to drop the unenv default
inject: { process: false },
}
: {
nativeModules: [],
hybridModules: ["process"],
// Use the module default export as the global `process`
inject: { process: "@cloudflare/unenv-preset/node/process" },
};
}
78 changes: 60 additions & 18 deletions packages/unenv-preset/src/runtime/node/process.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// The polyfill is only used with the process v1 native implementation
// process v2 implements all the APIs from workerd v1.20250924.0

import { hrtime as UnenvHrTime } from "unenv/node/internal/process/hrtime";
import { Process as UnenvProcess } from "unenv/node/internal/process/process";

Expand All @@ -19,47 +16,92 @@ export const getBuiltinModule: NodeJS.Process["getBuiltinModule"] =

const workerdProcess = getBuiltinModule("node:process");

// Workerd has 2 different implementation for `node:process`
//
// See:
// - [workerd `process` v1](https://github.com/cloudflare/workerd/blob/main/src/node/internal/legacy_process.ts)
// - [workerd `process` v2](https://github.com/cloudflare/workerd/blob/main/src/node/internal/public_process.ts)
// - [`enable_nodejs_process_v2` flag](https://github.com/cloudflare/workerd/blob/main/src/workerd/io/compatibility-date.capnp)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isWorkerdProcessV2 = (globalThis as any).Cloudflare.compatibilityFlags
.enable_nodejs_process_v2;

const unenvProcess = new UnenvProcess({
env: globalProcess.env,
hrtime: UnenvHrTime,
// `hrtime` is only available from workerd process v2
hrtime: isWorkerdProcessV2 ? workerdProcess.hrtime : UnenvHrTime,
// `nextTick` is available from workerd process v1
nextTick: workerdProcess.nextTick,
});

// APIs implemented by workerd process in both v1 and v2
// APIs implemented by workerd module in both v1 and v2
// Note that `env`, `hrtime` and `nextTick` are always retrieved from `unenv`
export const { exit, features, platform } = workerdProcess;

// APIs that can be implemented by either `unenv` or `workerd`.
// They are always retrieved from `unenv` which might use their `workerd` implementation.
export const {
// Always implemented by workerd
env,
// Only implemented in workerd v2
hrtime,
// Always implemented by workerd
nextTick,
} = unenvProcess;

// APIs that are not implemented by `workerd` (whether v1 or v2)
// They are retrieved from `unenv`.
export const {
_channel,
_debugEnd,
_debugProcess,
_disconnect,
_events,
_eventsCount,
_handleQueue,
_maxListeners,
_pendingMessage,
_send,
assert,
disconnect,
mainModule,
} = unenvProcess;

// API that are only implemented starting from v2 of workerd process
// They are retrieved from unenv when process v1 is used
export const {
// @ts-expect-error `_debugEnd` is missing typings
_debugEnd,
// @ts-expect-error `_debugProcess` is missing typings
_debugProcess,
// @ts-expect-error `_exiting` is missing typings
_exiting,
// @ts-expect-error `_fatalException` is missing typings
_fatalException,
// @ts-expect-error `_getActiveHandles` is missing typings
_getActiveHandles,
// @ts-expect-error `_getActiveRequests` is missing typings
_getActiveRequests,
_handleQueue,
// @ts-expect-error `_kill` is missing typings
_kill,
// @ts-expect-error `_linkedBinding` is missing typings
_linkedBinding,
_maxListeners,
_pendingMessage,
// @ts-expect-error `_preload_modules` is missing typings
_preload_modules,
// @ts-expect-error `_rawDebug` is missing typings
_rawDebug,
_send,
// @ts-expect-error `_startProfilerIdleNotifier` is missing typings
_startProfilerIdleNotifier,
// @ts-expect-error `_stopProfilerIdleNotifier` is missing typings
_stopProfilerIdleNotifier,
// @ts-expect-error `_tickCallback` is missing typings
_tickCallback,
abort,
addListener,
allowedNodeEnvironmentFlags,
arch,
argv,
argv0,
assert,
availableMemory,
// @ts-expect-error `binding` is missing typings
binding,
channel,
chdir,
Expand All @@ -69,12 +111,11 @@ export const {
cpuUsage,
cwd,
debugPort,
disconnect,
dlopen,
// @ts-expect-error `domain` is missing typings
domain,
emit,
emitWarning,
env,
eventNames,
execArgv,
execPath,
Expand All @@ -88,26 +129,27 @@ export const {
getMaxListeners,
getuid,
hasUncaughtExceptionCaptureCallback,
hrtime,
// @ts-expect-error `initgroups` is missing typings
initgroups,
kill,
listenerCount,
listeners,
loadEnvFile,
mainModule,
memoryUsage,
// @ts-expect-error `moduleLoadList` is missing typings
moduleLoadList,
nextTick,
off,
on,
once,
// @ts-expect-error `openStdin` is missing typings
openStdin,
permission,
pid,
ppid,
prependListener,
prependOnceListener,
rawListeners,
// @ts-expect-error `reallyExit` is missing typings
reallyExit,
ref,
release,
Expand Down Expand Up @@ -136,7 +178,7 @@ export const {
uptime,
version,
versions,
} = unenvProcess;
} = isWorkerdProcessV2 ? workerdProcess : unenvProcess;

const _process = {
abort,
Expand Down
Loading
Loading