Skip to content

feat(native): expose a minimal macOS WebView host - #107

Open
pranavp311 wants to merge 9 commits into
justrach:release/v0.2.53from
pranavp311:feat/native-macos-mvp
Open

feat(native): expose a minimal macOS WebView host#107
pranavp311 wants to merge 9 commits into
justrach:release/v0.2.53from
pranavp311:feat/native-macos-mvp

Conversation

@pranavp311

Copy link
Copy Markdown

Supersedes #100 with the first deliberately small native macOS slice.

What changed

  • Added mer.native.runLoopback, a minimal public API that presents an already-bound loopback server in the system NSWindow + WKWebView.
  • Reused that API from the existing desktop example, fixed its Zig 0.16 readiness calls, and initialized the framework I/O runtime before the server thread starts.
  • Kept the URL internal and loopback-only, validated window inputs, enforced AppKit's main-thread contract, and made closing the final window return from the event loop.
  • Added macOS compile/link and bundle validation to release-targeted CI and tagged-release gating.
  • Kept every commit below 400 changed lines; the largest is 228 lines. The whole PR is 499 changed lines across 8 files.

Why

  • Problem/failure mode: The existing desktop example duplicated all Objective-C host code, no longer compiled against the current ServerReady API, and could use the server before runtime.init. The previous native proposal grew to hundreds of files and mixed the shell with bridges, updaters, signing, packages, and unrelated framework work.
  • Reason for this approach: This promotes the already-proven macOS spike into one reusable framework seam while leaving HTTP routing and server behavior unchanged. It is the smallest useful foundation for downstream apps such as Codegraff.
  • Constraints and trade-offs: Apps still own server startup/shutdown and must link AppKit, WebKit, Foundation, and libc. The repository's example server remains process-lifetime because Server.listen has no graceful stop API yet.
  • Rejected alternatives: This does not salvage or split the old mega-PR. Manifest packaging, JavaScript-to-Zig commands, permissions, signing/notarization, updates, and other platforms are intentionally deferred to separately approved PRs.

Validation

  • zig build test --summary all — 25 passed, 2 skipped
  • zig build prod
  • zig build cli
  • zig build desktop -Doptimize=ReleaseSmall
  • plutil -lint zig-out/MerApp.app/Contents/Info.plist
  • targeted zig fmt --check
  • git diff --check
  • independent adversarial review loop completed with no actionable findings

pranavp311 and others added 9 commits August 4, 2026 15:10
Extract the system-WebView window primitive behind mer.native so downstream apps can present an existing loopback server without adopting the larger bridge, updater, or packaging roadmap. The host accepts only validated loopback inputs and terminates after the last window closes.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Replace the duplicated Objective-C shell in the desktop example with mer.native and repair its Zig 0.16 ServerReady calls. The example now demonstrates the consumer-facing seam while preserving loopback-only server startup and process-lifetime ownership.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Document the reusable loopback host and its explicit non-goals so bridge, packaging, signing, and cross-platform work stay out of this restart. Also make the desktop target regenerate routes before compiling to keep the example build reproducible.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Reject invalid UTF-8 and off-main-thread launches before entering AppKit, and release owned Objective-C objects after the event loop exits. Document the contract and add a release-targeted macOS CI build so the framework's only native path is compiled and linked on its host platform.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Convert the generated URL bytes to NSString before calling NSURL so WKWebView never receives a raw pointer as an Objective-C object. Extend native verification to release branches and tag releases, including framework tests and plist validation on macOS.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Stop the AppKit event loop when the final window closes instead of entering NSApplication's process-termination path, preserving the public return contract. Match the activation-policy ABI and harden dynamic delegate registration against class collisions and failed setup.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Objective-C class names are process-global, so verify that any reused delegate class resolves to this host's exact callback implementation. Retry lookup after an allocation race and reject collisions rather than invoking foreign lifecycle code.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Initialize merjs's global std.Io backend before spawning the desktop server thread and wire the runtime module into the target. Without this, the app could compile successfully but fail immediately when Server.listen used uninitialized I/O state.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Preserve the existing desktop guide structure while documenting only the new public host seam and current non-goals. This keeps the replacement PR within the repository's default 500-line review budget without weakening its runtime contract.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
@pranavp311

Copy link
Copy Markdown
Author

Hosted validation update:\n\n- Fork macOS job passed framework tests, ReleaseSmall desktop compile/link, executable check, and plutil -lint: https://github.com/pranavp311/merjs/actions/runs/30888094961\n- The inherited Ubuntu job failed in Zig 0.16 stdlib Io/Uring.zig; the exact base SHA already has the same upstream CI failure: https://github.com/justrach/merjs/actions/runs/24634534013\n- Upstream PR Actions are currently awaiting maintainer approval: https://github.com/justrach/merjs/actions/runs/30888112361\n\nNo core Linux/runtime changes are included here; that baseline CI failure should remain separate from this 8-file native PR.

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