diff --git a/packages/next/server/web/sandbox/context.ts b/packages/next/server/web/sandbox/context.ts index 0a51b50735e7..b609eebb6960 100644 --- a/packages/next/server/web/sandbox/context.ts +++ b/packages/next/server/web/sandbox/context.ts @@ -304,7 +304,13 @@ function createProcessPolyfill(options: Pick) { if (key === 'env') continue Object.defineProperty(processPolyfill, key, { get() { - return overridenValue[key] ?? (() => emitError(`process.${key}`)) + if (overridenValue[key]) { + return overridenValue[key] + } + if (typeof (process as any)[key] === 'function') { + return () => throwUnsupportedAPIError(`process.${key}`) + } + return undefined }, set(value) { overridenValue[key] = value @@ -318,14 +324,15 @@ function createProcessPolyfill(options: Pick) { function addStub(context: Primitives, name: string) { Object.defineProperty(context, name, { get() { - emitError(name) - return undefined + return function () { + throwUnsupportedAPIError(name) + } }, enumerable: false, }) } -function emitError(name: string) { +function throwUnsupportedAPIError(name: string) { const error = new Error(`A Node.js API is used (${name}) which is not supported in the Edge Runtime. Learn more: https://nextjs.org/docs/api-reference/edge-runtime`) diff --git a/test/integration/edge-runtime-with-node.js-apis/lib/utils.js b/test/integration/edge-runtime-with-node.js-apis/lib/utils.js index 22dedbc0b3f6..9206e7a9086f 100644 --- a/test/integration/edge-runtime-with-node.js-apis/lib/utils.js +++ b/test/integration/edge-runtime-with-node.js-apis/lib/utils.js @@ -11,6 +11,8 @@ export function invokeNodeAPI(useCase) { console.log(process.cwd()) } else if (useCase === 'process.getuid') { console.log(process.getuid()) + } else if (useCase === 'process.cpuUsage') { + console.log(process.cpuUsage()) } else if (useCase === 'BroadcastChannel') { new BroadcastChannel() } else if (useCase === 'ByteLengthQueuingStrategy') { @@ -43,5 +45,9 @@ export function invokeNodeAPI(useCase) { new TransformStreamDefaultController() } else if (useCase === 'WritableStreamDefaultController') { new WritableStreamDefaultController() + } else if (useCase === 'process.version') { + console.log(process.version) + } else if (useCase === 'process.arch') { + console.log(process.arch) } } diff --git a/test/integration/edge-runtime-with-node.js-apis/middleware.js b/test/integration/edge-runtime-with-node.js-apis/middleware.js index 295f0e82cdef..01aa356a4723 100644 --- a/test/integration/edge-runtime-with-node.js-apis/middleware.js +++ b/test/integration/edge-runtime-with-node.js-apis/middleware.js @@ -1,7 +1,9 @@ import { NextResponse } from 'next/server' import { invokeNodeAPI } from './lib/utils' -export default function middleware({ nextUrl: { pathname } }) { - invokeNodeAPI(pathname.slice(1)) - return NextResponse.next() +export default function middleware({ nextUrl }) { + invokeNodeAPI(nextUrl.pathname.slice(1)) + return nextUrl.pathname.startsWith('/api') + ? NextResponse.next() + : NextResponse.rewrite(new URL('/', nextUrl)) } diff --git a/test/integration/edge-runtime-with-node.js-apis/test/index.test.ts b/test/integration/edge-runtime-with-node.js-apis/test/index.test.ts index 42507fbff9b3..090395b2afd4 100644 --- a/test/integration/edge-runtime-with-node.js-apis/test/index.test.ts +++ b/test/integration/edge-runtime-with-node.js-apis/test/index.test.ts @@ -19,8 +19,14 @@ const unsupportedFunctions = [ 'clearImmediate', // no need to test all of the process methods 'process.cwd', + 'process.cpuUsage', 'process.getuid', ] +const undefinedPropertoes = [ + // no need to test all of the process properties + 'process.arch', + 'process.version', +] const unsupportedClasses = [ 'BroadcastChannel', 'ByteLengthQueuingStrategy', @@ -77,6 +83,16 @@ describe.each([ afterAll(() => killApp(app)) + it.each(undefinedPropertoes.map((api) => ({ api })))( + 'does not throw on using $api', + async ({ api }) => { + const res = await fetchViaHTTP(appPort, computeRoute(api)) + expect(res.status).toBe(200) + await waitFor(500) + expect(output).not.toInclude(`A Node.js API is used (${api})`) + } + ) + it.each([ ...unsupportedFunctions.map((api) => ({ api, @@ -86,7 +102,7 @@ describe.each([ api, errorHighlight: `new ${api}(`, })), - ])(`shows error when using $api`, async ({ api, errorHighlight }) => { + ])(`throws error when using $api`, async ({ api, errorHighlight }) => { const res = await fetchViaHTTP(appPort, computeRoute(api)) expect(res.status).toBe(500) await waitFor(500) @@ -117,5 +133,12 @@ Learn more: https://nextjs.org/docs/api-reference/edge-runtime`) )(`warns for $api during build`, ({ api }) => { expect(buildResult.stderr).toContain(`A Node.js API is used (${api}`) }) + + it.each(undefinedPropertoes.map((api) => ({ api })))( + 'does not warn on using $api', + ({ api }) => { + expect(buildResult.stderr).toContain(`A Node.js API is used (${api}`) + } + ) }) })