DioxusLabs / DioxusLabs/taffy

Wasm support (non-javascript environments)

Open
#658 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
3.6k
Forks
222
Avg merge
10h 41m
Merged PRs (30d)
40

Description

Note: For Javascript (in web or node/deno), there's https://github.com/DioxusLabs/taffy/issues/241 . This issue is about wasm on non-js environments like wasmtime/wasmer and requires a completely different approach (as wasm_bindgen is not available here).

## What problem does this solve or what need does it fill?

This issue is primarily about exposing host's (eg: game, text editor) taffy-based UI styling to wasm guests (eg: game mods, text editor extensions). The guests will use taffy's C API (dynamically linked) and the host will provide those bindings when instantiating the guests by wrapping normal taffy's API.

The quirk with wasm guests is that:
1. guests don't have access to host memory. So, they can't just dereference a pointer to anything in host memory.
2. core wasm functions can only use primitives (int/float) as inputs/outputs (i.e. cannot return a composite struct like point or rect). pointers are just integers in wasm.

A C FFI API that uses the "in-out" parameters (eg: win32 API) instead of returning composite structs or receiving host pointers as arguments will greatly simplify wasm bindings in this case.
```rust
struct taffy_node; // some opaque type to represent host-side taffy nodes. A pointer to it could simply be the node-id from taffy tree on host side.

// and finally when we need to deal with concrete POD (plain old data) c struct types, we will need to take care of allocating them on guest side and then call a ffi function, which will then read the data from that pointer.
#[repr(C)]
pub struct Point {
pub x: f32,
pub y: f32
}
// unsafe fn node_get_pos(this: * const taffy_node) -> Point; !!! won't work. returning composite Point is not possible. only primitives are allowed.

// Instead, you allocate a mut point on stack or heap, and pass the [mut] ptr to the above function.
unsafe fn node_get_pos(this: *const taffy_node, point: * mut Point); // point lives in guest memory and can be written to by host
unsafe fn node_set_pos(this: *mut taffy_node, point: * const Point); // point lives in guest memory and can be read by host.
```

## Alternative (Component Model)
Taffy could express its interface in a [wit world](https://github.com/bytecodealliance/wit-bindgen) (using wit syntax which is almost rust anyway) and the wasm runtime will take care of lowering/lifting the types so that wasm functions can return/take composite structs.

https://github.com/DioxusLabs/taffy/issues/617 is looking for a way to generate code from an interface file, so this might even help as lots (pretty much all) of wit-tooling is in rust.

## What solution would you like?
Use in-out parameter style in FFI API.

Using a decent macro-annotated header in taffy.h can automate bindings generation to a great extent. For example, [impeller (flutter's renderer)](https://github.com/flutter/flutter/blob/master/engine/src/flutter/impeller/toolkit/interop/impeller.h) uses macros like `IMPELLER_DEFINE_HANDLE(X)` to indicate that X is an opaque type. In my bindings crate, I just use a [python script with some regex](https://github.com/coderedart/impellers/blob/master/generate_impeller_api_json.py) to generate a [api json file](https://github.com/coderedart/impellers/blob/master/impeller_api.json), which can be used to provide a structured representation of API for automated generation of types (eg: luau/typescript type definition files for IDE support) or something else.

## What alternative(s) have you considered?

If we had https://github.com/DioxusLabs/taffy/issues/440 , plugins can use serialize/deserialization to just use raw CSS strings directly. It's too powerful and expensive.

## Additional context

There's projects like https://github.com/getditto/safer_ffi which have convenience macros for C bindings. Although, the macros might increase compile times.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing Taffy's existing API and the proposed taffy.h/C FFI surface, then compare the constraints of non-JavaScript Wasm hosts such as wasmtime and wasmer. Read the related component-model issue #617 before choosing an approach. Done means non-JavaScript Wasm guests can use the exposed API with opaque nodes and in-out data parameters.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, rust, wasm
Domain
api, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.