Replace manual memory management with FinalizationRegistry#1908
Closed
NickGerleman wants to merge 1 commit into
Closed
Replace manual memory management with FinalizationRegistry#1908NickGerleman wants to merge 1 commit into
NickGerleman wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@NickGerleman has exported this pull request. If you are a Meta employee, you can view the originating Diff in D95014519. |
928508c to
b2b6bae
Compare
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
b2b6bae to
a869bbe
Compare
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
a869bbe to
27150eb
Compare
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
27150eb to
0f928e3
Compare
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
0f928e3 to
a070f5e
Compare
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
a070f5e to
f4dd443
Compare
|
This pull request has been merged in e00b766. |
wjq990112
added a commit
to wjq990112/better-yoga
that referenced
this pull request
Jun 26, 2026
…y refactor Upstream yoga react#1908 ("Replace manual memory management with FinalizationRegistry") removed Node.free/freeRecursive, Config.free and the static Yoga.Node.destroy on main. better-yoga forks main, so consumers written for the stable yoga-layout@3.2.x (ink, vue-tui) crash with "node.free is not a function" on teardown. Re-add the four release APIs, adapted to the FinalizationRegistry model: - Node.free: unregister the GC finalizer, sync JS parent/child pointers, call _YGNodeFree, then null _ptr (idempotent guard against double-free) - Node.freeRecursive: JS-side depth-first recursion (native YGNodeFreeRecursive would leave descendant wrappers registered and double-free after GC) - Config.free: unregister + _YGConfigFree + idempotent - Yoga.Node.destroy(node): 3.2.x compat alias delegating to node.free() Adds tests/YGNodeFreeTest.test.ts (6 cases). Claude-Session: https://claude.ai/code/session_013wsNEdvdkhb89Uj9sQf9LT
wjq990112
added a commit
to wjq990112/better-yoga
that referenced
this pull request
Jun 27, 2026
Squash of the docs/rebrand-better-yoga-layout branch: - fix: restore Node.free/freeRecursive, Config.free and the static Yoga.Node.destroy removed by upstream's FinalizationRegistry refactor (react#1908); adds tests/YGNodeFreeTest.test.ts (6 cases) - chore(release): bump better-yoga-layout 0.2.0 -> 0.2.1 - docs(readme): rebrand to better-yoga-layout Claude-Session: https://claude.ai/code/session_013wsNEdvdkhb89Uj9sQf9LT
wjq990112
added a commit
to wjq990112/better-yoga
that referenced
this pull request
Jun 27, 2026
…out; release 0.2.1 (#2) * chore(release): bump better-yoga-layout to 0.2.0 Bump version 0.1.0 -> 0.2.0 for the first public release carrying the performance work (dynamic measurement cache + edge/axis fast-paths + ThinLTO). Pin publishConfig.registry to the public npm registry so the package is never accidentally published to an internal mirror. * docs(readme): rebrand to better-yoga-layout with optimizations & benchmarks Rewrite the project README and npm package README for the better-yoga fork, and add a Chinese translation (README.zh-CN.md, cross-linked). - Rename yoga-layout -> better-yoga-layout; npm + MIT badges (drop Maven/SPM, which this fork does not publish). - Position as a drop-in replacement for yoga-layout with identical behavior. - Document the three optimization themes with commit links: dynamic measurement cache (70c0142), edge/axis fast-paths, ThinLTO by default. - Add the three-way benchmark table (upstream Yoga vs better-yoga vs Taffy) with an honest framing: 1.5-1.9x vs upstream on typical trees, super-deep shown with context, plus a caveats section on the remaining algorithmic gap vs Taffy. - Credit upstream Yoga / Meta (MIT). * fix: restore manual-free APIs removed by upstream FinalizationRegistry refactor Upstream yoga react#1908 ("Replace manual memory management with FinalizationRegistry") removed Node.free/freeRecursive, Config.free and the static Yoga.Node.destroy on main. better-yoga forks main, so consumers written for the stable yoga-layout@3.2.x (ink, vue-tui) crash with "node.free is not a function" on teardown. Re-add the four release APIs, adapted to the FinalizationRegistry model: - Node.free: unregister the GC finalizer, sync JS parent/child pointers, call _YGNodeFree, then null _ptr (idempotent guard against double-free) - Node.freeRecursive: JS-side depth-first recursion (native YGNodeFreeRecursive would leave descendant wrappers registered and double-free after GC) - Config.free: unregister + _YGConfigFree + idempotent - Yoga.Node.destroy(node): 3.2.x compat alias delegating to node.free() Adds tests/YGNodeFreeTest.test.ts (6 cases). Claude-Session: https://claude.ai/code/session_013wsNEdvdkhb89Uj9sQf9LT * chore(release): bump better-yoga-layout to 0.2.1 Claude-Session: https://claude.ai/code/session_013wsNEdvdkhb89Uj9sQf9LT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
Yoga's JavaScript API currently requires users to manually call
node.free(),node.freeRecursive(), orconfig.free()to releaseWASM memory. This is error-prone and unusual for a JavaScript library.
This diff uses
FinalizationRegistry(available in all modern JSengines) to automatically free WASM memory when JS objects are garbage
collected, removing this footgun entirely.
Changes:
FinalizationRegistryinstances forNodeandConfiginwrapAssembly.ts. When aNodeImpl/ConfigImplis constructed, itis registered with the appropriate registry. The weak reference
callback receives the WASM pointer and calls the appropriate C free
function.
YGNodeFinalize(notYGNodeFree) tosafely deallocate without disconnecting nodes from their
owner/children, since an entire tree may be garbage collected
together.
free()andfreeRecursive()from the publicNodetypeand
free()from the publicConfigtype.Yoga.Node.destroy()andYoga.Config.destroy()factorymethods.
setDirtiedFuncto useWeakRef(this)instead of capturingthisdirectly in the closure stored in the dirtied func Map. Theprevious
() => dirtiedFunc(this)pattern created a strong referencefrom the Map to the Node, preventing GC of detached nodes with a
dirtied func set.
gentest-javascript.jsto stop generatingtry/finallycleanup blocks and
let rootdeclarations in test prologues/epilogues.free()/freeRecursive()/config.free()calls from 25generated test files and 9 hand-written test files.
README.mdto remove manual memory management documentation.Differential Revision: D95014519