# Rust Calls from JavaScript

## Background

* [UniFFI general documentation](https://mozilla.github.io/uniffi-rs/latest/internals/rust_calls.html).
* [Threading concerns](../developing-rust-components/threading.md)
* [Lifting and Lowering](./lifting-and-lowering.md)

## Sync Rust calls

* The generated JavaScript code calls [UniffiScaffolding.callSync()](https://searchfox.org/firefox-main/source/dom/chrome-webidl/UniFFI.webidl).
  * The first argument to `callSync()` is a numeric identifier for the FFI call, known to both the JavaScript and C++ code generators.
  * That is followed by lowered argument from the JavaScript call.
* The generated C++ code then performs the second phase of argument lowering and makes the Rust call.
  This code is statically linked to the Rust code, so it can make this call directly.
* The C++ code then returns a `UniFFIScaffoldingCallResult` to the JavaScript code, which is essentially a `UniffiCallStatus` plus a return value.
* The generated JavaScript code inspects the `UniFFIScaffoldingCallResult` and either returns a value or raises an exception.

## Wrapped-async calls

* `UniffiScaffolding.callAsyncWrapper` is called instead of `UniffiScaffolding.callSync`.
* The generated C++ code schedules the Rust call in a worker thread.
* The generated C++ code returns a `Promise` to JavaScript
* The generated C++ code resolves that promise using the returned Rust value.
* The C++ code resolves the promise with a `UniFFIScaffoldingCallResult` value.

## Async calls

* Use `UniffiScaffolding.callAsync()` is used to make the Rust call
* The generated C++ code returns a `Promise` to JavaScript
* The generated C++ code implements the future callback and polls the Rust function as described in the [UniFFI async overview](https://mozilla.github.io/uniffi-rs/latest/internals/async-overview.html).
* Once the Rust future is complete, the C++ code resolves the JavaScript promise with the result
* The C++ code resolves the promise with a `UniFFIScaffoldingCallResult` value.

Note: The generated code does not handle cancellation or the `foreign_future_dropped_callback`.
In JavaScript once an async task has started running, there's no way to force it to stop.
Other JavaScript bindings have handled this by passing an [Abort Controller](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) as an extra argument to async functions, maybe we could also do this in the future.
