Skip to content

Add initial C FFI bindings and error inspection - #5618

Merged
jedel1043 merged 12 commits into
boa-dev:mainfrom
rrogerc:ffi-base
Nov 9, 2026
Merged

jedel1043 merged 12 commits into
boa-dev:mainfrom
rrogerc:ffi-base

Conversation

@rrogerc

@rrogerc rrogerc commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

This Pull Request is related to #332, adding the initial Diplomat-based boa_ffi crate modeled on temporal_capi and the JsError C API. eval, try_native normalization, and enabling engine features (like ffi/wasm does) will follow in the next PR.

It changes the following:

  • Added ffi/boa_ffi and tools/diplomat-gen (publish = false) with generated C headers in ffi/boa_ffi/bindings/c/. Exported C functions use a boa_ prefix, like temporal_capi.
  • Implemented BoaContext, minimal JsValue handles for thrown values, context-free construction of Native and Opaque errors, and inspection of all three JsError variants (Native, Opaque, Engine).
  • Documented handle ownership rules in ffi/boa_ffi/README.md.
  • Included Rust tests, C11 tests in ffi/boa_ffi/tests/c/ (run by run.sh), and a Test FFI CI job on macOS and Linux that checks header freshness and runs the C tests.

boa_engine is untouched. Most of the diff comes from generated C headers, Cargo.lock, docs, and tests, while the bridge itself in ffi/boa_ffi/src/lib.rs is ~250 lines.

@github-actions github-actions Bot added C-Dependencies Pull requests that update a dependency file C-Documentation update documentation C-Tests Issues and PRs related to the tests. C-FFI Foreign Function Interface, to be able to use Boa from a different language, such as C C-Actions Pull requests that update Github Actions code Waiting On Review Waiting on reviews from the maintainers labels Oct 26, 2026
@github-actions github-actions Bot added this to the v0.23 milestone Oct 26, 2026
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Test262 conformance changes

Test result main count PR count difference
Total 53,578 53,578 0
Passed 51,450 51,450 0
Ignored 1,648 1,648 0
Failed 480 480 0
Panics 0 0 0
Conformance 96.03% 96.03% 0.00%

Tested main commit: 990c9836760a4ecf0ebc78b106901fda939d1cc0
Tested PR commit: 520481e1fed277ecbe2f70db26a837b565a4dbb6
Compare commits: 990c983...520481e

@codecov

codecov Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.23944% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.16%. Comparing base (6ddc2b4) to head (520481e).
⚠️ Report is 1085 commits behind head on main.

Files with missing lines Patch % Lines
tools/diplomat-gen/src/main.rs 0.00% 13 Missing ⚠️
ffi/boa_ffi/src/lib.rs 89.65% 6 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #5618       +/-   ##
===========================================
+ Coverage   47.24%   63.16%   +15.92%     
===========================================
  Files         476      538       +62     
  Lines       46892    60609    +13717     
===========================================
+ Hits        22154    38286    +16132     
+ Misses      24738    22323     -2415     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rrogerc
rrogerc marked this pull request as ready for review November 1, 2026 16:33
@rrogerc
rrogerc requested a review from a team as a code owner November 1, 2026 16:33

@jedel1043 jedel1043 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation-wise looks great! I especially like how you represented JsError through the FFI without losing many of its semantics.

I have a couple of comments but nothing too critical.

Comment thread .github/workflows/rust.yml Outdated
Comment on lines +265 to +274
- name: Check generated C headers
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
cargo run --locked --profile ci -p diplomat-gen
git status --short --untracked-files=all -- ffi/boa_ffi/c/generated/
test -z "$(git status --porcelain --untracked-files=all -- ffi/boa_ffi/c/generated/)"

- name: Test C bindings
if: ${{ matrix.os != 'windows-latest' }}
run: ./ffi/boa_ffi/c/tests/run.sh --ci

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these only work on Linux and MacOS, it might be worth extracting this into its own job and having a separate matrix for them instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I've moved both steps into their own Test FFI job with a separate matrix (same runners as the main test job, minus Windows). The header check used to only run on ubuntu-latest, now it runs on all three.

Comment thread tools/diplomat-gen/src/main.rs Outdated

fn main() -> io::Result<()> {
let crate_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../ffi/boa_ffi");
let headers = crate_dir.join("c/generated");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let headers = crate_dir.join("c/generated");
let headers = crate_dir.join("bindings/c");

Let's use the same nomenclature that we use on temporal_rs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, changed it! I've also moved the C tests from c/tests to tests/c and copied temporal_capi's .gitattributes (marks bindings/ as generated) so the layout matches temporal_rs now.

Comment thread Cargo.toml Outdated
Comment on lines +61 to +63
diplomat = "=0.15.0"
diplomat-runtime = "=0.15.1"
diplomat-tool = "=0.15.0"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the same versioning that we use on temporal_rs:

diplomat-tool = { version = "0.16.0", default-features = false }
diplomat-runtime = { version = ">= 0.15.2, < 0.17.0", default-features = false }
diplomat = { version = "0.16.0", default-features = false }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to those! Cargo.lock resolves them to 0.16.1 and the regenerated headers came out identical. I also merged main in, since the auto-merged lockfile still had askama_parser pointing at winnow 1.0.4 after main moved to 1.0.5 and that broke --locked. The only extra change in the merge commit is that line.

Match temporal_capi: `#[diplomat::abi_rename = "boa_{0}"]` prefixes every
exported C function to avoid symbol clashes with other libraries, and the
crate now forbids `unwrap`, `expect` and indexing outside tests, because a
panic in an `extern "C"` function aborts the host program. Also drop the
stale Diplomat version from a lint reason.

@jedel1043 jedel1043 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for working on this! Looks great!

@jedel1043
jedel1043 enabled auto-merge November 9, 2026 03:02
@jedel1043
jedel1043 added this pull request to the merge queue Nov 9, 2026
Merged via the queue into boa-dev:main with commit bfaa15a Nov 9, 2026
25 checks passed
@github-actions github-actions Bot removed the Waiting On Review Waiting on reviews from the maintainers label Nov 9, 2026
@rrogerc
rrogerc deleted the ffi-base branch November 9, 2026 04:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-Actions Pull requests that update Github Actions code C-Dependencies Pull requests that update a dependency file C-Documentation update documentation C-FFI Foreign Function Interface, to be able to use Boa from a different language, such as C C-Tests Issues and PRs related to the tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants