import { type WasmThreadingCapabilities, } from "../../../protocol/engine-variant"; export { gateWasmThreadingCapability, selectWebEngineVariant } from "../../../protocol/engine-variant"; export type { WasmThreadingCapabilities } from "../../../protocol/engine-variant"; export interface BrowserCapabilities extends WasmThreadingCapabilities { webgl2: boolean; offscreenCanvas: boolean; opfs: boolean; wasm: boolean; wasmSimd: boolean; wasmThreads: boolean; storageEstimate: boolean; indexedDb: boolean; } function supportsWasmFeature(feature: "simd" | "threads"): boolean { if (typeof WebAssembly === "undefined") return false; const modules: Record = { simd: new Uint8Array([ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x0a, 0x0b, 0x01, 0x09, 0x00, 0xfd, 0x00, 0x00, 0x0b, ]), threads: new Uint8Array([ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, 0x00, 0x00, 0x05, 0x04, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x04, 0x01, 0x02, 0x00, 0x0b, ]), }; try { return WebAssembly.validate(modules[feature] as BufferSource); } catch { return false; } } export function detectBrowserCapabilities(): BrowserCapabilities { const canvas = typeof document === "undefined" ? undefined : document.createElement("canvas"); const webgl2 = Boolean(canvas?.getContext("webgl2")); const storage = typeof navigator === "undefined" ? undefined : navigator.storage; return { crossOriginIsolated: globalThis.crossOriginIsolated === true, webgl2, offscreenCanvas: typeof OffscreenCanvas !== "undefined", opfs: Boolean(storage?.getDirectory), sharedArrayBuffer: typeof SharedArrayBuffer !== "undefined", worker: typeof Worker !== "undefined", wasm: typeof WebAssembly !== "undefined", wasmSimd: supportsWasmFeature("simd"), wasmThreads: supportsWasmFeature("threads"), storageEstimate: Boolean(storage?.estimate), indexedDb: typeof indexedDB !== "undefined", }; }