--- a/host.js +++ b/host.js @@ -3314,6 +3314,37 @@ return octets.reduce((a, o) => ((a << 8) | o) >>> 0, 0) | 0; } + // Browser Games Now: retry transient delivery failures once. Compile errors + // remain compile errors; production does not ship the WAT compiler inputs. + static async fetchWasmBytes(url, init) { + for (let attempt = 0; ; attempt++) { + let response; + try { + response = await fetch(url, init); + if (!response.ok) { + const error = new Error(`Unable to load ${url}: HTTP ${response.status}`); + error.responseBody = (await response.text()).slice(0, 2000); + throw error; + } + return await response.arrayBuffer(); + } catch (error) { + error.isDownloadError = true; + error.assetUrl = url; + error.attempts = attempt + 1; + if (response) { + error.status = response.status; + error.cfRay = response.headers.get('CF-Ray'); + } + const retryable = error instanceof TypeError || error.status >= 500; + if (!retryable || attempt >= 1) throw error; + console.warn('[host] retrying WASM download', { + url, status: error.status, cfRay: error.cfRay, message: error.message, + }); + await new Promise(resolve => setTimeout(resolve, 500)); + } + } + } + static getWasmModule() { if (!WineAssembly._wasmModulePromise) { const attempt = (WineAssembly._wasmCompileAttempt || 0) + 1; @@ -3351,16 +3382,11 @@ const artifact = tailCalls ? 'build/wine-assembly.wasm' : 'build/wine-assembly.compat.wasm'; - try { - const response = await fetch(WineAssembly.versionedUrl(artifact), fetchOptions); - if (!response.ok) throw new Error(`HTTP ${response.status}`); - const bytes = await response.arrayBuffer(); - const module = await WebAssembly.compile(bytes); - await recordWasmIdentity(artifact, bytes); - return module; - } catch (error) { - console.warn(`[host] unable to load ${artifact}; compiling WAT sources`, error); - } + const bytes = await WineAssembly.fetchWasmBytes( + WineAssembly.versionedUrl(artifact), fetchOptions); + const module = await WebAssembly.compile(bytes); + await recordWasmIdentity(artifact, bytes); + return module; } // Source compile goes through the WATX compiler Worker — the // Milestone 4 wiring from lib/watx-launcher.js's header. The Worker