ReviewOS

also looking at this

craft-native/craft

test(ios): check the event channel, the half nothing was checking

#128
Merged glennmichael123 wants to merge test/ios-event-channel-conformance into main
4 files +280 -0
10 days ago

The half that had no check

ios_conformance_test.zig covers one direction of the iOS page contract: the page calls an action, native answers. Every action the spec handles is served by Zig or explicitly owed, the count only goes down, and a page-callable method with nothing behind it fails the build.

The other direction had nothing. Native talks first, the page hears a CustomEvent on window, and no test in the repo looked at that channel at all — despite it carrying the same two failure modes, in a form that is quieter and therefore likelier to ship.

Zig → spec: the typo guard

ios_events.Event is thirteen string literals transcribed by hand from the spec's sendToWeb call sites. Its own header says as much and calls them "copied from a sendToWeb call" — copied once, then never re-checked.

craftLocationUpate for craftLocationUpdate compiles, dispatches, and reaches nobody. There is no promise to hang and no error to log; the stream simply never starts, which from the page's side looks exactly like a device with nothing to report. The new test reads the arms out of eventName and fails the build for a name the spec does not dispatch.

Page → emitter: the ota* bug, on the other channel

Four events the injected JavaScript subscribes to are dispatched by nothing in this repository. The callback a page hands to each is stored, retained, and never called.

eventsubscriberwhy nothing dispatches it
craftShortcutcraft.shortcuts.onShortcutNo template implements application(_:performActionFor:completionHandler:). setShortcuts installs real home-screen items; tapping one launches the app and stops there.
craftSiriShortcutcraft.siri.onInvokedonateSiriShortcut donates an NSUserActivity typed .<action>; the only onContinueUserActivity is bound to NSUserActivityTypeBrowsingWeb and routes to DeepLinkManager.
craftOTAProgresscraft.ota.onProgressThe OTA surface is unavailable.
craftOTAStatuscraft.ota.onStatusChangeSame.

The OTA pair is the sharpest of the four: when the five unhandled ota* methods were fixed to reject through _unavailable, the two subscription methods sitting beside them were left exactly as they were — because the scan that found the others only knew about actions. Half a surface fixed, and the shape of the check is why the other half stayed broken.

craftShortcut was already known, written into bridge_mobile_shortcuts.zig's header: prose, in the one module that happened to notice, that nothing verified and no other module could see. That is the shape of every deferral reason that had rotted before this migration started checking them. The note now points at the row instead of standing in for it.

All four are recorded in dead_subscriptions with the anti-rot guards the deferral table already uses — a row that stops being subscribed fails the build, a row that grows an emitter fails the build, and a fifth dead subscription fails immediately. None is fixable from Zig: the missing half is an app-delegate callback in the Swift template, and for OTA there is no implementation to report progress from even in principle. Tracked in #127.

What was checked, and how

Seven mutations, each expected to bite one guard, each verified to:

mutationresult
typo in a Zig event nameZigEmitsAnEventTheSpecDoesNotHave
a row deleted from the tablePageSubscribesToAnEventNothingEmits + the floor
a row naming an event nothing subscribes toDeadSubscriptionNoLongerSubscribed
a brand-new dead subscription in the specPageSubscribesToAnEventNothingEmits
a dead subscription gains a sendToWebDeadSubscriptionIsAliveNow
the addEventListener(' needle brokenthe scan floor
the sendToWeb(" needle brokenthe scan floor

Both scans are textual and carry the usual hazard — a needle that stops matching turns a real check into a vacuous one — so both have explicit floors, and the craft prefix the filters rely on is asserted rather than assumed.

zig build test:ios: 15/15. No production behaviour changes; this is a test, two header notes, and one addAnonymousImport.

What this does not claim

Zig's emitters are deliberately not consulted in the page → emitter check. The Zig → spec test already pins ios_events.Event as a subset of what the spec dispatches, so a union with it could not admit a name the spec's set lacks — including it anyway would read as though Zig could rescue a dead subscription, and it cannot.

4 changed files on the files tab, with 0 review threads.

Sign in to comment on this pull request.