Add WASM/JS bindings via wasm-bindgen#927
Add WASM/JS bindings via wasm-bindgen#927caweinshenker wants to merge 2 commits intoDioxusLabs:mainfrom
Conversation
Exposes Taffy's block, flexbox, and CSS grid layout algorithms to
JavaScript/TypeScript via wasm-bindgen. 339KB WASM binary.
API:
const layout = new TaffyLayout();
const child = layout.newLeaf({ width: 100, height: 50 });
const root = layout.newWithChildren(
{ display: 'flex', flexDirection: 'row', gap: 10 },
[child]
);
layout.computeLayout(root, 400, 200);
layout.getLayout(child); // { x, y, width, height }
Supported CSS properties:
- Display: flex, block, grid, none
- Flexbox: flexDirection, flexWrap, flexGrow/Shrink/Basis, align*, justify*
- Grid: gridTemplateColumns/Rows (fr/px/%), gridColumn/Row placement
- Box model: width/height, min/max, margin, padding, border
- Position: relative, absolute with insets
- Gap, overflow, aspectRatio
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Converting to draft — I should have filed the issue (#928) and waited for assignment before submitting. Happy to wait for maintainer feedback before proceeding. Will add tests in the meantime. |
9 tests covering flexbox, block, and CSS grid layouts: - flex_row_basic: horizontal flex with fixed-size children - flex_row_with_gap_and_padding: padding and gap spacing - flex_grow: flex-grow fills remaining space - flex_column: vertical flex stacking - block_vertical_stacking: block layout with auto height - block_with_margin: margin spacing in block layout - grid_2x2_equal: equal 1fr grid cells - grid_with_gap: grid gap spacing - percentage_width: percentage-based sizing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
nicoburns
left a comment
There was a problem hiding this comment.
This looks broadly reasonable architectually. It'll be slower than is possible for a couple of reasons:
- Use of an object-based API and Reflect::get. Yoga's WASM have individual setters instead.
- Strings for enums. #394 used enums exposed over FFI so that these would be encoded as a number over the WASM boundary.
- Strings for numeric values (px, %, fr, etc) (this may not be slower, not 100% sure).
However, given how long this feature request has been sitting for, I think it's reasonable to get something that works out and worry about performance later.
A few other notes:
- #929 adds more robust/complete string parsing based on the
cssparsercrate to Taffy (which I had coincidentally been working on as part of #926). I would suggest basing this PR on top of that PR and making use of it's string parsing. - Relatedly, you may want to make
grid-template-columnsand similar just one big string (or an option for that). That would allow support forrepeat()to work. - I notice that "measure functions" are not included in this PR. That might severely restrict the usefulness, as often you'll want to support things like text or images as "leaf nodes". Perhaps we ought to try to include that. #394 had a sketch of this. Can't remember how complete / working it is.
Finally, I would love to see some kind of usage example included in the PR as code. And also some instructions for publishing (would this be published to npm?). If possible for both node.js and web consumers. But if you've only been testing on one platform (web?) then a small runnable example for whatever platform you've been testing on would be fine.
| serde = { version = "1", features = ["derive"] } | ||
| serde-wasm-bindgen = "0.6" |
There was a problem hiding this comment.
These don't seem to be being used?
| /// Expected values are derived from Chrome DevTools measurements of equivalent | ||
| /// HTML/CSS layouts. |
There was a problem hiding this comment.
Is this true or AI generated?
| "flex-start" | "start" => AlignContent::FlexStart, | ||
| "flex-end" | "end" => AlignContent::FlexEnd, |
There was a problem hiding this comment.
start and end should map to the Start and End variants.
| "flex-start" | "start" => AlignItems::FlexStart, | ||
| "flex-end" | "end" => AlignItems::FlexEnd, |
There was a problem hiding this comment.
start and end should map to the Start and End variants.
Objective
Adds JavaScript/TypeScript bindings for Taffy via
wasm-bindgen, enabling use of Taffy's layout engine from JS/TS environments (browser and Node.js).Fixes #928. Relates to #394.
The bindings live in
bindings/wasm/as a separate crate and produce a ~339KB optimized WASM binary.What's included
TaffyLayoutclass exposing tree creation, style setting, layout computation, and result retrievalflex,block,grid,noneflexDirection,flexWrap,flexGrow/Shrink/Basis,alignItems,justifyContent, etc.gridTemplateColumns/Rows(withfr/px/%units),gridColumn/Rowplacementwidth/height,min/maxvariants,margin,padding,border(shorthand + per-side)relative,absolutewithtop/right/bottom/leftinsetsgap,overflow,aspectRatio"50%","auto","1fr","100px")Usage
Security review
unsafeblocks in the binding codeStylestruct translation)cargo test --workspace)AI disclosure
This code was generated with assistance from Claude (Anthropic). The binding architecture follows the same pattern as PR #394 (
bindings/wasm/crate withwasm-bindgen). All code has been reviewed, tested, and verified to compile and produce correct layout results for flexbox, block, and CSS grid layouts.Context
The bindings are intentionally minimal — they expose the most commonly used CSS properties rather than attempting full coverage. Happy to expand based on feedback.
Tested with
wasm-pack buildtargeting bothwebandnodejs, verified with flex/block/grid layout tests.