feat(Worklets): experimental bytecode worklets in legacy eval mode#9705
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces an experimental, opt-in path for Legacy Eval Mode to ship Hermes bytecode (instead of source strings) for worklets in production, aiming to mitigate the Hermes V1 memory regression referenced in #9650.
Changes:
- Add Babel plugin support to optionally compile worklets to Hermes bytecode in release builds (
hermesBytecode+getHBCBinary) and embed it into__initData. - Extend the runtime (JS + C++) to evaluate embedded bytecode (
evalBytecode) and to install unpackers from either code or bytecode. - Add/adjust Jest coverage and snapshots for the new wrapping/bytecode behavior; update example app configuration and an “About” indicator.
Reviewed changes
Copilot reviewed 19 out of 22 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/patches/fabric-example-babel-config.patch | Updates bundleMode toggle patch context for the fabric example babel config. |
| packages/react-native-worklets/src/WorkletsModule/workletsModuleProxy.ts | Renames the code unpacker loader method and adds a bytecode loader method to the proxy interface. |
| packages/react-native-worklets/src/WorkletsModule/NativeWorklets.native.ts | Installs unpackers via code or bytecode based on __initData contents. |
| packages/react-native-worklets/src/types.ts | Makes __initData.code optional and adds optional __initData.bytecode. |
| packages/react-native-worklets/src/memory/valueUnpacker.native.ts | Adds bytecode evaluation path (evalBytecode) and adjusts eval usage to match new code wrapping. |
| packages/react-native-worklets/plugin/src/workletStringCode.ts | Wrapes emitted worklet code as an expression (( … )) so evaluators return a function value. |
| packages/react-native-worklets/plugin/src/workletFactory.ts | Adds bytecode emission pipeline and embeds bytecode (as Uint8Array(...).buffer) into init data. |
| packages/react-native-worklets/plugin/src/options.ts | Documents new experimental plugin options. |
| packages/react-native-worklets/plugin/src/hermesBytecode.ts | New helper that calls hermesc to compile a worklet string to bytecode with fallbacks/warnings. |
| packages/react-native-worklets/plugin/index.js | Updates built plugin output to include bytecode compilation and wrapped code strings. |
| packages/react-native-worklets/plugin/index.d.ts | Exposes new experimental plugin options in type definitions. |
| packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.cpp | Adds global evalBytecode host function in release builds for Hermes worklet runtime. |
| packages/react-native-worklets/Common/cpp/worklets/Tools/ScriptBuffer.h | Adds BytecodeBuffer to pass Hermes bytecode to evaluateJavaScript. |
| packages/react-native-worklets/Common/cpp/worklets/SharedItems/UnpackerLoader.h | Refactors unpacker loading/installation to support both code and bytecode variants. |
| packages/react-native-worklets/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.cpp | Splits unpacker loading into two JSI methods: code vs bytecode, with new argument shapes. |
| packages/react-native-worklets/tests/plugin.test.ts | Updates regex expectations to match newly wrapped worklet code strings. |
| packages/react-native-worklets/tests/plugin-hermesBytecode.test.ts | New tests validating bytecode emission + fallbacks using a mocked execFileSync. |
| packages/react-native-worklets/tests/snapshots/plugin-shared.test.ts.snap | Snapshot updates reflecting wrapped initData code and changed hashes. |
| packages/react-native-worklets/tests/snapshots/plugin-bundleMode.test.ts.snap | Snapshot updates reflecting hash changes in bundleMode outputs. |
| apps/fabric-example/babel.config.js | Adds hermesBytecode and getHBCBinary wiring for the example app’s plugin config. |
| apps/common-app/src/apps/reanimated/examples/AboutExample.tsx | Displays whether Legacy Eval bytecode is present via __initData.bytecode. |
Files not reviewed (1)
- packages/react-native-worklets/plugin/index.js: Generated file
Comments suppressed due to low confidence (1)
packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.cpp:8
std::vectoris used in this file but there is no direct#include <vector>. Relying on transitive includes is brittle and can break with upstream header changes; include<vector>explicitly here.
#include <worklets/Tools/ScriptBuffer.h>
#include <worklets/WorkletRuntime/WorkletHermesRuntime.h>
#include <jsi/jsi.h>
#include <memory>
#include <string>
#include <utility>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tshmieldev
approved these changes
Jul 7, 2026
This was referenced Jul 8, 2026
pull Bot
pushed a commit
to BasixKOR/react-native-reanimated
that referenced
this pull request
Jul 8, 2026
## Summary Adding docs for using bytecode in production for legacy eval mode software-mansion#9705. ## Test plan 🚀
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
Adding an optional opt-in behavior for Legacy Eval Mode to use bytecode instead of plain code for worklets in production.
This is a workaround for the Hermes V1 memory issue #9650
(Fabric Example)
Docs for this feature will be added in a separate PR.
Test plan
App runs in Bundle Mode, Legacy Eval Mode (code) and Legacy Eval Mode (bytecode). To toggle bytecode, you must add
hermesBytecode:trueto babel.config.js in babel.config.js and also pass thegetHBCBinaryfunction.