@@ -9,6 +9,7 @@ import { execaCommand } from 'execa'
99import getPort from 'get-port'
1010import { spawn } from 'node:child_process'
1111import { createWriteStream , existsSync } from 'node:fs'
12+ import { createRequire } from 'node:module'
1213import { cp , mkdir , mkdtemp , readFile , rm , writeFile } from 'node:fs/promises'
1314import { tmpdir } from 'node:os'
1415import { basename , dirname , join , parse , relative } from 'node:path'
@@ -37,6 +38,12 @@ const bootstrapURL = await getBootstrapURL()
3738const actualCwd = await vi . importActual < typeof import ( 'process' ) > ( 'process' ) . then ( ( p ) => p . cwd ( ) )
3839const eszipHelper = join ( actualCwd , 'tools/deno/eszip.ts' )
3940
41+ const require = createRequire ( import . meta. url )
42+ const mod = require ( 'module' )
43+
44+ const originalRequire = mod . prototype . require
45+ const originalResolveFilename = mod . _resolveFilename
46+
4047async function installDependencies ( cwd : string ) {
4148 const NEXT_VERSION = process . env . NEXT_VERSION ?? 'latest'
4249 await setNextVersionInFixture ( cwd , NEXT_VERSION , { silent : true } )
@@ -110,6 +117,30 @@ export const createFixture = async (fixture: string, ctx: FixtureTestContext) =>
110117 // from any previous function invocations that might have run in the same process
111118 delete globalThis [ Symbol . for ( 'next.server.manifests' ) ]
112119
120+ // require hook leaves modified "require" and "require.resolve" modified - we restore here to original
121+ // https://github.com/vercel/next.js/blob/812c26ab8741f68fbd6e2fe095510e0f03eac4c5/packages/next/src/server/require-hook.ts
122+ mod . prototype . require = originalRequire
123+ mod . _resolveFilename = originalResolveFilename
124+
125+ // node environment baseline defines global WebSocket getter that requires compiled 'ws' package from first function modules
126+ // we need to reset the getter to not have it attempt to import 'ws' package from unrelated functions that might have already been deleted
127+ // https://github.com/vercel/next.js/blob/812c26ab8741f68fbd6e2fe095510e0f03eac4c5/packages/next/src/server/node-environment-baseline.ts#L11-L27
128+ // note that some next versions didn't have setter, so we can't just do "globalThis.WebSocket = undefined" as that would throw
129+ // "Cannot set property WebSocket of #<Object> which has only a getter" errors
130+ Object . defineProperty ( globalThis , 'WebSocket' , {
131+ get ( ) {
132+ return undefined
133+ } ,
134+ set ( value ) {
135+ Object . defineProperty ( globalThis , 'WebSocket' , {
136+ configurable : true ,
137+ writable : true ,
138+ value,
139+ } )
140+ } ,
141+ configurable : true ,
142+ } )
143+
113144 ctx . cwd = await mkdtemp ( join ( tmpdir ( ) , 'opennextjs-netlify-' ) )
114145 vi . spyOn ( process , 'cwd' ) . mockReturnValue ( ctx . cwd )
115146
@@ -147,6 +178,16 @@ export const createFixture = async (fixture: string, ctx: FixtureTestContext) =>
147178 } catch ( error ) {
148179 console . log ( `Fixture '${ fixture } ' has failed to cleanup at '${ ctx . cwd } '` , error )
149180 }
181+ if ( ctx . functionDist ) {
182+ try {
183+ await rm ( ctx . functionDist , { recursive : true , force : true } )
184+ } catch ( error ) {
185+ console . log (
186+ `Fixture's '${ fixture } ' bundled serverless function has failed to cleanup at '${ ctx . cwd } '` ,
187+ error ,
188+ )
189+ }
190+ }
150191 } )
151192 }
152193
0 commit comments