Skip to content

Ship a Windows arm64 build and detect missing Wasm SIMD - #93

Merged
wassgha merged 1 commit into
mainfrom
fix/windows-arm64-simd
Sep 3, 2026
Merged

Ship a Windows arm64 build and detect missing Wasm SIMD#93
wassgha merged 1 commit into
mainfrom
fix/windows-arm64-simd

Conversation

@wassgha

@wassgha wassgha commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Companion to #92. That PR stops export hanging; this one addresses a machine class where the editor can't start at all.

The evidence

Sentry has been collecting RuntimeError: Aborted(CompileError: WebAssembly.instantiate(): Compiling function #93 failed: Wasm SIMD unsupported @+70571) — 7 events, ongoing.

I traced the frame to the binary. Module offset +70571 falls inside the body of defined function #8 ([70569, 71918)), and the module has exactly 85 function imports (86 imports total, one of which is the memory), so 85 + 8 = #93. Exact match. It's ffmpeg-core.wasm failing to compile — not onnxruntime.

build.win was ["nsis"] with no arch, which electron-builder reads as x64 only. Windows on Arm users therefore run it under emulation, and V8 disables Wasm SIMD on x64 unless the emulated CPU reports SSE4.1 — which the older Windows-on-Arm x64 emulators do not.

Windows arm64

build.win now targets x64 and arm64. Verified by actually packing one rather than trusting the config edit:

dist/win-arm64-unpacked/Rescript.exe: PE32+ executable (GUI) Aarch64, for MS Windows

Cross-built from an x64 host — the app has no native modules (npmRebuild=false), so electron-builder just fetches the arm64 Electron. That's the same situation as the windows-latest release runner.

Both arches ship in one Rescript-Setup.exe. That's electron-builder's default for NSIS with more than one arch (NsisTarget.shouldBuildUniversalInstaller), and it's the option I'd argue for: download URL, artifact name and update manifests all stay exactly as they are. The cost is a roughly twice-as-large installer. Splitting into per-arch files would require adding ${arch} to nsis.artifactName — without it the two builds collide on one output path — which renames the file every existing download link points at. Happy to switch if the size matters more; it's a two-line change. Documented in RELEASING.md.

The SIMD probe

The arm64 build is the fix for the Snapdragon case specifically. The probe is what holds regardless.

There is no non-SIMD fallback available: @ffmpeg/core-mt and the single-threaded @ffmpeg/core both list +simd128 in their target_features custom section, and onnxruntime only ships as ort-wasm-simd-threaded. So on a machine without SIMD nothing works, and the honest thing is to say so up front.

SharedArrayBuffer and SIMD are both hard requirements, so they're now one gate. useCrossOriginIsolated becomes useMediaEngineSupport, returning "no-isolation" / "no-simd" so each gets its own advice. lib/wasmFeatures.ts holds the probe — the same module wasm-feature-detect uses, verified byte-for-byte against that package. validate rather than compile, because the "Wasm SIMD unsupported" error comes out of the decoder that both share, and because being synchronous lets the UI gate without a loading state.

Before: a missing-SIMD machine got Failed to process this file. After: a named cause and an action.

Also

The last hardcoded English string in lib/ffmpeg.ts ("The media engine isn't ready yet…") moves into the catalog, so both engine-unavailable messages localize rather than one of them sitting untranslated next to the other.

All nine locales updated; lint, typecheck, i18n tests and next build pass.

Caveat

I can't reproduce the Snapdragon case directly, so the emulation → no-SSE4.1 → no-SIMD chain is inference, not a confirmed repro. What is confirmed: the CompileError is ffmpeg-core.wasm, the Windows build is x64-only, and both cores require SIMD. The arm64 build is correct for those machines regardless of whether it turns out to be the whole story, and the probe guarantees a clear message either way.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
app.rescript Ready Ready Preview Sep 3, 2026 5:14am UTC

Sentry has been collecting `RuntimeError: Aborted(CompileError:
WebAssembly.instantiate(): Compiling function #93 failed: Wasm SIMD
unsupported)`. Function #93 is `ffmpeg-core.wasm`: the module has 85
function imports and the reported offset lands in defined function #8.
The core simply will not compile on these machines, so the editor cannot
start at all.

`build.win` shipped x64 only, so Windows on Arm users run it under
emulation — where V8 turns Wasm SIMD off unless the emulated CPU reports
SSE4.1, which the older x64 emulators do not. Target arm64 as well.
Verified by packing one: the output is a PE32+ Aarch64 binary,
cross-built from an x64 host, which is what the release runner is.

Both arches go into one Rescript-Setup.exe — electron-builder's default
for NSIS with more than one arch. That leaves the download URL, artifact
name and update manifests untouched, at the cost of installer size;
splitting them would need `${arch}` in `nsis.artifactName` to avoid an
output-path collision, renaming the file every download link points at.

The probe is the part that holds either way. Every wasm binary the app
ships is a SIMD build — both ffmpeg cores list `+simd128` in
`target_features`, and onnxruntime is only distributed as
`ort-wasm-simd-threaded` — so there is nothing to fall back to, and the
honest thing is to say so. SharedArrayBuffer and SIMD are now one gate:
`useCrossOriginIsolated` becomes `useMediaEngineSupport`, which
distinguishes the two so each can give its own advice. Previously a
missing-SIMD machine got "Failed to process this file."

Also moves the last hardcoded English string in `lib/ffmpeg.ts` into the
catalog, so both engine-unavailable messages localize.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@wassgha
wassgha force-pushed the fix/windows-arm64-simd branch from 4d9f709 to 80912ae Compare September 3, 2026 05:14
@wassgha
wassgha merged commit cfbd29f into main Sep 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant