Files
scriptc/tests/library-mode/contract/profile.json
Chris Tate 81b70b0ee6 feat: add host-callback channels to library mode (#148)
* feat: add host-callback channels to library mode

- the profile's `callbacks` array declares named channels and
  `abi.callback_register_symbol` names the one registration entry point:
  `int32_t <sym>(const char *name, void (*fn)(void), void *ctx)` — 0 on
  success, -1 for an unknown or NULL name, latest registration wins, a
  NULL fn clears, registrations persist across init/reset. The stored
  pointer's typed shape is the channel's with the opaque context first,
  the panic sink's layout
- channel signatures ride the existing marshalling classes: params are
  f64/bool/string/bytes plus the u8/u32/i32 plumbing classes (outbound
  plumbing keeps JS's ToUint32/ToInt32, the executable FFI rule);
  returns are scalar only (f64/bool/u8/u32/i32/void — a buffer return
  needs an ownership contract the mode does not define). string/bytes
  parameters arrive as (ptr, len) pairs borrowed for the call's duration
- compiled code reaches a channel as a signature-only ambient function
  declaration whose direct calls deliver synchronously on the calling
  thread; the recognition rides the FFI import machinery under a library
  flavor: SC4024 refuses a call the channels cannot serve (undeclared
  name or off-class signature), unused channels are legal capacity, and
  callback-free profiles keep the ambient ReferenceError semantics
- calling an unregistered channel is the SC4025 runtime trap: a detected
  trap through the library funnel, so the structured sink message names
  the channel in its text and the entry the host called in its symbol
  field, and profile teachings/remediations overlay it like the rest of
  the runtime family
- registration slots are per copy of the runtime state, the sink's story:
  per-archive under abi.localize_runtime (the register symbol joins the
  localization keep-list), per-thread instance under
  abi.instance_per_thread. The host callback must not reenter any library
  entry or unwind across library frames
- both emissions produce identical behavior by construction: the slot
  store/fetch lives in scr_library.c (scr_library_cb_set/_require/_ctx),
  the generated TU emits the registration dispatch and typed indirect
  calls, and the trap text is assembled once at export resolution
- callback-free profiles emit byte-identical program TUs and serialized
  IR, and executable builds are byte-identical end to end
- conformance: the CB suite (tests/harness/library-callbacks.test.ts)
  covers the acceptance stream, unregistered and pre-registration traps,
  symbol exactness, teaching overlays, SC4024 refusals, capacity and
  callback-free postures, the localized+thread-instanced composition
  probe, and ASan reruns; profile-shape refusals join
  library-profile.test.ts

* fix: preserve callback binding identity

* fix: harden library callback contracts

* fix: recognize project callback declarations

* fix: enforce host callback declarations
2026-08-13 21:44:55 -05:00

36 lines
1.2 KiB
JSON

{
"profile_format": 1,
"name": "conformance-contract",
"entry": "lib.ts",
"emission": "llvm",
"abi": {
"prefix": "kc_",
"init_symbol": "kc_init",
"sink_register_symbol": "kc_set_panic_sink",
"collect_symbol": null,
"result_reset_symbol": null,
"callback_register_symbol": "kc_set_callback"
},
"callbacks": [
{ "name": "contractNotice", "params": ["string"], "returns": "void" }
],
"exports": [
{ "export": "boot", "symbol": "kc_boot", "params": [], "returns": "void" },
{ "export": "send", "symbol": "kc_send", "params": ["f64", "f64"], "returns": "void" },
{ "export": "commandMsg", "symbol": "kc_command_msg", "params": ["string"], "returns": "void" },
{ "export": "title", "symbol": "kc_title", "params": [], "returns": "string" },
{ "export": "helperProbe", "symbol": "kc_helper_probe", "params": ["f64"], "returns": "string" },
{ "export": "boom", "symbol": "kc_boom", "params": ["f64"], "returns": "f64" }
],
"sidecar": {
"path": "app.contract.json",
"wire_version": 3,
"abi_version": 7,
"snapshot_format": 2,
"build_id_symbol": "kc_build_id",
"abi_version_symbol": "kc_abi_version",
"model": "Model",
"msg": "Msg"
}
}