Skip to content

Commit

Permalink
feat: does not throw when using process properties in Edge runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
feugy committed Jul 7, 2022
1 parent e42bdf7 commit 03964bb
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 8 deletions.
15 changes: 11 additions & 4 deletions packages/next/server/web/sandbox/context.ts
Expand Up @@ -304,7 +304,13 @@ function createProcessPolyfill(options: Pick<ModuleContextOptions, 'env'>) {
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
Expand All @@ -318,14 +324,15 @@ function createProcessPolyfill(options: Pick<ModuleContextOptions, 'env'>) {
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`)
Expand Down
6 changes: 6 additions & 0 deletions test/integration/edge-runtime-with-node.js-apis/lib/utils.js
Expand Up @@ -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') {
Expand Down Expand Up @@ -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)
}
}
8 changes: 5 additions & 3 deletions 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))
}
Expand Up @@ -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',
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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}`)
}
)
})
})

0 comments on commit 03964bb

Please sign in to comment.