Question about Hermes bytecode version policy #1993
-
|
Hello Hermes team, I have a question about the current Hermes bytecode versioning and compatibility policy. My previous understanding was that when the React Native / Hermes version changes, the Hermes bytecode version also changes accordingly. In practice, I had assumed that upgrading React Native would usually imply a change in the Hermes bytecode format version as well. However, when looking at RN 0.84 and RN 0.85, that no longer seems to be true. For example, the Hermes compiler version used in RN 0.84 appears to have changed across patch releases (for example, from something like hermes-compiler patch 7 to patch 10), while the bytecode version still appears to remain the same. That made me wonder whether the policy has changed starting from bytecode v1. More specifically:
The reason I am asking is that we want to ship a native app built with RN 0.84, but later deliver JS bundles built with a different RN/Hermes version if compatibility allows it. From the outside, it looks like bytecode version matching may be a prerequisite for this, but I am not sure whether it is also a sufficient compatibility signal that we can rely on in production. Thanks in advance. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
|
The bytecode version is the HBC file-format compatibility number, not a React Native release number. In the current Hermes source, I would not treat "same bytecode version" as a full support guarantee for shipping RN 0.85-built bundles into an RN 0.84 native app. It is useful evidence that the HBC container version did not change, but there can still be runtime, native module, RN integration, or Hermes bug-fix assumptions outside the bytecode header. For OTA-style delivery, the safe boundary is still to compile bundles with the Hermes/RN line you ship in the native binary, unless you have a controlled compatibility test matrix for the exact two RN/Hermes builds. |
Beta Was this translation helpful? Give feedback.
-
|
From digging through the source and commit history, the policy looks like this, even if it isn't written up as an explicit document anywhere I can find.
So the practical reading is:
Everything else lives outside the bytecode version. Compiler intrinsics, runtime helper signatures, builtin shapes, JSI surface, RN glue can all shift between Hermes patches without the integer moving. The runtime has no way to detect those mismatches at load time, so a bundle compiled with a slightly newer compiler can load fine and then crash later when it hits a path that calls into something the older runtime doesn't expose. That's probably why the team hasn't published it as a formal versioning policy. Doing so would commit them to a contract they likely don't want to give right now. In practice the bytecode version is best treated as a load-time sanity check, not a compatibility guarantee. The supported contract is still "match the Hermes version of the runtime that ships in your binary." Anything else relies on testing the specific pair of versions you care about. Would still be useful to hear from someone on the team whether this matches their intent. |
Beta Was this translation helpful? Give feedback.
-
Sorry for the delayed response. This question somehow slipped my mind. I will answer your specific questions first and then try to explain our policy.
That has never been the case. The Hermes bytecode version has always been orthogonal to the RN version. At the time of each RN release, RN picks whatever the current stable Hermes is with its bytecode version. Whether the version has been increased or not depends on Hermes development and is independent from the RN release.
The policy has not changed, but now we can express it a bit more clearly.
Not exactly. The bytecode version stays the same until we change the encoding - but we may change it in any release. There is no promise of stability across releases.
Same bytecode version means that the runtime can correctly load the bytecode and execute it as if it was source. However, newer runtimes may have introduced JS APIs that are missing from older runtimes, even if they run the same bytecode version.
If the bytecode version is the same, it will load and will run with correct JS semantics. However, the bytecode version does not imply the presence of JS or especially RN APIs.
There is nothing unsafe. However, the bytecode version does not in any way imply what version of RN is running, what APIs are provided by RN, etc.
Yes, this is possible. As long as the bytecode bundle only uses APIs available in RN 0.84 and has the correct bytecode version, it will work. The Hermes bytecode can be thought of as a form of encoding of the input source. If the bytecode version has changed, then the encoding has changed. A runtime can only decode bytecode of a specific version. However, once decoded, whether the result will run as expected depends on what JS APIs it uses. The presence of absence of JS APIs, either provided by Hermes or RN, is orthogonal to the bytecode version. For example, Hermes v1 and Hermes v2 might use hypothetically the same bytecode version, but v2 might have added new JS APIs like Temporal, which aren't present in v1. So, again, the bytecode version does not imply API compatibility. It only guarantees the ability to decode the bytecode and execute it with correct JS semantics. Our bytecode versioning policy is very simple:
|
Beta Was this translation helpful? Give feedback.
Sorry for the delayed response. This question somehow slipped my mind. I will answer your specific questions first and then try to explain our policy.
That has never been the case. The Hermes bytecode version has always been orthogonal to the RN version. At the time of each RN release, RN picks whatever the current …