Skip to content

fix: run yoga on chrome 57+ (mvp wasm) - #147

Merged
RuudBurger merged 4 commits into
mainfrom
ruud/yoga-mvp-wasm
Oct 15, 2026
Merged

RuudBurger merged 4 commits into
mainfrom
ruud/yoga-mvp-wasm

Conversation

@RuudBurger

@RuudBurger RuudBurger commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

The yoga-layout WASM we ship uses sign-ext opcodes, so it only compiles on Chrome 74+. That's about 62% of webOS + Tizen devices. Chrome 57-73 is another ~21% (webOS 5 = Chrome 68, Tizen 5.0 = 63, Tizen 5.5 = 69) and those can run WASM fine, just not that build. This lowers Yoga to MVP WASM so they can lay out at all.

What changed

  • Vendor a binaryen-lowered MVP build of yoga's WASM into packages/plugin-flexbox/src/yoga/vendor, generated by scripts/vendorYoga.ts (pnpm vendor:yoga). It has to be re-run after every yoga-layout bump, otherwise we keep shipping the old Yoga
  • yogaVendor.spec.ts guards it: no post-MVP features in the vendored binary (and it does catch them in the upstream one), it matches the installed yoga-layout version, and it lays out a tree
  • Inline worker is now built for chrome56 too, and stops using queueMicrotask and globalThis.location (both need Chrome 71, and nothing polyfills the worker)
  • Second commit: the ResizeObserver shim did class extends window.ResizeObserver, which throws inside render() on Chrome < 64 (Tizen 5.0). It now falls back to a no-op base, so Lightning targets still report and DOM targets are ignored. Same file falls back to a plain rect where DOMRectReadOnly is missing (Chrome < 61). Also swapped queueMicrotask (Chrome 71) for a small helper with a promise fallback in the host config, element updates and focus, and dropped Array.prototype.at (Chrome 92) / flat (Chrome 69) on the key, focus and StyleSheet paths

Proof

  • sign-ext opcodes 2 to 0, and binaryen --mvp-features validation passes
  • WASM size 71,736 to 71,738 B
  • Layouts identical against the upstream build
  • Perf the same within noise (micro bench 603.9 vs 602.7 ms)
  • New unit tests for the shim with no window.ResizeObserver / DOMRectReadOnly, and for the microtask fallback

Caveat: the plugin-flexbox dist chunk goes from 26 KB to 165 KB because Yoga is now inlined instead of imported. Should be neutral for consumers, they bundled yoga-layout's own 121 KB copy before.

Caveat: @lightningjs/renderer 3.1.1 still calls queueMicrotask itself (CoreNode, Texture), so apps still need a global polyfill for Chrome < 71. Not touching that here.

Not verified on a Chrome 57-73 device yet, only unit tests and the opcode check.

Two more commits: plugin-reanimated now goes through the exported scheduleMicrotask instead of queueMicrotask (animated styles and tracked reactions) and reads the :focus-within leaf by index instead of .at(-1), and VirtualList reads the pointer scroll hook off window / self instead of globalThis. So our own code no longer needs Chrome 71+ on any path I could find. Didn't add a global queueMicrotask polyfill for the renderer after all, because the Plex legacy builds already ship core-js's (web.queue-microtask plus es.global-this): plugin-legacy runs usage detection on the final chunks, renderer included, and on index-legacy it picks both up for chrome 53 and 56 but not for 79. core-js keeps the semantics (real microtask, a throw rethrows from the flush so it still shows up in the console). Other consumers without plugin-legacy still need their own polyfill for the renderer. Still unverified on a real Chrome 57-70 device.

@RuudBurger
RuudBurger marked this pull request as ready for review October 15, 2026 12:53
@RuudBurger
RuudBurger merged commit e843276 into main Oct 15, 2026
1 check passed
@RuudBurger
RuudBurger deleted the ruud/yoga-mvp-wasm branch October 15, 2026 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant