Skip to content

Replace manual memory management with FinalizationRegistry#1908

Closed
NickGerleman wants to merge 1 commit into
react:mainfrom
NickGerleman:export-D95014519
Closed

Replace manual memory management with FinalizationRegistry#1908
NickGerleman wants to merge 1 commit into
react:mainfrom
NickGerleman:export-D95014519

Conversation

@NickGerleman

Copy link
Copy Markdown
Contributor

Summary:
Yoga's JavaScript API currently requires users to manually call
node.free(), node.freeRecursive(), or config.free() to release
WASM memory. This is error-prone and unusual for a JavaScript library.

This diff uses FinalizationRegistry (available in all modern JS
engines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.

Changes:

  • Added FinalizationRegistry instances for Node and Config in
    wrapAssembly.ts. When a NodeImpl/ConfigImpl is constructed, it
    is registered with the appropriate registry. The weak reference
    callback receives the WASM pointer and calls the appropriate C free
    function.
  • The Node finalizer calls YGNodeFinalize (not YGNodeFree) to
    safely deallocate without disconnecting nodes from their
    owner/children, since an entire tree may be garbage collected
    together.
  • Removed free() and freeRecursive() from the public Node type
    and free() from the public Config type.
  • Removed Yoga.Node.destroy() and Yoga.Config.destroy() factory
    methods.
  • Fixed setDirtiedFunc to use WeakRef(this) instead of capturing
    this directly in the closure stored in the dirtied func Map. The
    previous () => dirtiedFunc(this) pattern created a strong reference
    from the Map to the Node, preventing GC of detached nodes with a
    dirtied func set.
  • Updated gentest-javascript.js to stop generating try/finally
    cleanup blocks and let root declarations in test prologues/epilogues.
  • Removed all free()/freeRecursive()/config.free() calls from 25
    generated test files and 9 hand-written test files.
  • Re-signed all generated test files with signedsource.
  • Updated README.md to remove manual memory management documentation.

Differential Revision: D95014519

@vercel

vercel Bot commented Mar 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
yoga-website Ready Ready Preview, Comment Mar 6, 2026 9:50am

Request Review

@meta-codesync

meta-codesync Bot commented Mar 3, 2026

Copy link
Copy Markdown

@NickGerleman has exported this pull request. If you are a Meta employee, you can view the originating Diff in D95014519.

NickGerleman added a commit to NickGerleman/yoga that referenced this pull request Mar 6, 2026
Summary:
Pull Request resolved: react#1908

Yoga's JavaScript API currently requires users to manually call
`node.free()`, `node.freeRecursive()`, or `config.free()` to release
WASM memory. This is error-prone and unusual for a JavaScript library.

This diff uses `FinalizationRegistry` (available in all modern JS
engines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.

Changes:
- Added `FinalizationRegistry` instances for `Node` and `Config` in
  `wrapAssembly.ts`. When a `NodeImpl`/`ConfigImpl` is constructed, it
  is registered with the appropriate registry. The weak reference
  callback receives the WASM pointer and calls the appropriate C free
  function.
- The Node finalizer calls `YGNodeFinalize` (not `YGNodeFree`) to
  safely deallocate without disconnecting nodes from their
  owner/children, since an entire tree may be garbage collected
  together.
- Removed `free()` and `freeRecursive()` from the public `Node` type
  and `free()` from the public `Config` type.
- Removed `Yoga.Node.destroy()` and `Yoga.Config.destroy()` factory
  methods.
- Fixed `setDirtiedFunc` to use `WeakRef(this)` instead of capturing
  `this` directly in the closure stored in the dirtied func Map. The
  previous `() => dirtiedFunc(this)` pattern created a strong reference
  from the Map to the Node, preventing GC of detached nodes with a
  dirtied func set.
- Updated `gentest-javascript.js` to stop generating `try`/`finally`
  cleanup blocks and `let root` declarations in test prologues/epilogues.
- Removed all `free()`/`freeRecursive()`/`config.free()` calls from 25
  generated test files and 9 hand-written test files.
- Re-signed all generated test files with signedsource.
- Updated `README.md` to remove manual memory management documentation.

Differential Revision: D95014519
NickGerleman added a commit to NickGerleman/yoga that referenced this pull request Mar 6, 2026
Summary:
Pull Request resolved: react#1908

Yoga's JavaScript API currently requires users to manually call
`node.free()`, `node.freeRecursive()`, or `config.free()` to release
WASM memory. This is error-prone and unusual for a JavaScript library.

This diff uses `FinalizationRegistry` (available in all modern JS
engines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.

Changes:
- Added `FinalizationRegistry` instances for `Node` and `Config` in
  `wrapAssembly.ts`. When a `NodeImpl`/`ConfigImpl` is constructed, it
  is registered with the appropriate registry. The weak reference
  callback receives the WASM pointer and calls the appropriate C free
  function.
- The Node finalizer calls `YGNodeFinalize` (not `YGNodeFree`) to
  safely deallocate without disconnecting nodes from their
  owner/children, since an entire tree may be garbage collected
  together.
- Removed `free()` and `freeRecursive()` from the public `Node` type
  and `free()` from the public `Config` type.
- Removed `Yoga.Node.destroy()` and `Yoga.Config.destroy()` factory
  methods.
- Fixed `setDirtiedFunc` to use `WeakRef(this)` instead of capturing
  `this` directly in the closure stored in the dirtied func Map. The
  previous `() => dirtiedFunc(this)` pattern created a strong reference
  from the Map to the Node, preventing GC of detached nodes with a
  dirtied func set.
- Updated `gentest-javascript.js` to stop generating `try`/`finally`
  cleanup blocks and `let root` declarations in test prologues/epilogues.
- Removed all `free()`/`freeRecursive()`/`config.free()` calls from 25
  generated test files and 9 hand-written test files.
- Re-signed all generated test files with signedsource.
- Updated `README.md` to remove manual memory management documentation.

Differential Revision: D95014519
NickGerleman added a commit to NickGerleman/yoga that referenced this pull request Mar 6, 2026
Summary:
Pull Request resolved: react#1908

Yoga's JavaScript API currently requires users to manually call
`node.free()`, `node.freeRecursive()`, or `config.free()` to release
WASM memory. This is error-prone and unusual for a JavaScript library.

This diff uses `FinalizationRegistry` (available in all modern JS
engines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.

Changes:
- Added `FinalizationRegistry` instances for `Node` and `Config` in
  `wrapAssembly.ts`. When a `NodeImpl`/`ConfigImpl` is constructed, it
  is registered with the appropriate registry. The weak reference
  callback receives the WASM pointer and calls the appropriate C free
  function.
- The Node finalizer calls `YGNodeFinalize` (not `YGNodeFree`) to
  safely deallocate without disconnecting nodes from their
  owner/children, since an entire tree may be garbage collected
  together.
- Removed `free()` and `freeRecursive()` from the public `Node` type
  and `free()` from the public `Config` type.
- Removed `Yoga.Node.destroy()` and `Yoga.Config.destroy()` factory
  methods.
- Fixed `setDirtiedFunc` to use `WeakRef(this)` instead of capturing
  `this` directly in the closure stored in the dirtied func Map. The
  previous `() => dirtiedFunc(this)` pattern created a strong reference
  from the Map to the Node, preventing GC of detached nodes with a
  dirtied func set.
- Updated `gentest-javascript.js` to stop generating `try`/`finally`
  cleanup blocks and `let root` declarations in test prologues/epilogues.
- Removed all `free()`/`freeRecursive()`/`config.free()` calls from 25
  generated test files and 9 hand-written test files.
- Re-signed all generated test files with signedsource.
- Updated `README.md` to remove manual memory management documentation.

Differential Revision: D95014519
NickGerleman added a commit to NickGerleman/yoga that referenced this pull request Mar 6, 2026
Summary:
Pull Request resolved: react#1908

Fixes react#1818
Fixes react#1572

Yoga's JavaScript API currently requires users to manually call
`node.free()`, `node.freeRecursive()`, or `config.free()` to release
WASM memory. This is error-prone and unusual for a JavaScript library.

This diff uses `FinalizationRegistry` (available in all modern JS
engines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.

Changes:
- Added `FinalizationRegistry` instances for `Node` and `Config` in
  `wrapAssembly.ts`. When a `NodeImpl`/`ConfigImpl` is constructed, it
  is registered with the appropriate registry. The weak reference
  callback receives the WASM pointer and calls the appropriate C free
  function.
- The Node finalizer calls `YGNodeFinalize` (not `YGNodeFree`) to
  safely deallocate without disconnecting nodes from their
  owner/children, since an entire tree may be garbage collected
  together.
- Removed `free()` and `freeRecursive()` from the public `Node` type
  and `free()` from the public `Config` type.
- Removed `Yoga.Node.destroy()` and `Yoga.Config.destroy()` factory
  methods.
- Fixed `setDirtiedFunc` to use `WeakRef(this)` instead of capturing
  `this` directly in the closure stored in the dirtied func Map. The
  previous `() => dirtiedFunc(this)` pattern created a strong reference
  from the Map to the Node, preventing GC of detached nodes with a
  dirtied func set.
- Updated `gentest-javascript.js` to stop generating `try`/`finally`
  cleanup blocks and `let root` declarations in test prologues/epilogues.
- Removed all `free()`/`freeRecursive()`/`config.free()` calls from 25
  generated test files and 9 hand-written test files.
- Re-signed all generated test files with signedsource.
- Updated `README.md` to remove manual memory management documentation.

Differential Revision: D95014519
NickGerleman added a commit to NickGerleman/yoga that referenced this pull request Mar 6, 2026
Summary:
Pull Request resolved: react#1908

Fixes react#1818
Fixes react#1572

Yoga's JavaScript API currently requires users to manually call
`node.free()`, `node.freeRecursive()`, or `config.free()` to release
WASM memory. This is error-prone and unusual for a JavaScript library.

This diff uses `FinalizationRegistry` (available in all modern JS
engines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.

Changes:
- Added `FinalizationRegistry` instances for `Node` and `Config` in
  `wrapAssembly.ts`. When a `NodeImpl`/`ConfigImpl` is constructed, it
  is registered with the appropriate registry. The weak reference
  callback receives the WASM pointer and calls the appropriate C free
  function.
- The Node finalizer calls `YGNodeFinalize` (not `YGNodeFree`) to
  safely deallocate without disconnecting nodes from their
  owner/children, since an entire tree may be garbage collected
  together.
- Removed `free()` and `freeRecursive()` from the public `Node` type
  and `free()` from the public `Config` type.
- Removed `Yoga.Node.destroy()` and `Yoga.Config.destroy()` factory
  methods.
- Fixed `setDirtiedFunc` to use `WeakRef(this)` instead of capturing
  `this` directly in the closure stored in the dirtied func Map. The
  previous `() => dirtiedFunc(this)` pattern created a strong reference
  from the Map to the Node, preventing GC of detached nodes with a
  dirtied func set.
- Updated `gentest-javascript.js` to stop generating `try`/`finally`
  cleanup blocks and `let root` declarations in test prologues/epilogues.
- Removed all `free()`/`freeRecursive()`/`config.free()` calls from 25
  generated test files and 9 hand-written test files.
- Re-signed all generated test files with signedsource.
- Updated `README.md` to remove manual memory management documentation.

Reviewed By: cipolleschi

Differential Revision: D95014519
Summary:
Pull Request resolved: react#1908

Fixes react#1818
Fixes react#1572

Yoga's JavaScript API currently requires users to manually call
`node.free()`, `node.freeRecursive()`, or `config.free()` to release
WASM memory. This is error-prone and unusual for a JavaScript library.

This diff uses `FinalizationRegistry` (available in all modern JS
engines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.

Changes:
- Added `FinalizationRegistry` instances for `Node` and `Config` in
  `wrapAssembly.ts`. When a `NodeImpl`/`ConfigImpl` is constructed, it
  is registered with the appropriate registry. The weak reference
  callback receives the WASM pointer and calls the appropriate C free
  function.
- The Node finalizer calls `YGNodeFinalize` (not `YGNodeFree`) to
  safely deallocate without disconnecting nodes from their
  owner/children, since an entire tree may be garbage collected
  together.
- Removed `free()` and `freeRecursive()` from the public `Node` type
  and `free()` from the public `Config` type.
- Removed `Yoga.Node.destroy()` and `Yoga.Config.destroy()` factory
  methods.
- Fixed `setDirtiedFunc` to use `WeakRef(this)` instead of capturing
  `this` directly in the closure stored in the dirtied func Map. The
  previous `() => dirtiedFunc(this)` pattern created a strong reference
  from the Map to the Node, preventing GC of detached nodes with a
  dirtied func set.
- Updated `gentest-javascript.js` to stop generating `try`/`finally`
  cleanup blocks and `let root` declarations in test prologues/epilogues.
- Removed all `free()`/`freeRecursive()`/`config.free()` calls from 25
  generated test files and 9 hand-written test files.
- Re-signed all generated test files with signedsource.
- Updated `README.md` to remove manual memory management documentation.

Reviewed By: cipolleschi

Differential Revision: D95014519
@meta-codesync

meta-codesync Bot commented Mar 6, 2026

Copy link
Copy Markdown

This pull request has been merged in e00b766.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants