Skip to content

feat!: rebuild WeaveFFI on C ABI 4, one model, and library mode - #55

Merged
owenthcarey merged 2 commits into
mainfrom
weaveffi-engine-v2
Oct 9, 2026
Merged

owenthcarey merged 2 commits into
mainfrom
weaveffi-engine-v2

Conversation

@owenthcarey

Copy link
Copy Markdown
Contributor

Summary

Engine v2: a pre-1.0 overhaul with no compatibility shims. Old code paths are deleted, not kept behind flags.

  • Four crates. The published crates are weaveffi (facade plus the runtime as weaveffi::abi), weaveffi-macros, weaveffi-model, and weaveffi-cli (now a library plus the binary, absorbing the generators). weaveffi-abi and weaveffi-gen are removed.
  • One validated model, schema 0.11.0.
    • validate(&Api, &Identity) builds a single Model once per run, and ResolvedApi is gone.
    • Names are global: types, free functions, and error codes are unique across the API.
    • Qualified type references are removed, and Ty::Prim wraps a single primitive enum.
    • Diagnostics point at the right span.
  • C ABI revision 4.
    • Load-time checks: per-declaration contract tables replace per-module checksums, so adding a function no longer breaks older bindings.
    • Callbacks: vtables gain a {size, flags, free} header. Callback methods can return any type (allocated with {p}_alloc), throw typed domain errors with payloads, and be optional parameters.
    • Soundness fixes: safe code can no longer adopt a raw object token. Thunks adopt every input before reporting a failure. Duplicate map keys are rejected. Iterators never hold their lock across next(). The foreign-error unwinding machinery is removed.
    • Executor: a thread pool plus a tokio feature replace one thread per async call.
  • Producer macro and library mode.
    • The macro runs the shared validator with real spans, honors item #[cfg], resolves type aliases, and emits much smaller thunks.
    • It embeds the API as metadata in the built library. generate, diff, validate, and extract build the crate and read that metadata, replacing the Rust source parser.
    • Also new: weaveffi dev and a Project library API.
  • Generators.
    • The backend trait is slimmed, and the inert capability gate and hash cache are removed.
    • All 11 targets implement ABI 4, with one codec per composite type, a documented trap policy, and escaping for reserved member names.
    • Python drops its .pyi, Kotlin uses unsigned types, Node.js guards against callback deadlocks, and Dart loads natives relative to the package.
  • Build and packaging.
    • weaveffi build cross-compiles per platform: @rpath install names, iOS static libraries, Android NDK detection, deployment targets, and prebuilt Node.js and JNI glue.
    • weaveffi package writes installable artifacts: wheels, npm tarballs, gems, NuGet packages, an XCFramework zip with its checksum, and C/C++ tarballs.
  • Samples, tests, CI, docs.
    • Three samples: calculator; codec, with shared vectors; and a feature-complete kvstore.
    • Consumers in all 11 languages give 34 conformance lanes.
    • The snapshot corpus is about a third smaller.
    • Missing tools fail CI. The fuzz, bench, and release workflows are fixed, and there's a new package-install smoke job.
    • Every documentation page is updated, including a normative ABI 4 contract and migration notes in docs/src/stability.md.

Test plan

  • Added or updated tests where appropriate (runtime, macro trybuild cases, model, CLI, per-target unit tests)
  • Ran cargo insta test --workspace --check (passes), plus cargo clippy --workspace --all-targets -D warnings, cargo test -p weaveffi --features tokio, and the strict rustdoc build
  • Reviewed and accepted intentional snapshot changes
  • Updated documentation for user-facing changes
  • PR title follows Conventional Commits
  • CI=true bash scripts/check-fixtures.sh for all 11 targets (with mypy): passes
  • bash conformance/run.sh: 34 passed, 0 failed, leak counters at zero
  • bash scripts/package-smoke.sh: the packaged Python wheel, npm tarball, and Swift XCFramework each install and call add(2, 3)

Notes for reviewers

  • Breaking everywhere, on purpose. Schema 0.11.0, ABI revision 4, and the CLI and config changes (crate input input = ".", a name override key, [build]/[package] dist; --force, --lenient, hooks, and [global] removed) are all covered in docs/src/stability.md.
  • Generated-code churn. Snapshots changed for every target. The C header (snapshot_c) and docs/src/reference/abi.md are the best places to start reviewing.
  • Known limitations (documented on the generator pages and the roadmap):
    • Dart: a value-returning callback invoked from a non-isolate thread aborts the process, because plain dart:ffi can't route it.
    • Node.js: a callback from another thread fails with -4 if the JS thread is blocked in one synchronous call for more than 1 s. This prevents a deadlock, but it also catches legitimately long synchronous calls.
    • C-style enums and interfaces must be declared in the module tree that uses them; the compiler gives a clear error otherwise.
    • Windows paths are compile-checked only. The packaged Kotlin Gradle project hasn't been built with Gradle.
  • Not addressed: SECURITY.md still has its placeholder contact address.

…mode

Engine v2 overhaul. No compatibility shims: old code paths are removed.

Crates
- Four published crates: `weaveffi` (facade plus the runtime as
  `weaveffi::abi`), `weaveffi-macros`, `weaveffi-model`, and `weaveffi-cli`
  (library plus binary, absorbing the generators). `weaveffi-abi` and
  `weaveffi-gen` are gone.

Model and schema 0.11.0
- One `Model` built once by `validate(&Api, &Identity)`; `ResolvedApi` is
  deleted and generators never see the document IR.
- Global names: types, free functions, and error codes are unique across
  the API; qualified type references are removed; `Ty::Prim` wraps one
  primitive enum. Better diagnostics (scoped spans, unsupported primitives).

C ABI revision 4
- Per-declaration contract tables replace per-module checksums, so adding a
  declaration no longer breaks older bindings.
- Callback vtables carry a `{size, flags, free}` header; callback methods
  return every family (consumer runs allocated with `{p}_alloc`), may
  `throw` typed domain errors with payloads, and callback parameters may be
  optional.
- Soundness: token-adopting decoders are `unsafe`, thunks adopt every input
  before failing, duplicate map keys are rejected, iterators never hold a
  lock across `next()`, and the foreign-error unwinding machinery is gone.
- A pooled default executor and a `tokio` feature replace thread-per-call;
  wasm32 no longer spins on a stalled future.

Producer macro and library mode
- The macro runs the shared validator with real spans, honors item `#[cfg]`,
  resolves type aliases, and emits much smaller thunks through runtime
  helpers.
- The macro embeds the API as metadata in the built library; `generate`,
  `diff`, `validate`, and `extract` build the crate and read it, replacing
  the Rust source parser. New `weaveffi dev` and a `Project` library API.

Generators
- A slim backend trait; the capability gate and hash cache are removed.
- All eleven targets implement ABI 4 with one codec per composite type,
  documented trap policy, and reserved-member-name escaping. Python drops
  its `.pyi`; Kotlin uses unsigned types; Node.js guards against callback
  deadlocks; Dart loads natives relative to the package.

Build and packaging
- New `weaveffi build` cross-compiles per platform with `@rpath` install
  names, iOS static libraries, NDK detection, deployment targets, and
  prebuilt Node.js and JNI glue. `weaveffi package` writes installable
  artifacts: wheels, npm tarballs, gems, NuGet packages, an XCFramework zip
  with its checksum, and C/C++ tarballs.
- Config cleanup: one `name` override key, `[build]`, `[package] dist`;
  hooks, `[global]`, and `--force` are removed.

Samples, tests, CI, docs
- Three samples (calculator, codec with shared vectors, feature-complete
  kvstore) with consumers in all eleven languages; 34 conformance lanes.
- Snapshot corpus cut by about a third; missing tools fail CI; fuzz, bench,
  and release workflows fixed; a package-install smoke job.
- Every documentation page updated, including a normative ABI 4 contract,
  migration notes, roadmap, and comparison.
- Define _GNU_SOURCE on Linux in the Node.js addon so libuv's headers
  compile under a strict -std=c11.
- Find the Swift module beside its C shim instead of relying on ls order,
  which differs by locale.
- Check that Swift listeners notify on the subscribing thread with
  pthread_equal instead of Thread.isMainThread, which is false for
  top-level async code on Linux.
- Match CLI error messages with miette's line wrapping undone.
@owenthcarey owenthcarey changed the title feat!: rebuild WeaveFFI on C ABI 4, one validated model, and library mode feat!: rebuild WeaveFFI on C ABI 4, one model, and library mode Oct 9, 2026
@owenthcarey
owenthcarey merged commit 9cf51a1 into main Oct 9, 2026
48 checks passed
@owenthcarey
owenthcarey deleted the weaveffi-engine-v2 branch October 9, 2026 00:07
@owenthcarey owenthcarey mentioned this pull request Oct 9, 2026
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