When no {.ffiCtor.} has stored a library, the FFI thread points `myLib` at a
default-valued fallback so handlers always have something to bind. For an
`object` library that is a usable zero value and callers legitimately depend on
it (tests/unit/test_ffi_handle drives a context that never runs a ctor), but for
a `ref` library the default is `nil`: the user body received a nil ref and
faulted on its first field access. A failing ctor is the common way to get
there, since the C entry point hands back a live context before the ctor body
has run on the FFI thread.
Track whether a ctor actually stored a library and, for `ref` library types
only, reject such requests with a clear error instead of dispatching them. The
check sits in the generated handler rather than the C entry point, so it runs
behind any queued constructor — a host that fires a call without awaiting the
create callback still succeeds, as before.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ULz7Md52AF6PmqZeCmh8b7
When no {.ffiCtor.} has stored a library, the FFI thread points `myLib` at a
default-valued fallback so handlers always have something to bind, and
`myLibOwned` is what distinguishes that fallback from a real one. For an
`object` library the fallback is a usable zero value and callers legitimately
depend on it, but for a `ref` library it is `nil`: the user body received a nil
ref and faulted on its first field access. A failing ctor is the common way to
get there, since the C entry point hands back a live context before the ctor
body has run on the FFI thread.
Guard on `myLibOwned` for `ref` library types only. The check sits in the
generated handler rather than the C entry point, so it runs behind any queued
constructor — a host that fires a call without awaiting the create callback
still succeeds, as before.
Backport of the same fix on master, where the state had to be added rather than
reused.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ULz7Md52AF6PmqZeCmh8b7