diff --git a/package.json b/package.json index 417509f05a..f4d35ec373 100644 --- a/package.json +++ b/package.json @@ -161,7 +161,7 @@ "ultrahtml": "^1.5.3", "uncrypto": "^0.1.3", "unctx": "^2.4.1", - "unenv": "2.0.0-rc.4", + "unenv": "2.0.0-rc.6", "unimport": "^4.0.0", "unplugin-utils": "^0.2.3", "unstorage": "^1.14.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b0674ee0c2..874e0894db 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -207,8 +207,8 @@ importers: specifier: ^2.4.1 version: 2.4.1 unenv: - specifier: 2.0.0-rc.4 - version: 2.0.0-rc.4 + specifier: 2.0.0-rc.6 + version: 2.0.0-rc.6 unimport: specifier: ^4.0.0 version: 4.1.1 @@ -5608,8 +5608,8 @@ packages: resolution: {integrity: sha512-Qy96NND4Dou5jKoSJ2gm8ax8AJM/Ey9o9mz7KN1bb9GP+G0l20Zw8afxTnY2f4b7hmhn/z8aC2kfArVQlAhFBw==} engines: {node: '>=20.18.1'} - unenv@2.0.0-rc.4: - resolution: {integrity: sha512-5yneal3PObCay6i1yUtgLACNCoTJHc3ZbzqodUwiwagkuCItv8SMHOOveAl4WbolsC27cltszBvv2xJ+uLAHlw==} + unenv@2.0.0-rc.6: + resolution: {integrity: sha512-1AQFWJU6weE9QSFYFFw17Acrows3QIxl216K31bFWlMmKST+lKhe0tMJBlrxxG2dx8qnSi2IsIXEarEP7IpIYA==} unhead@1.11.18: resolution: {integrity: sha512-TWgGUoZMpYe2yJwY6jZ0/9kpQT18ygr2h5lI6cUXdfD9UzDc0ytM9jGaleSYkj9guJWXkk7izYBnzJvxl8mRvQ==} @@ -12123,7 +12123,7 @@ snapshots: undici@7.3.0: {} - unenv@2.0.0-rc.4: + unenv@2.0.0-rc.6: dependencies: defu: 6.1.4 mlly: 1.7.4 diff --git a/src/presets/cloudflare/unenv/preset.ts b/src/presets/cloudflare/unenv/preset.ts index 5274170a7b..ce8a93bb7b 100644 --- a/src/presets/cloudflare/unenv/preset.ts +++ b/src/presets/cloudflare/unenv/preset.ts @@ -37,7 +37,15 @@ export const nodeCompatModules = [ ]; // Modules implemented via a mix of workerd APIs and polyfills -export const hybridNodeCompatModules = ["async_hooks", "crypto", "util"]; +export const hybridNodeCompatModules = [ + "async_hooks", + "console", + "crypto", + "module", + "perf_hooks", + "process", + "util", +]; const presetRuntimeDir = fileURLToPath(new URL("runtime/", import.meta.url)); const resolvePresetRuntime = (m: string) => join(presetRuntimeDir, `${m}.mjs`); @@ -68,8 +76,7 @@ export const unenvCfPreset: Preset = { "node-mock-http/_polyfill/buffer": "node:buffer", }, inject: { - // process: "TODO", - // console: "TODO", + process: resolvePresetRuntime("process"), Buffer: ["node:buffer", "Buffer"], "global.Buffer": ["node:buffer", "Buffer"], "globalThis.Buffer": ["node:buffer", "Buffer"], @@ -80,10 +87,17 @@ export const hybridNodePlugin: Plugin = { name: "nitro:cloudflare:hybrid-node-compat", resolveId(id) { if (id.startsWith("cloudflare:")) { - return { id, external: true }; + return { id, external: true, moduleSideEffects: false }; } if (id.startsWith("#workerd/node:")) { - return { id: id.slice("#workerd/".length), external: true }; + return { + id: id.slice("#workerd/".length), + external: true, + moduleSideEffects: false, + }; + } + if (id.startsWith(presetRuntimeDir)) { + return { id, moduleSideEffects: false }; } }, }; diff --git a/src/presets/cloudflare/unenv/runtime/async_hooks.mjs b/src/presets/cloudflare/unenv/runtime/async_hooks.mjs index e47d467761..266a7f8a04 100644 --- a/src/presets/cloudflare/unenv/runtime/async_hooks.mjs +++ b/src/presets/cloudflare/unenv/runtime/async_hooks.mjs @@ -1,3 +1,4 @@ +// https://github.com/cloudflare/workerd/blob/main/src/node/async_hooks.ts // https://github.com/cloudflare/workers-sdk/blob/main/packages/unenv-preset/src/runtime/node/async_hooks/index.ts import workerdAsyncHooks from "#workerd/node:async_hooks"; @@ -21,11 +22,11 @@ export { export const { AsyncLocalStorage, AsyncResource } = workerdAsyncHooks; export default { + AsyncLocalStorage, + AsyncResource, asyncWrapProviders, createHook, executionAsyncId, executionAsyncResource, triggerAsyncId, - AsyncLocalStorage, - AsyncResource, }; diff --git a/src/presets/cloudflare/unenv/runtime/console.mjs b/src/presets/cloudflare/unenv/runtime/console.mjs new file mode 100644 index 0000000000..f329a5fedb --- /dev/null +++ b/src/presets/cloudflare/unenv/runtime/console.mjs @@ -0,0 +1,71 @@ +// https://github.com/cloudflare/workers-sdk/blob/main/packages/unenv-preset/src/runtime/node/console/index.ts + +import workerdConsole from "#workerd/node:console"; + +import { + Console, + _ignoreErrors, + _stderr, + _stderrErrorHandler, + _stdout, + _stdoutErrorHandler, + _times, +} from "unenv/node/console"; + +export { + Console, + _ignoreErrors, + _stderr, + _stderrErrorHandler, + _stdout, + _stdoutErrorHandler, + _times, +} from "unenv/node/console"; + +export const { + assert, + clear, + context, + count, + countReset, + createTask, + debug, + dir, + dirxml, + error, + group, + groupCollapsed, + groupEnd, + info, + log, + profile, + profileEnd, + table, + time, + timeEnd, + timeLog, + timeStamp, + trace, + warn, +} = workerdConsole; + +const consolePolyfill = { + Console, + _ignoreErrors, + _stderr, + _stderrErrorHandler, + _stdout, + _stdoutErrorHandler, + _times, +}; + +const consoleModule = /*@__PURE__*/ new Proxy(workerdConsole, { + get(target, prop) { + if (Reflect.has(target, prop)) { + return Reflect.get(target, prop); + } + return Reflect.get(consolePolyfill, prop); + }, +}); + +export default consoleModule; diff --git a/src/presets/cloudflare/unenv/runtime/crypto.mjs b/src/presets/cloudflare/unenv/runtime/crypto.mjs index a2660e1315..fc08cdc89a 100644 --- a/src/presets/cloudflare/unenv/runtime/crypto.mjs +++ b/src/presets/cloudflare/unenv/runtime/crypto.mjs @@ -1,3 +1,4 @@ +// https://github.com/cloudflare/workerd/blob/main/src/node/crypto.ts // https://github.com/cloudflare/workers-sdk/blob/main/packages/unenv-preset/src/runtime/node/crypto/index.ts import workerdCrypto from "#workerd/node:crypto"; @@ -100,6 +101,7 @@ export const { setFips, subtle, timingSafeEqual, + fips, } = workerdCrypto; export const getRandomValues = workerdCrypto.getRandomValues.bind( @@ -113,8 +115,6 @@ export const webcrypto = { subtle, }; -const fips = workerdCrypto.fips; - export default { Certificate, Cipher, diff --git a/src/presets/cloudflare/unenv/runtime/module.mjs b/src/presets/cloudflare/unenv/runtime/module.mjs new file mode 100644 index 0000000000..a2b6850278 --- /dev/null +++ b/src/presets/cloudflare/unenv/runtime/module.mjs @@ -0,0 +1,110 @@ +// https://github.com/cloudflare/workerd/blob/main/src/node/module.ts +// https://github.com/cloudflare/workers-sdk/blob/main/packages/unenv-preset/src/runtime/node/module/index.ts + +import workerdModule from "#workerd/node:module"; + +import { notImplemented } from "unenv/_internal/utils"; + +import { + constants, + enableCompileCache, + findSourceMap, + getCompileCacheDir, + globalPaths, + Module, + register, + runMain, + SourceMap, + syncBuiltinESMExports, + wrap, + flushCompileCache, + stripTypeScriptTypes, + wrapper, + _readPackage, + _stat, + _cache, + _debug, + _extensions, + _findPath, + _initPaths, + _load, + _nodeModulePaths, + _pathCache, + _preloadModules, + _resolveFilename, + _resolveLookupPaths, +} from "unenv/node/module"; + +export { + Module, + SourceMap, + constants, + enableCompileCache, + findSourceMap, + getCompileCacheDir, + globalPaths, + register, + runMain, + syncBuiltinESMExports, + wrap, + flushCompileCache, + stripTypeScriptTypes, + wrapper, + _cache, + _extensions, + _debug, + _pathCache, + _findPath, + _initPaths, + _load, + _nodeModulePaths, + _preloadModules, + _resolveFilename, + _resolveLookupPaths, + _readPackage, + _stat, +} from "unenv/node/module"; + +export const { builtinModules, isBuiltin } = workerdModule; + +export const createRequire = (file) => { + return Object.assign(workerdModule.createRequire(file), { + resolve: Object.assign(notImplemented("module.require.resolve"), { + paths: notImplemented("module.require.resolve.paths"), + }), + cache: Object.create(null), + extensions: _extensions, + main: undefined, + }); +}; + +export default { + Module, + SourceMap, + builtinModules, + enableCompileCache, + constants, + createRequire, + findSourceMap, + getCompileCacheDir, + globalPaths, + isBuiltin, + register, + runMain, + syncBuiltinESMExports, + wrap, + flushCompileCache, + stripTypeScriptTypes, + wrapper, + _cache, + _extensions, + _debug, + _pathCache, + _findPath, + _initPaths, + _load, + _nodeModulePaths, + _preloadModules, + _resolveFilename, + _resolveLookupPaths, +}; diff --git a/src/presets/cloudflare/unenv/runtime/perf_hooks.mjs b/src/presets/cloudflare/unenv/runtime/perf_hooks.mjs new file mode 100644 index 0000000000..37d2f9d9e5 --- /dev/null +++ b/src/presets/cloudflare/unenv/runtime/perf_hooks.mjs @@ -0,0 +1,76 @@ +// https://github.com/unjs/unenv/blob/main/src/runtime/node/perf_hooks.ts + +import { + constants, + createHistogram, + monitorEventLoopDelay, + Performance, + PerformanceEntry, + PerformanceMark, + PerformanceMeasure, + PerformanceObserver, + PerformanceObserverEntryList, + PerformanceResourceTiming, + performance as unenvPerformance, +} from "unenv/node/perf_hooks"; + +export { + Performance, + PerformanceEntry, + PerformanceMark, + PerformanceMeasure, + PerformanceObserverEntryList, + PerformanceObserver, + PerformanceResourceTiming, + constants, + createHistogram, + monitorEventLoopDelay, +} from "unenv/node/perf_hooks"; + +const workerdGlobalPerformance = globalThis["perf" + "ormance"]; + +export const performance = /*@__PURE__*/ Object.assign( + workerdGlobalPerformance, + { + addEventListener: unenvPerformance.addEventListener.bind(unenvPerformance), + clearMarks: unenvPerformance.clearMarks.bind(unenvPerformance), + clearMeasures: unenvPerformance.clearMeasures.bind(unenvPerformance), + clearResourceTimings: + unenvPerformance.clearResourceTimings.bind(unenvPerformance), + dispatchEvent: unenvPerformance.dispatchEvent.bind(unenvPerformance), + eventLoopUtilization: + unenvPerformance.eventLoopUtilization.bind(unenvPerformance), + getEntries: unenvPerformance.getEntries.bind(unenvPerformance), + getEntriesByName: unenvPerformance.getEntriesByName.bind(unenvPerformance), + getEntriesByType: unenvPerformance.getEntriesByType.bind(unenvPerformance), + mark: unenvPerformance.mark.bind(unenvPerformance), + markResourceTiming: + unenvPerformance.markResourceTiming.bind(unenvPerformance), + measure: unenvPerformance.measure.bind(unenvPerformance), + nodeTiming: { ...unenvPerformance.nodeTiming }, + onresourcetimingbufferfull: + typeof unenvPerformance.onresourcetimingbufferfull === "function" + ? unenvPerformance.onresourcetimingbufferfull.bind(unenvPerformance) + : unenvPerformance.onresourcetimingbufferfull, + removeEventListener: + unenvPerformance.removeEventListener.bind(unenvPerformance), + setResourceTimingBufferSize: + unenvPerformance.setResourceTimingBufferSize.bind(unenvPerformance), + timerify: unenvPerformance.timerify.bind(unenvPerformance), + toJSON: unenvPerformance.toJSON.bind(unenvPerformance), + } +); + +export default { + Performance, + PerformanceEntry, + PerformanceMark, + PerformanceMeasure, + PerformanceObserverEntryList, + PerformanceObserver, + PerformanceResourceTiming, + constants, + createHistogram, + monitorEventLoopDelay, + performance, +}; diff --git a/src/presets/cloudflare/unenv/runtime/process.mjs b/src/presets/cloudflare/unenv/runtime/process.mjs new file mode 100644 index 0000000000..febae1a2db --- /dev/null +++ b/src/presets/cloudflare/unenv/runtime/process.mjs @@ -0,0 +1,128 @@ +// https://github.com/cloudflare/workerd/blob/main/src/node/internal/process.ts +// https://github.com/unjs/unenv/blob/main/src/runtime/node/process.ts + +import workerdProcess from "#workerd/node:process"; + +import { Process as UnenvProcess } from "unenv/node/internal/process/process"; +import { env as UnenvEnv } from "unenv/node/internal/process/env"; +import { hrtime as UnenvHrTime } from "unenv/node/internal/process/hrtime"; + +const mixedProcess = new UnenvProcess({ + env: UnenvEnv, + hrtime: UnenvHrTime, + nextTick: workerdProcess.nextTick, +}); + +if (workerdProcess.getBuiltinModule) { + mixedProcess.getBuiltinModule = workerdProcess.getBuiltinModule; +} + +export default mixedProcess; + +export const { + abort, + addListener, + allowedNodeEnvironmentFlags, + hasUncaughtExceptionCaptureCallback, + setUncaughtExceptionCaptureCallback, + loadEnvFile, + sourceMapsEnabled, + arch, + argv, + argv0, + chdir, + config, + connected, + constrainedMemory, + availableMemory, + cpuUsage, + cwd, + debugPort, + dlopen, + disconnect, + emit, + emitWarning, + env, + eventNames, + execArgv, + execPath, + exit, + finalization, + features, + getBuiltinModule, + getActiveResourcesInfo, + getMaxListeners, + hrtime, + kill, + listeners, + listenerCount, + memoryUsage, + nextTick, + on, + off, + once, + pid, + platform, + ppid, + prependListener, + prependOnceListener, + rawListeners, + release, + removeAllListeners, + removeListener, + report, + resourceUsage, + setMaxListeners, + setSourceMapsEnabled, + stderr, + stdin, + stdout, + title, + umask, + uptime, + version, + versions, + domain, + initgroups, + moduleLoadList, + reallyExit, + openStdin, + assert, + binding, + send, + exitCode, + channel, + getegid, + geteuid, + getgid, + getgroups, + getuid, + setegid, + seteuid, + setgid, + setgroups, + setuid, + permission, + mainModule, + _events, + _eventsCount, + _exiting, + _maxListeners, + _debugEnd, + _debugProcess, + _fatalException, + _getActiveHandles, + _getActiveRequests, + _kill, + _preload_modules, + _rawDebug, + _startProfilerIdleNotifier, + _stopProfilerIdleNotifier, + _tickCallback, + _disconnect, + _handleQueue, + _pendingMessage, + _channel, + _send, + _linkedBinding, +} = mixedProcess; diff --git a/src/presets/cloudflare/unenv/runtime/util.mjs b/src/presets/cloudflare/unenv/runtime/util.mjs index f42a691f37..276a0e199c 100644 --- a/src/presets/cloudflare/unenv/runtime/util.mjs +++ b/src/presets/cloudflare/unenv/runtime/util.mjs @@ -1,3 +1,4 @@ +// https://github.com/cloudflare/workerd/blob/main/src/node/util.ts // https://github.com/cloudflare/workers-sdk/blob/main/packages/unenv-preset/src/runtime/node/util/index.ts import workerdUtil from "#workerd/node:util"; @@ -7,11 +8,9 @@ import { _exceptionWithHostPort, getSystemErrorMap, getSystemErrorName, - isArray, isBoolean, isBuffer, isDate, - isDeepStrictEqual, isError, isFunction, isNull, @@ -32,11 +31,9 @@ export { _exceptionWithHostPort, getSystemErrorMap, getSystemErrorName, - isArray, isBoolean, isBuffer, isDate, - isDeepStrictEqual, isError, isFunction, isNull, @@ -75,6 +72,8 @@ export const { toUSVString, transferableAbortController, transferableAbortSignal, + isArray, + isDeepStrictEqual, } = workerdUtil; export const types = workerdUtil.types; diff --git a/src/rollup/config.ts b/src/rollup/config.ts index c51dc28bf0..04fc168e4e 100644 --- a/src/rollup/config.ts +++ b/src/rollup/config.ts @@ -59,6 +59,7 @@ export const getRollupConfig = (nitro: Nitro): RollupConfig => { const { env } = defineEnv({ nodeCompat: isNodeless, + npmShims: true, resolve: true, presets: [ unenvPresets.common, @@ -66,9 +67,7 @@ export const getRollupConfig = (nitro: Nitro): RollupConfig => { nitro.options.unenv, ], overrides: { - alias: { - ...nitro.options.alias, - }, + alias: nitro.options.alias, }, }); diff --git a/src/rollup/unenv.ts b/src/rollup/unenv.ts index ae7269186e..e0f34ddd35 100644 --- a/src/rollup/unenv.ts +++ b/src/rollup/unenv.ts @@ -2,13 +2,6 @@ import type { Preset } from "unenv"; export const common: Preset = { alias: { - "node-fetch": "unenv/npm/node-fetch", - "cross-fetch": "unenv/npm/cross-fetch", - "cross-fetch/polyfill": "unenv/mock/empty", - "isomorphic-fetch": "unenv/mock/empty", - debug: "unenv/npm/debug", - // buffer (npm) - buffer: "node:buffer", "buffer/": "node:buffer", "buffer/index": "node:buffer", "buffer/index.js": "node:buffer", @@ -23,22 +16,11 @@ export const node: Preset = { }; export const nodeless: Preset = { - alias: { - fsevents: "unenv/npm/fsevents", - inherits: "unenv/npm/inherits", - "whatwg-url": "unenv/npm/whatwg-url", - }, + alias: {}, inject: { performance: "unenv/polyfill/performance", - global: "unenv/polyfill/globalthis", - process: "unenv/node/process", - Buffer: ["unenv/node/buffer", "Buffer"], + "global.Buffer": ["unenv/node/buffer", "Buffer"], + "globalThis.Buffer": ["unenv/node/buffer", "Buffer"], }, - polyfill: [ - // Backward compatibility (remove in v2) - // https://github.com/unjs/unenv/pull/427 - "unenv/polyfill/globalthis-global", - "unenv/polyfill/process", - "unenv/polyfill/performance", - ], + polyfill: ["unenv/polyfill/globalthis-global", "unenv/polyfill/process"], }; diff --git a/test/fixture/routes/node-compat.ts b/test/fixture/routes/node-compat.ts index f8eb029440..dd8839c7fb 100644 --- a/test/fixture/routes/node-compat.ts +++ b/test/fixture/routes/node-compat.ts @@ -2,15 +2,13 @@ import nodeAsyncHooks from "node:async_hooks"; import nodeCrypto from "node:crypto"; const nodeCompatTests = { - buffer: { - Buffer: () => { - const _Buffer = Buffer; - return _Buffer && !("__unenv__" in _Buffer); - }, - "globalThis.Buffer": () => { - const _Buffer = globalThis.Buffer; - return _Buffer && !("__unenv__" in _Buffer); - }, + globals: { + // eslint-disable-next-line unicorn/prefer-global-this + global: () => globalThis.global === global, + // eslint-disable-next-line unicorn/prefer-global-this + Buffer: () => Buffer && globalThis.Buffer && global.Buffer, + // eslint-disable-next-line unicorn/prefer-global-this + process: () => process && globalThis.process && global.process, }, crypto: { createHash: () => { @@ -23,9 +21,6 @@ const nodeCompatTests = { }, async_hooks: { AsyncLocalStorage: async () => { - if ("__unenv__" in nodeAsyncHooks.AsyncLocalStorage) { - return false; - } const ctx = new nodeAsyncHooks.AsyncLocalStorage(); const rand = Math.random(); return ctx.run(rand, async () => {