import type { BrowserRPC } from '@vitest/browser/client' import type { WorkerGlobalState } from 'vitest' import { EvaluatedModules } from 'vite/module-runner' import { getBrowserState } from '../utils' const config = getBrowserState().config const sessionId = getBrowserState().sessionId const state: WorkerGlobalState = { ctx: { rpc: null as any, pool: 'browser', workerId: 1, config, projectName: config.name || '', files: [], environment: { name: 'browser', options: null, }, // this is populated before tests run providedContext: {}, invalidates: [], }, onCancel: null as any, config, environment: { name: 'browser', viteEnvironment: 'client', setup() { throw new Error('Not called in the browser') }, }, onCleanup: fn => getBrowserState().cleanups.push(fn), evaluatedModules: new EvaluatedModules(), resolvingModules: new Set(), moduleExecutionInfo: new Map(), metaEnv: null as any, rpc: null as any, durations: { environment: 0, prepare: performance.now(), }, providedContext: {}, } // @ts-expect-error not typed global globalThis.__vitest_browser__ = true // @ts-expect-error not typed global globalThis.__vitest_worker__ = state getBrowserState().cdp = createCdp() function rpc() { return state.rpc as any as BrowserRPC } function createCdp() { const listenersMap = new WeakMap() function getId(listener: Function) { const id = listenersMap.get(listener) || crypto.randomUUID() listenersMap.set(listener, id) return id } const listeners: Record = {} const cdp = { send(method: string, params?: Record) { return rpc().sendCdpEvent(sessionId, method, params) }, on(event: string, listener: (payload: any) => void) { const listenerId = getId(listener) listeners[event] = listeners[event] || [] listeners[event].push(listener) rpc().trackCdpEvent(sessionId, 'on', event, listenerId).catch(error) return cdp }, once(event: string, listener: (payload: any) => void) { const listenerId = getId(listener) const handler = (data: any) => { listener(data) cdp.off(event, listener) } listeners[event] = listeners[event] || [] listeners[event].push(handler) rpc().trackCdpEvent(sessionId, 'once', event, listenerId).catch(error) return cdp }, off(event: string, listener: (payload: any) => void) { const listenerId = getId(listener) if (listeners[event]) { listeners[event] = listeners[event].filter(l => l !== listener) } rpc().trackCdpEvent(sessionId, 'off', event, listenerId).catch(error) return cdp }, emit(event: string, payload: unknown) { if (listeners[event]) { listeners[event].forEach((l) => { try { l(payload) } catch (err) { error(err) } }) } }, } return cdp } function error(err: unknown) { window.dispatchEvent(new ErrorEvent('error', { error: err })) }