Skip to content

Commit

Permalink
Skip build-time dynamic code checks for specific polyfills in the Edg…
Browse files Browse the repository at this point in the history
…e runtime (#52009)

As discussed in https://vercel.slack.com/archives/C03ENM5HB4K/p1687999628589119 and #51910, it makes sense to have a known list for packages (mostly polyfills) that we know are having dynamic code (`eval`, `new Function`) but are safe to run in the Edge Runtime because that dynamic code will never be executed.
  • Loading branch information
shuding committed Jul 4, 2023
1 parent 6cb6092 commit cd66e76
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
14 changes: 14 additions & 0 deletions packages/next/src/build/webpack/plugins/middleware-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getModuleBuildInfo } from '../loaders/get-module-build-info'
import { getSortedRoutes } from '../../../shared/lib/router/utils'
import { webpack, sources } from 'next/dist/compiled/webpack/webpack'
import { isMatch } from 'next/dist/compiled/micromatch'
import path from 'path'
import {
EDGE_RUNTIME_WEBPACK,
EDGE_UNSUPPORTED_NODE_APIS,
Expand All @@ -29,6 +30,9 @@ import { normalizeAppPath } from '../../../shared/lib/router/utils/app-paths'
import { INSTRUMENTATION_HOOK_FILENAME } from '../../../lib/constants'
import { NextBuildContext } from '../../build-context'

const KNOWN_SAFE_DYNAMIC_PACKAGES =
require('../../../lib/known-edge-safe-packages.json') as string[]

export interface EdgeFunctionDefinition {
files: string[]
name: string
Expand Down Expand Up @@ -249,6 +253,16 @@ function isDynamicCodeEvaluationAllowed(
middlewareConfig?: MiddlewareConfig,
rootDir?: string
) {
// Some packages are known to use `eval` but are safe to use in the Edge
// Runtime because the dynamic code will never be executed.
if (
KNOWN_SAFE_DYNAMIC_PACKAGES.some((pkg) =>
fileName.includes(`/node_modules/${pkg}/`.replace(/\//g, path.sep))
)
) {
return true
}

const name = fileName.replace(rootDir ?? '', '')
return isMatch(name, middlewareConfig?.unstable_allowDynamicGlobs ?? [])
}
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/lib/known-edge-safe-packages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["function-bind"]
41 changes: 41 additions & 0 deletions test/production/edge-safe-dynamic-code/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { createNext } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'

// This test is basically for https://github.com/vercel/next.js/discussions/51910
// to make sure that some libs that we know are using `eval` but don't break
// because it will never run into that condition, but still can't to be DCE'd.

describe('Edge safe dynamic code', () => {
let next: NextInstance

afterAll(() => next.destroy())

it('should not fail when "function-bind" package is used', async () => {
next = await createNext({
skipStart: true,
dependencies: {
'function-bind': 'latest',
},
files: {
'pages/index.js': `
export default function Page() {
return <p>hello world</p>
}
`,
'middleware.js': `
import { NextResponse } from 'next/server'
import * as bind from 'function-bind'
console.log(bind)
export default async function middleware(request) {
return NextResponse.next()
}
`,
},
})
await next.start()

expect(next.cliOutput).not.toContain(
`Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Edge Runtime`
)
})
})

0 comments on commit cd66e76

Please sign in to comment.