@@ -11,14 +11,22 @@ import {
1111} from "@mrbbot/node-fetch" ;
1212import cron from "node-cron" ;
1313import sourceMap , { UrlAndMap } from "source-map-support" ;
14- import WebSocket from "ws" ;
14+ import StandardWebSocket from "ws" ;
1515import Youch from "youch" ;
16- import { MiniflareError } from "./error " ;
16+ import { MiniflareError } from "./helpers " ;
1717import { Cache , KVStorageNamespace } from "./kv" ;
1818import { ConsoleLog , Log , NoOpLog , logResponse } from "./log" ;
1919import { ResponseWaitUntil } from "./modules" ;
2020import { DurableObjectConstructor , DurableObjectNamespace } from "./modules/do" ;
21- import { ModuleFetchListener , ModuleScheduledListener } from "./modules/events" ;
21+ import {
22+ ModuleFetchListener ,
23+ ModuleScheduledListener ,
24+ addModuleFetchListenerSymbol ,
25+ addModuleScheduledListenerSymbol ,
26+ dispatchFetchSymbol ,
27+ dispatchScheduledSymbol ,
28+ } from "./modules/events" ;
29+ import { ServiceWorkerGlobalScope } from "./modules/events" ;
2230import { Context } from "./modules/module" ;
2331import * as modules from "./modules/modules" ;
2432import { terminateWebSocket } from "./modules/ws" ;
@@ -28,6 +36,7 @@ import {
2836 ModuleScriptInstance ,
2937 ScriptLinker ,
3038 ScriptScriptInstance ,
39+ createScriptContext ,
3140} from "./scripts" ;
3241
3342type ModuleName = keyof typeof modules ;
@@ -50,12 +59,11 @@ export class Miniflare {
5059 readonly #watcher: OptionsWatcher ;
5160 #options?: ProcessedOptions ;
5261
53- #sandbox: Context ;
54- #environment: Context ;
62+ #globalScope?: ServiceWorkerGlobalScope ;
5563 #scheduledTasks?: cron . ScheduledTask [ ] ;
5664 #extraSourceMaps?: Map < string , string > ;
5765
58- readonly #wss: WebSocket . Server ;
66+ readonly #wss: StandardWebSocket . Server ;
5967
6068 constructor ( options : Options = { } ) {
6169 if ( options . sourceMap ) {
@@ -77,12 +85,8 @@ export class Miniflare {
7785 { } as Modules
7886 ) ;
7987
80- // Defaults never used, will be overridden in #watchCallback
81- this . #sandbox = { } ;
82- this . #environment = { } ;
83-
8488 // Initialise web socket server
85- this . #wss = new WebSocket . Server ( { noServer : true } ) ;
89+ this . #wss = new StandardWebSocket . Server ( { noServer : true } ) ;
8690 this . #wss. addListener (
8791 "connection" ,
8892 this . #webSocketConnectionListener. bind ( this )
@@ -104,20 +108,20 @@ export class Miniflare {
104108 this . #options = options ;
105109 // Build sandbox and environment
106110 const modules = Object . values ( this . #modules) ;
107- this . # sandbox = modules . reduce (
111+ const sandbox = modules . reduce (
108112 ( sandbox , module ) => Object . assign ( sandbox , module . buildSandbox ( options ) ) ,
109113 { } as Context
110114 ) ;
111- this . # environment = modules . reduce (
115+ const environment = modules . reduce (
112116 ( environment , module ) =>
113117 Object . assign ( environment , module . buildEnvironment ( options ) ) ,
114118 { } as Context
115119 ) ;
116120 // Assign bindings last so they can override modules if required
117- Object . assign ( this . # environment, options . bindings ) ;
121+ Object . assign ( environment , options . bindings ) ;
118122
119123 this . #reloadScheduled( ) ;
120- await this . #reloadWorker( ) ;
124+ await this . #reloadWorker( sandbox , environment ) ;
121125 }
122126
123127 #reloadScheduled( ) : void {
@@ -137,7 +141,7 @@ export class Miniflare {
137141 ) ;
138142 }
139143
140- async #reloadWorker( ) : Promise < void > {
144+ async #reloadWorker( sandbox : Context , environment : Context ) : Promise < void > {
141145 // Only called in #watchCallback() after #options set and scripts and
142146 // processedModulesRules are always set in this
143147 assert ( this . #options?. scripts && this . #options. processedModulesRules ) ;
@@ -146,20 +150,20 @@ export class Miniflare {
146150 const linker = new ScriptLinker ( this . #options. processedModulesRules ) ;
147151 this . #extraSourceMaps = linker . extraSourceMaps ;
148152
153+ // Build new global scope (sandbox), this inherits from EventTarget
154+ const globalScope = new ServiceWorkerGlobalScope (
155+ this . log ,
156+ sandbox ,
157+ environment ,
158+ this . #options. modules
159+ ) ;
160+ this . #globalScope = globalScope ;
161+ const context = createScriptContext ( globalScope ) ;
162+
149163 // Reset state
150- this . #modules. EventsModule . resetEventListeners ( ) ;
151164 this . #modules. DurableObjectsModule . resetInstances ( ) ;
152165 this . #modules. StandardsModule . resetWebSockets ( ) ;
153166
154- // Build sandbox with global self-references, only including environment
155- // in global scope if not using modules
156- const sandbox = this . #options. modules
157- ? { ...this . #sandbox }
158- : { ...this . #sandbox, ...this . #environment } ;
159- sandbox . global = sandbox ;
160- sandbox . globalThis = sandbox ;
161- sandbox . self = sandbox ;
162-
163167 // Parse and run all scripts
164168 const moduleExports : Record < string , ModuleExports > = { } ;
165169 for ( const script of Object . values ( this . #options. scripts ) ) {
@@ -169,8 +173,8 @@ export class Miniflare {
169173 let instance : ScriptScriptInstance | ModuleScriptInstance < ModuleExports > ;
170174 try {
171175 instance = this . #options. modules
172- ? await script . buildModule ( sandbox , linker . linker )
173- : await script . buildScript ( sandbox ) ;
176+ ? await script . buildModule ( context , linker . linker )
177+ : await script . buildScript ( context ) ;
174178 } catch ( e ) {
175179 // If this is because --experimental-vm-modules disabled, rethrow
176180 if ( e instanceof MiniflareError ) throw e ;
@@ -202,18 +206,12 @@ export class Miniflare {
202206 if ( script . fileName === this . #options. scriptPath ) {
203207 const fetchListener = instance . exports ?. default ?. fetch ;
204208 if ( fetchListener ) {
205- this . #modules. EventsModule . addModuleFetchListener (
206- fetchListener ,
207- this . #environment
208- ) ;
209+ globalScope [ addModuleFetchListenerSymbol ] ( fetchListener ) ;
209210 }
210211
211212 const scheduledListener = instance . exports ?. default ?. scheduled ;
212213 if ( scheduledListener ) {
213- this . #modules. EventsModule . addModuleScheduledListener (
214- scheduledListener ,
215- this . #environment
216- ) ;
214+ globalScope [ addModuleScheduledListenerSymbol ] ( scheduledListener ) ;
217215 }
218216 }
219217 }
@@ -231,10 +229,7 @@ export class Miniflare {
231229 ) ;
232230 }
233231 }
234- this . #modules. DurableObjectsModule . setContext (
235- constructors ,
236- this . #environment
237- ) ;
232+ this . #modules. DurableObjectsModule . setContext ( constructors , environment ) ;
238233
239234 // Watch module referenced paths
240235 assert ( this . #watcher !== undefined ) ;
@@ -263,7 +258,9 @@ export class Miniflare {
263258 init ?: RequestInit
264259 ) : Promise < ResponseWaitUntil < WaitUntil > > {
265260 await this . #watcher. initPromise ;
266- return this . #modules. EventsModule . dispatchFetch < WaitUntil > (
261+ const globalScope = this . #globalScope;
262+ assert ( globalScope ) ;
263+ return globalScope [ dispatchFetchSymbol ] < WaitUntil > (
267264 new Request ( input , init ) ,
268265 this . #options?. upstreamUrl
269266 ) ;
@@ -274,10 +271,9 @@ export class Miniflare {
274271 cron ?: string
275272 ) : Promise < WaitUntil > {
276273 await this . #watcher. initPromise ;
277- return this . #modules. EventsModule . dispatchScheduled < WaitUntil > (
278- scheduledTime ,
279- cron
280- ) ;
274+ const globalScope = this . #globalScope;
275+ assert ( globalScope ) ;
276+ return globalScope [ dispatchScheduledSymbol ] < WaitUntil > ( scheduledTime , cron ) ;
281277 }
282278
283279 async getOptions ( ) : Promise < ProcessedOptions > {
@@ -448,7 +444,7 @@ export class Miniflare {
448444 }
449445
450446 async #webSocketConnectionListener(
451- ws : WebSocket ,
447+ ws : StandardWebSocket ,
452448 req : http . IncomingMessage
453449 ) : Promise < void > {
454450 // Handle request in worker
0 commit comments