Memory errors under specific conditions #1818

Open
opened 2025-06-16 05:42:31 -07:00 by Ledzz · 1 comment
Ledzz commented 2025-06-16 05:42:31 -07:00 (Migrated from github.com)

I have this issue in js bindings in yoga-layout@3.2.1.

If we have a tree-like structure and call freeRecursive on a node, updating measure function on children will cause memory errors, depending on memory content it can be:

  • null function or function signature mismatch
  • out of memory
  • memory access out of bounds

Here's a quick repro:

import {loadYoga} from 'yoga-layout/load';

const yoga = await loadYoga();

const root = yoga.Node.create();
const node1 = yoga.Node.create();
const node2 = yoga.Node.create();

root.insertChild(node1, 0)
node1.insertChild(node2, 0)

node2.setMeasureFunc(() => {
    return {
        width: 100,
        height: 100,
    };
})

node1.freeRecursive();

node2.setMeasureFunc(() => {
    return {
        width: 100,
        height: 100,
    };
})

I understand that this is not a good to free memory and then try to use it again, but maybe we can add some checks in the js bindings code?

I have this issue in js bindings in yoga-layout@3.2.1. If we have a tree-like structure and call freeRecursive on a node, updating measure function on children will cause memory errors, depending on memory content it can be: - null function or function signature mismatch - out of memory - memory access out of bounds Here's a quick repro: ```javascript import {loadYoga} from 'yoga-layout/load'; const yoga = await loadYoga(); const root = yoga.Node.create(); const node1 = yoga.Node.create(); const node2 = yoga.Node.create(); root.insertChild(node1, 0) node1.insertChild(node2, 0) node2.setMeasureFunc(() => { return { width: 100, height: 100, }; }) node1.freeRecursive(); node2.setMeasureFunc(() => { return { width: 100, height: 100, }; }) ``` I understand that this is not a good to free memory and then try to use it again, but maybe we can add some checks in the js bindings code?
NickGerleman commented 2025-06-17 16:38:42 -07:00 (Migrated from github.com)

FinalizationRegistry is getting to be well supported now: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry

I haven't been able to prioritize much work on Yoga or the JS bindings recently, but there is a series of refactoring that I think would dramatically improve perf and usability of the JS bindings:

  1. Switch to GC, instead of manual memory management, using something like the above. The way this works for Yoga's Java bindings, is that we have a managed node, that has children managed nodes, and each managed node owns the unmanaged node. If the managed Yoga node is garbage collected, the unmanaged node can safely be freed.
  2. Either removing embind entirely, and moving to direct calls, or moving to a version of it with AOT binding https://github.com/facebook/yoga/pull/1793#discussion_r1982231182

Longer term, we can also rely on WASM ESM integration, to get out of the packaging shenanigans we have, where we currently bundle into a single JS file, that requires dynamic execution to eval (Emscripten started adding support recently https://github.com/emscripten-core/emscripten/pull/23985)

`FinalizationRegistry` is getting to be well supported now: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry I haven't been able to prioritize much work on Yoga or the JS bindings recently, but there is a series of refactoring that I think would dramatically improve perf and usability of the JS bindings: 1. Switch to GC, instead of manual memory management, using something like the above. The way this works for Yoga's Java bindings, is that we have a managed node, that has children managed nodes, and each managed node owns the unmanaged node. If the managed Yoga node is garbage collected, the unmanaged node can safely be freed. 2. Either removing embind entirely, and moving to direct calls, or moving to a version of it with AOT binding https://github.com/facebook/yoga/pull/1793#discussion_r1982231182 Longer term, we can also rely on WASM ESM integration, to get out of the packaging shenanigans we have, where we currently bundle into a single JS file, that requires dynamic execution to eval (Emscripten started adding support recently https://github.com/emscripten-core/emscripten/pull/23985)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DaddyFrosty/yoga#1818
No description provided.