feat(apple): iOS host — pocket-apple core crate, PocketSurfaceView, external-guest mode - #255
Open
NathanWalker wants to merge 1 commit into
Open
feat(apple): iOS host — pocket-apple core crate, PocketSurfaceView, external-guest mode#255NathanWalker wants to merge 1 commit into
NathanWalker wants to merge 1 commit into
Conversation
NathanWalker
marked this pull request as ready for review
August 9, 2026 17:12
…xternal-guest mode
A new engine/apple workspace member packaging modern iOS as a PocketJS
host. The composition mirrors hosts/pocketbook: one pocket_mod::Guest
realm, one pocket_ui_surface::UiSurface, and pocketjs_core::raster driven
incrementally through a DamageTracker, exposed behind a small C ABI.
- engine/apple/src/lib.rs — guest-owning mode: create/load_pak/eval_bundle/
frame/render/hit_test_bounds/destroy, plus an effect channel over the
ui.svc* ops (set_effect_callback drains guest svcSend lines during frame;
post_event queues lines for the guest's next svcPoll).
- engine/apple/src/core_host.rs — external-guest mode: pocket_apple_core_*
owns only the core, pak feed, raster pipeline, and svc queues, for hosts
whose JS engine lives elsewhere (demonstrated with the NativeScript
runtime evaluating the guest bundle in its own context).
- engine/apple/apple/PocketSurfaceView.{h,m} — CADisplayLink capped at
60 Hz, latched touch contacts (a down+up between two ticks still reaches
the guest as one present frame then a release), aspect-fit inverse touch
mapping, damage-gated compositing of the ARGB32 framebuffer.
- engine/apple/build-xcframework.sh — clang-linked dynamic framework per
slice (device arm64 + simulator arm64), no Xcode project.
- pocket-ui-surface additionally mounts hitTestBounds (spec op 42), the
touch-path hit authority the gesture layer prefers over the ink-claiming
hitTest.
- apps/nsengine — reference guest: an effect driver over svcSend, a
per-frame poll pump, a focusable pressable button, and a platform-reach
probe that distinguishes a sidecar realm from an embedding-runtime host.
rquickjs uses its bindgen feature: no pregenerated bindings exist for
aarch64-apple-ios targets. Validation: the render_hero example drives the
ABI end to end — 180 frames of apps/hero/main.tsx at 480x272 density 2
render non-blank and byte-identical across two independent instances.
Build guests with --density matching the surface density (glyphs bake at
build time; density 4 supersamples cleanly on 3x screens).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
NathanWalker
force-pushed
the
feat/apple-host
branch
from
August 9, 2026 18:51
2dcab2e to
535d43a
Compare
This was referenced Aug 9, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A new
engine/appleworkspace member (pocket-apple) plus a UIKit view class, packaging modern iOS as a PocketJS host. The composition mirrorshosts/pocketbook: onepocket_mod::Guestrealm, onepocket_ui_surface::UiSurface, andpocketjs_core::rasterdriven incrementally through aDamageTracker, exposed behind a small C ABI.engine/apple/src/lib.rs— guest-owning mode:pocket_apple_create/load_pak/eval_bundle/frame/render/hit_test_bounds/destroy, plus an effect channel over theui.svc*ops (set_effect_callbackdrains guestsvcSendlines during frame;post_eventqueues lines for the guest's nextsvcPoll).engine/apple/src/core_host.rs— external-guest mode:pocket_apple_core_*owns only the core, pak feed, raster pipeline, and svc queues, for hosts whose JS engine lives elsewhere (demonstrated with the NativeScript runtime: the guest bundle evaluates in the embedding runtime's context andglobalThis.uidelegates each op over the bridge).engine/apple/apple/PocketSurfaceView.{h,m}— CADisplayLink capped at 60 Hz, packed touch words with aspect-fit inverse mapping, damage-gated compositing of the ARGB32 framebuffer intolayer.contents.engine/apple/build-xcframework.sh— clang-linked dynamic framework per slice (device arm64 + simulator arm64), no Xcode project.apps/nsengine— reference guest for the effect channel: an effect driver oversvcSend+ a per-frame poll pump, and a platform-reach probe (typeof UIDevice) that distinguishes a sidecar realm from an embedding-runtime host.rquickjsuses itsbindgenfeature here: no pregenerated bindings exist foraarch64-apple-iostargets.Validation
cargo run -p pocket-apple --example render_hero— 180 frames ofapps/hero/main.tsxat 480×272 density 2: non-blank, byte-identical across two independent instances, incremental damage plans active. Release mode renders 360 frames plus two guest boots in 0.34 s wall.Not included (follow-ups)
tools/iphone2g-profile.tspattern) is the likely next step beforePOCKET_TARGETSregistration.pocket-ui-wgpurendering into aCAMetalLayersurface as a second path behind the same view class.