Skip to content

fix(apple): keep a view's service alive while the view is used - #652

Merged
andiwand merged 1 commit into
mainfrom
fix/apple-html-view-owner
Aug 2, 2026
Merged

fix(apple): keep a view's service alive while the view is used#652
andiwand merged 1 commit into
mainfrom
fix/apple-html-view-owner

Conversation

@andiwand

@andiwand andiwand commented Aug 2, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

odr::HtmlView looks self-sufficient — it holds a shared_ptr — but the impl behind it, internal::html::HtmlView, keeps only a bare abstract::HtmlService * and forwards config() and write_html() through it. A view handed out by -[ODRHtmlService views] therefore dangles as soon as the service goes, and

let view = try XCTUnwrap(try service().views.first)   // service is a temporary
let html = try view.writeHtml(resources: &resources)  // 💥 SIGSEGV

segfaulted on both macOS and the simulator. That is ordinary Swift, not a contrived lifetime — the same call with the service in a local passes, which is why testRendersHtml was green next to it.

ODRHtmlView now carries its ODRHtmlService the way ODRElement already carries its ODRDocument. The other two bindings solved this when they bound views: JNI passes an owner into the NativeResource constructor, python pins the service onto the view as _service with the comment "translate(...).list_views()[0] must not dangle". Apple was the one that missed it.

Why this is urgent

apple is the only red workflow on main, and release.yml has needs: [version, apple] — a red test in the called workflow skips the release job, so no release can be cut until this lands.

testRenderedHtmlCarriesItsOwnStyles has been failing since it landed in #648: it was cancelled on that commit, first actually ran on #649, and failed. It has never been green on main. It is the crash, not a flake.

Verification

Built both macOS slices locally, assembled the xcframework, ran the suite via xcodebuild test:

  • with the fix — all 19 tests pass, including the previously-crashing testRenderedHtmlCarriesItsOwnStyles
  • with owner:nil spliced back in — testRenderedHtmlCarriesItsOwnStyles and the new testViewsKeepTheirServiceAlive both segfault, while testRendersHtml / testBringOfflineWritesFiles (which hold the service in a local) still pass

So the new test is load-bearing rather than decorative.

Also

apple/AGENTS.md said odr::Element was the exception to "a wrapper holding a shared_ptr is self-sufficient". It isn't any more, and that sentence is what makes this class of bug easy to reintroduce — updated, with the trap called out.

`odr::HtmlView` looks self-sufficient - it holds a `shared_ptr` - but the impl
behind it, `internal::html::HtmlView`, keeps only a bare `abstract::HtmlService *`
and forwards `config()` and `write_html()` through it. A view handed out by
`-[ODRHtmlService views]` therefore dangles as soon as the service goes, and
`try service().views.first` - a temporary service, which is how anyone would
write it - segfaulted on both macOS and the simulator.

`ODRHtmlView` now carries its `ODRHtmlService` the way `ODRElement` carries its
`ODRDocument`. The other two bindings already do this: JNI passes an `owner` to
the `NativeResource` constructor, python pins the service onto the view as
`_service`.

`testRenderedHtmlCarriesItsOwnStyles` has been red on main since it landed - it
is the crash, not a flake. `testViewsKeepTheirServiceAlive` states the invariant
directly, next to the element suite's equivalent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSePnR4Jcj5cq3H1D11xcd
@andiwand
andiwand merged commit 09bf14e into main Aug 2, 2026
45 checks passed
@andiwand
andiwand deleted the fix/apple-html-view-owner branch August 2, 2026 12:43
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