Skip to content

Raw WebAssembly ABI reference

This contributor reference describes the internal raw module and its host ABI. For package-manager installation and application examples, use the JavaScript user guide. Source builds and export checks below require a complete repository checkout.

2. Raw target and hosts

The raw crate's claimed compile target is:

wasm32-unknown-unknown

The module imports no host functions and exports its own memory. The promoted direct-host subset works with browser WebAssembly and with Node.js 20 or newer. JavaScript applications should normally use the npm wrapper because it owns allocator pairing and face cleanup.

Install and build the raw module:

rustup target add wasm32-unknown-unknown
cargo build -p fontdone-wasm \
  --target wasm32-unknown-unknown \
  --release --locked

Artifact:

target/wasm32-unknown-unknown/release/fontdone_wasm.wasm

Bzip2, LZW, and color-layer support are enabled by the matching default Cargo features. make optional-feature-contract separately proves the disabled host-facade behaviors against matching pinned FreeType configurations and checks the subpixel-rendering feature routes.

3. Machine-readable raw ABI

The Rust package contains two generated contracts:

  1. abi.json: every #[unsafe(no_mangle)] export plus every public #[repr(C)] record's field order, wasm32 byte offset, width, alignment, pointer interpretation, and ownership class.
  2. fontdone_wasm.d.ts: the directly callable JavaScript host subset used by the maintained raw example and the browser wrapper.

Regenerate and reject drift:

python3 scripts/generate_wasm_contract.py
python3 scripts/generate_wasm_contract.py --check

On wasm32, pointers and usize are 32-bit byte offsets into the instance's little-endian exported memory. Rust u64 and i64 parameters are JavaScript bigint; other promoted scalar parameters are JavaScript number.

4. Maintained integrations

Run the raw Node host path:

make test-wasm-consumer

Its copyable command is:

node fontdone-wasm/examples/node.mjs \
  target/wasm32-unknown-unknown/release/fontdone_wasm.wasm \
  tests/fixtures/input/fonts/DejaVuSans.ttf

The example instantiates the module, checks an invalid open, copies a font into linear memory, opens a face, selects 16 ppem, maps and renders A, copies the bitmap, checks invalid-handle error transport, and releases every allocation and handle.

make npm-package-verify additionally runs wrapper unit tests, inspects the actual npm tarball, installs it into a temporary dependency consumer, reruns the shipped verification scripts outside the checkout, and renders the same glyph through the package import.

5. Supported direct-host subset

Export Contract
fontdone_wasm_malloc(size) Allocate caller-owned linear memory
fontdone_wasm_free(ptr, size) Release exactly that allocation
fontdone_wasm_open_face_handle(ptr, len, face_index, size_pt, out_error) Copy bytes and return a face handle
fontdone_wasm_done_face(handle) Consume the face handle
fontdone_wasm_set_pixel_sizes(handle, width, height) Select integer ppem
fontdone_wasm_get_char_index(handle, codepoint) Map a Unicode value to a glyph
fontdone_wasm_load_glyph(handle, glyph, flags) Replace the current face-owned slot
fontdone_wasm_render_glyph(handle, mode) Replace the slot with a rendered slot
fontdone_wasm_bitmap_{buffer,len,width,rows,pitch}(handle) Borrow bitmap bytes and scalar metadata

Other exports exist to keep the cross-facade parity harness honest. They are inventoried in abi.json, but are not all promoted as ergonomic JavaScript calls. Struct-returning C ABI functions in particular can use target ABI lowering that differs from a direct JavaScript scalar call. Use the promoted subset unless both the schema and generated module signature are handled.

Export presence and parity-route evidence do not mean every function is application-ready. Consult the repository's function adoption map and compatibility snapshot before depending on a broader export.

6. Allocation and pointer rules

fontdone_wasm_malloc uses 8-byte alignment and allocates max(size, 1) bytes. A zero-size request therefore produces a releasable one-byte allocation. Null reports layout or allocation failure.

fontdone_wasm_free:

  • accepts null as a no-op;
  • requires the identical size used for allocation, including zero;
  • consumes a non-null allocation exactly once;
  • does not validate arbitrary or already-freed offsets.

An invalid pointer, double free, or size mismatch violates the ABI precondition and can trap or corrupt that instance. It is not an FT_Error.

For every pointer/length input, the complete byte range must lie in current exported memory for the synchronous call. Reacquire memory.buffer views after any call that can grow memory.

7. Handle and borrowed-output lifecycle

Value Ownership and validity Release
face handle Owned scalar returned on successful open fontdone_wasm_done_face once
input font allocation Caller-owned; bytes are copied by successful open fontdone_wasm_free after open
current glyph slot Face-owned; replaced by the next load/render mutation Released with face
bitmap buffer offset Borrowed from current slot; invalid after slot replacement or face teardown Never free
caller output record Caller-allocated linear memory; fields follow abi.json Caller frees its allocation
returned string/table offsets Borrowed or owned exactly as named by the export schema Follow abi.json and the matching free export

All handles are instance-local. Never pass a handle or memory offset between different WebAssembly.Instance objects.

Every exported record is #[repr(C)]. abi.json is authoritative for field order, wasm32 offsets and widths, record size and alignment, pointer meaning, and ownership. FT_Pos, outline coordinates, bearings, and ordinary advances use signed 26.6 units after scaling. FT_Fixed and matrix coefficients use signed 16.16. Bitmap length is abs(pitch) * rows.

8. Packaging and license

The internal Cargo archive contains source, this README, the generated raw contracts, the Node example, and LICENSE, FTL.TXT, and NOTICE.md. It excludes test fonts, generated fixture outputs, C oracle source, the compiled Wasm binary, and local tooling.

The npm archive contains the ESM wrapper, declarations, prebuilt Wasm binary, ABI inventory, browser and Node examples, verification scripts, and the same legal files. It excludes Rust/C source, fixture fonts, oracle material, and repository tooling.

Inspect the internal raw archive and public npm artifact with:

cargo package -p fontdone-wasm --list
make npm-package-verify