Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(edge-runtime): undefined global in edge runtime. #38769

Merged
merged 3 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,9 @@ export default function middlewareLoader(this: any) {
}

return `
import { adapter } from 'next/dist/server/web/adapter'
import { adapter, enhanceGlobals } from 'next/dist/server/web/adapter'

// The condition is true when the "process" module is provided
if (process !== global.process) {
// prefer local process but global.process has correct "env"
process.env = global.process.env;
global.process = process;
}
enhanceGlobals()

var mod = require(${stringifiedPagePath})
var handler = mod.middleware || mod.default;
Expand Down
9 changes: 2 additions & 7 deletions packages/next/build/webpack/loaders/next-middleware-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,9 @@ export default function middlewareLoader(this: any) {
}

return `
import { adapter, blockUnallowedResponse } from 'next/dist/server/web/adapter'
import { adapter, blockUnallowedResponse, enhanceGlobals } from 'next/dist/server/web/adapter'

// The condition is true when the "process" module is provided
if (process !== global.process) {
// prefer local process but global.process has correct "env"
process.env = global.process.env;
global.process = process;
}
enhanceGlobals()

var mod = require(${stringifiedPagePath})
var handler = mod.middleware || mod.default;
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/webpack/plugins/middleware-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export async function handleWebpackExtenalForEdgeRuntime({
contextInfo: any
}) {
if (contextInfo.issuerLayer === 'middleware' && isNodeJsModule(request)) {
return `root __import_unsupported('${request}')`
return `root globalThis.__import_unsupported('${request}')`
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/next/server/dev/next-dev-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ export default class DevServer extends Server {
const frames = parseStack(err.stack!)
const frame = frames.find(
({ file }) =>
!file?.startsWith('eval') && !file?.includes('sandbox/context')
!file?.startsWith('eval') && !file?.includes('web/adapter')
)!

if (frame.lineNumber && frame?.file) {
Expand Down
44 changes: 44 additions & 0 deletions packages/next/server/web/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,50 @@ export function blockUnallowedResponse(
})
}

export function enhanceGlobals() {
// The condition is true when the "process" module is provided
if (process !== global.process) {
// prefer local process but global.process has correct "env"
process.env = global.process.env
global.process = process
}

// to allow building code that import but does not use node.js modules,
// webpack will expect this function to exist in global scope
Object.defineProperty(globalThis, '__import_unsupported', {
value: __import_unsupported,
enumerable: false,
configurable: false,
})
}

function __import_unsupported(moduleName: string) {
const proxy: any = new Proxy(function () {}, {
get(_obj, prop) {
if (prop === 'then') {
return {}
}
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
ijjk marked this conversation as resolved.
Show resolved Hide resolved
},
construct() {
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
},
apply(_target, _this, args) {
if (typeof args[0] === 'function') {
return args[0](proxy)
}
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
},
})
return new Proxy({}, { get: () => proxy })
}

function getUnsupportedModuleErrorMessage(module: string) {
// warning: if you change these messages, you must adjust how react-dev-overlay's middleware detects modules not found
return `The edge runtime does not support Node.js '${module}' module.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`
}

class NextRequestHint extends NextRequest {
sourcePage: string

Expand Down
29 changes: 0 additions & 29 deletions packages/next/server/web/sandbox/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,29 +129,6 @@ async function createModuleContext(options: ModuleContextOptions) {
return fn()
}

context.__import_unsupported = function __import_unsupported(
moduleName: string
) {
const proxy: any = new Proxy(function () {}, {
get(_obj, prop) {
if (prop === 'then') {
return {}
}
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
},
construct() {
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
},
apply(_target, _this, args) {
if (args[0] instanceof Function) {
return args[0](proxy)
}
throw new Error(getUnsupportedModuleErrorMessage(moduleName))
},
})
return new Proxy({}, { get: () => proxy })
}

context.__next_webassembly_compile__ =
function __next_webassembly_compile__(fn: Function) {
const key = fn.toString()
Expand Down Expand Up @@ -354,9 +331,3 @@ function decorateUnhandledError(error: any) {
decorateServerError(error, 'edge-server')
}
}

function getUnsupportedModuleErrorMessage(module: string) {
// warning: if you change these messages, you must adjust how react-dev-overlay's middleware detects modules not found
return `The edge runtime does not support Node.js '${module}' module.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`
}