Our workarounds, and what each fix removes
What GWonMac does to the client today, why each workaround exists, what it costs us per client build, and exactly what we delete after each upstream fix.
This page is everything our host does to the client today: why each workaround exists, what it costs per client build, and exactly what each upstream fix lets us delete.
Ground rules
The downloaded artifact from ArenaNet stays canonical: we never change it on disk and never redistribute it. When the client is broken on this platform, the host derives a separate patched copy in memory, verifying the input by hash and the output by hash. If any check fails, the host serves the untouched official module — so a new client build degrades to "the feature is missing", never to a broken client.
certified, template-only, or uncertified, decided by one
component. A build we don't recognise runs as the plain official client, with
every workaround switched off.Workaround 1 — the template file bridge
Removed by: UR-01, UR-02, UR-03, UR-04, and the probe part of
UR-06.
The host appends five forwarder functions to the module and repoints the call sites of the four stub routines at them. Each forwarder calls the host through a marker value on a syscall import the module already has — no real call can produce that value. The host then does the file work in the Emscripten file system: create a directory tree, list a directory, derive a relative name, delete a file, and test for a file.
Cost per client build. The five routines have to be found again, with proof that their callers didn't change. This part is automated: a machine locates each routine by body bytes, signature, and caller set, then hashes the complete body of every caller the transform touches. If any of that changed, the transform refuses to run.
Deleted after the fix: all of it — five forwarders, five marker values, the host file-system bridge, and the whole certification table for this transform.
Workaround 2 — the entry name without an extension
Removed by: UR-05.
Our bridge returns each entry name without its extension, so the client
calls Path::RemoveExtension on a name where the off-by-one can't fire.
Deleted after the fix: nothing on day one — removing an absent extension does nothing, so the workaround stays correct. It goes together with workaround 1.
Workaround 3 — the double-click flag
Removed by: UR-07.
The host appends one exported mutable i32 global to the module and splices
three instructions into the mousedown callback. They store the global's value
into the record word the client already carries to FrMouse, and the host
writes the Chromium click count into that global on every trusted press. The
transform adds no function and moves no index or table entry.
Cost per client build. The exact body hash of the mousedown callback, plus two byte offsets. A machine re-derives this; a human confirms it.
Deleted after the fix: the transform, its table, and the renderer code that writes the global.
An earlier workaround for the same defect synthesised a pair of touch taps. It delivered four clicks instead of two, so we deleted it — UR-07 has the measurement.
Workaround 4 — the native cursor
Removed by: nothing today. UR-12 would remove it.
The host adds a small companion component to the module. It reads the client's cursor state — the active art pointer, the texture chain, and the colour buffer — and publishes a 32 by 32 image into a region the host allocated; the host sets that image as the native cursor. The component imports no function and writes nothing the game owns. Every read goes through bounds-checked pointer chases, and every chase can fail safely.
Cost per client build. Our most expensive workaround: twelve memory addresses and two function indices. No machine can prove a memory address, so a human measures them on each build. Until that's done, the player gets the plain system pointer.
Deleted after UR-12: the twelve cursor addresses and the component's
read path.
Workaround 5 — the pointer replay
Removed by: UR-09.
After a click that produced no cursor event, the host dispatches one synthetic
out-and-back mousemove pair at the last click position; the physical pointer
doesn't move. It retries every 150 ms for at most 2,500 ms. The replay can't
start a click and can't leave the pointer at a new position. The host also
synthesises pointer moves while the player rotates the camera, because the
client steers from absolute coordinates — that path can't originate a click
either.
Deleted after the fix: the whole retry path.
Workaround 6 — the heap warning and safe reload
Removed by: UR-10.
The host monitors the effective heap cap, warns while the player still has room to return somewhere safe, then offers a user-controlled reload. WASM memory capacity cannot shrink inside one process; reload starts a new heap.
Deleted after the fix: emergency reload guidance can go once ArenaNet's ownership policy is bounded and long content-diverse sessions remain well below the effective cap. The general crash-recovery path remains.
Research profile — paired 4 GB JS/WASM transform
Reduced or removed by: UR-10.
An off-by-default developer profile raises build 38797's WASM maximum to 4 GiB minus one page and transforms the matching generated JavaScript to normalize wasm32 pointers above 2 GiB. It is a paired transform: changing only the WASM maximum would hand negative pointer values to JavaScript and is refused.
The exact pair has passed ArenaNet-allocator qualification above 3 GiB and a live Electron string-glue test at 2,625 MiB. It remains a research profile, not a default player setting. All five variants the production chain can emit are hash-pinned. Before an experimental release it still needs packaged high-address gameplay coverage, system-memory testing, and explicit opt-in copy. Diagnostics record the effective mode and cap.
Cost per client build. Both official artifact hashes, every accepted predecessor hash, both derived hashes, and the generated-glue pointer audit. Any ArenaNet update disables the profile until it is re-certified.
Deleted after the fix: the whole transform and its certification table. A source-built 4 GB client already has the compiler's matching unsigned-pointer support; a bounded cache/lifecycle fix removes the reason for our emergency headroom.
What our workarounds never do
- They never change the artifact on disk.
- They never redistribute game files.
- They never send credentials, account identifiers, or game traffic anywhere.
- They never automate gameplay. The host does not choose a target, move a character, use a skill, or send chat.
- They never run on a build that we have not certified.
The bottom line
Six of the twelve requests exist because of file handling; one exists because
of a single unwritten byte. Fix UR-01 to UR-07 and three production
workarounds disappear outright. A source-level UR-10 correction also avoids
turning the research-only 4 GB profile into another permanent certification
burden.