Skip to content

Commit 3e686ff

Browse files
committed
fix: prevent Next from defining duplicate global property in edge functions
1 parent ad01f58 commit 3e686ff

File tree

1 file changed

+19
-9
lines changed
  • packages/runtime/src/helpers

1 file changed

+19
-9
lines changed

packages/runtime/src/helpers/edge.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,21 @@ const sanitizeName = (name: string) => `next_${name.replace(/\W/g, '_')}`
7171
/**
7272
* Initialization added to the top of the edge function bundle
7373
*/
74-
const bootstrap = /* js */ `
74+
const preamble = /* js */ `
75+
7576
globalThis.process = { env: {...Deno.env.toObject(), NEXT_RUNTIME: 'edge', 'NEXT_PRIVATE_MINIMAL_MODE': '1' } }
76-
globalThis._ENTRIES ||= {}
77+
const _ENTRIES = {}
7778
// Deno defines "window", but naughty libraries think this means it's a browser
7879
delete globalThis.window
79-
80+
// Next uses "self" as a function-scoped global-like object
81+
const self = {}
8082
`
8183

84+
// Slightly different spacing in different versions!
85+
const IMPORT_UNSUPPORTED = [
86+
`Object.defineProperty(globalThis,"__import_unsupported"`,
87+
` Object.defineProperty(globalThis, "__import_unsupported"`,
88+
]
8289
/**
8390
* Concatenates the Next edge function code with the required chunks and adds an export
8491
*/
@@ -90,17 +97,20 @@ const getMiddlewareBundle = async ({
9097
netlifyConfig: NetlifyConfig
9198
}): Promise<string> => {
9299
const { publish } = netlifyConfig.build
93-
const chunks: Array<string> = [bootstrap]
100+
const chunks: Array<string> = [preamble]
94101
for (const file of edgeFunctionDefinition.files) {
95102
const filePath = join(publish, file)
96-
const data = await fs.readFile(filePath, 'utf8')
103+
104+
let data = await fs.readFile(filePath, 'utf8')
105+
// Next defines an immutable global variable, which is fine unless you have more than one in the bundle
106+
// This adds a check to see if the global is already defined
107+
data = IMPORT_UNSUPPORTED.reduce(
108+
(acc, val) => acc.replace(val, `('__import_unsupported' in globalThis)||${val}`),
109+
data,
110+
)
97111
chunks.push('{', data, '}')
98112
}
99113

100-
const middleware = await fs.readFile(join(publish, `server`, `${edgeFunctionDefinition.name}.js`), 'utf8')
101-
102-
chunks.push(middleware)
103-
104114
const exports = /* js */ `export default _ENTRIES["middleware_${edgeFunctionDefinition.name}"].default;`
105115
chunks.push(exports)
106116
return chunks.join('\n')

0 commit comments

Comments
 (0)