-
Notifications
You must be signed in to change notification settings - Fork 342
Description
Description
The Cap.js widget's WASM proof-of-work solver crashes on all WebKit-based browsers (Mobile Safari, Chrome Mobile iOS, DuckDuckGo iOS, Edge iOS, Firefox iOS, Safari macOS). The error is an unhandled promise rejection from the minified widget code.
Error
TypeError: null is not an object (evaluating 'this.#c._ensureSize')
Source: @cap.js/widget@latest/cap.min.js:1:8997 (minified function #f)
Mechanism: onunhandledrejection — the promise rejection is unhandled, so the widget silently breaks.
Impact
- 65 occurrences across 54 unique users over 16 days (March 2–18, 2026)
- Affects
/registerand/rmapages where the Cap widget is used - The widget becomes non-functional — users cannot complete the captcha, blocking form submission
Environment
| Browser | Occurrences |
|---|---|
| Mobile Safari | 30 |
| Safari (macOS) | 9 |
| Chrome Mobile iOS | 6 |
| DuckDuckGo Mobile/Desktop | 3 |
| Edge Mobile (iOS) | 2 |
| Firefox iOS | 1 |
| Other iOS WebViews | 2 |
100% WebKit engine. Zero occurrences on Chromium (Android/Windows) or Gecko (Firefox desktop).
iOS versions observed: 18.x, 26.x
Safari versions observed: 18.6, 26.2, 26.3
Analysis
The private class field #c appears to be the WASM module instance. _ensureSize is characteristic of wasm-bindgen generated memory management code. The crash indicates that WASM initialization failed silently — the module instance is null when the solver later attempts to use it.
Possible contributing factors:
- WebKit's known issues with WASM features like
reference-typesandmultivalue(see Following upgrade to wasm-bindgen 0.2.95, Ruffle no longer works on Safari 15 and below wasm-bindgen/wasm-bindgen#4227) - iOS aggressive memory management killing Web Workers / WASM instances under pressure
- No null-guard on the WASM instance before calling
_ensureSize
Expected Behavior
If WASM initialization fails, the widget should:
- Catch the initialization failure
- Fall back to the pure JavaScript SHA-256 solver
- Or at minimum, surface a meaningful error via the
errorevent so the host page can handle it
Current Behavior
The WASM init failure goes undetected. When the solver later tries to use the null WASM instance, it throws an unhandled rejection that the host page cannot catch through normal Cap widget event listeners.
Reproduction
This appears to be intermittent and tied to WebKit's WASM runtime behavior. We see it consistently across multiple iOS versions and all WebKit-based browsers, but not on every page load. It may be related to memory pressure or timing of Web Worker initialization.
Widget Version
Loaded via CDN: https://cdn.jsdelivr.net/npm/@cap.js/widget@latest/cap.min.js
Suggested Fix
Add a null-check on the WASM module instance before calling _ensureSize, and implement automatic fallback to the JS solver when WASM initialization fails.